kopia lustrzana https://github.com/jameshball/osci-render
Complete infinite lua slider support
rodzic
2ec4eaba52
commit
b117aae5f5
|
@ -1,7 +1,7 @@
|
|||
#include "LuaComponent.h"
|
||||
#include "PluginEditor.h"
|
||||
|
||||
LuaComponent::LuaComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessorEditor& editor) : audioProcessor(p), pluginEditor(editor), slidersModel(sliders) {
|
||||
LuaComponent::LuaComponent(OscirenderAudioProcessor& p, OscirenderAudioProcessorEditor& editor) : audioProcessor(p), pluginEditor(editor), slidersModel(sliders, p) {
|
||||
setText(".lua File Settings");
|
||||
|
||||
sliders.setModel(&slidersModel);
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include "audio/VectorCancellingEffect.h"
|
||||
#include "audio/DistortEffect.h"
|
||||
#include "audio/SmoothEffect.h"
|
||||
#include "audio/BitCrushEffect.h"
|
||||
#include "audio/BulgeEffect.h"
|
||||
#include "audio/LuaEffect.h"
|
||||
|
||||
//==============================================================================
|
||||
OscirenderAudioProcessor::OscirenderAudioProcessor()
|
||||
|
@ -38,6 +41,10 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
allEffects.push_back(std::make_shared<Effect>(std::make_unique<DistortEffect>(true), "Vertical shift", "verticalDistort"));
|
||||
allEffects.push_back(std::make_shared<Effect>(std::make_unique<DistortEffect>(false), "Horizontal shift", "horizontalDistort"));
|
||||
allEffects.push_back(std::make_shared<Effect>(std::make_unique<SmoothEffect>(), "Smoothing", "smoothing"));
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
addLuaSlider();
|
||||
}
|
||||
}
|
||||
|
||||
OscirenderAudioProcessor::~OscirenderAudioProcessor()
|
||||
|
@ -145,6 +152,26 @@ bool OscirenderAudioProcessor::isBusesLayoutSupported (const BusesLayout& layout
|
|||
}
|
||||
#endif
|
||||
|
||||
void OscirenderAudioProcessor::addLuaSlider() {
|
||||
juce::String sliderName = "";
|
||||
|
||||
int sliderNum = luaEffects.size() + 1;
|
||||
while (sliderNum > 0) {
|
||||
int mod = (sliderNum - 1) % 26;
|
||||
sliderName = (char)(mod + 'A') + sliderName;
|
||||
sliderNum = (sliderNum - mod) / 26;
|
||||
}
|
||||
|
||||
luaEffects.push_back(std::make_shared<Effect>(std::make_unique<LuaEffect>(sliderName, *this), "Lua " + sliderName, "lua" + sliderName));
|
||||
}
|
||||
|
||||
void OscirenderAudioProcessor::updateLuaValues() {
|
||||
Vector2 vector;
|
||||
for (auto& effect : luaEffects) {
|
||||
effect->apply(0, vector);
|
||||
}
|
||||
}
|
||||
|
||||
void OscirenderAudioProcessor::updateAngleDelta() {
|
||||
auto cyclesPerSample = frequency / currentSampleRate;
|
||||
thetaDelta = cyclesPerSample * 2.0 * juce::MathConstants<double>::pi;
|
||||
|
@ -238,6 +265,7 @@ void OscirenderAudioProcessor::openFile(int index) {
|
|||
producer->setSource(parsers[index], index);
|
||||
currentFile = index;
|
||||
invalidateFrameBuffer = true;
|
||||
updateLuaValues();
|
||||
}
|
||||
|
||||
void OscirenderAudioProcessor::changeCurrentFile(int index) {
|
||||
|
@ -257,6 +285,10 @@ int OscirenderAudioProcessor::getCurrentFileIndex() {
|
|||
return currentFile;
|
||||
}
|
||||
|
||||
std::shared_ptr<FileParser> OscirenderAudioProcessor::getCurrentFileParser() {
|
||||
return parsers[currentFile];
|
||||
}
|
||||
|
||||
juce::File OscirenderAudioProcessor::getCurrentFile() {
|
||||
return files[currentFile];
|
||||
}
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
#include "parser/FrameProducer.h"
|
||||
#include "parser/FrameConsumer.h"
|
||||
#include "audio/Effect.h"
|
||||
#include "audio/BitCrushEffect.h"
|
||||
#include "audio/BulgeEffect.h"
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
|
@ -72,8 +70,7 @@ public:
|
|||
std::vector<std::shared_ptr<Effect>> allEffects;
|
||||
std::shared_ptr<std::vector<std::shared_ptr<Effect>>> enabledEffects = std::make_shared<std::vector<std::shared_ptr<Effect>>>();
|
||||
|
||||
BitCrushEffect bitCrushEffect = BitCrushEffect();
|
||||
BulgeEffect bulgeEffect = BulgeEffect();
|
||||
std::vector<std::shared_ptr<Effect>> luaEffects;
|
||||
|
||||
std::vector<std::shared_ptr<FileParser>> parsers;
|
||||
std::vector<std::shared_ptr<juce::MemoryBlock>> fileBlocks;
|
||||
|
@ -82,6 +79,8 @@ public:
|
|||
|
||||
std::unique_ptr<FrameProducer> producer;
|
||||
|
||||
void addLuaSlider();
|
||||
void updateLuaValues();
|
||||
void updateAngleDelta();
|
||||
void addFrame(std::vector<std::unique_ptr<Shape>> frame, int fileIndex) override;
|
||||
void enableEffect(std::shared_ptr<Effect> effect);
|
||||
|
@ -94,6 +93,7 @@ public:
|
|||
void openFile(int index);
|
||||
void changeCurrentFile(int index);
|
||||
int getCurrentFileIndex();
|
||||
std::shared_ptr<FileParser> getCurrentFileParser();
|
||||
juce::File getCurrentFile();
|
||||
juce::File getFile(int index);
|
||||
std::shared_ptr<juce::MemoryBlock> getFileBlock(int index);
|
||||
|
@ -116,6 +116,7 @@ private:
|
|||
|
||||
void updateFrame();
|
||||
void updateLengthIncrement();
|
||||
void syncLuaSliders();
|
||||
|
||||
const double MIN_LENGTH_INCREMENT = 0.000001;
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#include "LuaEffect.h"
|
||||
#include "../lua/LuaParser.h"
|
||||
|
||||
Vector2 LuaEffect::apply(int index, Vector2 input, double value, double frequency, double sampleRate) {
|
||||
int fileIndex = audioProcessor.getCurrentFileIndex();
|
||||
if (fileIndex == -1) {
|
||||
return input;
|
||||
}
|
||||
std::shared_ptr<LuaParser> parser = audioProcessor.getCurrentFileParser()->getLua();
|
||||
if (parser != nullptr) {
|
||||
parser->setVariable("slider_" + name.toLowerCase(), value);
|
||||
}
|
||||
return input;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "EffectApplication.h"
|
||||
#include "../shape/Vector2.h"
|
||||
#include "../audio/Effect.h"
|
||||
#include "../PluginProcessor.h"
|
||||
|
||||
class LuaEffect : public EffectApplication {
|
||||
public:
|
||||
LuaEffect(juce::String name, OscirenderAudioProcessor& p) : audioProcessor(p), name(name) {};
|
||||
|
||||
Vector2 apply(int index, Vector2 input, double value, double frequency, double sampleRate) override;
|
||||
private:
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
juce::String name;
|
||||
};
|
|
@ -1,17 +1,28 @@
|
|||
#include "EffectComponent.h"
|
||||
|
||||
EffectComponent::EffectComponent(double min, double max, double step, double value, juce::String name, juce::String id) : name(name), id(id) {
|
||||
componentSetup();
|
||||
slider.setRange(min, max, step);
|
||||
slider.setValue(value, juce::dontSendNotification);
|
||||
}
|
||||
|
||||
EffectComponent::EffectComponent(double min, double max, double step, Effect& effect) : name(effect.getName()), id(effect.getId()) {
|
||||
componentSetup();
|
||||
slider.setRange(min, max, step);
|
||||
slider.setValue(effect.getValue(), juce::dontSendNotification);
|
||||
}
|
||||
|
||||
void EffectComponent::componentSetup() {
|
||||
addAndMakeVisible(slider);
|
||||
addAndMakeVisible(selected);
|
||||
|
||||
slider.setSliderStyle(juce::Slider::LinearHorizontal);
|
||||
slider.setTextBoxStyle(juce::Slider::TextBoxRight, false, 90, slider.getTextBoxHeight());
|
||||
slider.setRange(min, max, step);
|
||||
slider.setValue(value, juce::dontSendNotification);
|
||||
|
||||
selected.setToggleState(false, juce::dontSendNotification);
|
||||
selected.setToggleState(false, juce::dontSendNotification);
|
||||
}
|
||||
|
||||
|
||||
EffectComponent::~EffectComponent() {}
|
||||
|
||||
void EffectComponent::resized() {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
class EffectComponent : public juce::Component {
|
||||
public:
|
||||
EffectComponent(double min, double max, double step, double value, juce::String name, juce::String id);
|
||||
EffectComponent(double min, double max, double step, Effect& effect);
|
||||
~EffectComponent();
|
||||
|
||||
void resized() override;
|
||||
|
@ -20,6 +21,7 @@ public:
|
|||
juce::ToggleButton selected;
|
||||
|
||||
private:
|
||||
void componentSetup();
|
||||
bool hideCheckbox = false;
|
||||
juce::Rectangle<int> textBounds;
|
||||
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
#include "LuaListComponent.h"
|
||||
|
||||
LuaListComponent::LuaListComponent(int sliderNum) {
|
||||
juce::String sliderName = "";
|
||||
|
||||
sliderNum++;
|
||||
while (sliderNum > 0) {
|
||||
int mod = (sliderNum - 1) % 26;
|
||||
sliderName = (char)(mod + 'A') + sliderName;
|
||||
sliderNum = (sliderNum - mod) / 26;
|
||||
}
|
||||
|
||||
effectComponent = std::make_shared<EffectComponent>(0.0, 1.0, 0.01, 0, "Lua " + sliderName, "lua" + sliderName);
|
||||
LuaListComponent::LuaListComponent(OscirenderAudioProcessor& p, Effect& effect) {
|
||||
effectComponent = std::make_shared<EffectComponent>(0.0, 1.0, 0.01, effect);
|
||||
effectComponent->setHideCheckbox(true);
|
||||
|
||||
effectComponent->slider.onValueChange = [this, &effect, &p] {
|
||||
effect.setValue(effectComponent->slider.getValue());
|
||||
effect.apply(0, Vector2());
|
||||
};
|
||||
|
||||
addAndMakeVisible(*effectComponent);
|
||||
}
|
||||
|
||||
|
@ -24,23 +21,23 @@ void LuaListComponent::resized() {
|
|||
void paintListBoxItem(int sliderNum, juce::Graphics& g, int width, int height, bool rowIsSelected) {}
|
||||
|
||||
int LuaListBoxModel::getNumRows() {
|
||||
return numSliders + 1;
|
||||
return audioProcessor.luaEffects.size() + 1;
|
||||
}
|
||||
|
||||
void LuaListBoxModel::paintListBoxItem(int rowNumber, juce::Graphics& g, int width, int height, bool rowIsSelected) {}
|
||||
|
||||
juce::Component* LuaListBoxModel::refreshComponentForRow(int sliderNum, bool isRowSelected, juce::Component *existingComponentToUpdate) {
|
||||
if (sliderNum < getNumRows() - 1) {
|
||||
juce::Component* LuaListBoxModel::refreshComponentForRow(int rowNum, bool isRowSelected, juce::Component *existingComponentToUpdate) {
|
||||
if (rowNum < getNumRows() - 1) {
|
||||
std::unique_ptr<LuaListComponent> item(dynamic_cast<LuaListComponent*>(existingComponentToUpdate));
|
||||
if (juce::isPositiveAndBelow(sliderNum, getNumRows())) {
|
||||
item = std::make_unique<LuaListComponent>(sliderNum);
|
||||
if (juce::isPositiveAndBelow(rowNum, getNumRows())) {
|
||||
item = std::make_unique<LuaListComponent>(audioProcessor, *audioProcessor.luaEffects[rowNum]);
|
||||
}
|
||||
return item.release();
|
||||
} else {
|
||||
std::unique_ptr<juce::TextButton> item(dynamic_cast<juce::TextButton*>(existingComponentToUpdate));
|
||||
item = std::make_unique<juce::TextButton>("Add");
|
||||
item = std::make_unique<juce::TextButton>("+");
|
||||
item->onClick = [this]() {
|
||||
numSliders++;
|
||||
audioProcessor.addLuaSlider();
|
||||
listBox.updateContent();
|
||||
};
|
||||
return item.release();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
class LuaListComponent : public juce::Component
|
||||
{
|
||||
public:
|
||||
LuaListComponent(int sliderNum);
|
||||
LuaListComponent(OscirenderAudioProcessor& p, Effect& effect);
|
||||
~LuaListComponent();
|
||||
|
||||
void resized() override;
|
||||
|
@ -21,7 +21,7 @@ private:
|
|||
class LuaListBoxModel : public juce::ListBoxModel
|
||||
{
|
||||
public:
|
||||
LuaListBoxModel(juce::ListBox& lb) : listBox(lb) {}
|
||||
LuaListBoxModel(juce::ListBox& lb, OscirenderAudioProcessor& p) : listBox(lb), audioProcessor(p) {}
|
||||
|
||||
int getNumRows() override;
|
||||
void paintListBoxItem(int rowNumber, juce::Graphics& g, int width, int height, bool rowIsSelected) override;
|
||||
|
@ -30,4 +30,5 @@ public:
|
|||
private:
|
||||
int numSliders = 5;
|
||||
juce::ListBox& listBox;
|
||||
OscirenderAudioProcessor& audioProcessor;
|
||||
};
|
||||
|
|
|
@ -27,6 +27,7 @@ void LuaParser::parse() {
|
|||
}
|
||||
}
|
||||
|
||||
// only the audio thread runs this fuction
|
||||
Vector2 LuaParser::draw() {
|
||||
Vector2 sample;
|
||||
|
||||
|
@ -36,6 +37,22 @@ Vector2 LuaParser::draw() {
|
|||
|
||||
lua_pushnumber(L, step);
|
||||
lua_setglobal(L, "step");
|
||||
|
||||
// this CANNOT run at the same time as setVariable
|
||||
if (updateVariables) {
|
||||
bool expected = false;
|
||||
if (accessingVariables.compare_exchange_strong(expected, true)) {
|
||||
for (int i = 0; i < variableNames.size(); i++) {
|
||||
lua_pushnumber(L, variables[i]);
|
||||
lua_setglobal(L, variableNames[i].toUTF8());
|
||||
DBG("set " + variableNames[i] + " to " + juce::String(variables[i]));
|
||||
}
|
||||
variableNames.clear();
|
||||
variables.clear();
|
||||
accessingVariables = false;
|
||||
updateVariables = false;
|
||||
}
|
||||
}
|
||||
|
||||
lua_geti(L, LUA_REGISTRYINDEX, functionRef);
|
||||
|
||||
|
@ -66,3 +83,18 @@ Vector2 LuaParser::draw() {
|
|||
|
||||
return sample;
|
||||
}
|
||||
|
||||
// this CANNOT run at the same time as draw()
|
||||
// many threads can run this function
|
||||
bool LuaParser::setVariable(juce::String variableName, double value) {
|
||||
bool expected = false;
|
||||
// this is very unlikely to fail, and if it does, it's not a big deal
|
||||
if (accessingVariables.compare_exchange_strong(expected, true)) {
|
||||
variableNames.push_back(variableName);
|
||||
variables.push_back(value);
|
||||
accessingVariables = false;
|
||||
updateVariables = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -10,10 +10,17 @@ public:
|
|||
~LuaParser();
|
||||
|
||||
Vector2 draw();
|
||||
bool setVariable(juce::String variableName, double value);
|
||||
|
||||
private:
|
||||
void parse();
|
||||
|
||||
int functionRef = -1;
|
||||
long step = 1;
|
||||
lua_State* L;
|
||||
juce::String script;
|
||||
std::atomic<bool> updateVariables = false;
|
||||
std::atomic<bool> accessingVariables = false;
|
||||
std::vector<juce::String> variableNames;
|
||||
std::vector<double> variables;
|
||||
};
|
|
@ -67,3 +67,23 @@ void FileParser::disable() {
|
|||
void FileParser::enable() {
|
||||
active = true;
|
||||
}
|
||||
|
||||
std::shared_ptr<WorldObject> FileParser::getObject() {
|
||||
return object;
|
||||
}
|
||||
|
||||
std::shared_ptr<Camera> FileParser::getCamera() {
|
||||
return camera;
|
||||
}
|
||||
|
||||
std::shared_ptr<SvgParser> FileParser::getSvg() {
|
||||
return svg;
|
||||
}
|
||||
|
||||
std::shared_ptr<TextParser> FileParser::getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
std::shared_ptr<LuaParser> FileParser::getLua() {
|
||||
return lua;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,12 @@ public:
|
|||
void disable() override;
|
||||
void enable() override;
|
||||
|
||||
std::shared_ptr<WorldObject> getObject();
|
||||
std::shared_ptr<Camera> getCamera();
|
||||
std::shared_ptr<SvgParser> getSvg();
|
||||
std::shared_ptr<TextParser> getText();
|
||||
std::shared_ptr<LuaParser> getLua();
|
||||
|
||||
private:
|
||||
bool active = true;
|
||||
bool sampleSource = false;
|
||||
|
|
|
@ -113,6 +113,8 @@
|
|||
file="Source/audio/EffectApplication.cpp"/>
|
||||
<FILE id="MIYJ9y" name="EffectApplication.h" compile="0" resource="0"
|
||||
file="Source/audio/EffectApplication.h"/>
|
||||
<FILE id="uhyh7T" name="LuaEffect.cpp" compile="1" resource="0" file="Source/audio/LuaEffect.cpp"/>
|
||||
<FILE id="jqDcZq" name="LuaEffect.h" compile="0" resource="0" file="Source/audio/LuaEffect.h"/>
|
||||
<FILE id="PbbNqz" name="RotateEffect.cpp" compile="1" resource="0"
|
||||
file="Source/audio/RotateEffect.cpp"/>
|
||||
<FILE id="tUwNZV" name="RotateEffect.h" compile="0" resource="0" file="Source/audio/RotateEffect.h"/>
|
||||
|
|
Ładowanie…
Reference in New Issue