Merge pull request #41 from jameshball/smooth-effects

Most effects now change smoothly between values, making the visuals MUCH smoother when using sliders
pull/170/head
James H Ball 2023-07-14 15:36:07 +01:00 zatwierdzone przez GitHub
commit 02d5aef922
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
33 zmienionych plików z 262 dodań i 188 usunięć

Wyświetl plik

@ -10,13 +10,10 @@ EffectsComponent::EffectsComponent(OscirenderAudioProcessor& p) : audioProcessor
frequency.slider.setSkewFactorFromMidPoint(500.0); frequency.slider.setSkewFactorFromMidPoint(500.0);
frequency.slider.setTextValueSuffix("Hz"); frequency.slider.setTextValueSuffix("Hz");
frequency.slider.setValue(audioProcessor.frequency, juce::dontSendNotification); frequency.slider.setValue(audioProcessor.frequencyEffect->getValue(), juce::dontSendNotification);
frequency.slider.onValueChange = [this] { frequency.slider.onValueChange = [this] {
audioProcessor.frequency = frequency.slider.getValue(); audioProcessor.frequencyEffect->setValue(frequency.slider.getValue());
if (audioProcessor.currentSampleRate > 0.0) {
audioProcessor.updateAngleDelta();
}
}; };
{ {

Wyświetl plik

@ -23,7 +23,7 @@ private:
EffectsListBoxModel listBoxModel; EffectsListBoxModel listBoxModel;
DraggableListBox listBox; DraggableListBox listBox;
EffectComponent frequency = EffectComponent(0.0, 12000.0, 0.1, 400, "Frequency", "frequency"); EffectComponent frequency = EffectComponent(0.0, 12000.0, 0.1, *audioProcessor.frequencyEffect, false);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectsComponent) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectsComponent)
}; };

Wyświetl plik

@ -16,8 +16,8 @@ ObjComponent::ObjComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessor
focalLength.slider.onValueChange = [this] { focalLength.slider.onValueChange = [this] {
juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock); juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock);
audioProcessor.focalLength.setValue(focalLength.slider.getValue()); audioProcessor.focalLength->setValue(focalLength.slider.getValue());
audioProcessor.focalLength.apply(); audioProcessor.focalLength->apply();
}; };
auto onRotationChange = [this]() { auto onRotationChange = [this]() {
@ -25,23 +25,21 @@ ObjComponent::ObjComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessor
double x = fixedRotateX->getToggleState() ? 0 : rotateX.slider.getValue(); double x = fixedRotateX->getToggleState() ? 0 : rotateX.slider.getValue();
double y = fixedRotateY->getToggleState() ? 0 : rotateY.slider.getValue(); double y = fixedRotateY->getToggleState() ? 0 : rotateY.slider.getValue();
double z = fixedRotateZ->getToggleState() ? 0 : rotateZ.slider.getValue(); double z = fixedRotateZ->getToggleState() ? 0 : rotateZ.slider.getValue();
audioProcessor.rotateX.setValue(x); audioProcessor.rotateX->setValue(x);
audioProcessor.rotateY.setValue(y); audioProcessor.rotateY->setValue(y);
audioProcessor.rotateZ.setValue(z); audioProcessor.rotateZ->setValue(z);
// all the rotate apply functions are the same
audioProcessor.rotateX.apply();
if (fixedRotateX->getToggleState()) { if (fixedRotateX->getToggleState()) {
audioProcessor.currentRotateX.setValue(rotateX.slider.getValue()); audioProcessor.currentRotateX->setValue(rotateX.slider.getValue());
audioProcessor.currentRotateX.apply(); audioProcessor.currentRotateX->apply();
} }
if (fixedRotateY->getToggleState()) { if (fixedRotateY->getToggleState()) {
audioProcessor.currentRotateY.setValue(rotateY.slider.getValue()); audioProcessor.currentRotateY->setValue(rotateY.slider.getValue());
audioProcessor.currentRotateY.apply(); audioProcessor.currentRotateY->apply();
} }
if (fixedRotateZ->getToggleState()) { if (fixedRotateZ->getToggleState()) {
audioProcessor.currentRotateZ.setValue(rotateZ.slider.getValue()); audioProcessor.currentRotateZ->setValue(rotateZ.slider.getValue());
audioProcessor.currentRotateZ.apply(); audioProcessor.currentRotateZ->apply();
} }
audioProcessor.fixedRotateX = fixedRotateX->getToggleState(); audioProcessor.fixedRotateX = fixedRotateX->getToggleState();
@ -55,8 +53,8 @@ ObjComponent::ObjComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessor
rotateSpeed.slider.onValueChange = [this] { rotateSpeed.slider.onValueChange = [this] {
juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock); juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock);
audioProcessor.rotateSpeed.setValue(rotateSpeed.slider.getValue()); audioProcessor.rotateSpeed->setValue(rotateSpeed.slider.getValue());
audioProcessor.rotateSpeed.apply(); audioProcessor.rotateSpeed->apply();
}; };
addAndMakeVisible(resetRotation); addAndMakeVisible(resetRotation);
@ -75,12 +73,12 @@ ObjComponent::ObjComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessor
mouseRotate.setToggleState(false, juce::NotificationType::dontSendNotification); mouseRotate.setToggleState(false, juce::NotificationType::dontSendNotification);
juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock); juce::SpinLock::ScopedLockType lock(audioProcessor.parsersLock);
audioProcessor.currentRotateX.setValue(0); audioProcessor.currentRotateX->setValue(0);
audioProcessor.currentRotateY.setValue(0); audioProcessor.currentRotateY->setValue(0);
audioProcessor.currentRotateZ.setValue(0); audioProcessor.currentRotateZ->setValue(0);
audioProcessor.currentRotateX.apply(); audioProcessor.currentRotateX->apply();
audioProcessor.currentRotateY.apply(); audioProcessor.currentRotateY->apply();
audioProcessor.currentRotateZ.apply(); audioProcessor.currentRotateZ->apply();
}; };
auto doc = juce::XmlDocument::parse(BinaryData::fixed_rotate_svg); auto doc = juce::XmlDocument::parse(BinaryData::fixed_rotate_svg);

Wyświetl plik

@ -17,11 +17,11 @@ private:
OscirenderAudioProcessor& audioProcessor; OscirenderAudioProcessor& audioProcessor;
OscirenderAudioProcessorEditor& pluginEditor; OscirenderAudioProcessorEditor& pluginEditor;
EffectComponent focalLength{0, 2, 0.01, audioProcessor.focalLength, false}; EffectComponent focalLength{0, 2, 0.001, *audioProcessor.focalLength, false};
EffectComponent rotateX{-1, 1, 0.01, audioProcessor.rotateX, false}; EffectComponent rotateX{-1, 1, 0.001, *audioProcessor.rotateX, false};
EffectComponent rotateY{-1, 1, 0.01, audioProcessor.rotateY, false}; EffectComponent rotateY{-1, 1, 0.001, *audioProcessor.rotateY, false};
EffectComponent rotateZ{-1, 1, 0.01, audioProcessor.rotateZ, false}; EffectComponent rotateZ{-1, 1, 0.001, *audioProcessor.rotateZ, false};
EffectComponent rotateSpeed{-1, 1, 0.01, audioProcessor.rotateSpeed, false}; EffectComponent rotateSpeed{-1, 1, 0.001, *audioProcessor.rotateSpeed, false};
juce::TextButton resetRotation{"Reset Rotation"}; juce::TextButton resetRotation{"Reset Rotation"};
juce::ToggleButton mouseRotate{"Rotate with Mouse (Esc to disable)"}; juce::ToggleButton mouseRotate{"Rotate with Mouse (Esc to disable)"};

Wyświetl plik

@ -35,24 +35,33 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
juce::SpinLock::ScopedLockType lock(effectsLock); juce::SpinLock::ScopedLockType lock(effectsLock);
allEffects.push_back(std::make_shared<Effect>(std::make_shared<BitCrushEffect>(), "Bit Crush", "bitCrush")); allEffects.push_back(std::make_shared<Effect>(std::make_shared<BitCrushEffect>(), "Bit Crush", "bitCrush", true));
allEffects.push_back(std::make_shared<Effect>(std::make_shared<BulgeEffect>(), "Bulge", "bulge")); allEffects.push_back(std::make_shared<Effect>(std::make_shared<BulgeEffect>(), "Bulge", "bulge", true));
allEffects.push_back(std::make_shared<Effect>(std::make_shared<RotateEffect>(), "2D Rotate Speed", "rotateSpeed")); allEffects.push_back(std::make_shared<Effect>(std::make_shared<RotateEffect>(), "2D Rotate Speed", "rotateSpeed", true));
allEffects.push_back(std::make_shared<Effect>(std::make_shared<VectorCancellingEffect>(), "Vector cancelling", "vectorCancelling")); allEffects.push_back(std::make_shared<Effect>(std::make_shared<VectorCancellingEffect>(), "Vector cancelling", "vectorCancelling", true));
allEffects.push_back(std::make_shared<Effect>(std::make_shared<DistortEffect>(true), "Vertical shift", "verticalDistort")); allEffects.push_back(std::make_shared<Effect>(std::make_shared<DistortEffect>(true), "Vertical shift", "verticalDistort", true));
allEffects.push_back(std::make_shared<Effect>(std::make_shared<DistortEffect>(false), "Horizontal shift", "horizontalDistort")); allEffects.push_back(std::make_shared<Effect>(std::make_shared<DistortEffect>(false), "Horizontal shift", "horizontalDistort", true));
allEffects.push_back(std::make_shared<Effect>(std::make_shared<SmoothEffect>(), "Smoothing", "smoothing")); allEffects.push_back(std::make_shared<Effect>(std::make_shared<SmoothEffect>(), "Smoothing", "smoothing", true));
allEffects.push_back(std::make_shared<Effect>(wobbleEffect, "Wobble", "wobble")); allEffects.push_back(std::make_shared<Effect>(wobbleEffect, "Wobble", "wobble", true));
allEffects.push_back(std::make_shared<Effect>( allEffects.push_back(std::make_shared<Effect>(
delayEffect, delayEffect,
std::vector<EffectDetails>{ std::vector<EffectDetails>{
EffectDetails{ "Delay Decay", "delayDecay", 0 }, EffectDetails{ "Delay Decay", "delayDecay", 0 },
EffectDetails{ "Delay Length", "delayEchoLength", 0.5 } EffectDetails{ "Delay Length", "delayEchoLength", 0.5 }
} }, true
)); ));
allEffects.push_back(traceMax); allEffects.push_back(traceMax);
allEffects.push_back(traceMin); allEffects.push_back(traceMin);
permanentEffects.push_back(frequencyEffect);
permanentEffects.push_back(volumeEffect);
permanentEffects.push_back(thresholdEffect);
permanentEffects.push_back(rotateSpeed);
permanentEffects.push_back(rotateX);
permanentEffects.push_back(rotateY);
permanentEffects.push_back(rotateZ);
permanentEffects.push_back(focalLength);
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
addLuaSlider(); addLuaSlider();
} }
@ -113,7 +122,6 @@ void OscirenderAudioProcessor::changeProgramName(int index, const juce::String&
void OscirenderAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) { void OscirenderAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) {
currentSampleRate = sampleRate; currentSampleRate = sampleRate;
pitchDetector.setSampleRate(sampleRate); pitchDetector.setSampleRate(sampleRate);
updateAngleDelta();
} }
void OscirenderAudioProcessor::releaseResources() { void OscirenderAudioProcessor::releaseResources() {
@ -158,7 +166,7 @@ void OscirenderAudioProcessor::addLuaSlider() {
sliderNum = (sliderNum - mod) / 26; sliderNum = (sliderNum - mod) / 26;
} }
luaEffects.push_back(std::make_shared<Effect>(std::make_shared<LuaEffect>(sliderName, *this), "Lua " + sliderName, "lua" + sliderName)); luaEffects.push_back(std::make_shared<Effect>(std::make_shared<LuaEffect>(sliderName, *this), "Lua " + sliderName, "lua" + sliderName, false));
} }
// effectsLock should be held when calling this // effectsLock should be held when calling this
@ -170,14 +178,11 @@ void OscirenderAudioProcessor::updateLuaValues() {
// parsersLock should be held when calling this // parsersLock should be held when calling this
void OscirenderAudioProcessor::updateObjValues() { void OscirenderAudioProcessor::updateObjValues() {
focalLength.apply(); focalLength->apply();
rotateX.apply(); rotateX->apply();
rotateSpeed.apply(); rotateY->apply();
} rotateZ->apply();
rotateSpeed->apply();
void OscirenderAudioProcessor::updateAngleDelta() {
auto cyclesPerSample = frequency / currentSampleRate;
thetaDelta = cyclesPerSample * 2.0 * juce::MathConstants<double>::pi;
} }
// effectsLock MUST be held when calling this // effectsLock MUST be held when calling this
@ -365,7 +370,7 @@ void OscirenderAudioProcessor::updateLengthIncrement() {
lengthIncrement = juce::jmax(proportionalLength / (currentSampleRate / frequency), MIN_LENGTH_INCREMENT); lengthIncrement = juce::jmax(proportionalLength / (currentSampleRate / frequency), MIN_LENGTH_INCREMENT);
} }
void OscirenderAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages) void OscirenderAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{ {
juce::ScopedNoDenormals noDenormals; juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels(); auto totalNumInputChannels = getTotalNumInputChannels();
@ -429,6 +434,9 @@ void OscirenderAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, j
for (auto& effect : enabledEffects) { for (auto& effect : enabledEffects) {
channels = effect->apply(sample, channels); channels = effect->apply(sample, channels);
} }
for (auto& effect : permanentEffects) {
channels = effect->apply(sample, channels);
}
} }
x = channels.x; x = channels.x;
@ -450,8 +458,8 @@ void OscirenderAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, j
audioProducer.write(x, y); audioProducer.write(x, y);
actualTraceMax = juce::jmax(actualTraceMin + MIN_TRACE, juce::jmin(traceMax->getValue(), 1.0)); actualTraceMax = juce::jmax(actualTraceMin + MIN_TRACE, juce::jmin(traceMaxValue, 1.0));
actualTraceMin = juce::jmax(MIN_TRACE, juce::jmin(traceMin->getValue(), actualTraceMax - MIN_TRACE)); actualTraceMin = juce::jmax(MIN_TRACE, juce::jmin(traceMinValue, actualTraceMax - MIN_TRACE));
if (!renderingSample) { if (!renderingSample) {
incrementShapeDrawing(); incrementShapeDrawing();

Wyświetl plik

@ -68,10 +68,6 @@ public:
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;
std::atomic<float> frequency = 440.0f;
std::atomic<double> volume = 1.0;
std::atomic<double> threshold = 1.0;
std::atomic<double> currentSampleRate = 0.0; std::atomic<double> currentSampleRate = 0.0;
juce::SpinLock effectsLock; juce::SpinLock effectsLock;
@ -79,88 +75,107 @@ public:
std::vector<std::shared_ptr<Effect>> enabledEffects; std::vector<std::shared_ptr<Effect>> enabledEffects;
std::vector<std::shared_ptr<Effect>> luaEffects; std::vector<std::shared_ptr<Effect>> luaEffects;
// TODO see if there is a way to move this code to .cpp std::shared_ptr<Effect> frequencyEffect = std::make_shared<Effect>(
std::function<Vector2(int, Vector2, std::vector<EffectDetails>, double)> onRotationChange = [this](int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) { [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
if (getCurrentFileIndex() != -1) { frequency = values[0];
auto obj = getCurrentFileParser()->getObject(); return input;
if (obj == nullptr) return input; }, "Frequency", "frequency", 440
obj->setBaseRotation( );
rotateX.getValue() * std::numbers::pi,
rotateY.getValue() * std::numbers::pi,
rotateZ.getValue() * std::numbers::pi
);
}
return input;
};
Effect focalLength{ std::shared_ptr<Effect> volumeEffect = std::make_shared<Effect>(
[this](int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) { [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
volume = values[0];
return input;
}, "Volume", "volume", 1
);
std::shared_ptr<Effect> thresholdEffect = std::make_shared<Effect>(
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
threshold = values[0];
return input;
}, "Threshold", "threshold", 3
);
std::shared_ptr<Effect> focalLength = std::make_shared<Effect>(
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
if (getCurrentFileIndex() != -1) { if (getCurrentFileIndex() != -1) {
auto camera = getCurrentFileParser()->getCamera(); auto camera = getCurrentFileParser()->getCamera();
if (camera == nullptr) return input; if (camera == nullptr) return input;
camera->setFocalLength(details[0].value); camera->setFocalLength(values[0]);
} }
return input; return input;
}, }, "Focal length", "focalLength", 1
"Focal length", );
"focalLength", std::shared_ptr<Effect> rotateX = std::make_shared<Effect>(
1 [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
};
Effect rotateX{onRotationChange, "Rotate x", "rotateX", 1};
Effect rotateY{onRotationChange, "Rotate y", "rotateY", 1};
Effect rotateZ{onRotationChange, "Rotate z", "rotateZ", 0};
Effect currentRotateX{
[this](int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) {
if (getCurrentFileIndex() != -1) { if (getCurrentFileIndex() != -1) {
auto obj = getCurrentFileParser()->getObject(); auto obj = getCurrentFileParser()->getObject();
if (obj == nullptr) return input; if (obj == nullptr) return input;
obj->setCurrentRotationX(details[0].value * std::numbers::pi); obj->setBaseRotationX(values[0] * std::numbers::pi);
} }
return input; return input;
}, }, "Rotate x", "rotateX", 1
"Current Rotate x", );
"currentRotateX", std::shared_ptr<Effect> rotateY = std::make_shared<Effect>(
0 [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
};
Effect currentRotateY{
[this](int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) {
if (getCurrentFileIndex() != -1) { if (getCurrentFileIndex() != -1) {
auto obj = getCurrentFileParser()->getObject(); auto obj = getCurrentFileParser()->getObject();
if (obj == nullptr) return input; if (obj == nullptr) return input;
obj->setCurrentRotationY(details[0].value * std::numbers::pi); obj->setBaseRotationY(values[0] * std::numbers::pi);
} }
return input; return input;
}, }, "Rotate y", "rotateY", 1
"Current Rotate y", );
"currentRotateY", std::shared_ptr<Effect> rotateZ = std::make_shared<Effect>(
0 [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
};
Effect currentRotateZ{
[this](int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) {
if (getCurrentFileIndex() != -1) { if (getCurrentFileIndex() != -1) {
auto obj = getCurrentFileParser()->getObject(); auto obj = getCurrentFileParser()->getObject();
if (obj == nullptr) return input; if (obj == nullptr) return input;
obj->setCurrentRotationZ(details[0].value * std::numbers::pi); obj->setBaseRotationZ(values[0] * std::numbers::pi);
} }
return input; return input;
}, }, "Rotate z", "rotateZ", 0
"Current Rotate z", );
"currentRotateZ", std::shared_ptr<Effect> currentRotateX = std::make_shared<Effect>(
0 [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
};
Effect rotateSpeed{
[this](int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) {
if (getCurrentFileIndex() != -1) { if (getCurrentFileIndex() != -1) {
auto obj = getCurrentFileParser()->getObject(); auto obj = getCurrentFileParser()->getObject();
if (obj == nullptr) return input; if (obj == nullptr) return input;
obj->setRotationSpeed(details[0].value); obj->setCurrentRotationX(values[0] * std::numbers::pi);
} }
return input; return input;
}, }, "Current Rotate x", "currentRotateX", 0, false
"Rotate speed", );
"rotateSpeed", std::shared_ptr<Effect> currentRotateY = std::make_shared<Effect>(
0 [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
}; if (getCurrentFileIndex() != -1) {
auto obj = getCurrentFileParser()->getObject();
if (obj == nullptr) return input;
obj->setCurrentRotationY(values[0] * std::numbers::pi);
}
return input;
}, "Current Rotate y", "currentRotateY", 0, false
);
std::shared_ptr<Effect> currentRotateZ = std::make_shared<Effect>(
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
if (getCurrentFileIndex() != -1) {
auto obj = getCurrentFileParser()->getObject();
if (obj == nullptr) return input;
obj->setCurrentRotationZ(values[0] * std::numbers::pi);
}
return input;
}, "Current Rotate z", "currentRotateZ", 0, false
);
std::shared_ptr<Effect> rotateSpeed = std::make_shared<Effect>(
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
if (getCurrentFileIndex() != -1) {
auto obj = getCurrentFileParser()->getObject();
if (obj == nullptr) return input;
obj->setRotationSpeed(values[0]);
}
return input;
}, "Rotate speed", "rotateSpeed", 0
);
std::atomic<bool> fixedRotateX = false; std::atomic<bool> fixedRotateX = false;
std::atomic<bool> fixedRotateY = false; std::atomic<bool> fixedRotateY = false;
std::atomic<bool> fixedRotateZ = false; std::atomic<bool> fixedRotateZ = false;
@ -181,7 +196,6 @@ public:
std::shared_ptr<WobbleEffect> wobbleEffect = std::make_shared<WobbleEffect>(pitchDetector); std::shared_ptr<WobbleEffect> wobbleEffect = std::make_shared<WobbleEffect>(pitchDetector);
void addLuaSlider(); void addLuaSlider();
void updateAngleDelta();
void addFrame(std::vector<std::unique_ptr<Shape>> frame, int fileIndex) override; void addFrame(std::vector<std::unique_ptr<Shape>> frame, int fileIndex) override;
void enableEffect(std::shared_ptr<Effect> effect); void enableEffect(std::shared_ptr<Effect> effect);
void disableEffect(std::shared_ptr<Effect> effect); void disableEffect(std::shared_ptr<Effect> effect);
@ -198,8 +212,9 @@ public:
juce::String getFileName(int index); juce::String getFileName(int index);
std::shared_ptr<juce::MemoryBlock> getFileBlock(int index); std::shared_ptr<juce::MemoryBlock> getFileBlock(int index);
private: private:
double theta = 0.0; std::atomic<float> frequency = 440.0f;
double thetaDelta = 0.0; std::atomic<double> volume = 1.0;
std::atomic<double> threshold = 1.0;
juce::AbstractFifo frameFifo{ 10 }; juce::AbstractFifo frameFifo{ 10 };
std::vector<std::unique_ptr<Shape>> frameBuffer[10]; std::vector<std::unique_ptr<Shape>> frameBuffer[10];
@ -214,27 +229,27 @@ private:
double lengthIncrement = 0.0; double lengthIncrement = 0.0;
bool invalidateFrameBuffer = false; bool invalidateFrameBuffer = false;
std::vector<std::shared_ptr<Effect>> permanentEffects;
std::shared_ptr<Effect> traceMax = std::make_shared<Effect>( std::shared_ptr<Effect> traceMax = std::make_shared<Effect>(
[this](int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) { [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
traceMaxValue = values[0];
traceMaxEnabled = true; traceMaxEnabled = true;
return input; return input;
}, }, "Trace max", "traceMax", 1, true
"Trace max",
"traceMax",
1
); );
std::shared_ptr<Effect> traceMin = std::make_shared<Effect>( std::shared_ptr<Effect> traceMin = std::make_shared<Effect>(
[this](int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) { [this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
traceMinValue = values[0];
traceMinEnabled = true; traceMinEnabled = true;
return input; return input;
}, }, "Trace min", "traceMin", 0, true
"Trace min",
"traceMin",
0
); );
const double MIN_TRACE = 0.005; const double MIN_TRACE = 0.005;
double actualTraceMax = traceMax->getValue(); double traceMaxValue = traceMax->getValue();
double actualTraceMin = traceMin->getValue(); double traceMinValue = traceMin->getValue();
double actualTraceMax = traceMaxValue;
double actualTraceMin = traceMinValue;
bool traceMaxEnabled = false; bool traceMaxEnabled = false;
bool traceMinEnabled = false; bool traceMinEnabled = false;

Wyświetl plik

@ -5,8 +5,8 @@ BitCrushEffect::BitCrushEffect() {}
BitCrushEffect::~BitCrushEffect() {} BitCrushEffect::~BitCrushEffect() {}
// algorithm from https://www.kvraudio.com/forum/viewtopic.php?t=163880 // algorithm from https://www.kvraudio.com/forum/viewtopic.php?t=163880
Vector2 BitCrushEffect::apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) { Vector2 BitCrushEffect::apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
double value = details[0].value; double value = values[0];
// change rage of value from 0-1 to 0.0-0.78 // change rage of value from 0-1 to 0.0-0.78
double rangedValue = value * 0.78; double rangedValue = value * 0.78;
double powValue = pow(2.0f, 1.0 - rangedValue) - 1.0; double powValue = pow(2.0f, 1.0 - rangedValue) - 1.0;

Wyświetl plik

@ -7,5 +7,5 @@ public:
BitCrushEffect(); BitCrushEffect();
~BitCrushEffect(); ~BitCrushEffect();
Vector2 apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) override; Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) override;
}; };

Wyświetl plik

@ -4,8 +4,8 @@ BulgeEffect::BulgeEffect() {}
BulgeEffect::~BulgeEffect() {} BulgeEffect::~BulgeEffect() {}
Vector2 BulgeEffect::apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) { Vector2 BulgeEffect::apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
double value = details[0].value; double value = values[0];
double translatedBulge = -value + 1; double translatedBulge = -value + 1;
double r = input.magnitude(); double r = input.magnitude();

Wyświetl plik

@ -7,5 +7,5 @@ public:
BulgeEffect(); BulgeEffect();
~BulgeEffect(); ~BulgeEffect();
Vector2 apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) override; Vector2 apply(int index, Vector2 input, const std::vector<double>&, double sampleRate) override;
}; };

Wyświetl plik

@ -4,9 +4,9 @@ DelayEffect::DelayEffect() {}
DelayEffect::~DelayEffect() {} DelayEffect::~DelayEffect() {}
Vector2 DelayEffect::apply(int index, Vector2 vector, std::vector<EffectDetails> details, double sampleRate) { Vector2 DelayEffect::apply(int index, Vector2 vector, const std::vector<double>& values, double sampleRate) {
double decay = details[0].value; double decay = values[0];
double decayLength = details[1].value; double decayLength = values[1];
int delayBufferLength = (int)(sampleRate * decayLength); int delayBufferLength = (int)(sampleRate * decayLength);
if (head >= delayBuffer.size()){ if (head >= delayBuffer.size()){
head = 0; head = 0;

Wyświetl plik

@ -7,7 +7,7 @@ public:
DelayEffect(); DelayEffect();
~DelayEffect(); ~DelayEffect();
Vector2 apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) override; Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) override;
private: private:
const static int MAX_DELAY = 192000 * 10; const static int MAX_DELAY = 192000 * 10;

Wyświetl plik

@ -4,8 +4,8 @@ DistortEffect::DistortEffect(bool vertical) : vertical(vertical) {}
DistortEffect::~DistortEffect() {} DistortEffect::~DistortEffect() {}
Vector2 DistortEffect::apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) { Vector2 DistortEffect::apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
double value = details[0].value; double value = values[0];
int vertical = (int)this->vertical; int vertical = (int)this->vertical;
if (index % 2 == 0) { if (index % 2 == 0) {
input.translate((1 - vertical) * value, vertical * value); input.translate((1 - vertical) * value, vertical * value);

Wyświetl plik

@ -7,7 +7,7 @@ public:
DistortEffect(bool vertical); DistortEffect(bool vertical);
~DistortEffect(); ~DistortEffect();
Vector2 apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) override; Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) override;
private: private:
bool vertical; bool vertical;
}; };

Wyświetl plik

@ -1,32 +1,44 @@
#include "Effect.h" #include "Effect.h"
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectDetails> details) : effectApplication(effectApplication), details(details) {} Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectDetails> details, bool smoothValueChange) : effectApplication(effectApplication), details(details), smoothValueChange(smoothValueChange) {
smoothValues = std::vector<double>(details.size(), 0.0);
}
Effect::Effect(std::function<Vector2(int, Vector2, std::vector<EffectDetails>, double)> application, std::vector<EffectDetails> details) : application(application), details(details) {} Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, std::vector<EffectDetails> details, bool smoothValueChange) : application(application), details(details), smoothValueChange(smoothValueChange) {
smoothValues = std::vector<double>(details.size(), 0.0);
}
Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, juce::String name, juce::String id) { Effect::Effect(std::shared_ptr<EffectApplication> effectApplication, juce::String name, juce::String id, bool smoothValueChange) : smoothValueChange(smoothValueChange) {
this->effectApplication = effectApplication; this->effectApplication = effectApplication;
details = std::vector<EffectDetails>(1, EffectDetails{name, id, 0.0}); details = std::vector<EffectDetails>(1, EffectDetails{name, id, 0.0});
smoothValues = std::vector<double>(details.size(), 0.0);
} }
Effect::Effect(juce::String name, juce::String id, double value) { Effect::Effect(juce::String name, juce::String id, double value, bool smoothValueChange) : smoothValueChange(smoothValueChange) {
details = std::vector<EffectDetails>(1, EffectDetails{name, id, value}); details = std::vector<EffectDetails>(1, EffectDetails{name, id, value});
smoothValues = std::vector<double>(details.size(), 0.0);
} }
Effect::Effect(juce::String name, juce::String id) { Effect::Effect(juce::String name, juce::String id, bool smoothValueChange) : smoothValueChange(smoothValueChange) {
details = std::vector<EffectDetails>(1, EffectDetails{name, id, 0.0}); details = std::vector<EffectDetails>(1, EffectDetails{name, id, 0.0});
smoothValues = std::vector<double>(details.size(), 0.0);
} }
Effect::Effect(std::function<Vector2(int, Vector2, std::vector<EffectDetails> values, double)> application, juce::String name, juce::String id, double value) { Effect::Effect(std::function<Vector2(int, Vector2, const std::vector<double>& values, double)> application, juce::String name, juce::String id, double value, bool smoothValueChange) : smoothValueChange(smoothValueChange) {
details = std::vector<EffectDetails>(1, EffectDetails{name, id, value}); details = std::vector<EffectDetails>(1, EffectDetails{name, id, value});
smoothValues = std::vector<double>(details.size(), 0.0);
this->application = application; this->application = application;
}; };
Vector2 Effect::apply(int index, Vector2 input) { Vector2 Effect::apply(int index, Vector2 input) {
double weight = smoothValueChange ? 0.0005 : 1.0;
for (int i = 0; i < details.size(); i++) {
smoothValues[i] = (1.0 - weight) * smoothValues[i] + weight * details[i].value;
}
if (application) { if (application) {
return application(index, input, details, sampleRate); return application(index, input, smoothValues, sampleRate);
} else if (effectApplication != nullptr) { } else if (effectApplication != nullptr) {
return effectApplication->apply(index, input, details, sampleRate); return effectApplication->apply(index, input, smoothValues, sampleRate);
} }
return input; return input;
} }

Wyświetl plik

@ -5,12 +5,12 @@
class Effect { class Effect {
public: public:
Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectDetails> details); Effect(std::shared_ptr<EffectApplication> effectApplication, std::vector<EffectDetails> details, bool smoothValueChange = true);
Effect(std::function<Vector2(int, Vector2, std::vector<EffectDetails>, double)> application, std::vector<EffectDetails> details); Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, std::vector<EffectDetails> details, bool smoothValueChange = true);
Effect(std::shared_ptr<EffectApplication> effectApplication, juce::String name, juce::String id); Effect(std::shared_ptr<EffectApplication> effectApplication, juce::String name, juce::String id, bool smoothValueChange = true);
Effect(juce::String name, juce::String id, double value); Effect(juce::String name, juce::String id, double value, bool smoothValueChange = true);
Effect(juce::String name, juce::String id); Effect(juce::String name, juce::String id, bool smoothValueChange = true);
Effect(std::function<Vector2(int, Vector2, std::vector<EffectDetails>, double)> application, juce::String name, juce::String id, double value); Effect(std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application, juce::String name, juce::String id, double value, bool smoothValueChange = true);
Vector2 apply(int index, Vector2 input); Vector2 apply(int index, Vector2 input);
void apply(); void apply();
@ -26,10 +26,12 @@ public:
private: private:
std::vector<EffectDetails> details; std::vector<EffectDetails> details;
std::vector<double> smoothValues;
bool smoothValueChange = true;
double frequency = 1.0; double frequency = 1.0;
int precedence = -1; int precedence = -1;
int sampleRate = 192000; int sampleRate = 192000;
std::function<Vector2(int, Vector2, std::vector<EffectDetails>, double)> application; std::function<Vector2(int, Vector2, const std::vector<double>&, double)> application;
std::shared_ptr<EffectApplication> effectApplication; std::shared_ptr<EffectApplication> effectApplication;
}; };

Wyświetl plik

@ -12,7 +12,7 @@ class EffectApplication {
public: public:
EffectApplication() {}; EffectApplication() {};
virtual Vector2 apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) = 0; virtual Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) = 0;
void resetPhase(); void resetPhase();
double nextPhase(double frequency, double sampleRate); double nextPhase(double frequency, double sampleRate);

Wyświetl plik

@ -1,14 +1,14 @@
#include "LuaEffect.h" #include "LuaEffect.h"
#include "../lua/LuaParser.h" #include "../lua/LuaParser.h"
Vector2 LuaEffect::apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) { Vector2 LuaEffect::apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
int fileIndex = audioProcessor.getCurrentFileIndex(); int fileIndex = audioProcessor.getCurrentFileIndex();
if (fileIndex == -1) { if (fileIndex == -1) {
return input; return input;
} }
std::shared_ptr<LuaParser> parser = audioProcessor.getCurrentFileParser()->getLua(); std::shared_ptr<LuaParser> parser = audioProcessor.getCurrentFileParser()->getLua();
if (parser != nullptr) { if (parser != nullptr) {
parser->setVariable("slider_" + name.toLowerCase(), details[0].value); parser->setVariable("slider_" + name.toLowerCase(), values[0]);
} }
return input; return input;
} }

Wyświetl plik

@ -8,7 +8,7 @@ class LuaEffect : public EffectApplication {
public: public:
LuaEffect(juce::String name, OscirenderAudioProcessor& p) : audioProcessor(p), name(name) {}; LuaEffect(juce::String name, OscirenderAudioProcessor& p) : audioProcessor(p), name(name) {};
Vector2 apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) override; Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) override;
private: private:
OscirenderAudioProcessor& audioProcessor; OscirenderAudioProcessor& audioProcessor;
juce::String name; juce::String name;

Wyświetl plik

@ -4,7 +4,7 @@ RotateEffect::RotateEffect() {}
RotateEffect::~RotateEffect() {} RotateEffect::~RotateEffect() {}
Vector2 RotateEffect::apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) { Vector2 RotateEffect::apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
input.rotate(nextPhase(details[0].value, sampleRate)); input.rotate(nextPhase(values[0], sampleRate));
return input; return input;
} }

Wyświetl plik

@ -7,5 +7,5 @@ public:
RotateEffect(); RotateEffect();
~RotateEffect(); ~RotateEffect();
Vector2 apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) override; Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) override;
}; };

Wyświetl plik

@ -4,10 +4,10 @@ SmoothEffect::SmoothEffect() {}
SmoothEffect::~SmoothEffect() {} SmoothEffect::~SmoothEffect() {}
Vector2 SmoothEffect::apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) { Vector2 SmoothEffect::apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
double weight = details[0].value; double weight = values[0];
weight *= 0.95; weight *= 0.95;
double strength = 1000000; double strength = 10;
weight = std::log(strength * weight + 1) / std::log(strength + 1); weight = std::log(strength * weight + 1) / std::log(strength + 1);
// TODO: This doesn't consider the sample rate! // TODO: This doesn't consider the sample rate!
leftAvg = weight * leftAvg + (1 - weight) * input.x; leftAvg = weight * leftAvg + (1 - weight) * input.x;

Wyświetl plik

@ -7,7 +7,7 @@ public:
SmoothEffect(); SmoothEffect();
~SmoothEffect(); ~SmoothEffect();
Vector2 apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) override; Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) override;
private: private:
double leftAvg = 0; double leftAvg = 0;
double rightAvg = 0; double rightAvg = 0;

Wyświetl plik

@ -4,8 +4,8 @@ VectorCancellingEffect::VectorCancellingEffect() {}
VectorCancellingEffect::~VectorCancellingEffect() {} VectorCancellingEffect::~VectorCancellingEffect() {}
Vector2 VectorCancellingEffect::apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) { Vector2 VectorCancellingEffect::apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
double value = details[0].value; double value = values[0];
if (value < 0.001) { if (value < 0.001) {
return input; return input;
} }

Wyświetl plik

@ -7,7 +7,7 @@ public:
VectorCancellingEffect(); VectorCancellingEffect();
~VectorCancellingEffect(); ~VectorCancellingEffect();
Vector2 apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) override; Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) override;
private: private:
int lastIndex = 0; int lastIndex = 0;
double nextInvert = 0; double nextInvert = 0;

Wyświetl plik

@ -4,11 +4,11 @@ WobbleEffect::WobbleEffect(PitchDetector& pitchDetector) : pitchDetector(pitchDe
WobbleEffect::~WobbleEffect() {} WobbleEffect::~WobbleEffect() {}
Vector2 WobbleEffect::apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) { Vector2 WobbleEffect::apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
// TODO: this doesn't consider sample rate // TODO: this doesn't consider sample rate
smoothedFrequency = smoothedFrequency * 0.99995 + pitchDetector.frequency * 0.00005; smoothedFrequency = smoothedFrequency * 0.99995 + pitchDetector.frequency * 0.00005;
double theta = nextPhase(smoothedFrequency, sampleRate); double theta = nextPhase(smoothedFrequency, sampleRate);
double delta = details[0].value * std::sin(theta); double delta = values[0] * std::sin(theta);
double x = input.x + delta; double x = input.x + delta;
double y = input.y + delta; double y = input.y + delta;

Wyświetl plik

@ -8,7 +8,7 @@ public:
WobbleEffect(PitchDetector& pitchDetector); WobbleEffect(PitchDetector& pitchDetector);
~WobbleEffect(); ~WobbleEffect();
Vector2 apply(int index, Vector2 input, std::vector<EffectDetails> details, double sampleRate) override; Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) override;
private: private:
PitchDetector& pitchDetector; PitchDetector& pitchDetector;

Wyświetl plik

@ -1,7 +1,7 @@
#include "LuaListComponent.h" #include "LuaListComponent.h"
LuaListComponent::LuaListComponent(OscirenderAudioProcessor& p, Effect& effect) { LuaListComponent::LuaListComponent(OscirenderAudioProcessor& p, Effect& effect) {
effectComponent = std::make_shared<EffectComponent>(0.0, 1.0, 0.01, effect); effectComponent = std::make_shared<EffectComponent>(0.0, 1.0, 0.001, effect);
effectComponent->setCheckboxVisible(false); effectComponent->setCheckboxVisible(false);
effectComponent->slider.onValueChange = [this, &effect, &p] { effectComponent->slider.onValueChange = [this, &effect, &p] {

Wyświetl plik

@ -33,10 +33,12 @@ void VisualiserComponent::paint(juce::Graphics& g) {
g.setColour(waveformColour); g.setColour(waveformColour);
juce::SpinLock::ScopedLockType scope(lock); juce::SpinLock::ScopedLockType scope(lock);
paintXY(g, r.removeFromRight(r.getHeight())); if (buffer.size() > 0) {
paintXY(g, r.removeFromRight(r.getHeight()));
for (int i = 0; i < numChannels; ++i) { for (int i = 0; i < numChannels; ++i) {
paintChannel(g, r.removeFromTop(channelHeight), i); paintChannel(g, r.removeFromTop(channelHeight), i);
}
} }
} }

Wyświetl plik

@ -28,11 +28,11 @@ VolumeComponent::VolumeComponent(OscirenderAudioProcessor& p) : audioProcessor(p
thresholdSlider.setColour(juce::Slider::ColourIds::thumbColourId, juce::Colours::black); thresholdSlider.setColour(juce::Slider::ColourIds::thumbColourId, juce::Colours::black);
volumeSlider.onValueChange = [this]() { volumeSlider.onValueChange = [this]() {
audioProcessor.volume = volumeSlider.getValue(); audioProcessor.volumeEffect->setValue(volumeSlider.getValue());
}; };
thresholdSlider.onValueChange = [this]() { thresholdSlider.onValueChange = [this]() {
audioProcessor.threshold = thresholdSlider.getValue(); audioProcessor.thresholdEffect->setValue(thresholdSlider.getValue());
}; };
auto doc = juce::XmlDocument::parse(BinaryData::volume_svg); auto doc = juce::XmlDocument::parse(BinaryData::volume_svg);

Wyświetl plik

@ -3,6 +3,35 @@
#include <JuceHeader.h> #include <JuceHeader.h>
#include "BufferConsumer.h" #include "BufferConsumer.h"
// This is needed over juce::SpinLock because juce::SpinLock yeilds, which
// leads to some consumers never holding the lock.
// TODO: verify that this is a legitimate solution.
struct crude_spinlock {
std::atomic<bool> lock_ = {0};
void lock() noexcept {
for (;;) {
// Optimistically assume the lock is free on the first try
if (!lock_.exchange(true, std::memory_order_acquire)) {
return;
}
// Wait for lock to be released without generating cache misses
while (lock_.load(std::memory_order_relaxed)) {}
}
}
bool try_lock() noexcept {
// First do a relaxed load to check if lock is free in order to prevent
// unnecessary cache misses if someone does while(!try_lock())
return !lock_.load(std::memory_order_relaxed) &&
!lock_.exchange(true, std::memory_order_acquire);
}
void unlock() noexcept {
lock_.store(false, std::memory_order_release);
}
};
class BufferProducer { class BufferProducer {
public: public:
BufferProducer() {} BufferProducer() {}
@ -13,16 +42,17 @@ public:
// being written to. // being written to.
// This is only called by the thread that owns the consumer thread. // This is only called by the thread that owns the consumer thread.
void registerConsumer(std::shared_ptr<BufferConsumer> consumer) { void registerConsumer(std::shared_ptr<BufferConsumer> consumer) {
juce::SpinLock::ScopedLockType scope(lock); lock.lock();
consumers.push_back(consumer); consumers.push_back(consumer);
bufferPositions.push_back(0); bufferPositions.push_back(0);
consumer->getBuffer(true); consumer->getBuffer(true);
lock.unlock();
} }
// This is only called by the thread that owns the consumer thread. // This is only called by the thread that owns the consumer thread.
// This can't happen at the same time as write() it locks the producer lock. // This can't happen at the same time as write() it locks the producer lock.
void unregisterConsumer(std::shared_ptr<BufferConsumer> consumer) { void unregisterConsumer(std::shared_ptr<BufferConsumer> consumer) {
juce::SpinLock::ScopedLockType scope(lock); lock.lock();
for (int i = 0; i < consumers.size(); i++) { for (int i = 0; i < consumers.size(); i++) {
if (consumers[i] == consumer) { if (consumers[i] == consumer) {
consumer->releaseLock(); consumer->releaseLock();
@ -31,11 +61,12 @@ public:
break; break;
} }
} }
lock.unlock();
} }
// Writes a sample to the current buffer for all consumers. // Writes a sample to the current buffer for all consumers.
void write(float left, float right) { void write(float left, float right) {
juce::SpinLock::ScopedLockType scope(lock); lock.lock();
for (int i = 0; i < consumers.size(); i++) { for (int i = 0; i < consumers.size(); i++) {
std::shared_ptr<std::vector<float>> buffer = consumers[i]->getBuffer(false); std::shared_ptr<std::vector<float>> buffer = consumers[i]->getBuffer(false);
if (buffer == nullptr) { if (buffer == nullptr) {
@ -54,10 +85,11 @@ public:
consumers[i]->finishedWriting(); consumers[i]->finishedWriting();
} }
} }
lock.unlock();
} }
private: private:
juce::SpinLock lock; crude_spinlock lock;
std::vector<std::shared_ptr<BufferConsumer>> consumers; std::vector<std::shared_ptr<BufferConsumer>> consumers;
std::vector<int> bufferPositions; std::vector<int> bufferPositions;
}; };

Wyświetl plik

@ -207,10 +207,16 @@ WorldObject::WorldObject(std::string obj_string) {
} }
} }
void WorldObject::setBaseRotation(double x, double y, double z) { void WorldObject::setBaseRotationX(double x) {
baseRotateX = x; baseRotateX = x;
baseRotateY = y; }
baseRotateZ = z;
void WorldObject::setBaseRotationY(double y) {
baseRotateY = y;
}
void WorldObject::setBaseRotationZ(double z) {
baseRotateZ = z;
} }
void WorldObject::setCurrentRotationX(double x) { void WorldObject::setCurrentRotationX(double x) {

Wyświetl plik

@ -6,7 +6,9 @@ class WorldObject {
public: public:
WorldObject(std::string); WorldObject(std::string);
void setBaseRotation(double x, double y, double z); void setBaseRotationX(double x);
void setBaseRotationY(double y);
void setBaseRotationZ(double z);
void setCurrentRotationX(double x); void setCurrentRotationX(double x);
void setCurrentRotationY(double y); void setCurrentRotationY(double y);
void setCurrentRotationZ(double z); void setCurrentRotationZ(double z);