kopia lustrzana https://github.com/jameshball/osci-render
Add non-editable perspective effect
rodzic
ee181b0276
commit
e3c2010917
|
@ -79,6 +79,17 @@ OscirenderAudioProcessor::OscirenderAudioProcessor()
|
|||
delayEffect,
|
||||
std::vector<EffectParameter*>{new EffectParameter("Delay Decay", "delayDecay", 0.0, 0.0, 1.0), new EffectParameter("Delay Length", "delayEchoLength", 0.5, 0.0, 1.0)}
|
||||
));
|
||||
toggleableEffects.push_back(std::make_shared<Effect>(
|
||||
perspectiveEffect,
|
||||
std::vector<EffectParameter*>{
|
||||
new EffectParameter("3D Perspective", "depthScale", 0.0, 0.0, 1.0),
|
||||
new EffectParameter("3D Depth (z)", "zPos", 0.1, 0.0, 1.0),
|
||||
new EffectParameter("3D Rotate Speed", "rotateSpeed3D", 0.0, -1.0, 1.0),
|
||||
new EffectParameter("Rotate X", "rotateX", 1.0, -1.0, 1.0),
|
||||
new EffectParameter("Rotate Y", "rotateY", 1.0, -1.0, 1.0),
|
||||
new EffectParameter("Rotate Z", "rotateZ", 0.0, -1.0, 1.0),
|
||||
}
|
||||
));
|
||||
toggleableEffects.push_back(traceMax);
|
||||
toggleableEffects.push_back(traceMin);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "audio/DelayEffect.h"
|
||||
#include "audio/PitchDetector.h"
|
||||
#include "audio/WobbleEffect.h"
|
||||
#include "audio/PerspectiveEffect.h"
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
|
@ -122,7 +123,7 @@ public:
|
|||
}
|
||||
}
|
||||
return input;
|
||||
}, new EffectParameter("Rotate X", "rotateX", 1.0, -1.0, 1.0)
|
||||
}, new EffectParameter("Rotate X", "objRotateX", 1.0, -1.0, 1.0)
|
||||
);
|
||||
std::shared_ptr<Effect> rotateY = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
|
@ -137,7 +138,7 @@ public:
|
|||
}
|
||||
}
|
||||
return input;
|
||||
}, new EffectParameter("Rotate Y", "rotateY", 1.0, -1.0, 1.0)
|
||||
}, new EffectParameter("Rotate Y", "objRotateY", 1.0, -1.0, 1.0)
|
||||
);
|
||||
std::shared_ptr<Effect> rotateZ = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
|
@ -152,7 +153,7 @@ public:
|
|||
}
|
||||
}
|
||||
return input;
|
||||
}, new EffectParameter("Rotate Z", "rotateZ", 0.0, -1.0, 1.0)
|
||||
}, new EffectParameter("Rotate Z", "objRotateZ", 0.0, -1.0, 1.0)
|
||||
);
|
||||
std::shared_ptr<Effect> rotateSpeed = std::make_shared<Effect>(
|
||||
[this](int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
|
@ -162,10 +163,11 @@ public:
|
|||
obj->setRotationSpeed(values[0]);
|
||||
}
|
||||
return input;
|
||||
}, new EffectParameter("Rotate Speed", "rotateSpeed3D", 0.0, -1.0, 1.0)
|
||||
}, new EffectParameter("Rotate Speed", "objRotateSpeed", 0.0, -1.0, 1.0)
|
||||
);
|
||||
|
||||
std::shared_ptr<DelayEffect> delayEffect = std::make_shared<DelayEffect>();
|
||||
std::shared_ptr<PerspectiveEffect> perspectiveEffect = std::make_shared<PerspectiveEffect>();
|
||||
|
||||
juce::SpinLock parsersLock;
|
||||
std::vector<std::shared_ptr<FileParser>> parsers;
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
#include "PerspectiveEffect.h"
|
||||
#include <numbers>
|
||||
|
||||
PerspectiveEffect::PerspectiveEffect() {}
|
||||
|
||||
Vector2 PerspectiveEffect::apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) {
|
||||
auto effectScale = values[0];
|
||||
auto depth = 1.0 + (values[1] - 0.1) * 3;
|
||||
auto rotateSpeed = linearSpeedToActualSpeed(values[2]);
|
||||
auto baseRotateX = values[3] * std::numbers::pi;
|
||||
auto baseRotateY = values[4] * std::numbers::pi;
|
||||
auto baseRotateZ = values[5] * std::numbers::pi;
|
||||
|
||||
currentRotateX += baseRotateX * rotateSpeed;
|
||||
currentRotateY += baseRotateY * rotateSpeed;
|
||||
currentRotateZ += baseRotateZ * rotateSpeed;
|
||||
|
||||
auto x = input.x;
|
||||
auto y = input.y;
|
||||
auto z = 0.0;
|
||||
|
||||
parser.setVariable("x", x);
|
||||
parser.setVariable("y", y);
|
||||
parser.setVariable("z", z);
|
||||
|
||||
auto result = parser.run();
|
||||
if (result.size() >= 3) {
|
||||
x = result[0];
|
||||
y = result[1];
|
||||
z = result[2];
|
||||
}
|
||||
|
||||
auto rotateX = baseRotateX + currentRotateX;
|
||||
auto rotateY = baseRotateY + currentRotateY;
|
||||
auto rotateZ = baseRotateZ + currentRotateZ;
|
||||
|
||||
// rotate around x-axis
|
||||
double cosValue = std::cos(rotateX);
|
||||
double sinValue = std::sin(rotateX);
|
||||
double y2 = cosValue * y - sinValue * z;
|
||||
double z2 = sinValue * y + cosValue * z;
|
||||
|
||||
// rotate around y-axis
|
||||
cosValue = std::cos(rotateY);
|
||||
sinValue = std::sin(rotateY);
|
||||
double x2 = cosValue * x + sinValue * z2;
|
||||
double z3 = -sinValue * x + cosValue * z2;
|
||||
|
||||
// rotate around z-axis
|
||||
cosValue = cos(rotateZ);
|
||||
sinValue = sin(rotateZ);
|
||||
double x3 = cosValue * x2 - sinValue * y2;
|
||||
double y3 = sinValue * x2 + cosValue * y2;
|
||||
|
||||
// perspective projection
|
||||
auto focalLength = 1.0;
|
||||
return Vector2(
|
||||
(1 - effectScale) * input.x + effectScale * (x3 * focalLength / (z3 - depth)),
|
||||
(1 - effectScale) * input.y + effectScale * (y3 * focalLength / (z3 - depth))
|
||||
);
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
#include "EffectApplication.h"
|
||||
#include "../shape/Vector2.h"
|
||||
#include "../audio/Effect.h"
|
||||
#include "../lua/LuaParser.h"
|
||||
|
||||
class PerspectiveEffect : public EffectApplication {
|
||||
public:
|
||||
PerspectiveEffect();
|
||||
|
||||
Vector2 apply(int index, Vector2 input, const std::vector<double>& values, double sampleRate) override;
|
||||
private:
|
||||
const juce::String DEFAULT_SCRIPT = "return { x, y, z }";
|
||||
juce::MemoryBlock code{DEFAULT_SCRIPT.toRawUTF8(), DEFAULT_SCRIPT.getNumBytesAsUTF8() + 1};
|
||||
LuaParser parser{DEFAULT_SCRIPT};
|
||||
|
||||
float currentRotateX = 0;
|
||||
float currentRotateY = 0;
|
||||
float currentRotateZ = 0;
|
||||
|
||||
float linearSpeedToActualSpeed(float rotateSpeed) {
|
||||
return (std::exp(3 * juce::jmin(10.0f, std::abs(rotateSpeed))) - 1) / 50000.0;
|
||||
}
|
||||
};
|
|
@ -28,11 +28,11 @@ void LuaParser::parse() {
|
|||
}
|
||||
|
||||
// only the audio thread runs this fuction
|
||||
Vector2 LuaParser::draw() {
|
||||
Vector2 sample;
|
||||
std::vector<float> LuaParser::run() {
|
||||
std::vector<float> values;
|
||||
|
||||
if (functionRef == -1) {
|
||||
return sample;
|
||||
return values;
|
||||
}
|
||||
|
||||
lua_pushnumber(L, step);
|
||||
|
@ -60,29 +60,25 @@ Vector2 LuaParser::draw() {
|
|||
DBG(error);
|
||||
functionRef = -1;
|
||||
} else if (lua_istable(L, -1)) {
|
||||
// get the first element of the table
|
||||
lua_pushinteger(L, 1);
|
||||
lua_gettable(L, -2);
|
||||
float x = lua_tonumber(L, -1);
|
||||
lua_pop(L, 1);
|
||||
auto length = lua_rawlen(L, -1);
|
||||
|
||||
// get the second element of the table
|
||||
lua_pushinteger(L, 2);
|
||||
lua_gettable(L, -2);
|
||||
float y = lua_tonumber(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
sample = Vector2(x, y);
|
||||
for (int i = 1; i <= length; i++) {
|
||||
lua_pushinteger(L, i);
|
||||
lua_gettable(L, -2);
|
||||
float value = lua_tonumber(L, -1);
|
||||
lua_pop(L, 1);
|
||||
values.push_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
step++;
|
||||
|
||||
return sample;
|
||||
return values;
|
||||
}
|
||||
|
||||
// this CANNOT run at the same time as draw()
|
||||
// this CANNOT run at the same time as run()
|
||||
// many threads can run this function
|
||||
void LuaParser::setVariable(juce::String variableName, double value) {
|
||||
juce::SpinLock::ScopedLockType lock(variableLock);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#pragma once
|
||||
#include "../shape/Vector2.h"
|
||||
#include <JuceHeader.h>
|
||||
#include "../shape/Shape.h"
|
||||
|
||||
|
@ -9,7 +8,7 @@ public:
|
|||
LuaParser(juce::String script);
|
||||
~LuaParser();
|
||||
|
||||
Vector2 draw();
|
||||
std::vector<float> run();
|
||||
void setVariable(juce::String variableName, double value);
|
||||
|
||||
private:
|
||||
|
|
|
@ -48,7 +48,11 @@ Vector2 FileParser::nextSample() {
|
|||
juce::SpinLock::ScopedLockType scope(lock);
|
||||
|
||||
if (lua != nullptr) {
|
||||
return lua->draw();
|
||||
auto values = lua->run();
|
||||
if (values.size() < 2) {
|
||||
return Vector2();
|
||||
}
|
||||
return Vector2(values[0], values[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,10 @@
|
|||
file="Source/audio/EffectParameter.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="QBWW9w" name="PerspectiveEffect.cpp" compile="1" resource="0"
|
||||
file="Source/audio/PerspectiveEffect.cpp"/>
|
||||
<FILE id="h0dMim" name="PerspectiveEffect.h" compile="0" resource="0"
|
||||
file="Source/audio/PerspectiveEffect.h"/>
|
||||
<FILE id="t2bsR8" name="PitchDetector.cpp" compile="1" resource="0"
|
||||
file="Source/audio/PitchDetector.cpp"/>
|
||||
<FILE id="rQC2gX" name="PitchDetector.h" compile="0" resource="0" file="Source/audio/PitchDetector.h"/>
|
||||
|
|
Ładowanie…
Reference in New Issue