| @@ -1,12 +1,17 @@ | |||
| #include "Fundamental.hpp" | |||
| #include "dsp/digital.hpp" | |||
| struct LFOGenerator { | |||
| float phase = 0.0; | |||
| float pw = 0.5; | |||
| float freq = 1.0; | |||
| float offset = 0.0; | |||
| float factor = 1.0; | |||
| bool offset = false; | |||
| bool invert = false; | |||
| SchmittTrigger resetTrigger; | |||
| LFOGenerator() { | |||
| resetTrigger.setThresholds(0.0, 0.01); | |||
| } | |||
| void setPitch(float pitch) { | |||
| pitch = fminf(pitch, 8.0); | |||
| freq = powf(2.0, pitch); | |||
| @@ -15,11 +20,10 @@ struct LFOGenerator { | |||
| const float pwMin = 0.01; | |||
| pw = clampf(pw_, pwMin, 1.0 - pwMin); | |||
| } | |||
| void setOffset(bool offset_) { | |||
| offset = offset_ ? 1.0 : 0.0; | |||
| } | |||
| void setInvert(bool invert) { | |||
| factor = invert ? -1.0 : 1.0; | |||
| void setReset(float reset) { | |||
| if (resetTrigger.process(reset)) { | |||
| phase = 0.0; | |||
| } | |||
| } | |||
| void step(float dt) { | |||
| float deltaPhase = fminf(freq * dt, 0.5); | |||
| @@ -28,30 +32,32 @@ struct LFOGenerator { | |||
| phase -= 1.0; | |||
| } | |||
| float sin() { | |||
| float sin = sinf(2*M_PI * phase); | |||
| return factor * sin + offset; | |||
| if (offset) | |||
| return 1.0 - cosf(2*M_PI * phase) * (invert ? -1.0 : 1.0); | |||
| else | |||
| return sinf(2*M_PI * phase) * (invert ? -1.0 : 1.0); | |||
| } | |||
| float tri(float x) { | |||
| return 4.0 * fabsf(x - roundf(x)); | |||
| } | |||
| float tri() { | |||
| float tri; | |||
| if (phase < 0.25) | |||
| tri = 4.0*phase; | |||
| else if (phase < 0.75) | |||
| tri = 2.0 - 4.0*phase; | |||
| if (offset) | |||
| return tri(invert ? phase - 0.5 : phase); | |||
| else | |||
| tri = -4.0 + 4.0*phase; | |||
| return factor * tri + offset; | |||
| return -1.0 + tri(invert ? phase - 0.25 : phase - 0.75); | |||
| } | |||
| float saw(float x) { | |||
| return 2.0 * (x - roundf(x)); | |||
| } | |||
| float saw() { | |||
| float saw; | |||
| if (phase < 0.5) | |||
| saw = 2.0*phase; | |||
| if (offset) | |||
| return invert ? 2.0 * (1.0 - phase) : 2.0 * phase; | |||
| else | |||
| saw = -2.0 + 2.0*phase; | |||
| return factor * saw + offset; | |||
| return saw(phase) * (invert ? -1.0 : 1.0); | |||
| } | |||
| float sqr() { | |||
| float sqr = phase < pw ? 1.0 : -1.0; | |||
| return factor * sqr + offset; | |||
| float sqr = (phase < pw) ^ invert ? 1.0 : -1.0; | |||
| return offset ? sqr + 1.0 : sqr; | |||
| } | |||
| }; | |||
| @@ -93,9 +99,10 @@ struct LFO : Module { | |||
| void LFO::step() { | |||
| generator.setPitch(params[FREQ_PARAM].value + params[FM1_PARAM].value * inputs[FM1_INPUT].value + params[FM2_PARAM].value * inputs[FM2_INPUT].value); | |||
| generator.setPulseWidth(params[PW_PARAM].value + params[PWM_PARAM].value * inputs[PW_INPUT].value / 10.0); | |||
| generator.setOffset(params[OFFSET_PARAM].value > 0.0); | |||
| generator.setInvert(params[INVERT_PARAM].value <= 0.0); | |||
| generator.offset = (params[OFFSET_PARAM].value > 0.0); | |||
| generator.invert = (params[INVERT_PARAM].value <= 0.0); | |||
| generator.step(1.0 / gSampleRate); | |||
| generator.setReset(inputs[RESET_INPUT].value); | |||
| outputs[SIN_OUTPUT].value = 5.0 * generator.sin(); | |||
| outputs[TRI_OUTPUT].value = 5.0 * generator.tri(); | |||
| @@ -177,9 +184,10 @@ struct LFO2 : Module { | |||
| void LFO2::step() { | |||
| generator.setPitch(params[FREQ_PARAM].value + params[FM_PARAM].value * inputs[FM_INPUT].value); | |||
| generator.setOffset(params[OFFSET_PARAM].value > 0.0); | |||
| generator.setInvert(params[INVERT_PARAM].value <= 0.0); | |||
| generator.offset = (params[OFFSET_PARAM].value > 0.0); | |||
| generator.invert = (params[INVERT_PARAM].value <= 0.0); | |||
| generator.step(1.0 / gSampleRate); | |||
| generator.setReset(inputs[RESET_INPUT].value); | |||
| float wave = params[WAVE_PARAM].value + inputs[WAVE_INPUT].value; | |||
| wave = clampf(wave, 0.0, 3.0); | |||