Fix the most major mac bugs

pull/170/head
James Ball 2023-09-05 20:46:05 +01:00
rodzic c6c3b21e06
commit 81bea16c91
11 zmienionych plików z 54 dodań i 14 usunięć

Wyświetl plik

@ -416,8 +416,14 @@ void OscirenderAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, ju
auto totalNumOutputChannels = getTotalNumOutputChannels(); auto totalNumOutputChannels = getTotalNumOutputChannels();
buffer.clear(); buffer.clear();
synth.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples());
midiMessages.clear(); midiMessages.clear();
// TODO: Make this less hacky and more permanent
if (!playedNote) {
playedNote = true;
midiMessages.addEvent(juce::MidiMessage::noteOn(1, 60, 1.0f), 0);
}
synth.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples());
auto* channelData = buffer.getArrayOfWritePointers(); auto* channelData = buffer.getArrayOfWritePointers();
@ -594,17 +600,24 @@ void OscirenderAudioProcessor::setStateInformation(const void* data, int sizeInB
} }
} }
std::shared_ptr<BufferConsumer> OscirenderAudioProcessor::consumerRegister(std::vector<float>& buffer) {
void OscirenderAudioProcessor::read(std::vector<float>& buffer) {
std::shared_ptr<BufferConsumer> consumer = std::make_shared<BufferConsumer>(buffer); std::shared_ptr<BufferConsumer> consumer = std::make_shared<BufferConsumer>(buffer);
{ juce::SpinLock::ScopedLockType scope(consumerLock);
juce::SpinLock::ScopedLockType scope(consumerLock); consumers.push_back(consumer);
consumers.push_back(consumer);
} return consumer;
}
void OscirenderAudioProcessor::consumerRead(std::shared_ptr<BufferConsumer> consumer) {
consumer->waitUntilFull(); consumer->waitUntilFull();
{ juce::SpinLock::ScopedLockType scope(consumerLock);
consumers.erase(std::remove(consumers.begin(), consumers.end(), consumer), consumers.end());
}
void OscirenderAudioProcessor::consumerStop(std::shared_ptr<BufferConsumer> consumer) {
if (consumer != nullptr) {
juce::SpinLock::ScopedLockType scope(consumerLock); juce::SpinLock::ScopedLockType scope(consumerLock);
consumers.erase(std::remove(consumers.begin(), consumers.end(), consumer), consumers.end()); consumer->forceNotify();
} }
} }

Wyświetl plik

@ -58,7 +58,9 @@ public:
void changeProgramName(int index, const juce::String& newName) override; void changeProgramName(int index, const juce::String& newName) override;
void getStateInformation(juce::MemoryBlock& destData) override; void getStateInformation(juce::MemoryBlock& destData) override;
void setStateInformation(const void* data, int sizeInBytes) override; void setStateInformation(const void* data, int sizeInBytes) override;
void read(std::vector<float>& buffer); std::shared_ptr<BufferConsumer> consumerRegister(std::vector<float>& buffer);
void consumerStop(std::shared_ptr<BufferConsumer> consumer);
void consumerRead(std::shared_ptr<BufferConsumer> consumer);
int VERSION_HINT = 1; int VERSION_HINT = 1;
@ -216,6 +218,7 @@ private:
std::vector<std::shared_ptr<Effect>> allEffects; std::vector<std::shared_ptr<Effect>> allEffects;
std::vector<std::shared_ptr<Effect>> permanentEffects; std::vector<std::shared_ptr<Effect>> permanentEffects;
bool playedNote = false;
juce::Synthesiser synth; juce::Synthesiser synth;
juce::SpinLock consumerLock; juce::SpinLock consumerLock;

Wyświetl plik

@ -41,12 +41,14 @@ AudioWebSocketServer::AudioWebSocketServer(OscirenderAudioProcessor& audioProces
AudioWebSocketServer::~AudioWebSocketServer() { AudioWebSocketServer::~AudioWebSocketServer() {
server.stop(); server.stop();
ix::uninitNetSystem(); ix::uninitNetSystem();
audioProcessor.consumerStop(consumer);
stopThread(1000); stopThread(1000);
} }
void AudioWebSocketServer::run() { void AudioWebSocketServer::run() {
while (!threadShouldExit()) { while (!threadShouldExit()) {
audioProcessor.read(floatBuffer); consumer = audioProcessor.consumerRegister(floatBuffer);
audioProcessor.consumerRead(consumer);
for (int i = 0; i < floatBuffer.size(); i++) { for (int i = 0; i < floatBuffer.size(); i++) {
short sample = floatBuffer[i] * 32767; short sample = floatBuffer[i] * 32767;

Wyświetl plik

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <JuceHeader.h> #include <JuceHeader.h>
#include "../ixwebsocket/IXWebSocketServer.h" #include "../ixwebsocket/IXWebSocketServer.h"
#include "../concurrency/BufferConsumer.h"
class OscirenderAudioProcessor; class OscirenderAudioProcessor;
class AudioWebSocketServer : juce::Thread { class AudioWebSocketServer : juce::Thread {
@ -15,4 +16,6 @@ private:
OscirenderAudioProcessor& audioProcessor; OscirenderAudioProcessor& audioProcessor;
std::vector<float> floatBuffer = std::vector<float>(2 * 4096); std::vector<float> floatBuffer = std::vector<float>(2 * 4096);
char buffer[4096 * 2 * 2]; char buffer[4096 * 2 * 2];
std::shared_ptr<BufferConsumer> consumer;
}; };

Wyświetl plik

@ -6,12 +6,14 @@ PitchDetector::PitchDetector(OscirenderAudioProcessor& audioProcessor) : juce::T
} }
PitchDetector::~PitchDetector() { PitchDetector::~PitchDetector() {
audioProcessor.consumerStop(consumer);
stopThread(1000); stopThread(1000);
} }
void PitchDetector::run() { void PitchDetector::run() {
while (!threadShouldExit()) { while (!threadShouldExit()) {
audioProcessor.read(buffer); consumer = audioProcessor.consumerRegister(buffer);
audioProcessor.consumerRead(consumer);
// buffer is for 2 channels, so we need to only use one // buffer is for 2 channels, so we need to only use one
for (int i = 0; i < fftSize; i++) { for (int i = 0; i < fftSize; i++) {

Wyświetl plik

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <JuceHeader.h> #include <JuceHeader.h>
#include "../concurrency/BufferConsumer.h"
class OscirenderAudioProcessor; class OscirenderAudioProcessor;
class PitchDetector : public juce::Thread, public juce::AsyncUpdater { class PitchDetector : public juce::Thread, public juce::AsyncUpdater {
@ -19,6 +20,7 @@ private:
static constexpr int fftOrder = 15; static constexpr int fftOrder = 15;
static constexpr int fftSize = 1 << fftOrder; static constexpr int fftSize = 1 << fftOrder;
std::shared_ptr<BufferConsumer> consumer;
std::vector<float> buffer = std::vector<float>(2 * fftSize); std::vector<float> buffer = std::vector<float>(2 * fftSize);
juce::dsp::FFT forwardFFT{fftOrder}; juce::dsp::FFT forwardFFT{fftOrder};
std::array<float, fftSize * 2> fftData; std::array<float, fftSize * 2> fftData;

Wyświetl plik

@ -7,6 +7,7 @@ VisualiserComponent::VisualiserComponent(int numChannels, OscirenderAudioProcess
} }
VisualiserComponent::~VisualiserComponent() { VisualiserComponent::~VisualiserComponent() {
audioProcessor.consumerStop(consumer);
stopThread(1000); stopThread(1000);
} }
@ -44,7 +45,8 @@ void VisualiserComponent::timerCallback() {
void VisualiserComponent::run() { void VisualiserComponent::run() {
while (!threadShouldExit()) { while (!threadShouldExit()) {
audioProcessor.read(tempBuffer); consumer = audioProcessor.consumerRegister(tempBuffer);
audioProcessor.consumerRead(consumer);
setBuffer(tempBuffer); setBuffer(tempBuffer);
} }
} }

Wyświetl plik

@ -25,6 +25,8 @@ private:
OscirenderAudioProcessor& audioProcessor; OscirenderAudioProcessor& audioProcessor;
std::vector<float> tempBuffer = std::vector<float>(2 * 4096); std::vector<float> tempBuffer = std::vector<float>(2 * 4096);
int precision = 4; int precision = 4;
std::shared_ptr<BufferConsumer> consumer;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VisualiserComponent) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VisualiserComponent)
}; };

Wyświetl plik

@ -47,6 +47,7 @@ VolumeComponent::VolumeComponent(OscirenderAudioProcessor& p) : audioProcessor(p
} }
VolumeComponent::~VolumeComponent() { VolumeComponent::~VolumeComponent() {
audioProcessor.consumerStop(consumer);
stopThread(1000); stopThread(1000);
} }
@ -92,7 +93,8 @@ void VolumeComponent::timerCallback() {
void VolumeComponent::run() { void VolumeComponent::run() {
while (!threadShouldExit()) { while (!threadShouldExit()) {
audioProcessor.read(buffer); consumer = audioProcessor.consumerRegister(buffer);
audioProcessor.consumerRead(consumer);
float leftVolume = 0; float leftVolume = 0;
float rightVolume = 0; float rightVolume = 0;

Wyświetl plik

@ -3,6 +3,7 @@
#include <JuceHeader.h> #include <JuceHeader.h>
#include "../PluginProcessor.h" #include "../PluginProcessor.h"
#include "../LookAndFeel.h" #include "../LookAndFeel.h"
#include "../concurrency/BufferConsumer.h"
class ThumbRadiusLookAndFeel : public OscirenderLookAndFeel { class ThumbRadiusLookAndFeel : public OscirenderLookAndFeel {
public: public:
@ -84,6 +85,8 @@ private:
std::unique_ptr<juce::Drawable> volumeIcon; std::unique_ptr<juce::Drawable> volumeIcon;
std::unique_ptr<juce::Drawable> thresholdIcon; std::unique_ptr<juce::Drawable> thresholdIcon;
std::shared_ptr<BufferConsumer> consumer;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VolumeComponent) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VolumeComponent)
}; };

Wyświetl plik

@ -54,6 +54,12 @@ public:
sema.release(); sema.release();
} }
} }
// to be used when the audio thread is being destroyed to
// make sure that everything waiting on it stops waiting.
void forceNotify() {
sema.release();
}
void write(double d) { void write(double d) {
if (offset < buffer.size()) { if (offset < buffer.size()) {