-
-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LuaJIT, .gif failsafe, and external input to Lua #259
base: main
Are you sure you want to change the base?
Conversation
This reverts commit 762b183. Revert changes that were done badly
Warning: Currently MIDI seems to be bugged. Working on it. |
Source/img/ImageParser.cpp
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change makes it so that when the GIF decoder fails to decode an image, it falls back to a test pattern instead of crashing entirely.
@@ -325,7 +321,7 @@ static int luaPrint(lua_State* L) { | |||
int nargs = lua_gettop(L); | |||
|
|||
for (int i = 1; i <= nargs; ++i) { | |||
LuaParser::onPrint(luaL_tolstring(L, i, nullptr)); | |||
LuaParser::onPrint(lua_tolstring(L, i, nullptr)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Backing up to Lua 5.1 to use LuaJIT
@@ -468,7 +467,7 @@ void LuaParser::revertToFallback(lua_State*& L) { | |||
} | |||
|
|||
void LuaParser::readTable(lua_State*& L, std::vector<float>& values) { | |||
auto length = lua_rawlen(L, -1); | |||
auto length = lua_objlen(L, -1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Backing up to Lua 5.1 to use LuaJIT
@@ -493,7 +492,7 @@ std::vector<float> LuaParser::run(lua_State*& L, LuaVariables& vars) { | |||
setGlobalVariables(L, vars); | |||
|
|||
// Get the function from the registry | |||
lua_geti(L, LUA_REGISTRYINDEX, functionRef); | |||
lua_rawgeti(L, LUA_REGISTRYINDEX, functionRef); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Backing up to Lua 5.1 to use LuaJIT
setGlobalVariable(L, "x", vars.x); | ||
setGlobalVariable(L, "y", vars.y); | ||
setGlobalVariable(L, "x", vars.x); | ||
setGlobalVariable(L, "y", vars.y); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced tabs with spaces (marked as a difference for some reason)
@@ -440,9 +436,12 @@ void LuaParser::setGlobalVariables(lua_State*& L, LuaVariables& vars) { | |||
setGlobalVariable(L, SLIDER_NAMES[i], vars.sliders[i]); | |||
} | |||
|
|||
setGlobalVariable(L, "ext_x", vars.ext_x); | |||
setGlobalVariable(L, "ext_y", vars.ext_y); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pass external input into Lua interpreter
@@ -50,6 +54,9 @@ struct LuaVariables { | |||
double sampleRate = 0; | |||
double frequency = 0; | |||
|
|||
double ext_x = 0; | |||
double ext_y = 0; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
External input variables for Lua
Source/lua/lualib.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is auto-generated by LuaJIT
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra fields V and W added to the Point class. This is necessary because some audio effects are not able to take extra arguments. V and W are currently used for carrying external audio into effects, but they could also be used for other things in the future.
} | ||
else { | ||
return std::string("(" + std::to_string(x) + ", " + std::to_string(y) + ", " + std::to_string(z) + ")"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I split this as adding stuff to the string for a field that's usually 0,0 seems unnecessary unless said stuff contains useful data
Source/shape/Point.h
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding V and W as described in Point.cpp
osci-render.jucer
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Auto-generated by Projucer
.gitmodules
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add LuaJIT as a submodule
|
||
if (usingInput && totalNumInputChannels >= 2) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved the copy of the input buffer into the output buffer from inside the check to outside. The buffer gets cleared by the synth instead, unless the audio will be used by Lua.
double sx = outputBuffer3d.getSample(0, sample); | ||
double sy = outputBuffer3d.getSample(1, sample); | ||
double sz = outputBuffer3d.getSample(2, sample); | ||
Point channels = { sx, sy, sz, left, right }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be optimized into the old version if building for Release, but by doing it this way debugging is much easier.
auto lua = currentFile >= 0 ? sounds[currentFile]->parser->getLua() : nullptr; | ||
if (lua != nullptr || custom->enabled->getBoolValue()) { | ||
for (auto& effect : luaEffects) { | ||
effect->apply(sample, channels, currentVolume); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block is functionally identical but removes some stray brackets that didn't have any conditional or loop attached to them, making them do nothing.
@@ -19,6 +19,8 @@ Point CustomEffect::apply(int index, Point input, const std::vector<std::atomic< | |||
auto x = input.x; | |||
auto y = input.y; | |||
auto z = input.z; | |||
auto eX = input.v; | |||
auto eY = input.w; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Get external input variables from the input point
@@ -30,16 +32,20 @@ Point CustomEffect::apply(int index, Point input, const std::vector<std::atomic< | |||
vars.y = y; | |||
vars.z = z; | |||
|
|||
vars.ext_x = eX; | |||
vars.ext_y = eY; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pass external input variables into the Lua variables
|
||
x = result[0]; | ||
y = (rs > 1) ? result[1] : y; | ||
z = (rs > 2) ? result[2] : z; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Simplified control flow
(1 - effectScale) * input.z + effectScale * z | ||
(1 - effectScale) * input.z + effectScale * z, | ||
input.v, | ||
input.w |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be changed later so Lua can modify the external input, but at the moment that wouldn't change anything as Lua is the only thing that uses the external input points.
return effectApplication->apply(index, input, actualValues, sampleRate); | ||
} else if (application) { | ||
return application(index, input, actualValues, sampleRate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Swapped to give precedence to the EffectApplication rather than the function pointer. This likely has no effect right now, but it makes debugging far easier if both are available.
@@ -13,7 +13,7 @@ bool ShapeVoice::canPlaySound(juce::SynthesiserSound* sound) { | |||
void ShapeVoice::startNote(int midiNoteNumber, float velocity, juce::SynthesiserSound* sound, int currentPitchWheelPosition) { | |||
this->velocity = velocity; | |||
pitchWheelMoved(currentPitchWheelPosition); | |||
auto* shapeSound = dynamic_cast<ShapeSound*>(sound); | |||
ShapeSound* shapeSound = dynamic_cast<ShapeSound*>(sound); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No actual effect, but easier to read. I really should do this for all the code...
if (!(parser != nullptr && parser->isSample())) { | ||
outputBuffer.clear(startSample, numSamples); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clear the audio buffer if the current sound is not a Lua synth
double x = 0.0; | ||
double y = 0.0; | ||
double z = 0.0; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved for debugging an issue that is now fixed, but could still be useful for later debugging
@@ -111,13 +123,16 @@ void ShapeVoice::renderNextBlock(juce::AudioSampleBuffer& outputBuffer, int star | |||
vars.sampleRate = audioProcessor.currentSampleRate; | |||
vars.frequency = actualFrequency; | |||
std::copy(std::begin(audioProcessor.luaValues), std::end(audioProcessor.luaValues), std::begin(vars.sliders)); | |||
|
|||
vars.ext_x = outputBuffer.getSample(0, sample); | |||
vars.ext_y = outputBuffer.getSample(1, sample); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
External input strikes back
double length = shape->length(); | ||
double drawingProgress = length == 0.0 ? 1 : shapeDrawn / length; | ||
channels = shape->nextVector(drawingProgress); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Split open the if block as I had added some more code before the if statement, but it turned out not to be necessary. Gets optimized into the old version by the compiler.
@@ -162,7 +177,7 @@ void ShapeVoice::renderNextBlock(juce::AudioSampleBuffer& outputBuffer, int star | |||
double drawnFrameLength = traceMaxEnabled ? actualTraceMax * frameLength : frameLength; | |||
|
|||
if (!renderingSample && frameDrawn >= drawnFrameLength) { | |||
if (sound.load() != nullptr && currentlyPlaying) { | |||
if (sound.load() != nullptr && currentlyPlaying) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing whitespace that has no effect on the code whatsoever, but I wanted to add a comment because I spent a minute trying to figure out what changed
@@ -180,10 +195,10 @@ void ShapeVoice::renderNextBlock(juce::AudioSampleBuffer& outputBuffer, int star | |||
} | |||
} | |||
} | |||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Explicitly put here instead of relying on the compiler. Does nothing new, but adds a place to put a breakpoint during debugging.
@@ -192,6 +207,7 @@ void ShapeVoice::stopNote(float velocity, bool allowTailOff) { | |||
|
|||
void ShapeVoice::noteStopped() { | |||
clearCurrentNote(); | |||
currentlyPlaying = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved here to fix animation during MIDI note release
#include "luaimport.h" | ||
#include "../shape/Line.h" | ||
#include "../shape/CircleArc.h" | ||
#include "../shape/QuadraticBezierCurve.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to the header because it's good practice and more readable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added comments to all the important changes. Things like newlines aren't commented, but they should be obvious.
Ready to merge if you think it's ready! |
As advertised, this PR switches from the basic Lua interpreter to LuaJIT, a just-in-time compiler for Lua that offers immense performance gains. Additionally, it adds a failsafe to .gif loading that prevents a crash if the file fails to load, and it allows Lua programs to access the external audio input to osci-render.