This is the code I have for a "function generator" signal that I'll use to modulate some params (taken inspiration from Rampage module, within VCV Rack):
Code: Select all
#include <iostream>
#include <math.h>
const double sampleRate = 44100.0;
inline float interpolate(float a, float b, float frac) {
return a + frac * (b - a);
}
inline float shapeDelta(float delta, float length, float shape) {
float mul = 1.0;
float lin = copysignf(1.0f, delta) * 10.0 / length;
float exp = mul * M_E * delta / length;
return interpolate(lin, exp, shape * 0.90f);
}
int main() {
float lengthInSeconds = 1e-2;
float in = 10.0;
// linear
float out = 0.0;
float shape = 0.0;
int numSteps = 0;
while (in - out > 1e-3) {
float delta = in - out;
float inc = shapeDelta(delta, lengthInSeconds, shape) * (1.0 / sampleRate);
out += inc;
numSteps++;
}
std::cout << "shape: " << shape << " | num steps: " << numSteps << " | value: " << out << std::endl;
// exp
out = 0.0;
shape = 1.0; // changing the shape
numSteps = 0;
while (in - out > 1e-3) {
float delta = in - out;
float inc = shapeDelta(delta, lengthInSeconds, shape) * (1.0 / sampleRate);
out += inc;
numSteps++;
}
std::cout << "shape: " << shape << " | num steps: " << numSteps << " | value: " << out << std::endl;
}
With shape = 1, its exponential, but it takes (length) 582 samples to complete (more than 0.01 seconds).
I'd like to keep the same (~) length, using both linear or exp (also considering to modulate/change shape in the middle of the cycle).
I guess that all I need is to change that mul factor (due to the position/delta/shape?!?!).
That's the question: how would you manage that mul?
It seems to me a nice way of easily generate CV signal, but I'd like to keep fixed the time of each cycle while changing the shape.
Thanks guys, as usual!