kopia lustrzana https://github.com/jameshball/osci-render
Fix the most major mac bugs
rodzic
c6c3b21e06
commit
81bea16c91
|
@ -416,8 +416,14 @@ void OscirenderAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, ju
|
|||
auto totalNumOutputChannels = getTotalNumOutputChannels();
|
||||
|
||||
buffer.clear();
|
||||
synth.renderNextBlock(buffer, midiMessages, 0, buffer.getNumSamples());
|
||||
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();
|
||||
|
||||
|
@ -594,17 +600,24 @@ void OscirenderAudioProcessor::setStateInformation(const void* data, int sizeInB
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void OscirenderAudioProcessor::read(std::vector<float>& buffer) {
|
||||
std::shared_ptr<BufferConsumer> OscirenderAudioProcessor::consumerRegister(std::vector<float>& buffer) {
|
||||
std::shared_ptr<BufferConsumer> consumer = std::make_shared<BufferConsumer>(buffer);
|
||||
{
|
||||
juce::SpinLock::ScopedLockType scope(consumerLock);
|
||||
consumers.push_back(consumer);
|
||||
}
|
||||
juce::SpinLock::ScopedLockType scope(consumerLock);
|
||||
consumers.push_back(consumer);
|
||||
|
||||
return consumer;
|
||||
}
|
||||
|
||||
void OscirenderAudioProcessor::consumerRead(std::shared_ptr<BufferConsumer> consumer) {
|
||||
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);
|
||||
consumers.erase(std::remove(consumers.begin(), consumers.end(), consumer), consumers.end());
|
||||
consumer->forceNotify();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,9 @@ public:
|
|||
void changeProgramName(int index, const juce::String& newName) override;
|
||||
void getStateInformation(juce::MemoryBlock& destData) 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;
|
||||
|
||||
|
@ -216,6 +218,7 @@ private:
|
|||
std::vector<std::shared_ptr<Effect>> allEffects;
|
||||
std::vector<std::shared_ptr<Effect>> permanentEffects;
|
||||
|
||||
bool playedNote = false;
|
||||
juce::Synthesiser synth;
|
||||
|
||||
juce::SpinLock consumerLock;
|
||||
|
|
|
@ -41,12 +41,14 @@ AudioWebSocketServer::AudioWebSocketServer(OscirenderAudioProcessor& audioProces
|
|||
AudioWebSocketServer::~AudioWebSocketServer() {
|
||||
server.stop();
|
||||
ix::uninitNetSystem();
|
||||
audioProcessor.consumerStop(consumer);
|
||||
stopThread(1000);
|
||||
}
|
||||
|
||||
void AudioWebSocketServer::run() {
|
||||
while (!threadShouldExit()) {
|
||||
audioProcessor.read(floatBuffer);
|
||||
consumer = audioProcessor.consumerRegister(floatBuffer);
|
||||
audioProcessor.consumerRead(consumer);
|
||||
|
||||
for (int i = 0; i < floatBuffer.size(); i++) {
|
||||
short sample = floatBuffer[i] * 32767;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <JuceHeader.h>
|
||||
#include "../ixwebsocket/IXWebSocketServer.h"
|
||||
#include "../concurrency/BufferConsumer.h"
|
||||
|
||||
class OscirenderAudioProcessor;
|
||||
class AudioWebSocketServer : juce::Thread {
|
||||
|
@ -15,4 +16,6 @@ private:
|
|||
OscirenderAudioProcessor& audioProcessor;
|
||||
std::vector<float> floatBuffer = std::vector<float>(2 * 4096);
|
||||
char buffer[4096 * 2 * 2];
|
||||
|
||||
std::shared_ptr<BufferConsumer> consumer;
|
||||
};
|
||||
|
|
|
@ -6,12 +6,14 @@ PitchDetector::PitchDetector(OscirenderAudioProcessor& audioProcessor) : juce::T
|
|||
}
|
||||
|
||||
PitchDetector::~PitchDetector() {
|
||||
audioProcessor.consumerStop(consumer);
|
||||
stopThread(1000);
|
||||
}
|
||||
|
||||
void PitchDetector::run() {
|
||||
while (!threadShouldExit()) {
|
||||
audioProcessor.read(buffer);
|
||||
consumer = audioProcessor.consumerRegister(buffer);
|
||||
audioProcessor.consumerRead(consumer);
|
||||
|
||||
// buffer is for 2 channels, so we need to only use one
|
||||
for (int i = 0; i < fftSize; i++) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <JuceHeader.h>
|
||||
#include "../concurrency/BufferConsumer.h"
|
||||
|
||||
class OscirenderAudioProcessor;
|
||||
class PitchDetector : public juce::Thread, public juce::AsyncUpdater {
|
||||
|
@ -19,6 +20,7 @@ private:
|
|||
static constexpr int fftOrder = 15;
|
||||
static constexpr int fftSize = 1 << fftOrder;
|
||||
|
||||
std::shared_ptr<BufferConsumer> consumer;
|
||||
std::vector<float> buffer = std::vector<float>(2 * fftSize);
|
||||
juce::dsp::FFT forwardFFT{fftOrder};
|
||||
std::array<float, fftSize * 2> fftData;
|
||||
|
|
|
@ -7,6 +7,7 @@ VisualiserComponent::VisualiserComponent(int numChannels, OscirenderAudioProcess
|
|||
}
|
||||
|
||||
VisualiserComponent::~VisualiserComponent() {
|
||||
audioProcessor.consumerStop(consumer);
|
||||
stopThread(1000);
|
||||
}
|
||||
|
||||
|
@ -44,7 +45,8 @@ void VisualiserComponent::timerCallback() {
|
|||
|
||||
void VisualiserComponent::run() {
|
||||
while (!threadShouldExit()) {
|
||||
audioProcessor.read(tempBuffer);
|
||||
consumer = audioProcessor.consumerRegister(tempBuffer);
|
||||
audioProcessor.consumerRead(consumer);
|
||||
setBuffer(tempBuffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ private:
|
|||
OscirenderAudioProcessor& audioProcessor;
|
||||
std::vector<float> tempBuffer = std::vector<float>(2 * 4096);
|
||||
int precision = 4;
|
||||
|
||||
std::shared_ptr<BufferConsumer> consumer;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VisualiserComponent)
|
||||
};
|
||||
|
|
|
@ -47,6 +47,7 @@ VolumeComponent::VolumeComponent(OscirenderAudioProcessor& p) : audioProcessor(p
|
|||
}
|
||||
|
||||
VolumeComponent::~VolumeComponent() {
|
||||
audioProcessor.consumerStop(consumer);
|
||||
stopThread(1000);
|
||||
}
|
||||
|
||||
|
@ -92,7 +93,8 @@ void VolumeComponent::timerCallback() {
|
|||
|
||||
void VolumeComponent::run() {
|
||||
while (!threadShouldExit()) {
|
||||
audioProcessor.read(buffer);
|
||||
consumer = audioProcessor.consumerRegister(buffer);
|
||||
audioProcessor.consumerRead(consumer);
|
||||
|
||||
float leftVolume = 0;
|
||||
float rightVolume = 0;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <JuceHeader.h>
|
||||
#include "../PluginProcessor.h"
|
||||
#include "../LookAndFeel.h"
|
||||
#include "../concurrency/BufferConsumer.h"
|
||||
|
||||
class ThumbRadiusLookAndFeel : public OscirenderLookAndFeel {
|
||||
public:
|
||||
|
@ -84,6 +85,8 @@ private:
|
|||
|
||||
std::unique_ptr<juce::Drawable> volumeIcon;
|
||||
std::unique_ptr<juce::Drawable> thresholdIcon;
|
||||
|
||||
std::shared_ptr<BufferConsumer> consumer;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VolumeComponent)
|
||||
};
|
||||
|
|
|
@ -54,6 +54,12 @@ public:
|
|||
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) {
|
||||
if (offset < buffer.size()) {
|
||||
|
|
Ładowanie…
Reference in New Issue