Browse Source

Add LFO-2

tags/v0.4.0
Andrew Belt 6 years ago
parent
commit
0bf6cb76ef
4 changed files with 160 additions and 51 deletions
  1. +3
    -3
      res/LFO-2.svg
  2. +1
    -0
      src/Fundamental.cpp
  3. +4
    -0
      src/Fundamental.hpp
  4. +152
    -48
      src/LFO.cpp

+ 3
- 3
res/LFO-2.svg View File

@@ -25,9 +25,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="2.0045011"
inkscape:cy="167.93165"
inkscape:zoom="11.2"
inkscape:cx="44.405311"
inkscape:cy="195.77864"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"


+ 1
- 0
src/Fundamental.cpp View File

@@ -12,6 +12,7 @@ void init(rack::Plugin *p) {
createModel<VCFWidget>(plugin, "VCF", "VCF");
createModel<VCAWidget>(plugin, "VCA", "VCA");
createModel<LFOWidget>(plugin, "LFO", "LFO-1");
createModel<LFO2Widget>(plugin, "LFO2", "LFO-2");
createModel<DelayWidget>(plugin, "Delay", "Delay");
createModel<ADSRWidget>(plugin, "ADSR", "ADSR");
createModel<VCMixerWidget>(plugin, "VCMixer", "VC Mixer");


+ 4
- 0
src/Fundamental.hpp View File

@@ -26,6 +26,10 @@ struct LFOWidget : ModuleWidget {
LFOWidget();
};

struct LFO2Widget : ModuleWidget {
LFO2Widget();
};

struct DelayWidget : ModuleWidget {
DelayWidget();
};


+ 152
- 48
src/LFO.cpp View File

@@ -1,6 +1,61 @@
#include "Fundamental.hpp"


struct LFOGenerator {
float phase = 0.0;
float pw = 0.5;
float freq = 1.0;
float offset = 0.0;
float factor = 1.0;
void setPitch(float pitch) {
pitch = fminf(pitch, 8.0);
freq = powf(2.0, pitch);
}
void setPulseWidth(float pw_) {
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 step(float dt) {
float deltaPhase = fminf(freq * dt, 0.5);
phase += deltaPhase;
if (phase >= 1.0)
phase -= 1.0;
}
float sin() {
float sin = sinf(2*M_PI * phase);
return factor * sin + offset;
}
float tri() {
float tri;
if (phase < 0.25)
tri = 4.0*phase;
else if (phase < 0.75)
tri = 2.0 - 4.0*phase;
else
tri = -4.0 + 4.0*phase;
return factor * tri + offset;
}
float saw() {
float saw;
if (phase < 0.5)
saw = 2.0*phase;
else
saw = -2.0 + 2.0*phase;
return factor * saw + offset;
}
float sqr() {
float sqr = phase < pw ? 1.0 : -1.0;
return factor * sqr + offset;
}
};


struct LFO : Module {
enum ParamIds {
OFFSET_PARAM,
@@ -27,8 +82,7 @@ struct LFO : Module {
NUM_OUTPUTS
};

float phase = 0.0;

LFOGenerator generator;
float lights[1] = {};

LFO() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {}
@@ -37,52 +91,18 @@ struct LFO : Module {


void LFO::step() {
// Compute frequency
float pitch = params[FREQ_PARAM].value;
pitch += params[FM1_PARAM].value * inputs[FM1_INPUT].value;
pitch += params[FM2_PARAM].value * inputs[FM2_INPUT].value;
pitch = fminf(pitch, 8.0);
float freq = powf(2.0, pitch);

// Pulse width
const float pwMin = 0.01;
float pw = clampf(params[PW_PARAM].value + params[PWM_PARAM].value * inputs[PW_INPUT].value / 10.0, pwMin, 1.0 - pwMin);

// Advance phase
float deltaPhase = fminf(freq / gSampleRate, 0.5);
phase += deltaPhase;
if (phase >= 1.0)
phase -= 1.0;

float offset = params[OFFSET_PARAM].value > 0.0 ? 5.0 : 0.0;
float factor = params[INVERT_PARAM].value > 0.0 ? 5.0 : -5.0;

// Outputs
float sin = sinf(2*M_PI * phase);

float tri;
if (phase < 0.25)
tri = 4.0*phase;
else if (phase < 0.75)
tri = 2.0 - 4.0*phase;
else
tri = -4.0 + 4.0*phase;

float saw;
if (phase < 0.5)
saw = 2.0*phase;
else
saw = -2.0 + 2.0*phase;

float sqr = phase < pw ? 1.0 : -1.0;

outputs[SIN_OUTPUT].value = factor * sin + offset;
outputs[TRI_OUTPUT].value = factor * tri + offset;
outputs[SAW_OUTPUT].value = factor * saw + offset;
outputs[SQR_OUTPUT].value = factor * sqr + offset;

// Lights
lights[0] = -1.0 + 2.0*phase;
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.step(1.0 / gSampleRate);

outputs[SIN_OUTPUT].value = 5.0 * generator.sin();
outputs[TRI_OUTPUT].value = 5.0 * generator.tri();
outputs[SAW_OUTPUT].value = 5.0 * generator.saw();
outputs[SQR_OUTPUT].value = 5.0 * generator.sqr();

lights[0] = -1.0 + 2.0*generator.phase;
}


@@ -124,3 +144,87 @@ LFOWidget::LFOWidget() {

addChild(createValueLight<SmallLight<GreenRedPolarityLight>>(Vec(99, 41), &module->lights[0]));
}



struct LFO2 : Module {
enum ParamIds {
OFFSET_PARAM,
INVERT_PARAM,
FREQ_PARAM,
WAVE_PARAM,
FM_PARAM,
NUM_PARAMS
};
enum InputIds {
FM_INPUT,
RESET_INPUT,
WAVE_INPUT,
NUM_INPUTS
};
enum OutputIds {
INTERP_OUTPUT,
NUM_OUTPUTS
};

LFOGenerator generator;
float lights[1] = {};

LFO2() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {}
void step();
};


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.step(1.0 / gSampleRate);

float wave = params[WAVE_PARAM].value + inputs[WAVE_INPUT].value;
wave = clampf(wave, 0.0, 3.0);
float interp;
if (wave < 1.0)
interp = crossf(generator.sin(), generator.tri(), wave);
else if (wave < 2.0)
interp = crossf(generator.tri(), generator.saw(), wave - 1.0);
else
interp = crossf(generator.saw(), generator.sqr(), wave - 2.0);
outputs[INTERP_OUTPUT].value = 5.0 * interp;

lights[0] = -1.0 + 2.0*generator.phase;
}


LFO2Widget::LFO2Widget() {
LFO2 *module = new LFO2();
setModule(module);
box.size = Vec(15*6, 380);

{
SVGPanel *panel = new SVGPanel();
panel->box.size = box.size;
panel->setBackground(SVG::load(assetPlugin(plugin, "res/LFO-2.svg")));
addChild(panel);
}

addChild(createScrew<ScrewSilver>(Vec(15, 0)));
addChild(createScrew<ScrewSilver>(Vec(box.size.x-30, 0)));
addChild(createScrew<ScrewSilver>(Vec(15, 365)));
addChild(createScrew<ScrewSilver>(Vec(box.size.x-30, 365)));

addParam(createParam<CKSS>(Vec(62, 150), module, LFO2::OFFSET_PARAM, 0.0, 1.0, 1.0));
addParam(createParam<CKSS>(Vec(62, 215), module, LFO2::INVERT_PARAM, 0.0, 1.0, 1.0));

addParam(createParam<RoundHugeBlackKnob>(Vec(18, 60), module, LFO2::FREQ_PARAM, -8.0, 6.0, -1.0));
addParam(createParam<RoundBlackKnob>(Vec(11, 142), module, LFO2::WAVE_PARAM, 0.0, 3.0, 0.0));
addParam(createParam<RoundBlackKnob>(Vec(11, 207), module, LFO2::FM_PARAM, 0.0, 1.0, 0.5));

addInput(createInput<PJ301MPort>(Vec(11, 276), module, LFO2::FM_INPUT));
addInput(createInput<PJ301MPort>(Vec(54, 276), module, LFO2::RESET_INPUT));
addInput(createInput<PJ301MPort>(Vec(11, 319), module, LFO2::WAVE_INPUT));

addOutput(createOutput<PJ301MPort>(Vec(54, 319), module, LFO2::INTERP_OUTPUT));

addChild(createValueLight<SmallLight<GreenRedPolarityLight>>(Vec(68, 41), &module->lights[0]));
}

Loading…
Cancel
Save