kopia lustrzana https://github.com/jameshball/osci-render
Introduce more locks to prevent concurrency issues
rodzic
3ea8bad02b
commit
89452a4dd6
|
@ -31,8 +31,7 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
)
|
||||
#endif
|
||||
{
|
||||
producer = std::make_unique<FrameProducer>(*this, std::make_shared<FileParser>());
|
||||
producer->startThread();
|
||||
producer.startThread();
|
||||
|
||||
juce::SpinLock::ScopedLockType lock(effectsLock);
|
||||
|
||||
|
@ -295,12 +294,12 @@ void OscirenderAudioProcessor::openFile(int index) {
|
|||
void OscirenderAudioProcessor::changeCurrentFile(int index) {
|
||||
if (index == -1) {
|
||||
currentFile = -1;
|
||||
producer->setSource(std::make_shared<FileParser>(), -1);
|
||||
producer.setSource(std::make_shared<FileParser>(), -1);
|
||||
}
|
||||
if (index < 0 || index >= fileBlocks.size()) {
|
||||
return;
|
||||
}
|
||||
producer->setSource(parsers[index], index);
|
||||
producer.setSource(parsers[index], index);
|
||||
currentFile = index;
|
||||
invalidateFrameBuffer = true;
|
||||
updateLuaValues();
|
||||
|
@ -370,8 +369,6 @@ void OscirenderAudioProcessor::updateFrame() {
|
|||
|
||||
frameLength = Shape::totalLength(frame);
|
||||
}
|
||||
} else {
|
||||
DBG("frame not ready!");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -171,7 +171,7 @@ public:
|
|||
std::vector<juce::String> fileNames;
|
||||
std::atomic<int> currentFile = -1;
|
||||
|
||||
std::unique_ptr<FrameProducer> producer;
|
||||
FrameProducer producer = FrameProducer(*this, std::make_shared<FileParser>());
|
||||
|
||||
BufferProducer audioProducer;
|
||||
|
||||
|
|
|
@ -1,33 +1,15 @@
|
|||
#include "SmoothEffect.h"
|
||||
|
||||
SmoothEffect::SmoothEffect() {
|
||||
this->window = std::vector<Vector2>(MAX_WINDOW_SIZE);
|
||||
}
|
||||
SmoothEffect::SmoothEffect() {}
|
||||
|
||||
SmoothEffect::~SmoothEffect() {}
|
||||
|
||||
Vector2 SmoothEffect::apply(int index, Vector2 input, std::vector<EffectDetails> details, double frequency, double sampleRate) {
|
||||
double value = details[0].value;
|
||||
int newWindowSize = (int)(256 * value);
|
||||
windowSize = std::max(1, std::min(MAX_WINDOW_SIZE, newWindowSize));
|
||||
|
||||
window[head++] = input;
|
||||
if (head >= MAX_WINDOW_SIZE) {
|
||||
head = 0;
|
||||
}
|
||||
double totalX = 0;
|
||||
double totalY = 0;
|
||||
int newHead = head - 1;
|
||||
for (int i = 0; i < windowSize; i++) {
|
||||
if (newHead < 0) {
|
||||
newHead = MAX_WINDOW_SIZE - 1;
|
||||
}
|
||||
|
||||
totalX += window[newHead].x;
|
||||
totalY += window[newHead].y;
|
||||
|
||||
newHead--;
|
||||
}
|
||||
|
||||
return Vector2(totalX / windowSize, totalY / windowSize);
|
||||
double weight = details[0].value;
|
||||
weight *= 0.95;
|
||||
double strength = 1000000;
|
||||
weight = std::log(strength * weight + 1) / std::log(strength + 1);
|
||||
leftAvg = weight * leftAvg + (1 - weight) * input.x;
|
||||
rightAvg = weight * rightAvg + (1 - weight) * input.y;
|
||||
return Vector2(leftAvg, rightAvg);
|
||||
}
|
||||
|
|
|
@ -9,8 +9,6 @@ public:
|
|||
|
||||
Vector2 apply(int index, Vector2 input, std::vector<EffectDetails> details, double frequency, double sampleRate) override;
|
||||
private:
|
||||
const int MAX_WINDOW_SIZE = 2048;
|
||||
std::vector<Vector2> window;
|
||||
int windowSize = 1;
|
||||
int head = 0;
|
||||
double leftAvg = 0;
|
||||
double rightAvg = 0;
|
||||
};
|
|
@ -6,13 +6,13 @@ void DraggableListBoxItem::paint(juce::Graphics& g)
|
|||
{
|
||||
if (insertAfter)
|
||||
{
|
||||
g.setColour(juce::Colours::red);
|
||||
g.fillRect(0, getHeight() - 3, getWidth(), 3);
|
||||
g.setColour(juce::Colour(0xff00ff00));
|
||||
g.fillRect(0, getHeight() - 4, getWidth(), 4);
|
||||
}
|
||||
else if (insertBefore)
|
||||
{
|
||||
g.setColour(juce::Colours::red);
|
||||
g.fillRect(0, 0, getWidth(), 3);
|
||||
g.setColour(juce::Colour(0xff00ff00));
|
||||
g.fillRect(0, 0, getWidth(), 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,10 +54,8 @@ void EffectComponent::resized() {
|
|||
}
|
||||
|
||||
void EffectComponent::paint(juce::Graphics& g) {
|
||||
g.fillAll(juce::Colours::lightgrey);
|
||||
g.setColour(juce::Colours::black);
|
||||
auto bounds = getLocalBounds();
|
||||
g.drawRect(bounds);
|
||||
g.fillAll(juce::Colours::black);
|
||||
g.setColour(juce::Colours::white);
|
||||
g.drawText(name, textBounds, juce::Justification::left);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectListBoxItemData& data, int rn, std::shared_ptr<Effect> effect) : DraggableListBoxItem(lb, data, rn), effect(effect) {
|
||||
auto details = effect->getDetails();
|
||||
for (int i = 0; i < details.size(); i++) {
|
||||
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(0, 1, 0.01, details[i], i == 0);
|
||||
std::shared_ptr<EffectComponent> effectComponent = std::make_shared<EffectComponent>(0, 1, 0.001, details[i], i == 0);
|
||||
// using weak_ptr to avoid circular reference and memory leak
|
||||
std::weak_ptr<EffectComponent> weakEffectComponent = effectComponent;
|
||||
effectComponent->slider.setValue(details[i].value, juce::dontSendNotification);
|
||||
|
@ -48,21 +48,29 @@ EffectsListComponent::EffectsListComponent(DraggableListBox& lb, AudioEffectList
|
|||
EffectsListComponent::~EffectsListComponent() {}
|
||||
|
||||
void EffectsListComponent::paint(juce::Graphics& g) {
|
||||
DraggableListBoxItem::paint(g);
|
||||
auto bounds = getLocalBounds();
|
||||
g.fillAll(juce::Colours::darkgrey);
|
||||
g.setColour(juce::Colours::white);
|
||||
bounds.removeFromLeft(20);
|
||||
// draw drag and drop handle using circles
|
||||
g.setColour(juce::Colours::white);
|
||||
double size = 4;
|
||||
double leftPad = 4;
|
||||
double spacing = 7;
|
||||
double topPad = 7;
|
||||
g.fillEllipse(leftPad, topPad, size, size);
|
||||
g.fillEllipse(leftPad, topPad + spacing, size, size);
|
||||
g.fillEllipse(leftPad, topPad + 2 * spacing, size, size);
|
||||
g.fillEllipse(leftPad + spacing, topPad, size, size);
|
||||
g.fillEllipse(leftPad + spacing, topPad + spacing, size, size);
|
||||
g.fillEllipse(leftPad + spacing, topPad + 2 * spacing, size, size);
|
||||
double topPad = 6;
|
||||
double y = bounds.getHeight() / 2 - 15;
|
||||
g.fillEllipse(leftPad, y + topPad, size, size);
|
||||
g.fillEllipse(leftPad, y + topPad + spacing, size, size);
|
||||
g.fillEllipse(leftPad, y + topPad + 2 * spacing, size, size);
|
||||
g.fillEllipse(leftPad + spacing, y + topPad, size, size);
|
||||
g.fillEllipse(leftPad + spacing, y + topPad + spacing, size, size);
|
||||
g.fillEllipse(leftPad + spacing, y + topPad + 2 * spacing, size, size);
|
||||
DraggableListBoxItem::paint(g);
|
||||
}
|
||||
|
||||
void EffectsListComponent::paintOverChildren(juce::Graphics& g) {
|
||||
auto bounds = getLocalBounds();
|
||||
g.setColour(juce::Colours::white);
|
||||
g.drawRect(bounds);
|
||||
}
|
||||
|
||||
void EffectsListComponent::resized() {
|
||||
|
|
|
@ -93,6 +93,7 @@ public:
|
|||
~EffectsListComponent();
|
||||
|
||||
void paint(juce::Graphics& g) override;
|
||||
void paintOverChildren(juce::Graphics& g) override;
|
||||
void resized() override;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
FileParser::FileParser() {}
|
||||
|
||||
void FileParser::parse(juce::String extension, std::unique_ptr<juce::InputStream> stream) {
|
||||
juce::SpinLock::ScopedLockType scope(lock);
|
||||
|
||||
object = nullptr;
|
||||
camera = nullptr;
|
||||
svg = nullptr;
|
||||
|
@ -28,17 +30,14 @@ void FileParser::parse(juce::String extension, std::unique_ptr<juce::InputStream
|
|||
}
|
||||
|
||||
std::vector<std::unique_ptr<Shape>> FileParser::nextFrame() {
|
||||
auto tempObject = object;
|
||||
auto tempCamera = camera;
|
||||
auto tempSvg = svg;
|
||||
auto tempText = text;
|
||||
juce::SpinLock::ScopedLockType scope(lock);
|
||||
|
||||
if (tempObject != nullptr && tempCamera != nullptr) {
|
||||
return tempCamera->draw(*tempObject);
|
||||
} else if (tempSvg != nullptr) {
|
||||
return tempSvg->draw();
|
||||
} else if (tempText != nullptr) {
|
||||
return tempText->draw();
|
||||
if (object != nullptr && camera != nullptr) {
|
||||
return camera->draw(*object);
|
||||
} else if (svg != nullptr) {
|
||||
return svg->draw();
|
||||
} else if (text != nullptr) {
|
||||
return text->draw();
|
||||
}
|
||||
auto tempShapes = std::vector<std::unique_ptr<Shape>>();
|
||||
tempShapes.push_back(std::make_unique<CircleArc>(0, 0, 0.5, 0.5, std::numbers::pi / 4.0, 2 * std::numbers::pi));
|
||||
|
@ -46,9 +45,10 @@ std::vector<std::unique_ptr<Shape>> FileParser::nextFrame() {
|
|||
}
|
||||
|
||||
Vector2 FileParser::nextSample() {
|
||||
auto tempLua = lua;
|
||||
if (tempLua != nullptr) {
|
||||
return tempLua->draw();
|
||||
juce::SpinLock::ScopedLockType scope(lock);
|
||||
|
||||
if (lua != nullptr) {
|
||||
return lua->draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ private:
|
|||
bool active = true;
|
||||
bool sampleSource = false;
|
||||
|
||||
juce::SpinLock lock;
|
||||
|
||||
std::shared_ptr<WorldObject> object;
|
||||
std::shared_ptr<Camera> camera;
|
||||
std::shared_ptr<SvgParser> svg;
|
||||
|
|
|
@ -8,13 +8,16 @@ FrameProducer::~FrameProducer() {
|
|||
}
|
||||
|
||||
void FrameProducer::run() {
|
||||
while (!threadShouldExit() && frameSource->isActive()) {
|
||||
while (!threadShouldExit()) {
|
||||
// this lock is needed so that frameSource isn't deleted whilst nextFrame() is being called
|
||||
juce::SpinLock::ScopedLockType scope(lock);
|
||||
frameConsumer.addFrame(frameSource->nextFrame(), sourceFileIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void FrameProducer::setSource(std::shared_ptr<FrameSource> source, int fileIndex) {
|
||||
// TODO: should make this atomic
|
||||
juce::SpinLock::ScopedLockType scope(lock);
|
||||
frameSource->disable();
|
||||
frameSource = source;
|
||||
sourceFileIndex = fileIndex;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ public:
|
|||
void run() override;
|
||||
void setSource(std::shared_ptr<FrameSource>, int fileIndex);
|
||||
private:
|
||||
juce::SpinLock lock;
|
||||
FrameConsumer& frameConsumer;
|
||||
std::shared_ptr<FrameSource> frameSource;
|
||||
int sourceFileIndex = -1;
|
||||
|
|
Ładowanie…
Reference in New Issue