@@ -21,7 +21,6 @@ void init(rack::Plugin *p) { | |||||
p->addModel(modelBlinds); | p->addModel(modelBlinds); | ||||
p->addModel(modelVeils); | p->addModel(modelVeils); | ||||
p->addModel(modelFrames); | p->addModel(modelFrames); | ||||
// p->addModel(modelPeaks); | |||||
p->addModel(modelMarbles); | p->addModel(modelMarbles); | ||||
p->addModel(modelStages); | p->addModel(modelStages); | ||||
} | } |
@@ -1,4 +1,4 @@ | |||||
#include "rack0.hpp" | |||||
#include "rack.hpp" | |||||
using namespace rack; | using namespace rack; | ||||
@@ -21,6 +21,5 @@ extern Model *modelBranches; | |||||
extern Model *modelBlinds; | extern Model *modelBlinds; | ||||
extern Model *modelVeils; | extern Model *modelVeils; | ||||
extern Model *modelFrames; | extern Model *modelFrames; | ||||
extern Model *modelPeaks; | |||||
extern Model *modelStages; | extern Model *modelStages; | ||||
extern Model *modelMarbles; | extern Model *modelMarbles; |
@@ -43,25 +43,35 @@ struct Blinds : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
Blinds() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} | |||||
void step() override; | |||||
Blinds() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Blinds::GAIN1_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Blinds::GAIN2_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Blinds::GAIN3_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Blinds::GAIN4_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Blinds::MOD1_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Blinds::MOD2_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Blinds::MOD3_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Blinds::MOD4_PARAM, -1.0, 1.0, 0.0); | |||||
} | |||||
void process(const ProcessArgs &args) override; | |||||
}; | }; | ||||
void Blinds::step() { | |||||
void Blinds::process(const ProcessArgs &args) { | |||||
float out = 0.0; | float out = 0.0; | ||||
for (int i = 0; i < 4; i++) { | for (int i = 0; i < 4; i++) { | ||||
float g = params[GAIN1_PARAM + i].value; | |||||
g += params[MOD1_PARAM + i].value * inputs[CV1_INPUT + i].value / 5.0; | |||||
float g = params[GAIN1_PARAM + i].getValue(); | |||||
g += params[MOD1_PARAM + i].getValue() * inputs[CV1_INPUT + i].getVoltage() / 5.0; | |||||
g = clamp(g, -2.0f, 2.0f); | g = clamp(g, -2.0f, 2.0f); | ||||
lights[CV1_POS_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, g)); | |||||
lights[CV1_NEG_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, -g)); | |||||
out += g * inputs[IN1_INPUT + i].normalize(5.0); | |||||
lights[OUT1_POS_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, out / 5.0)); | |||||
lights[OUT1_NEG_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, -out / 5.0)); | |||||
if (outputs[OUT1_OUTPUT + i].active) { | |||||
outputs[OUT1_OUTPUT + i].value = out; | |||||
lights[CV1_POS_LIGHT + 2*i].setSmoothBrightness(fmaxf(0.0, g), args.sampleTime); | |||||
lights[CV1_NEG_LIGHT + 2*i].setSmoothBrightness(fmaxf(0.0, -g), args.sampleTime); | |||||
out += g * inputs[IN1_INPUT + i].getNormalVoltage(5.0); | |||||
lights[OUT1_POS_LIGHT + 2*i].setSmoothBrightness(fmaxf(0.0, out / 5.0), args.sampleTime); | |||||
lights[OUT1_NEG_LIGHT + 2*i].setSmoothBrightness(fmaxf(0.0, -out / 5.0), args.sampleTime); | |||||
if (outputs[OUT1_OUTPUT + i].isConnected()) { | |||||
outputs[OUT1_OUTPUT + i].setVoltage(out); | |||||
out = 0.0; | out = 0.0; | ||||
} | } | ||||
} | } | ||||
@@ -69,38 +79,39 @@ void Blinds::step() { | |||||
struct BlindsWidget : ModuleWidget { | struct BlindsWidget : ModuleWidget { | ||||
BlindsWidget(Blinds *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Blinds.svg"))); | |||||
BlindsWidget(Blinds *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Blinds.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 0))); | addChild(createWidget<ScrewSilver>(Vec(15, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(150, 0))); | addChild(createWidget<ScrewSilver>(Vec(150, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addChild(createWidget<ScrewSilver>(Vec(150, 365))); | addChild(createWidget<ScrewSilver>(Vec(150, 365))); | ||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 52), module, Blinds::GAIN1_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 131), module, Blinds::GAIN2_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 210), module, Blinds::GAIN3_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 288), module, Blinds::GAIN4_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(72, 63), module, Blinds::MOD1_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(72, 142), module, Blinds::MOD2_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(72, 221), module, Blinds::MOD3_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(72, 300), module, Blinds::MOD4_PARAM, -1.0, 1.0, 0.0)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 41), PortWidget::INPUT, module, Blinds::IN1_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 120), PortWidget::INPUT, module, Blinds::IN2_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 198), PortWidget::INPUT, module, Blinds::IN3_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 277), PortWidget::INPUT, module, Blinds::IN4_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 80), PortWidget::INPUT, module, Blinds::CV1_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 159), PortWidget::INPUT, module, Blinds::CV2_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 238), PortWidget::INPUT, module, Blinds::CV3_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 316), PortWidget::INPUT, module, Blinds::CV4_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(144, 41), PortWidget::OUTPUT, module, Blinds::OUT1_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(144, 120), PortWidget::OUTPUT, module, Blinds::OUT2_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(144, 198), PortWidget::OUTPUT, module, Blinds::OUT3_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(144, 277), PortWidget::OUTPUT, module, Blinds::OUT4_OUTPUT)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 52), module, Blinds::GAIN1_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 131), module, Blinds::GAIN2_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 210), module, Blinds::GAIN3_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 288), module, Blinds::GAIN4_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(72, 63), module, Blinds::MOD1_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(72, 142), module, Blinds::MOD2_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(72, 221), module, Blinds::MOD3_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(72, 300), module, Blinds::MOD4_PARAM)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 41), module, Blinds::IN1_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 120), module, Blinds::IN2_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 198), module, Blinds::IN3_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 277), module, Blinds::IN4_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 80), module, Blinds::CV1_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 159), module, Blinds::CV2_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 238), module, Blinds::CV3_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 316), module, Blinds::CV4_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(144, 41), module, Blinds::OUT1_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(144, 120), module, Blinds::OUT2_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(144, 198), module, Blinds::OUT3_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(144, 277), module, Blinds::OUT4_OUTPUT)); | |||||
addChild(createLight<SmallLight<GreenRedLight>>(Vec(78, 96), module, Blinds::CV1_POS_LIGHT)); | addChild(createLight<SmallLight<GreenRedLight>>(Vec(78, 96), module, Blinds::CV1_POS_LIGHT)); | ||||
addChild(createLight<SmallLight<GreenRedLight>>(Vec(78, 175), module, Blinds::CV2_POS_LIGHT)); | addChild(createLight<SmallLight<GreenRedLight>>(Vec(78, 175), module, Blinds::CV2_POS_LIGHT)); | ||||
@@ -33,13 +33,35 @@ struct Braids : Module { | |||||
braids::VcoJitterSource jitter_source; | braids::VcoJitterSource jitter_source; | ||||
braids::SignatureWaveshaper ws; | braids::SignatureWaveshaper ws; | ||||
SampleRateConverter<1> src; | |||||
DoubleRingBuffer<Frame<1>, 256> outputBuffer; | |||||
dsp::SampleRateConverter<1> src; | |||||
dsp::DoubleRingBuffer<dsp::Frame<1>, 256> outputBuffer; | |||||
bool lastTrig = false; | bool lastTrig = false; | ||||
bool lowCpu = false; | bool lowCpu = false; | ||||
Braids(); | |||||
void step() override; | |||||
Braids() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); | |||||
configParam(Braids::SHAPE_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Braids::FINE_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Braids::COARSE_PARAM, -2.0, 2.0, 0.0); | |||||
configParam(Braids::FM_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Braids::TIMBRE_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Braids::MODULATION_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Braids::COLOR_PARAM, 0.0, 1.0, 0.5); | |||||
memset(&osc, 0, sizeof(osc)); | |||||
osc.Init(); | |||||
memset(&jitter_source, 0, sizeof(jitter_source)); | |||||
jitter_source.Init(); | |||||
memset(&ws, 0, sizeof(ws)); | |||||
ws.Init(0x0000); | |||||
memset(&settings, 0, sizeof(settings)); | |||||
// List of supported settings | |||||
settings.meta_modulation = 0; | |||||
settings.vco_drift = 0; | |||||
settings.signature = 0; | |||||
} | |||||
void process(const ProcessArgs &args) override; | |||||
void setShape(int shape); | void setShape(int shape); | ||||
json_t *dataToJson() override { | json_t *dataToJson() override { | ||||
@@ -77,24 +99,9 @@ struct Braids : Module { | |||||
}; | }; | ||||
Braids::Braids() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) { | |||||
memset(&osc, 0, sizeof(osc)); | |||||
osc.Init(); | |||||
memset(&jitter_source, 0, sizeof(jitter_source)); | |||||
jitter_source.Init(); | |||||
memset(&ws, 0, sizeof(ws)); | |||||
ws.Init(0x0000); | |||||
memset(&settings, 0, sizeof(settings)); | |||||
// List of supported settings | |||||
settings.meta_modulation = 0; | |||||
settings.vco_drift = 0; | |||||
settings.signature = 0; | |||||
} | |||||
void Braids::step() { | |||||
void Braids::process(const ProcessArgs &args) { | |||||
// Trigger | // Trigger | ||||
bool trig = inputs[TRIG_INPUT].value >= 1.0; | |||||
bool trig = inputs[TRIG_INPUT].getVoltage() >= 1.0; | |||||
if (!lastTrig && trig) { | if (!lastTrig && trig) { | ||||
osc.Strike(); | osc.Strike(); | ||||
} | } | ||||
@@ -102,10 +109,10 @@ void Braids::step() { | |||||
// Render frames | // Render frames | ||||
if (outputBuffer.empty()) { | if (outputBuffer.empty()) { | ||||
float fm = params[FM_PARAM].value * inputs[FM_INPUT].value; | |||||
float fm = params[FM_PARAM].getValue() * inputs[FM_INPUT].getVoltage(); | |||||
// Set shape | // Set shape | ||||
int shape = roundf(params[SHAPE_PARAM].value * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); | |||||
int shape = roundf(params[SHAPE_PARAM].getValue() * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); | |||||
if (settings.meta_modulation) { | if (settings.meta_modulation) { | ||||
shape += roundf(fm / 10.0 * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); | shape += roundf(fm / 10.0 * braids::MACRO_OSC_SHAPE_LAST_ACCESSIBLE_FROM_META); | ||||
} | } | ||||
@@ -115,18 +122,18 @@ void Braids::step() { | |||||
osc.set_shape((braids::MacroOscillatorShape) settings.shape); | osc.set_shape((braids::MacroOscillatorShape) settings.shape); | ||||
// Set timbre/modulation | // Set timbre/modulation | ||||
float timbre = params[TIMBRE_PARAM].value + params[MODULATION_PARAM].value * inputs[TIMBRE_INPUT].value / 5.0; | |||||
float modulation = params[COLOR_PARAM].value + inputs[COLOR_INPUT].value / 5.0; | |||||
float timbre = params[TIMBRE_PARAM].getValue() + params[MODULATION_PARAM].getValue() * inputs[TIMBRE_INPUT].getVoltage() / 5.0; | |||||
float modulation = params[COLOR_PARAM].getValue() + inputs[COLOR_INPUT].getVoltage() / 5.0; | |||||
int16_t param1 = rescale(clamp(timbre, 0.0f, 1.0f), 0.0f, 1.0f, 0, INT16_MAX); | int16_t param1 = rescale(clamp(timbre, 0.0f, 1.0f), 0.0f, 1.0f, 0, INT16_MAX); | ||||
int16_t param2 = rescale(clamp(modulation, 0.0f, 1.0f), 0.0f, 1.0f, 0, INT16_MAX); | int16_t param2 = rescale(clamp(modulation, 0.0f, 1.0f), 0.0f, 1.0f, 0, INT16_MAX); | ||||
osc.set_parameters(param1, param2); | osc.set_parameters(param1, param2); | ||||
// Set pitch | // Set pitch | ||||
float pitchV = inputs[PITCH_INPUT].value + params[COARSE_PARAM].value + params[FINE_PARAM].value / 12.0; | |||||
float pitchV = inputs[PITCH_INPUT].getVoltage() + params[COARSE_PARAM].getValue() + params[FINE_PARAM].getValue() / 12.0; | |||||
if (!settings.meta_modulation) | if (!settings.meta_modulation) | ||||
pitchV += fm; | pitchV += fm; | ||||
if (lowCpu) | if (lowCpu) | ||||
pitchV += log2f(96000.f * engineGetSampleTime()); | |||||
pitchV += log2f(96000.f * args.sampleTime); | |||||
int32_t pitch = (pitchV * 12.0 + 60) * 128; | int32_t pitch = (pitchV * 12.0 + 60) * 128; | ||||
pitch += jitter_source.Render(settings.vco_drift); | pitch += jitter_source.Render(settings.vco_drift); | ||||
pitch = clamp(pitch, 0, 16383); | pitch = clamp(pitch, 0, 16383); | ||||
@@ -149,18 +156,18 @@ void Braids::step() { | |||||
if (lowCpu) { | if (lowCpu) { | ||||
for (int i = 0; i < 24; i++) { | for (int i = 0; i < 24; i++) { | ||||
Frame<1> f; | |||||
dsp::Frame<1> f; | |||||
f.samples[0] = render_buffer[i] / 32768.0; | f.samples[0] = render_buffer[i] / 32768.0; | ||||
outputBuffer.push(f); | outputBuffer.push(f); | ||||
} | } | ||||
} | } | ||||
else { | else { | ||||
// Sample rate convert | // Sample rate convert | ||||
Frame<1> in[24]; | |||||
dsp::Frame<1> in[24]; | |||||
for (int i = 0; i < 24; i++) { | for (int i = 0; i < 24; i++) { | ||||
in[i].samples[0] = render_buffer[i] / 32768.0; | in[i].samples[0] = render_buffer[i] / 32768.0; | ||||
} | } | ||||
src.setRates(96000, engineGetSampleRate()); | |||||
src.setRates(96000, args.sampleRate); | |||||
int inLen = 24; | int inLen = 24; | ||||
int outLen = outputBuffer.capacity(); | int outLen = outputBuffer.capacity(); | ||||
@@ -171,8 +178,8 @@ void Braids::step() { | |||||
// Output | // Output | ||||
if (!outputBuffer.empty()) { | if (!outputBuffer.empty()) { | ||||
Frame<1> f = outputBuffer.shift(); | |||||
outputs[OUT_OUTPUT].value = 5.0 * f.samples[0]; | |||||
dsp::Frame<1> f = outputBuffer.shift(); | |||||
outputs[OUT_OUTPUT].setVoltage(5.0 * f.samples[0]); | |||||
} | } | ||||
} | } | ||||
@@ -233,33 +240,33 @@ struct BraidsDisplay : TransparentWidget { | |||||
std::shared_ptr<Font> font; | std::shared_ptr<Font> font; | ||||
BraidsDisplay() { | BraidsDisplay() { | ||||
font = Font::load(assetPlugin(pluginInstance, "res/hdad-segment14-1.002/Segment14.ttf")); | |||||
font = APP->window->loadFont(asset::plugin(pluginInstance, "res/hdad-segment14-1.002/Segment14.ttf")); | |||||
} | } | ||||
void draw(NVGcontext *vg) override { | |||||
void draw(const DrawArgs &args) override { | |||||
int shape = module ? module->settings.shape : 0; | int shape = module ? module->settings.shape : 0; | ||||
// Background | // Background | ||||
NVGcolor backgroundColor = nvgRGB(0x38, 0x38, 0x38); | NVGcolor backgroundColor = nvgRGB(0x38, 0x38, 0x38); | ||||
NVGcolor borderColor = nvgRGB(0x10, 0x10, 0x10); | NVGcolor borderColor = nvgRGB(0x10, 0x10, 0x10); | ||||
nvgBeginPath(vg); | |||||
nvgRoundedRect(vg, 0.0, 0.0, box.size.x, box.size.y, 5.0); | |||||
nvgFillColor(vg, backgroundColor); | |||||
nvgFill(vg); | |||||
nvgStrokeWidth(vg, 1.0); | |||||
nvgStrokeColor(vg, borderColor); | |||||
nvgStroke(vg); | |||||
nvgFontSize(vg, 36); | |||||
nvgFontFaceId(vg, font->handle); | |||||
nvgTextLetterSpacing(vg, 2.5); | |||||
nvgBeginPath(args.vg); | |||||
nvgRoundedRect(args.vg, 0.0, 0.0, box.size.x, box.size.y, 5.0); | |||||
nvgFillColor(args.vg, backgroundColor); | |||||
nvgFill(args.vg); | |||||
nvgStrokeWidth(args.vg, 1.0); | |||||
nvgStrokeColor(args.vg, borderColor); | |||||
nvgStroke(args.vg); | |||||
nvgFontSize(args.vg, 36); | |||||
nvgFontFaceId(args.vg, font->handle); | |||||
nvgTextLetterSpacing(args.vg, 2.5); | |||||
Vec textPos = Vec(10, 48); | Vec textPos = Vec(10, 48); | ||||
NVGcolor textColor = nvgRGB(0xaf, 0xd2, 0x2c); | NVGcolor textColor = nvgRGB(0xaf, 0xd2, 0x2c); | ||||
nvgFillColor(vg, nvgTransRGBA(textColor, 16)); | |||||
nvgText(vg, textPos.x, textPos.y, "~~~~", NULL); | |||||
nvgFillColor(vg, textColor); | |||||
nvgText(vg, textPos.x, textPos.y, algo_values[shape], NULL); | |||||
nvgFillColor(args.vg, nvgTransRGBA(textColor, 16)); | |||||
nvgText(args.vg, textPos.x, textPos.y, "~~~~", NULL); | |||||
nvgFillColor(args.vg, textColor); | |||||
nvgText(args.vg, textPos.x, textPos.y, algo_values[shape], NULL); | |||||
} | } | ||||
}; | }; | ||||
@@ -291,8 +298,9 @@ struct BraidsLowCpuItem : MenuItem { | |||||
struct BraidsWidget : ModuleWidget { | struct BraidsWidget : ModuleWidget { | ||||
BraidsWidget(Braids *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Braids.svg"))); | |||||
BraidsWidget(Braids *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Braids.svg"))); | |||||
{ | { | ||||
BraidsDisplay *display = new BraidsDisplay(); | BraidsDisplay *display = new BraidsDisplay(); | ||||
@@ -307,22 +315,22 @@ struct BraidsWidget : ModuleWidget { | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addChild(createWidget<ScrewSilver>(Vec(210, 365))); | addChild(createWidget<ScrewSilver>(Vec(210, 365))); | ||||
addParam(createParam<Rogan2SGray>(Vec(176, 59), module, Braids::SHAPE_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan2SGray>(Vec(176, 59), module, Braids::SHAPE_PARAM)); | |||||
addParam(createParam<Rogan2PSWhite>(Vec(19, 138), module, Braids::FINE_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan2PSWhite>(Vec(97, 138), module, Braids::COARSE_PARAM, -2.0, 2.0, 0.0)); | |||||
addParam(createParam<Rogan2PSWhite>(Vec(176, 138), module, Braids::FM_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan2PSWhite>(Vec(19, 138), module, Braids::FINE_PARAM)); | |||||
addParam(createParam<Rogan2PSWhite>(Vec(97, 138), module, Braids::COARSE_PARAM)); | |||||
addParam(createParam<Rogan2PSWhite>(Vec(176, 138), module, Braids::FM_PARAM)); | |||||
addParam(createParam<Rogan2PSGreen>(Vec(19, 217), module, Braids::TIMBRE_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan2PSGreen>(Vec(97, 217), module, Braids::MODULATION_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan2PSRed>(Vec(176, 217), module, Braids::COLOR_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan2PSGreen>(Vec(19, 217), module, Braids::TIMBRE_PARAM)); | |||||
addParam(createParam<Rogan2PSGreen>(Vec(97, 217), module, Braids::MODULATION_PARAM)); | |||||
addParam(createParam<Rogan2PSRed>(Vec(176, 217), module, Braids::COLOR_PARAM)); | |||||
addInput(createPort<PJ301MPort>(Vec(10, 316), PortWidget::INPUT, module, Braids::TRIG_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(47, 316), PortWidget::INPUT, module, Braids::PITCH_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(84, 316), PortWidget::INPUT, module, Braids::FM_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(122, 316), PortWidget::INPUT, module, Braids::TIMBRE_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(160, 316), PortWidget::INPUT, module, Braids::COLOR_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(205, 316), PortWidget::OUTPUT, module, Braids::OUT_OUTPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(10, 316), module, Braids::TRIG_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(47, 316), module, Braids::PITCH_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(84, 316), module, Braids::FM_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(122, 316), module, Braids::TIMBRE_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(160, 316), module, Braids::COLOR_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(205, 316), module, Braids::OUT_OUTPUT)); | |||||
} | } | ||||
void appendContextMenu(Menu *menu) override { | void appendContextMenu(Menu *menu) override { | ||||
@@ -31,12 +31,18 @@ struct Branches : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
SchmittTrigger gateTriggers[2]; | |||||
SchmittTrigger modeTriggers[2]; | |||||
dsp::SchmittTrigger gateTriggers[2]; | |||||
dsp::SchmittTrigger modeTriggers[2]; | |||||
bool modes[2] = {}; | bool modes[2] = {}; | ||||
bool outcomes[2] = {}; | bool outcomes[2] = {}; | ||||
Branches() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} | |||||
Branches() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Branches::THRESHOLD1_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Branches::MODE1_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Branches::THRESHOLD2_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Branches::MODE2_PARAM, 0.0, 1.0, 0.0); | |||||
} | |||||
json_t *dataToJson() override { | json_t *dataToJson() override { | ||||
json_t *rootJ = json_object(); | json_t *rootJ = json_object(); | ||||
@@ -59,7 +65,7 @@ struct Branches : Module { | |||||
} | } | ||||
} | } | ||||
void step() override; | |||||
void process(const ProcessArgs &args) override; | |||||
void onReset() override { | void onReset() override { | ||||
for (int i = 0; i < 2; i++) { | for (int i = 0; i < 2; i++) { | ||||
@@ -70,20 +76,20 @@ struct Branches : Module { | |||||
}; | }; | ||||
void Branches::step() { | |||||
void Branches::process(const ProcessArgs &args) { | |||||
float gate = 0.0; | float gate = 0.0; | ||||
for (int i = 0; i < 2; i++) { | for (int i = 0; i < 2; i++) { | ||||
// mode button | // mode button | ||||
if (modeTriggers[i].process(params[MODE1_PARAM + i].value)) | |||||
if (modeTriggers[i].process(params[MODE1_PARAM + i].getValue())) | |||||
modes[i] = !modes[i]; | modes[i] = !modes[i]; | ||||
if (inputs[IN1_INPUT + i].active) | |||||
gate = inputs[IN1_INPUT + i].value; | |||||
if (inputs[IN1_INPUT + i].isConnected()) | |||||
gate = inputs[IN1_INPUT + i].getVoltage(); | |||||
if (gateTriggers[i].process(gate)) { | if (gateTriggers[i].process(gate)) { | ||||
// trigger | // trigger | ||||
float r = randomUniform(); | |||||
float threshold = clamp(params[THRESHOLD1_PARAM + i].value + inputs[P1_INPUT + i].value / 10.f, 0.f, 1.f); | |||||
float r = random::uniform(); | |||||
float threshold = clamp(params[THRESHOLD1_PARAM + i].getValue() + inputs[P1_INPUT + i].getVoltage() / 10.f, 0.f, 1.f); | |||||
bool toss = (r < threshold); | bool toss = (r < threshold); | ||||
if (!modes[i]) { | if (!modes[i]) { | ||||
// direct modes | // direct modes | ||||
@@ -100,36 +106,37 @@ void Branches::step() { | |||||
lights[STATE1_NEG_LIGHT + 2*i].value = 1.0; | lights[STATE1_NEG_LIGHT + 2*i].value = 1.0; | ||||
} | } | ||||
lights[STATE1_POS_LIGHT + 2*i].value *= 1.0 - engineGetSampleTime() * 15.0; | |||||
lights[STATE1_NEG_LIGHT + 2*i].value *= 1.0 - engineGetSampleTime() * 15.0; | |||||
lights[STATE1_POS_LIGHT + 2*i].value *= 1.0 - args.sampleTime * 15.0; | |||||
lights[STATE1_NEG_LIGHT + 2*i].value *= 1.0 - args.sampleTime * 15.0; | |||||
lights[MODE1_LIGHT + i].value = modes[i] ? 1.0 : 0.0; | lights[MODE1_LIGHT + i].value = modes[i] ? 1.0 : 0.0; | ||||
outputs[OUT1A_OUTPUT + i].value = outcomes[i] ? 0.0 : gate; | |||||
outputs[OUT1B_OUTPUT + i].value = outcomes[i] ? gate : 0.0; | |||||
outputs[OUT1A_OUTPUT + i].setVoltage(outcomes[i] ? 0.0 : gate); | |||||
outputs[OUT1B_OUTPUT + i].setVoltage(outcomes[i] ? gate : 0.0); | |||||
} | } | ||||
} | } | ||||
struct BranchesWidget : ModuleWidget { | struct BranchesWidget : ModuleWidget { | ||||
BranchesWidget(Branches *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Branches.svg"))); | |||||
BranchesWidget(Branches *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Branches.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 0))); | addChild(createWidget<ScrewSilver>(Vec(15, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addParam(createParam<Rogan1PSRed>(Vec(24, 64), module, Branches::THRESHOLD1_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<TL1105>(Vec(69, 58), module, Branches::MODE1_PARAM, 0.0, 1.0, 0.0)); | |||||
addInput(createPort<PJ301MPort>(Vec(9, 122), PortWidget::INPUT, module, Branches::IN1_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(55, 122), PortWidget::INPUT, module, Branches::P1_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(9, 160), PortWidget::OUTPUT, module, Branches::OUT1A_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(55, 160), PortWidget::OUTPUT, module, Branches::OUT1B_OUTPUT)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(24, 220), module, Branches::THRESHOLD2_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<TL1105>(Vec(69, 214), module, Branches::MODE2_PARAM, 0.0, 1.0, 0.0)); | |||||
addInput(createPort<PJ301MPort>(Vec(9, 278), PortWidget::INPUT, module, Branches::IN2_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(55, 278), PortWidget::INPUT, module, Branches::P2_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(9, 316), PortWidget::OUTPUT, module, Branches::OUT2A_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(55, 316), PortWidget::OUTPUT, module, Branches::OUT2B_OUTPUT)); | |||||
addParam(createParam<Rogan1PSRed>(Vec(24, 64), module, Branches::THRESHOLD1_PARAM)); | |||||
addParam(createParam<TL1105>(Vec(69, 58), module, Branches::MODE1_PARAM)); | |||||
addInput(createInput<PJ301MPort>(Vec(9, 122), module, Branches::IN1_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(55, 122), module, Branches::P1_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(9, 160), module, Branches::OUT1A_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(55, 160), module, Branches::OUT1B_OUTPUT)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(24, 220), module, Branches::THRESHOLD2_PARAM)); | |||||
addParam(createParam<TL1105>(Vec(69, 214), module, Branches::MODE2_PARAM)); | |||||
addInput(createInput<PJ301MPort>(Vec(9, 278), module, Branches::IN2_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(55, 278), module, Branches::P2_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(9, 316), module, Branches::OUT2A_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(55, 316), module, Branches::OUT2B_OUTPUT)); | |||||
addChild(createLight<SmallLight<GreenRedLight>>(Vec(40, 169), module, Branches::STATE1_POS_LIGHT)); | addChild(createLight<SmallLight<GreenRedLight>>(Vec(40, 169), module, Branches::STATE1_POS_LIGHT)); | ||||
addChild(createLight<SmallLight<GreenRedLight>>(Vec(40, 325), module, Branches::STATE2_POS_LIGHT)); | addChild(createLight<SmallLight<GreenRedLight>>(Vec(40, 325), module, Branches::STATE2_POS_LIGHT)); | ||||
@@ -46,10 +46,10 @@ struct Clouds : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
SampleRateConverter<2> inputSrc; | |||||
SampleRateConverter<2> outputSrc; | |||||
DoubleRingBuffer<Frame<2>, 256> inputBuffer; | |||||
DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||||
dsp::SampleRateConverter<2> inputSrc; | |||||
dsp::SampleRateConverter<2> outputSrc; | |||||
dsp::DoubleRingBuffer<dsp::Frame<2>, 256> inputBuffer; | |||||
dsp::DoubleRingBuffer<dsp::Frame<2>, 256> outputBuffer; | |||||
uint8_t *block_mem; | uint8_t *block_mem; | ||||
uint8_t *block_ccm; | uint8_t *block_ccm; | ||||
@@ -57,9 +57,9 @@ struct Clouds : Module { | |||||
bool triggered = false; | bool triggered = false; | ||||
SchmittTrigger freezeTrigger; | |||||
dsp::SchmittTrigger freezeTrigger; | |||||
bool freeze = false; | bool freeze = false; | ||||
SchmittTrigger blendTrigger; | |||||
dsp::SchmittTrigger blendTrigger; | |||||
int blendMode = 0; | int blendMode = 0; | ||||
clouds::PlaybackMode playback; | clouds::PlaybackMode playback; | ||||
@@ -67,7 +67,7 @@ struct Clouds : Module { | |||||
Clouds(); | Clouds(); | ||||
~Clouds(); | ~Clouds(); | ||||
void step() override; | |||||
void process(const ProcessArgs &args) override; | |||||
void onReset() override { | void onReset() override { | ||||
freeze = false; | freeze = false; | ||||
@@ -105,7 +105,22 @@ struct Clouds : Module { | |||||
}; | }; | ||||
Clouds::Clouds() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
Clouds::Clouds() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Clouds::POSITION_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Clouds::SIZE_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Clouds::PITCH_PARAM, -2.0, 2.0, 0.0); | |||||
configParam(Clouds::IN_GAIN_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Clouds::DENSITY_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Clouds::TEXTURE_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Clouds::BLEND_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Clouds::SPREAD_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Clouds::FEEDBACK_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Clouds::REVERB_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Clouds::FREEZE_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Clouds::MODE_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Clouds::LOAD_PARAM, 0.0, 1.0, 0.0); | |||||
const int memLen = 118784; | const int memLen = 118784; | ||||
const int ccmLen = 65536 - 128; | const int ccmLen = 65536 - 128; | ||||
block_mem = new uint8_t[memLen](); | block_mem = new uint8_t[memLen](); | ||||
@@ -123,24 +138,24 @@ Clouds::~Clouds() { | |||||
delete[] block_ccm; | delete[] block_ccm; | ||||
} | } | ||||
void Clouds::step() { | |||||
void Clouds::process(const ProcessArgs &args) { | |||||
// Get input | // Get input | ||||
Frame<2> inputFrame = {}; | |||||
dsp::Frame<2> inputFrame = {}; | |||||
if (!inputBuffer.full()) { | if (!inputBuffer.full()) { | ||||
inputFrame.samples[0] = inputs[IN_L_INPUT].value * params[IN_GAIN_PARAM].value / 5.0; | |||||
inputFrame.samples[1] = inputs[IN_R_INPUT].active ? inputs[IN_R_INPUT].value * params[IN_GAIN_PARAM].value / 5.0 : inputFrame.samples[0]; | |||||
inputFrame.samples[0] = inputs[IN_L_INPUT].getVoltage() * params[IN_GAIN_PARAM].getValue() / 5.0; | |||||
inputFrame.samples[1] = inputs[IN_R_INPUT].isConnected() ? inputs[IN_R_INPUT].getVoltage() * params[IN_GAIN_PARAM].getValue() / 5.0 : inputFrame.samples[0]; | |||||
inputBuffer.push(inputFrame); | inputBuffer.push(inputFrame); | ||||
} | } | ||||
if (freezeTrigger.process(params[FREEZE_PARAM].value)) { | |||||
if (freezeTrigger.process(params[FREEZE_PARAM].getValue())) { | |||||
freeze ^= true; | freeze ^= true; | ||||
} | } | ||||
if (blendTrigger.process(params[MODE_PARAM].value)) { | |||||
if (blendTrigger.process(params[MODE_PARAM].getValue())) { | |||||
blendMode = (blendMode + 1) % 4; | blendMode = (blendMode + 1) % 4; | ||||
} | } | ||||
// Trigger | // Trigger | ||||
if (inputs[TRIG_INPUT].value >= 1.0) { | |||||
if (inputs[TRIG_INPUT].getVoltage() >= 1.0) { | |||||
triggered = true; | triggered = true; | ||||
} | } | ||||
@@ -149,8 +164,8 @@ void Clouds::step() { | |||||
clouds::ShortFrame input[32] = {}; | clouds::ShortFrame input[32] = {}; | ||||
// Convert input buffer | // Convert input buffer | ||||
{ | { | ||||
inputSrc.setRates(engineGetSampleRate(), 32000); | |||||
Frame<2> inputFrames[32]; | |||||
inputSrc.setRates(args.sampleRate, 32000); | |||||
dsp::Frame<2> inputFrames[32]; | |||||
int inLen = inputBuffer.size(); | int inLen = inputBuffer.size(); | ||||
int outLen = 32; | int outLen = 32; | ||||
inputSrc.process(inputBuffer.startData(), &inLen, inputFrames, &outLen); | inputSrc.process(inputBuffer.startData(), &inLen, inputFrames, &outLen); | ||||
@@ -171,19 +186,19 @@ void Clouds::step() { | |||||
clouds::Parameters *p = processor->mutable_parameters(); | clouds::Parameters *p = processor->mutable_parameters(); | ||||
p->trigger = triggered; | p->trigger = triggered; | ||||
p->gate = triggered; | p->gate = triggered; | ||||
p->freeze = freeze || (inputs[FREEZE_INPUT].value >= 1.0); | |||||
p->position = clamp(params[POSITION_PARAM].value + inputs[POSITION_INPUT].value / 5.0f, 0.0f, 1.0f); | |||||
p->size = clamp(params[SIZE_PARAM].value + inputs[SIZE_INPUT].value / 5.0f, 0.0f, 1.0f); | |||||
p->pitch = clamp((params[PITCH_PARAM].value + inputs[PITCH_INPUT].value) * 12.0f, -48.0f, 48.0f); | |||||
p->density = clamp(params[DENSITY_PARAM].value + inputs[DENSITY_INPUT].value / 5.0f, 0.0f, 1.0f); | |||||
p->texture = clamp(params[TEXTURE_PARAM].value + inputs[TEXTURE_INPUT].value / 5.0f, 0.0f, 1.0f); | |||||
p->dry_wet = params[BLEND_PARAM].value; | |||||
p->stereo_spread = params[SPREAD_PARAM].value; | |||||
p->feedback = params[FEEDBACK_PARAM].value; | |||||
p->freeze = freeze || (inputs[FREEZE_INPUT].getVoltage() >= 1.0); | |||||
p->position = clamp(params[POSITION_PARAM].getValue() + inputs[POSITION_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||||
p->size = clamp(params[SIZE_PARAM].getValue() + inputs[SIZE_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||||
p->pitch = clamp((params[PITCH_PARAM].getValue() + inputs[PITCH_INPUT].getVoltage()) * 12.0f, -48.0f, 48.0f); | |||||
p->density = clamp(params[DENSITY_PARAM].getValue() + inputs[DENSITY_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||||
p->texture = clamp(params[TEXTURE_PARAM].getValue() + inputs[TEXTURE_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||||
p->dry_wet = params[BLEND_PARAM].getValue(); | |||||
p->stereo_spread = params[SPREAD_PARAM].getValue(); | |||||
p->feedback = params[FEEDBACK_PARAM].getValue(); | |||||
// TODO | // TODO | ||||
// Why doesn't dry audio get reverbed? | // Why doesn't dry audio get reverbed? | ||||
p->reverb = params[REVERB_PARAM].value; | |||||
float blend = inputs[BLEND_INPUT].value / 5.0f; | |||||
p->reverb = params[REVERB_PARAM].getValue(); | |||||
float blend = inputs[BLEND_INPUT].getVoltage() / 5.0f; | |||||
switch (blendMode) { | switch (blendMode) { | ||||
case 0: | case 0: | ||||
p->dry_wet += blend; | p->dry_wet += blend; | ||||
@@ -208,13 +223,13 @@ void Clouds::step() { | |||||
// Convert output buffer | // Convert output buffer | ||||
{ | { | ||||
Frame<2> outputFrames[32]; | |||||
dsp::Frame<2> outputFrames[32]; | |||||
for (int i = 0; i < 32; i++) { | for (int i = 0; i < 32; i++) { | ||||
outputFrames[i].samples[0] = output[i].l / 32768.0; | outputFrames[i].samples[0] = output[i].l / 32768.0; | ||||
outputFrames[i].samples[1] = output[i].r / 32768.0; | outputFrames[i].samples[1] = output[i].r / 32768.0; | ||||
} | } | ||||
outputSrc.setRates(32000, engineGetSampleRate()); | |||||
outputSrc.setRates(32000, args.sampleRate); | |||||
int inLen = 32; | int inLen = 32; | ||||
int outLen = outputBuffer.capacity(); | int outLen = outputBuffer.capacity(); | ||||
outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen); | outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen); | ||||
@@ -225,28 +240,28 @@ void Clouds::step() { | |||||
} | } | ||||
// Set output | // Set output | ||||
Frame<2> outputFrame = {}; | |||||
dsp::Frame<2> outputFrame = {}; | |||||
if (!outputBuffer.empty()) { | if (!outputBuffer.empty()) { | ||||
outputFrame = outputBuffer.shift(); | outputFrame = outputBuffer.shift(); | ||||
outputs[OUT_L_OUTPUT].value = 5.0 * outputFrame.samples[0]; | |||||
outputs[OUT_R_OUTPUT].value = 5.0 * outputFrame.samples[1]; | |||||
outputs[OUT_L_OUTPUT].setVoltage(5.0 * outputFrame.samples[0]); | |||||
outputs[OUT_R_OUTPUT].setVoltage(5.0 * outputFrame.samples[1]); | |||||
} | } | ||||
// Lights | // Lights | ||||
clouds::Parameters *p = processor->mutable_parameters(); | clouds::Parameters *p = processor->mutable_parameters(); | ||||
VUMeter vuMeter; | |||||
dsp::VuMeter vuMeter; | |||||
vuMeter.dBInterval = 6.0; | vuMeter.dBInterval = 6.0; | ||||
Frame<2> lightFrame = p->freeze ? outputFrame : inputFrame; | |||||
dsp::Frame<2> lightFrame = p->freeze ? outputFrame : inputFrame; | |||||
vuMeter.setValue(fmaxf(fabsf(lightFrame.samples[0]), fabsf(lightFrame.samples[1]))); | vuMeter.setValue(fmaxf(fabsf(lightFrame.samples[0]), fabsf(lightFrame.samples[1]))); | ||||
lights[FREEZE_LIGHT].setBrightness(p->freeze ? 0.75 : 0.0); | lights[FREEZE_LIGHT].setBrightness(p->freeze ? 0.75 : 0.0); | ||||
lights[MIX_GREEN_LIGHT].setBrightnessSmooth(vuMeter.getBrightness(3)); | |||||
lights[PAN_GREEN_LIGHT].setBrightnessSmooth(vuMeter.getBrightness(2)); | |||||
lights[FEEDBACK_GREEN_LIGHT].setBrightnessSmooth(vuMeter.getBrightness(1)); | |||||
lights[MIX_GREEN_LIGHT].setSmoothBrightness(vuMeter.getBrightness(3), args.sampleTime); | |||||
lights[PAN_GREEN_LIGHT].setSmoothBrightness(vuMeter.getBrightness(2), args.sampleTime); | |||||
lights[FEEDBACK_GREEN_LIGHT].setSmoothBrightness(vuMeter.getBrightness(1), args.sampleTime); | |||||
lights[REVERB_GREEN_LIGHT].setBrightness(0.0); | lights[REVERB_GREEN_LIGHT].setBrightness(0.0); | ||||
lights[MIX_RED_LIGHT].setBrightness(0.0); | lights[MIX_RED_LIGHT].setBrightness(0.0); | ||||
lights[PAN_RED_LIGHT].setBrightness(0.0); | lights[PAN_RED_LIGHT].setBrightness(0.0); | ||||
lights[FEEDBACK_RED_LIGHT].setBrightnessSmooth(vuMeter.getBrightness(1)); | |||||
lights[REVERB_RED_LIGHT].setBrightnessSmooth(vuMeter.getBrightness(0)); | |||||
lights[FEEDBACK_RED_LIGHT].setSmoothBrightness(vuMeter.getBrightness(1), args.sampleTime); | |||||
lights[REVERB_RED_LIGHT].setSmoothBrightness(vuMeter.getBrightness(0), args.sampleTime); | |||||
} | } | ||||
@@ -254,7 +269,7 @@ void Clouds::step() { | |||||
struct FreezeLight : YellowLight { | struct FreezeLight : YellowLight { | ||||
FreezeLight() { | FreezeLight() { | ||||
box.size = Vec(28-6, 28-6); | box.size = Vec(28-6, 28-6); | ||||
bgColor = COLOR_BLACK_TRANSPARENT; | |||||
bgColor = color::BLACK_TRANSPARENT; | |||||
} | } | ||||
}; | }; | ||||
@@ -304,47 +319,48 @@ struct CloudsWidget : ModuleWidget { | |||||
ParamWidget *feedbackParam; | ParamWidget *feedbackParam; | ||||
ParamWidget *reverbParam; | ParamWidget *reverbParam; | ||||
CloudsWidget(Clouds *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Clouds.svg"))); | |||||
CloudsWidget(Clouds *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Clouds.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 0))); | addChild(createWidget<ScrewSilver>(Vec(15, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(240, 0))); | addChild(createWidget<ScrewSilver>(Vec(240, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addChild(createWidget<ScrewSilver>(Vec(240, 365))); | addChild(createWidget<ScrewSilver>(Vec(240, 365))); | ||||
addParam(createParam<Rogan3PSRed>(Vec(27, 93), module, Clouds::POSITION_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan3PSGreen>(Vec(108, 93), module, Clouds::SIZE_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan3PSWhite>(Vec(190, 93), module, Clouds::PITCH_PARAM, -2.0, 2.0, 0.0)); | |||||
addParam(createParam<Rogan3PSRed>(Vec(27, 93), module, Clouds::POSITION_PARAM)); | |||||
addParam(createParam<Rogan3PSGreen>(Vec(108, 93), module, Clouds::SIZE_PARAM)); | |||||
addParam(createParam<Rogan3PSWhite>(Vec(190, 93), module, Clouds::PITCH_PARAM)); | |||||
addParam(createParam<Rogan1PSRed>(Vec(14, 180), module, Clouds::IN_GAIN_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSRed>(Vec(81, 180), module, Clouds::DENSITY_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(146, 180), module, Clouds::TEXTURE_PARAM, 0.0, 1.0, 0.5)); | |||||
blendParam = createParam<Rogan1PSWhite>(Vec(213, 180), module, Clouds::BLEND_PARAM, 0.0, 1.0, 0.5); | |||||
addParam(createParam<Rogan1PSRed>(Vec(14, 180), module, Clouds::IN_GAIN_PARAM)); | |||||
addParam(createParam<Rogan1PSRed>(Vec(81, 180), module, Clouds::DENSITY_PARAM)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(146, 180), module, Clouds::TEXTURE_PARAM)); | |||||
blendParam = createParam<Rogan1PSWhite>(Vec(213, 180), module, Clouds::BLEND_PARAM); | |||||
addParam(blendParam); | addParam(blendParam); | ||||
spreadParam = createParam<Rogan1PSRed>(Vec(213, 180), module, Clouds::SPREAD_PARAM, 0.0, 1.0, 0.0); | |||||
spreadParam = createParam<Rogan1PSRed>(Vec(213, 180), module, Clouds::SPREAD_PARAM); | |||||
addParam(spreadParam); | addParam(spreadParam); | ||||
feedbackParam = createParam<Rogan1PSGreen>(Vec(213, 180), module, Clouds::FEEDBACK_PARAM, 0.0, 1.0, 0.0); | |||||
feedbackParam = createParam<Rogan1PSGreen>(Vec(213, 180), module, Clouds::FEEDBACK_PARAM); | |||||
addParam(feedbackParam); | addParam(feedbackParam); | ||||
reverbParam = createParam<Rogan1PSBlue>(Vec(213, 180), module, Clouds::REVERB_PARAM, 0.0, 1.0, 0.0); | |||||
reverbParam = createParam<Rogan1PSBlue>(Vec(213, 180), module, Clouds::REVERB_PARAM); | |||||
addParam(reverbParam); | addParam(reverbParam); | ||||
addParam(createParam<CKD6>(Vec(12, 43), module, Clouds::FREEZE_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<TL1105>(Vec(211, 50), module, Clouds::MODE_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<TL1105>(Vec(239, 50), module, Clouds::LOAD_PARAM, 0.0, 1.0, 0.0)); | |||||
addInput(createPort<PJ301MPort>(Vec(15, 274), PortWidget::INPUT, module, Clouds::FREEZE_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(58, 274), PortWidget::INPUT, module, Clouds::TRIG_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(101, 274), PortWidget::INPUT, module, Clouds::POSITION_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(144, 274), PortWidget::INPUT, module, Clouds::SIZE_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(188, 274), PortWidget::INPUT, module, Clouds::PITCH_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(230, 274), PortWidget::INPUT, module, Clouds::BLEND_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(15, 317), PortWidget::INPUT, module, Clouds::IN_L_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(58, 317), PortWidget::INPUT, module, Clouds::IN_R_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(101, 317), PortWidget::INPUT, module, Clouds::DENSITY_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(144, 317), PortWidget::INPUT, module, Clouds::TEXTURE_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(188, 317), PortWidget::OUTPUT, module, Clouds::OUT_L_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(230, 317), PortWidget::OUTPUT, module, Clouds::OUT_R_OUTPUT)); | |||||
addParam(createParam<CKD6>(Vec(12, 43), module, Clouds::FREEZE_PARAM)); | |||||
addParam(createParam<TL1105>(Vec(211, 50), module, Clouds::MODE_PARAM)); | |||||
addParam(createParam<TL1105>(Vec(239, 50), module, Clouds::LOAD_PARAM)); | |||||
addInput(createInput<PJ301MPort>(Vec(15, 274), module, Clouds::FREEZE_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(58, 274), module, Clouds::TRIG_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(101, 274), module, Clouds::POSITION_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(144, 274), module, Clouds::SIZE_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(188, 274), module, Clouds::PITCH_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(230, 274), module, Clouds::BLEND_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(15, 317), module, Clouds::IN_L_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(58, 317), module, Clouds::IN_R_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(101, 317), module, Clouds::DENSITY_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(144, 317), module, Clouds::TEXTURE_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(188, 317), module, Clouds::OUT_L_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(230, 317), module, Clouds::OUT_R_OUTPUT)); | |||||
addChild(createLight<FreezeLight>(Vec(12+3, 43+3), module, Clouds::FREEZE_LIGHT)); | addChild(createLight<FreezeLight>(Vec(12+3, 43+3), module, Clouds::FREEZE_LIGHT)); | ||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(82.5, 53), module, Clouds::MIX_GREEN_LIGHT)); | addChild(createLight<MediumLight<GreenRedLight>>(Vec(82.5, 53), module, Clouds::MIX_GREEN_LIGHT)); | ||||
@@ -70,17 +70,17 @@ struct Elements : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
SampleRateConverter<2> inputSrc; | |||||
SampleRateConverter<2> outputSrc; | |||||
DoubleRingBuffer<Frame<2>, 256> inputBuffer; | |||||
DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||||
dsp::SampleRateConverter<2> inputSrc; | |||||
dsp::SampleRateConverter<2> outputSrc; | |||||
dsp::DoubleRingBuffer<dsp::Frame<2>, 256> inputBuffer; | |||||
dsp::DoubleRingBuffer<dsp::Frame<2>, 256> outputBuffer; | |||||
uint16_t reverb_buffer[32768] = {}; | uint16_t reverb_buffer[32768] = {}; | ||||
elements::Part *part; | elements::Part *part; | ||||
Elements(); | Elements(); | ||||
~Elements(); | ~Elements(); | ||||
void step() override; | |||||
void process(const ProcessArgs &args) override; | |||||
json_t *dataToJson() override { | json_t *dataToJson() override { | ||||
json_t *rootJ = json_object(); | json_t *rootJ = json_object(); | ||||
@@ -105,7 +105,37 @@ struct Elements : Module { | |||||
}; | }; | ||||
Elements::Elements() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
Elements::Elements() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Elements::CONTOUR_PARAM, 0.0, 1.0, 1.0); | |||||
configParam(Elements::BOW_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Elements::BLOW_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Elements::STRIKE_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Elements::COARSE_PARAM, -30.0, 30.0, 0.0); | |||||
configParam(Elements::FINE_PARAM, -2.0, 2.0, 0.0); | |||||
configParam(Elements::FM_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Elements::FLOW_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Elements::MALLET_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Elements::GEOMETRY_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Elements::BRIGHTNESS_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Elements::BOW_TIMBRE_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Elements::BLOW_TIMBRE_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Elements::STRIKE_TIMBRE_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Elements::DAMPING_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Elements::POSITION_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Elements::SPACE_PARAM, 0.0, 2.0, 0.0); | |||||
configParam(Elements::BOW_TIMBRE_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Elements::FLOW_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Elements::BLOW_TIMBRE_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Elements::MALLET_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Elements::STRIKE_TIMBRE_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Elements::DAMPING_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Elements::GEOMETRY_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Elements::POSITION_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Elements::BRIGHTNESS_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Elements::SPACE_MOD_PARAM, -2.0, 2.0, 0.0); | |||||
configParam(Elements::PLAY_PARAM, 0.0, 1.0, 0.0); | |||||
part = new elements::Part(); | part = new elements::Part(); | ||||
// In the Mutable Instruments code, Part doesn't initialize itself, so zero it here. | // In the Mutable Instruments code, Part doesn't initialize itself, so zero it here. | ||||
memset(part, 0, sizeof(*part)); | memset(part, 0, sizeof(*part)); | ||||
@@ -119,12 +149,12 @@ Elements::~Elements() { | |||||
delete part; | delete part; | ||||
} | } | ||||
void Elements::step() { | |||||
void Elements::process(const ProcessArgs &args) { | |||||
// Get input | // Get input | ||||
if (!inputBuffer.full()) { | if (!inputBuffer.full()) { | ||||
Frame<2> inputFrame; | |||||
inputFrame.samples[0] = inputs[BLOW_INPUT].value / 5.0; | |||||
inputFrame.samples[1] = inputs[STRIKE_INPUT].value / 5.0; | |||||
dsp::Frame<2> inputFrame; | |||||
inputFrame.samples[0] = inputs[BLOW_INPUT].getVoltage() / 5.0; | |||||
inputFrame.samples[1] = inputs[STRIKE_INPUT].getVoltage() / 5.0; | |||||
inputBuffer.push(inputFrame); | inputBuffer.push(inputFrame); | ||||
} | } | ||||
@@ -137,8 +167,8 @@ void Elements::step() { | |||||
// Convert input buffer | // Convert input buffer | ||||
{ | { | ||||
inputSrc.setRates(engineGetSampleRate(), 32000); | |||||
Frame<2> inputFrames[16]; | |||||
inputSrc.setRates(args.sampleRate, 32000); | |||||
dsp::Frame<2> inputFrames[16]; | |||||
int inLen = inputBuffer.size(); | int inLen = inputBuffer.size(); | ||||
int outLen = 16; | int outLen = 16; | ||||
inputSrc.process(inputBuffer.startData(), &inLen, inputFrames, &outLen); | inputSrc.process(inputBuffer.startData(), &inLen, inputFrames, &outLen); | ||||
@@ -152,12 +182,12 @@ void Elements::step() { | |||||
// Set patch from parameters | // Set patch from parameters | ||||
elements::Patch* p = part->mutable_patch(); | elements::Patch* p = part->mutable_patch(); | ||||
p->exciter_envelope_shape = params[CONTOUR_PARAM].value; | |||||
p->exciter_bow_level = params[BOW_PARAM].value; | |||||
p->exciter_blow_level = params[BLOW_PARAM].value; | |||||
p->exciter_strike_level = params[STRIKE_PARAM].value; | |||||
p->exciter_envelope_shape = params[CONTOUR_PARAM].getValue(); | |||||
p->exciter_bow_level = params[BOW_PARAM].getValue(); | |||||
p->exciter_blow_level = params[BLOW_PARAM].getValue(); | |||||
p->exciter_strike_level = params[STRIKE_PARAM].getValue(); | |||||
#define BIND(_p, _m, _i) clamp(params[_p].value + 3.3f*quadraticBipolar(params[_m].value)*inputs[_i].value/5.0f, 0.0f, 0.9995f) | |||||
#define BIND(_p, _m, _i) clamp(params[_p].getValue() + 3.3f*dsp::quadraticBipolar(params[_m].getValue())*inputs[_i].getVoltage()/5.0f, 0.0f, 0.9995f) | |||||
p->exciter_bow_timbre = BIND(BOW_TIMBRE_PARAM, BOW_TIMBRE_MOD_PARAM, BOW_TIMBRE_MOD_INPUT); | p->exciter_bow_timbre = BIND(BOW_TIMBRE_PARAM, BOW_TIMBRE_MOD_PARAM, BOW_TIMBRE_MOD_INPUT); | ||||
p->exciter_blow_meta = BIND(FLOW_PARAM, FLOW_MOD_PARAM, FLOW_MOD_INPUT); | p->exciter_blow_meta = BIND(FLOW_PARAM, FLOW_MOD_PARAM, FLOW_MOD_INPUT); | ||||
@@ -168,27 +198,27 @@ void Elements::step() { | |||||
p->resonator_brightness = BIND(BRIGHTNESS_PARAM, BRIGHTNESS_MOD_PARAM, BRIGHTNESS_MOD_INPUT); | p->resonator_brightness = BIND(BRIGHTNESS_PARAM, BRIGHTNESS_MOD_PARAM, BRIGHTNESS_MOD_INPUT); | ||||
p->resonator_damping = BIND(DAMPING_PARAM, DAMPING_MOD_PARAM, DAMPING_MOD_INPUT); | p->resonator_damping = BIND(DAMPING_PARAM, DAMPING_MOD_PARAM, DAMPING_MOD_INPUT); | ||||
p->resonator_position = BIND(POSITION_PARAM, POSITION_MOD_PARAM, POSITION_MOD_INPUT); | p->resonator_position = BIND(POSITION_PARAM, POSITION_MOD_PARAM, POSITION_MOD_INPUT); | ||||
p->space = clamp(params[SPACE_PARAM].value + params[SPACE_MOD_PARAM].value*inputs[SPACE_MOD_INPUT].value/5.0f, 0.0f, 2.0f); | |||||
p->space = clamp(params[SPACE_PARAM].getValue() + params[SPACE_MOD_PARAM].getValue()*inputs[SPACE_MOD_INPUT].getVoltage()/5.0f, 0.0f, 2.0f); | |||||
// Get performance inputs | // Get performance inputs | ||||
elements::PerformanceState performance; | elements::PerformanceState performance; | ||||
performance.note = 12.0*inputs[NOTE_INPUT].value + roundf(params[COARSE_PARAM].value) + params[FINE_PARAM].value + 69.0; | |||||
performance.modulation = 3.3*quarticBipolar(params[FM_PARAM].value) * 49.5 * inputs[FM_INPUT].value/5.0; | |||||
performance.gate = params[PLAY_PARAM].value >= 1.0 || inputs[GATE_INPUT].value >= 1.0; | |||||
performance.strength = clamp(1.0 - inputs[STRENGTH_INPUT].value/5.0f, 0.0f, 1.0f); | |||||
performance.note = 12.0*inputs[NOTE_INPUT].getVoltage() + roundf(params[COARSE_PARAM].getValue()) + params[FINE_PARAM].getValue() + 69.0; | |||||
performance.modulation = 3.3*dsp::quarticBipolar(params[FM_PARAM].getValue()) * 49.5 * inputs[FM_INPUT].getVoltage()/5.0; | |||||
performance.gate = params[PLAY_PARAM].getValue() >= 1.0 || inputs[GATE_INPUT].getVoltage() >= 1.0; | |||||
performance.strength = clamp(1.0 - inputs[STRENGTH_INPUT].getVoltage()/5.0f, 0.0f, 1.0f); | |||||
// Generate audio | // Generate audio | ||||
part->Process(performance, blow, strike, main, aux, 16); | part->Process(performance, blow, strike, main, aux, 16); | ||||
// Convert output buffer | // Convert output buffer | ||||
{ | { | ||||
Frame<2> outputFrames[16]; | |||||
dsp::Frame<2> outputFrames[16]; | |||||
for (int i = 0; i < 16; i++) { | for (int i = 0; i < 16; i++) { | ||||
outputFrames[i].samples[0] = main[i]; | outputFrames[i].samples[0] = main[i]; | ||||
outputFrames[i].samples[1] = aux[i]; | outputFrames[i].samples[1] = aux[i]; | ||||
} | } | ||||
outputSrc.setRates(32000, engineGetSampleRate()); | |||||
outputSrc.setRates(32000, args.sampleRate); | |||||
int inLen = 16; | int inLen = 16; | ||||
int outLen = outputBuffer.capacity(); | int outLen = outputBuffer.capacity(); | ||||
outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen); | outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen); | ||||
@@ -203,9 +233,9 @@ void Elements::step() { | |||||
// Set output | // Set output | ||||
if (!outputBuffer.empty()) { | if (!outputBuffer.empty()) { | ||||
Frame<2> outputFrame = outputBuffer.shift(); | |||||
outputs[AUX_OUTPUT].value = 5.0 * outputFrame.samples[0]; | |||||
outputs[MAIN_OUTPUT].value = 5.0 * outputFrame.samples[1]; | |||||
dsp::Frame<2> outputFrame = outputBuffer.shift(); | |||||
outputs[AUX_OUTPUT].setVoltage(5.0 * outputFrame.samples[0]); | |||||
outputs[MAIN_OUTPUT].setVoltage(5.0 * outputFrame.samples[1]); | |||||
} | } | ||||
} | } | ||||
@@ -224,74 +254,75 @@ struct ElementsModalItem : MenuItem { | |||||
struct ElementsWidget : ModuleWidget { | struct ElementsWidget : ModuleWidget { | ||||
ElementsWidget(Elements *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Elements.svg"))); | |||||
ElementsWidget(Elements *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Elements.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 0))); | addChild(createWidget<ScrewSilver>(Vec(15, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(480, 0))); | addChild(createWidget<ScrewSilver>(Vec(480, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addChild(createWidget<ScrewSilver>(Vec(480, 365))); | addChild(createWidget<ScrewSilver>(Vec(480, 365))); | ||||
addParam(createParam<Rogan1PSWhite>(Vec(28, 42), module, Elements::CONTOUR_PARAM, 0.0, 1.0, 1.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(99, 42), module, Elements::BOW_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSRed>(Vec(169, 42), module, Elements::BLOW_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(239, 42), module, Elements::STRIKE_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(310, 42), module, Elements::COARSE_PARAM, -30.0, 30.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(381, 42), module, Elements::FINE_PARAM, -2.0, 2.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(451, 42), module, Elements::FM_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan3PSRed>(Vec(115, 116), module, Elements::FLOW_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan3PSGreen>(Vec(212, 116), module, Elements::MALLET_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan3PSWhite>(Vec(326, 116), module, Elements::GEOMETRY_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan3PSWhite>(Vec(423, 116), module, Elements::BRIGHTNESS_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(99, 202), module, Elements::BOW_TIMBRE_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSRed>(Vec(170, 202), module, Elements::BLOW_TIMBRE_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(239, 202), module, Elements::STRIKE_TIMBRE_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(310, 202), module, Elements::DAMPING_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(380, 202), module, Elements::POSITION_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(451, 202), module, Elements::SPACE_PARAM, 0.0, 2.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(104.5, 273), module, Elements::BOW_TIMBRE_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(142.5, 273), module, Elements::FLOW_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(181.5, 273), module, Elements::BLOW_TIMBRE_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(219.5, 273), module, Elements::MALLET_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(257.5, 273), module, Elements::STRIKE_TIMBRE_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(315.5, 273), module, Elements::DAMPING_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(354.5, 273), module, Elements::GEOMETRY_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(392.5, 273), module, Elements::POSITION_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(430.5, 273), module, Elements::BRIGHTNESS_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(469.5, 273), module, Elements::SPACE_MOD_PARAM, -2.0, 2.0, 0.0)); | |||||
addInput(createPort<PJ301MPort>(Vec(20, 178), PortWidget::INPUT, module, Elements::NOTE_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(55, 178), PortWidget::INPUT, module, Elements::FM_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(20, 224), PortWidget::INPUT, module, Elements::GATE_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(55, 224), PortWidget::INPUT, module, Elements::STRENGTH_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(20, 270), PortWidget::INPUT, module, Elements::BLOW_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(55, 270), PortWidget::INPUT, module, Elements::STRIKE_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(20, 316), PortWidget::OUTPUT, module, Elements::AUX_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(55, 316), PortWidget::OUTPUT, module, Elements::MAIN_OUTPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(101, 316), PortWidget::INPUT, module, Elements::BOW_TIMBRE_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(139, 316), PortWidget::INPUT, module, Elements::FLOW_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(178, 316), PortWidget::INPUT, module, Elements::BLOW_TIMBRE_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(216, 316), PortWidget::INPUT, module, Elements::MALLET_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(254, 316), PortWidget::INPUT, module, Elements::STRIKE_TIMBRE_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(312, 316), PortWidget::INPUT, module, Elements::DAMPING_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(350, 316), PortWidget::INPUT, module, Elements::GEOMETRY_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(389, 316), PortWidget::INPUT, module, Elements::POSITION_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(427, 316), PortWidget::INPUT, module, Elements::BRIGHTNESS_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(466, 316), PortWidget::INPUT, module, Elements::SPACE_MOD_INPUT)); | |||||
addParam(createParam<CKD6>(Vec(36, 116), module, Elements::PLAY_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(28, 42), module, Elements::CONTOUR_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(99, 42), module, Elements::BOW_PARAM)); | |||||
addParam(createParam<Rogan1PSRed>(Vec(169, 42), module, Elements::BLOW_PARAM)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(239, 42), module, Elements::STRIKE_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(310, 42), module, Elements::COARSE_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(381, 42), module, Elements::FINE_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(451, 42), module, Elements::FM_PARAM)); | |||||
addParam(createParam<Rogan3PSRed>(Vec(115, 116), module, Elements::FLOW_PARAM)); | |||||
addParam(createParam<Rogan3PSGreen>(Vec(212, 116), module, Elements::MALLET_PARAM)); | |||||
addParam(createParam<Rogan3PSWhite>(Vec(326, 116), module, Elements::GEOMETRY_PARAM)); | |||||
addParam(createParam<Rogan3PSWhite>(Vec(423, 116), module, Elements::BRIGHTNESS_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(99, 202), module, Elements::BOW_TIMBRE_PARAM)); | |||||
addParam(createParam<Rogan1PSRed>(Vec(170, 202), module, Elements::BLOW_TIMBRE_PARAM)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(239, 202), module, Elements::STRIKE_TIMBRE_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(310, 202), module, Elements::DAMPING_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(380, 202), module, Elements::POSITION_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(451, 202), module, Elements::SPACE_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(104.5, 273), module, Elements::BOW_TIMBRE_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(142.5, 273), module, Elements::FLOW_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(181.5, 273), module, Elements::BLOW_TIMBRE_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(219.5, 273), module, Elements::MALLET_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(257.5, 273), module, Elements::STRIKE_TIMBRE_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(315.5, 273), module, Elements::DAMPING_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(354.5, 273), module, Elements::GEOMETRY_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(392.5, 273), module, Elements::POSITION_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(430.5, 273), module, Elements::BRIGHTNESS_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(469.5, 273), module, Elements::SPACE_MOD_PARAM)); | |||||
addInput(createInput<PJ301MPort>(Vec(20, 178), module, Elements::NOTE_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(55, 178), module, Elements::FM_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(20, 224), module, Elements::GATE_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(55, 224), module, Elements::STRENGTH_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(20, 270), module, Elements::BLOW_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(55, 270), module, Elements::STRIKE_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(20, 316), module, Elements::AUX_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(55, 316), module, Elements::MAIN_OUTPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(101, 316), module, Elements::BOW_TIMBRE_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(139, 316), module, Elements::FLOW_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(178, 316), module, Elements::BLOW_TIMBRE_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(216, 316), module, Elements::MALLET_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(254, 316), module, Elements::STRIKE_TIMBRE_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(312, 316), module, Elements::DAMPING_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(350, 316), module, Elements::GEOMETRY_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(389, 316), module, Elements::POSITION_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(427, 316), module, Elements::BRIGHTNESS_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(466, 316), module, Elements::SPACE_MOD_INPUT)); | |||||
addParam(createParam<CKD6>(Vec(36, 116), module, Elements::PLAY_PARAM)); | |||||
struct GateLight : YellowLight { | struct GateLight : YellowLight { | ||||
GateLight() { | GateLight() { | ||||
box.size = Vec(28-6, 28-6); | box.size = Vec(28-6, 28-6); | ||||
bgColor = COLOR_BLACK_TRANSPARENT; | |||||
bgColor = color::BLACK_TRANSPARENT; | |||||
} | } | ||||
}; | }; | ||||
@@ -46,11 +46,11 @@ struct Frames : Module { | |||||
bool poly_lfo_mode = false; | bool poly_lfo_mode = false; | ||||
uint16_t lastControls[4] = {}; | uint16_t lastControls[4] = {}; | ||||
SchmittTrigger addTrigger; | |||||
SchmittTrigger delTrigger; | |||||
dsp::SchmittTrigger addTrigger; | |||||
dsp::SchmittTrigger delTrigger; | |||||
Frames(); | Frames(); | ||||
void step() override; | |||||
void process(const ProcessArgs &args) override; | |||||
json_t *dataToJson() override { | json_t *dataToJson() override { | ||||
json_t *rootJ = json_object(); | json_t *rootJ = json_object(); | ||||
@@ -130,7 +130,18 @@ struct Frames : Module { | |||||
}; | }; | ||||
Frames::Frames() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
Frames::Frames() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Frames::GAIN1_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Frames::GAIN2_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Frames::GAIN3_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Frames::GAIN4_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Frames::FRAME_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Frames::MODULATION_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Frames::ADD_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Frames::DEL_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Frames::OFFSET_PARAM, 0.0, 1.0, 0.0); | |||||
memset(&keyframer, 0, sizeof(keyframer)); | memset(&keyframer, 0, sizeof(keyframer)); | ||||
keyframer.Init(); | keyframer.Init(); | ||||
memset(&poly_lfo, 0, sizeof(poly_lfo)); | memset(&poly_lfo, 0, sizeof(poly_lfo)); | ||||
@@ -140,15 +151,15 @@ Frames::Frames() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
} | } | ||||
void Frames::step() { | |||||
void Frames::process(const ProcessArgs &args) { | |||||
// Set gain and timestamp knobs | // Set gain and timestamp knobs | ||||
uint16_t controls[4]; | uint16_t controls[4]; | ||||
for (int i = 0; i < 4; i++) { | for (int i = 0; i < 4; i++) { | ||||
controls[i] = params[GAIN1_PARAM + i].value * 65535.0; | |||||
controls[i] = params[GAIN1_PARAM + i].getValue() * 65535.0; | |||||
} | } | ||||
int32_t timestamp = params[FRAME_PARAM].value * 65535.0; | |||||
int32_t timestampMod = timestamp + params[MODULATION_PARAM].value * inputs[FRAME_INPUT].value / 10.0 * 65535.0; | |||||
int32_t timestamp = params[FRAME_PARAM].getValue() * 65535.0; | |||||
int32_t timestampMod = timestamp + params[MODULATION_PARAM].getValue() * inputs[FRAME_INPUT].getVoltage() / 10.0 * 65535.0; | |||||
timestamp = clamp(timestamp, 0, 65535); | timestamp = clamp(timestamp, 0, 65535); | ||||
timestampMod = clamp(timestampMod, 0, 65535); | timestampMod = clamp(timestampMod, 0, 65535); | ||||
int16_t nearestIndex = -1; | int16_t nearestIndex = -1; | ||||
@@ -182,12 +193,12 @@ void Frames::step() { | |||||
} | } | ||||
} | } | ||||
if (addTrigger.process(params[ADD_PARAM].value)) { | |||||
if (addTrigger.process(params[ADD_PARAM].getValue())) { | |||||
if (nearestIndex < 0) { | if (nearestIndex < 0) { | ||||
keyframer.AddKeyframe(timestamp, controls); | keyframer.AddKeyframe(timestamp, controls); | ||||
} | } | ||||
} | } | ||||
if (delTrigger.process(params[DEL_PARAM].value)) { | |||||
if (delTrigger.process(params[DEL_PARAM].getValue())) { | |||||
if (nearestIndex >= 0) { | if (nearestIndex >= 0) { | ||||
int32_t nearestTimestamp = keyframer.keyframe(nearestIndex).timestamp; | int32_t nearestTimestamp = keyframer.keyframe(nearestIndex).timestamp; | ||||
keyframer.RemoveKeyframe(nearestTimestamp); | keyframer.RemoveKeyframe(nearestTimestamp); | ||||
@@ -221,29 +232,29 @@ void Frames::step() { | |||||
} | } | ||||
// Get inputs | // Get inputs | ||||
float all = ((int)params[OFFSET_PARAM].value == 1) ? 10.0 : 0.0; | |||||
if (inputs[ALL_INPUT].active) { | |||||
all = inputs[ALL_INPUT].value; | |||||
float all = ((int)params[OFFSET_PARAM].getValue() == 1) ? 10.0 : 0.0; | |||||
if (inputs[ALL_INPUT].isConnected()) { | |||||
all = inputs[ALL_INPUT].getVoltage(); | |||||
} | } | ||||
float ins[4]; | float ins[4]; | ||||
for (int i = 0; i < 4; i++) { | for (int i = 0; i < 4; i++) { | ||||
ins[i] = inputs[IN1_INPUT + i].normalize(all) * gains[i]; | |||||
ins[i] = inputs[IN1_INPUT + i].getNormalVoltage(all) * gains[i]; | |||||
} | } | ||||
// Set outputs | // Set outputs | ||||
float mix = 0.0; | float mix = 0.0; | ||||
for (int i = 0; i < 4; i++) { | for (int i = 0; i < 4; i++) { | ||||
if (outputs[OUT1_OUTPUT + i].active) { | |||||
outputs[OUT1_OUTPUT + i].value = ins[i]; | |||||
if (outputs[OUT1_OUTPUT + i].isConnected()) { | |||||
outputs[OUT1_OUTPUT + i].setVoltage(ins[i]); | |||||
} | } | ||||
else { | else { | ||||
mix += ins[i]; | mix += ins[i]; | ||||
} | } | ||||
} | } | ||||
outputs[MIX_OUTPUT].value = clamp(mix / 2.0, -10.0f, 10.0f); | |||||
outputs[MIX_OUTPUT].setVoltage(clamp(mix / 2.0, -10.0f, 10.0f)); | |||||
// Set lights | // Set lights | ||||
for (int i = 0; i < 4; i++) { | for (int i = 0; i < 4; i++) { | ||||
@@ -275,44 +286,45 @@ void Frames::step() { | |||||
struct CKSSRot : SVGSwitch { | struct CKSSRot : SVGSwitch { | ||||
CKSSRot() { | CKSSRot() { | ||||
addFrame(SVG::load(assetPlugin(pluginInstance, "res/CKSS_rot_0.svg"))); | |||||
addFrame(SVG::load(assetPlugin(pluginInstance, "res/CKSS_rot_1.svg"))); | |||||
addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/CKSS_rot_0.svg"))); | |||||
addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/CKSS_rot_1.svg"))); | |||||
} | } | ||||
}; | }; | ||||
struct FramesWidget : ModuleWidget { | struct FramesWidget : ModuleWidget { | ||||
FramesWidget(Frames *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Frames.svg"))); | |||||
FramesWidget(Frames *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Frames.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 0))); | addChild(createWidget<ScrewSilver>(Vec(15, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(box.size.x-30, 0))); | addChild(createWidget<ScrewSilver>(Vec(box.size.x-30, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addChild(createWidget<ScrewSilver>(Vec(box.size.x-30, 365))); | addChild(createWidget<ScrewSilver>(Vec(box.size.x-30, 365))); | ||||
addParam(createParam<Rogan1PSWhite>(Vec(14, 52), module, Frames::GAIN1_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(81, 52), module, Frames::GAIN2_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(149, 52), module, Frames::GAIN3_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(216, 52), module, Frames::GAIN4_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan6PSWhite>(Vec(89, 115), module, Frames::FRAME_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(208, 141), module, Frames::MODULATION_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<CKD6>(Vec(19, 123), module, Frames::ADD_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<CKD6>(Vec(19, 172), module, Frames::DEL_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<CKSSRot>(Vec(18, 239), module, Frames::OFFSET_PARAM, 0.0, 1.0, 0.0)); | |||||
addInput(createPort<PJ301MPort>(Vec(16, 273), PortWidget::INPUT, module, Frames::ALL_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(59, 273), PortWidget::INPUT, module, Frames::IN1_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(102, 273), PortWidget::INPUT, module, Frames::IN2_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(145, 273), PortWidget::INPUT, module, Frames::IN3_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(188, 273), PortWidget::INPUT, module, Frames::IN4_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(231, 273), PortWidget::INPUT, module, Frames::FRAME_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(16, 315), PortWidget::OUTPUT, module, Frames::MIX_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(59, 315), PortWidget::OUTPUT, module, Frames::OUT1_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(102, 315), PortWidget::OUTPUT, module, Frames::OUT2_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(145, 315), PortWidget::OUTPUT, module, Frames::OUT3_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(188, 315), PortWidget::OUTPUT, module, Frames::OUT4_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(231, 315), PortWidget::OUTPUT, module, Frames::FRAME_STEP_OUTPUT)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(14, 52), module, Frames::GAIN1_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(81, 52), module, Frames::GAIN2_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(149, 52), module, Frames::GAIN3_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(216, 52), module, Frames::GAIN4_PARAM)); | |||||
addParam(createParam<Rogan6PSWhite>(Vec(89, 115), module, Frames::FRAME_PARAM)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(208, 141), module, Frames::MODULATION_PARAM)); | |||||
addParam(createParam<CKD6>(Vec(19, 123), module, Frames::ADD_PARAM)); | |||||
addParam(createParam<CKD6>(Vec(19, 172), module, Frames::DEL_PARAM)); | |||||
addParam(createParam<CKSSRot>(Vec(18, 239), module, Frames::OFFSET_PARAM)); | |||||
addInput(createInput<PJ301MPort>(Vec(16, 273), module, Frames::ALL_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(59, 273), module, Frames::IN1_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(102, 273), module, Frames::IN2_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(145, 273), module, Frames::IN3_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(188, 273), module, Frames::IN4_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(231, 273), module, Frames::FRAME_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(16, 315), module, Frames::MIX_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(59, 315), module, Frames::OUT1_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(102, 315), module, Frames::OUT2_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(145, 315), module, Frames::OUT3_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(188, 315), module, Frames::OUT4_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(231, 315), module, Frames::FRAME_STEP_OUTPUT)); | |||||
addChild(createLight<SmallLight<GreenLight>>(Vec(30, 101), module, Frames::GAIN1_LIGHT + 0)); | addChild(createLight<SmallLight<GreenLight>>(Vec(30, 101), module, Frames::GAIN1_LIGHT + 0)); | ||||
addChild(createLight<SmallLight<GreenLight>>(Vec(97, 101), module, Frames::GAIN1_LIGHT + 1)); | addChild(createLight<SmallLight<GreenLight>>(Vec(97, 101), module, Frames::GAIN1_LIGHT + 1)); | ||||
@@ -328,9 +340,6 @@ struct FramesWidget : ModuleWidget { | |||||
addChild(createLight<FrameLight>(Vec(100, 126), module, Frames::FRAME_LIGHT)); | addChild(createLight<FrameLight>(Vec(100, 126), module, Frames::FRAME_LIGHT)); | ||||
} | } | ||||
void appendContextMenu(Menu *menu) override { | void appendContextMenu(Menu *menu) override { | ||||
Frames *frames = dynamic_cast<Frames*>(module); | Frames *frames = dynamic_cast<Frames*>(module); | ||||
assert(frames); | assert(frames); | ||||
@@ -30,64 +30,66 @@ struct Kinks : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
SchmittTrigger trigger; | |||||
dsp::SchmittTrigger trigger; | |||||
float sample = 0.0; | float sample = 0.0; | ||||
Kinks() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} | |||||
void step() override; | |||||
Kinks() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);} | |||||
void process(const ProcessArgs &args) override; | |||||
}; | }; | ||||
void Kinks::step() { | |||||
void Kinks::process(const ProcessArgs &args) { | |||||
// Gaussian noise generator | // Gaussian noise generator | ||||
float noise = 2.0 * randomNormal(); | |||||
float noise = 2.0 * random::normal(); | |||||
// S&H | // S&H | ||||
if (trigger.process(inputs[TRIG_INPUT].value / 0.7)) { | |||||
sample = inputs[SH_INPUT].normalize(noise); | |||||
if (trigger.process(inputs[TRIG_INPUT].getVoltage() / 0.7)) { | |||||
sample = inputs[SH_INPUT].getNormalVoltage(noise); | |||||
} | } | ||||
// lights | // lights | ||||
lights[SIGN_POS_LIGHT].setBrightnessSmooth(fmaxf(0.0, inputs[SIGN_INPUT].value / 5.0)); | |||||
lights[SIGN_NEG_LIGHT].setBrightnessSmooth(fmaxf(0.0, -inputs[SIGN_INPUT].value / 5.0)); | |||||
float logicSum = inputs[LOGIC_A_INPUT].value + inputs[LOGIC_B_INPUT].value; | |||||
lights[LOGIC_POS_LIGHT].setBrightnessSmooth(fmaxf(0.0, logicSum / 5.0)); | |||||
lights[LOGIC_NEG_LIGHT].setBrightnessSmooth(fmaxf(0.0, -logicSum / 5.0)); | |||||
lights[SIGN_POS_LIGHT].setSmoothBrightness(fmaxf(0.0, inputs[SIGN_INPUT].getVoltage() / 5.0), args.sampleTime); | |||||
lights[SIGN_NEG_LIGHT].setSmoothBrightness(fmaxf(0.0, -inputs[SIGN_INPUT].getVoltage() / 5.0), args.sampleTime); | |||||
float logicSum = inputs[LOGIC_A_INPUT].getVoltage() + inputs[LOGIC_B_INPUT].getVoltage(); | |||||
lights[LOGIC_POS_LIGHT].setSmoothBrightness(fmaxf(0.0, logicSum / 5.0), args.sampleTime); | |||||
lights[LOGIC_NEG_LIGHT].setSmoothBrightness(fmaxf(0.0, -logicSum / 5.0), args.sampleTime); | |||||
lights[SH_POS_LIGHT].setBrightness(fmaxf(0.0, sample / 5.0)); | lights[SH_POS_LIGHT].setBrightness(fmaxf(0.0, sample / 5.0)); | ||||
lights[SH_NEG_LIGHT].setBrightness(fmaxf(0.0, -sample / 5.0)); | lights[SH_NEG_LIGHT].setBrightness(fmaxf(0.0, -sample / 5.0)); | ||||
// outputs | // outputs | ||||
outputs[INVERT_OUTPUT].value = -inputs[SIGN_INPUT].value; | |||||
outputs[HALF_RECTIFY_OUTPUT].value = fmaxf(0.0, inputs[SIGN_INPUT].value); | |||||
outputs[FULL_RECTIFY_OUTPUT].value = fabsf(inputs[SIGN_INPUT].value); | |||||
outputs[MAX_OUTPUT].value = fmaxf(inputs[LOGIC_A_INPUT].value, inputs[LOGIC_B_INPUT].value); | |||||
outputs[MIN_OUTPUT].value = fminf(inputs[LOGIC_A_INPUT].value, inputs[LOGIC_B_INPUT].value); | |||||
outputs[NOISE_OUTPUT].value = noise; | |||||
outputs[SH_OUTPUT].value = sample; | |||||
outputs[INVERT_OUTPUT].setVoltage(-inputs[SIGN_INPUT].getVoltage()); | |||||
outputs[HALF_RECTIFY_OUTPUT].setVoltage(fmaxf(0.0, inputs[SIGN_INPUT].getVoltage())); | |||||
outputs[FULL_RECTIFY_OUTPUT].setVoltage(fabsf(inputs[SIGN_INPUT].getVoltage())); | |||||
outputs[MAX_OUTPUT].setVoltage(fmaxf(inputs[LOGIC_A_INPUT].getVoltage(), inputs[LOGIC_B_INPUT].getVoltage())); | |||||
outputs[MIN_OUTPUT].setVoltage(fminf(inputs[LOGIC_A_INPUT].getVoltage(), inputs[LOGIC_B_INPUT].getVoltage())); | |||||
outputs[NOISE_OUTPUT].setVoltage(noise); | |||||
outputs[SH_OUTPUT].setVoltage(sample); | |||||
} | } | ||||
struct KinksWidget : ModuleWidget { | struct KinksWidget : ModuleWidget { | ||||
KinksWidget(Kinks *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Kinks.svg"))); | |||||
KinksWidget(Kinks *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Kinks.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 0))); | addChild(createWidget<ScrewSilver>(Vec(15, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addInput(createPort<PJ301MPort>(Vec(4, 75), PortWidget::INPUT, module, Kinks::SIGN_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(31, 75), PortWidget::OUTPUT, module, Kinks::INVERT_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(4, 113), PortWidget::OUTPUT, module, Kinks::HALF_RECTIFY_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(31, 113), PortWidget::OUTPUT, module, Kinks::FULL_RECTIFY_OUTPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(4, 75), module, Kinks::SIGN_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(31, 75), module, Kinks::INVERT_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(4, 113), module, Kinks::HALF_RECTIFY_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(31, 113), module, Kinks::FULL_RECTIFY_OUTPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(4, 177), PortWidget::INPUT, module, Kinks::LOGIC_A_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(31, 177), PortWidget::INPUT, module, Kinks::LOGIC_B_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(4, 214), PortWidget::OUTPUT, module, Kinks::MAX_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(31, 214), PortWidget::OUTPUT, module, Kinks::MIN_OUTPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(4, 177), module, Kinks::LOGIC_A_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(31, 177), module, Kinks::LOGIC_B_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(4, 214), module, Kinks::MAX_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(31, 214), module, Kinks::MIN_OUTPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(4, 278), PortWidget::INPUT, module, Kinks::SH_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(31, 278), PortWidget::INPUT, module, Kinks::TRIG_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(4, 316), PortWidget::OUTPUT, module, Kinks::NOISE_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(31, 316), PortWidget::OUTPUT, module, Kinks::SH_OUTPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(4, 278), module, Kinks::SH_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(31, 278), module, Kinks::TRIG_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(4, 316), module, Kinks::NOISE_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(31, 316), module, Kinks::SH_OUTPUT)); | |||||
addChild(createLight<SmallLight<GreenRedLight>>(Vec(11, 59), module, Kinks::SIGN_POS_LIGHT)); | addChild(createLight<SmallLight<GreenRedLight>>(Vec(11, 59), module, Kinks::SIGN_POS_LIGHT)); | ||||
addChild(createLight<SmallLight<GreenRedLight>>(Vec(11, 161), module, Kinks::LOGIC_POS_LIGHT)); | addChild(createLight<SmallLight<GreenRedLight>>(Vec(11, 161), module, Kinks::LOGIC_POS_LIGHT)); | ||||
@@ -30,53 +30,55 @@ struct Links : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
Links() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} | |||||
void step() override; | |||||
Links() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);} | |||||
void process(const ProcessArgs &args) override; | |||||
}; | }; | ||||
void Links::step() { | |||||
float inA = inputs[A1_INPUT].value; | |||||
float inB = inputs[B1_INPUT].value + inputs[B2_INPUT].value; | |||||
float inC = inputs[C1_INPUT].value + inputs[C2_INPUT].value + inputs[C3_INPUT].value; | |||||
outputs[A1_OUTPUT].value = inA; | |||||
outputs[A2_OUTPUT].value = inA; | |||||
outputs[A3_OUTPUT].value = inA; | |||||
outputs[B1_OUTPUT].value = inB; | |||||
outputs[B2_OUTPUT].value = inB; | |||||
outputs[C1_OUTPUT].value = inC; | |||||
lights[A_POS_LIGHT].setBrightnessSmooth(fmaxf(0.0, inA / 5.0)); | |||||
lights[A_NEG_LIGHT].setBrightnessSmooth(fmaxf(0.0, -inA / 5.0)); | |||||
lights[B_POS_LIGHT].setBrightnessSmooth(fmaxf(0.0, inB / 5.0)); | |||||
lights[B_NEG_LIGHT].setBrightnessSmooth(fmaxf(0.0, -inB / 5.0)); | |||||
lights[C_POS_LIGHT].setBrightnessSmooth(fmaxf(0.0, inC / 5.0)); | |||||
lights[C_NEG_LIGHT].setBrightnessSmooth(fmaxf(0.0, -inC / 5.0)); | |||||
void Links::process(const ProcessArgs &args) { | |||||
float inA = inputs[A1_INPUT].getVoltage(); | |||||
float inB = inputs[B1_INPUT].getVoltage() + inputs[B2_INPUT].getVoltage(); | |||||
float inC = inputs[C1_INPUT].getVoltage() + inputs[C2_INPUT].getVoltage() + inputs[C3_INPUT].getVoltage(); | |||||
outputs[A1_OUTPUT].setVoltage(inA); | |||||
outputs[A2_OUTPUT].setVoltage(inA); | |||||
outputs[A3_OUTPUT].setVoltage(inA); | |||||
outputs[B1_OUTPUT].setVoltage(inB); | |||||
outputs[B2_OUTPUT].setVoltage(inB); | |||||
outputs[C1_OUTPUT].setVoltage(inC); | |||||
lights[A_POS_LIGHT].setSmoothBrightness(fmaxf(0.0, inA / 5.0), args.sampleTime); | |||||
lights[A_NEG_LIGHT].setSmoothBrightness(fmaxf(0.0, -inA / 5.0), args.sampleTime); | |||||
lights[B_POS_LIGHT].setSmoothBrightness(fmaxf(0.0, inB / 5.0), args.sampleTime); | |||||
lights[B_NEG_LIGHT].setSmoothBrightness(fmaxf(0.0, -inB / 5.0), args.sampleTime); | |||||
lights[C_POS_LIGHT].setSmoothBrightness(fmaxf(0.0, inC / 5.0), args.sampleTime); | |||||
lights[C_NEG_LIGHT].setSmoothBrightness(fmaxf(0.0, -inC / 5.0), args.sampleTime); | |||||
} | } | ||||
struct LinksWidget : ModuleWidget { | struct LinksWidget : ModuleWidget { | ||||
LinksWidget(Links *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Links.svg"))); | |||||
LinksWidget(Links *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Links.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 0))); | addChild(createWidget<ScrewSilver>(Vec(15, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addInput(createPort<PJ301MPort>(Vec(4, 75), PortWidget::INPUT, module, Links::A1_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(31, 75), PortWidget::OUTPUT, module, Links::A1_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(4, 113), PortWidget::OUTPUT, module, Links::A2_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(31, 113), PortWidget::OUTPUT, module, Links::A3_OUTPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(4, 75), module, Links::A1_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(31, 75), module, Links::A1_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(4, 113), module, Links::A2_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(31, 113), module, Links::A3_OUTPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(4, 177), PortWidget::INPUT, module, Links::B1_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(31, 177), PortWidget::INPUT, module, Links::B2_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(4, 214), PortWidget::OUTPUT, module, Links::B1_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(31, 214), PortWidget::OUTPUT, module, Links::B2_OUTPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(4, 177), module, Links::B1_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(31, 177), module, Links::B2_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(4, 214), module, Links::B1_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(31, 214), module, Links::B2_OUTPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(4, 278), PortWidget::INPUT, module, Links::C1_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(31, 278), PortWidget::INPUT, module, Links::C2_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(4, 316), PortWidget::INPUT, module, Links::C3_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(31, 316), PortWidget::OUTPUT, module, Links::C1_OUTPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(4, 278), module, Links::C1_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(31, 278), module, Links::C2_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(4, 316), module, Links::C3_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(31, 316), module, Links::C1_OUTPUT)); | |||||
addChild(createLight<SmallLight<GreenRedLight>>(Vec(26, 59), module, Links::A_POS_LIGHT)); | addChild(createLight<SmallLight<GreenRedLight>>(Vec(26, 59), module, Links::A_POS_LIGHT)); | ||||
addChild(createLight<SmallLight<GreenRedLight>>(Vec(26, 161), module, Links::B_POS_LIGHT)); | addChild(createLight<SmallLight<GreenRedLight>>(Vec(26, 161), module, Links::B_POS_LIGHT)); | ||||
@@ -193,13 +193,13 @@ struct Marbles : Module { | |||||
marbles::NoteFilter note_filter; | marbles::NoteFilter note_filter; | ||||
// State | // State | ||||
BooleanTrigger tDejaVuTrigger; | |||||
BooleanTrigger xDejaVuTrigger; | |||||
BooleanTrigger tModeTrigger; | |||||
BooleanTrigger xModeTrigger; | |||||
BooleanTrigger tRangeTrigger; | |||||
BooleanTrigger xRangeTrigger; | |||||
BooleanTrigger externalTrigger; | |||||
dsp::BooleanTrigger tDejaVuTrigger; | |||||
dsp::BooleanTrigger xDejaVuTrigger; | |||||
dsp::BooleanTrigger tModeTrigger; | |||||
dsp::BooleanTrigger xModeTrigger; | |||||
dsp::BooleanTrigger tRangeTrigger; | |||||
dsp::BooleanTrigger xRangeTrigger; | |||||
dsp::BooleanTrigger externalTrigger; | |||||
bool t_deja_vu; | bool t_deja_vu; | ||||
bool x_deja_vu; | bool x_deja_vu; | ||||
int t_mode; | int t_mode; | ||||
@@ -223,7 +223,24 @@ struct Marbles : Module { | |||||
float voltages[BLOCK_SIZE * 4] = {}; | float voltages[BLOCK_SIZE * 4] = {}; | ||||
int blockIndex = 0; | int blockIndex = 0; | ||||
Marbles() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
Marbles() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Marbles::T_DEJA_VU_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Marbles::X_DEJA_VU_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Marbles::DEJA_VU_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Marbles::T_RATE_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Marbles::X_SPREAD_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Marbles::T_MODE_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Marbles::X_MODE_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Marbles::DEJA_VU_LENGTH_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Marbles::T_BIAS_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Marbles::X_BIAS_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Marbles::T_RANGE_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Marbles::X_RANGE_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Marbles::EXTERNAL_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Marbles::T_JITTER_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Marbles::X_STEPS_PARAM, 0.0, 1.0, 0.5); | |||||
random_generator.Init(1); | random_generator.Init(1); | ||||
random_stream.Init(&random_generator); | random_stream.Init(&random_generator); | ||||
note_filter.Init(); | note_filter.Init(); | ||||
@@ -245,14 +262,14 @@ struct Marbles : Module { | |||||
} | } | ||||
void onRandomize() override { | void onRandomize() override { | ||||
t_mode = randomu32() % 3; | |||||
x_mode = randomu32() % 3; | |||||
t_range = randomu32() % 3; | |||||
x_range = randomu32() % 3; | |||||
t_mode = random::u32() % 3; | |||||
x_mode = random::u32() % 3; | |||||
t_range = random::u32() % 3; | |||||
x_range = random::u32() % 3; | |||||
} | } | ||||
void onSampleRateChange() override { | void onSampleRateChange() override { | ||||
float sampleRate = engineGetSampleRate(); | |||||
float sampleRate = APP->engine->getSampleRate(); | |||||
t_generator.Init(&random_stream, sampleRate); | t_generator.Init(&random_stream, sampleRate); | ||||
xy_generator.Init(&random_stream, sampleRate); | xy_generator.Init(&random_stream, sampleRate); | ||||
@@ -321,36 +338,36 @@ struct Marbles : Module { | |||||
x_clock_source_internal = json_integer_value(x_clock_source_internalJ); | x_clock_source_internal = json_integer_value(x_clock_source_internalJ); | ||||
} | } | ||||
void step() override { | |||||
void process(const ProcessArgs &args) override { | |||||
// Buttons | // Buttons | ||||
if (tDejaVuTrigger.process(params[T_DEJA_VU_PARAM].value <= 0.f)) { | |||||
if (tDejaVuTrigger.process(params[T_DEJA_VU_PARAM].getValue() <= 0.f)) { | |||||
t_deja_vu = !t_deja_vu; | t_deja_vu = !t_deja_vu; | ||||
} | } | ||||
if (xDejaVuTrigger.process(params[X_DEJA_VU_PARAM].value <= 0.f)) { | |||||
if (xDejaVuTrigger.process(params[X_DEJA_VU_PARAM].getValue() <= 0.f)) { | |||||
x_deja_vu = !x_deja_vu; | x_deja_vu = !x_deja_vu; | ||||
} | } | ||||
if (tModeTrigger.process(params[T_MODE_PARAM].value <= 0.f)) { | |||||
if (tModeTrigger.process(params[T_MODE_PARAM].getValue() <= 0.f)) { | |||||
t_mode = (t_mode + 1) % 3; | t_mode = (t_mode + 1) % 3; | ||||
} | } | ||||
if (xModeTrigger.process(params[X_MODE_PARAM].value <= 0.f)) { | |||||
if (xModeTrigger.process(params[X_MODE_PARAM].getValue() <= 0.f)) { | |||||
x_mode = (x_mode + 1) % 3; | x_mode = (x_mode + 1) % 3; | ||||
} | } | ||||
if (tRangeTrigger.process(params[T_RANGE_PARAM].value <= 0.f)) { | |||||
if (tRangeTrigger.process(params[T_RANGE_PARAM].getValue() <= 0.f)) { | |||||
t_range = (t_range + 1) % 3; | t_range = (t_range + 1) % 3; | ||||
} | } | ||||
if (xRangeTrigger.process(params[X_RANGE_PARAM].value <= 0.f)) { | |||||
if (xRangeTrigger.process(params[X_RANGE_PARAM].getValue() <= 0.f)) { | |||||
x_range = (x_range + 1) % 3; | x_range = (x_range + 1) % 3; | ||||
} | } | ||||
if (externalTrigger.process(params[EXTERNAL_PARAM].value <= 0.f)) { | |||||
if (externalTrigger.process(params[EXTERNAL_PARAM].getValue() <= 0.f)) { | |||||
external = !external; | external = !external; | ||||
} | } | ||||
// Clocks | // Clocks | ||||
bool t_gate = (inputs[T_CLOCK_INPUT].value >= 1.7f); | |||||
bool t_gate = (inputs[T_CLOCK_INPUT].getVoltage() >= 1.7f); | |||||
last_t_clock = stmlib::ExtractGateFlags(last_t_clock, t_gate); | last_t_clock = stmlib::ExtractGateFlags(last_t_clock, t_gate); | ||||
t_clocks[blockIndex] = last_t_clock; | t_clocks[blockIndex] = last_t_clock; | ||||
bool x_gate = (inputs[X_CLOCK_INPUT].value >= 1.7f); | |||||
bool x_gate = (inputs[X_CLOCK_INPUT].getVoltage() >= 1.7f); | |||||
last_xy_clock = stmlib::ExtractGateFlags(last_xy_clock, x_gate); | last_xy_clock = stmlib::ExtractGateFlags(last_xy_clock, x_gate); | ||||
xy_clocks[blockIndex] = last_xy_clock; | xy_clocks[blockIndex] = last_xy_clock; | ||||
@@ -379,21 +396,21 @@ struct Marbles : Module { | |||||
lights[EXTERNAL_LIGHT].setBrightness(external); | lights[EXTERNAL_LIGHT].setBrightness(external); | ||||
outputs[T1_OUTPUT].value = gates[blockIndex*2 + 0] ? 10.f : 0.f; | |||||
lights[T1_LIGHT].setBrightnessSmooth(gates[blockIndex*2 + 0]); | |||||
outputs[T2_OUTPUT].value = (ramp_master[blockIndex] < 0.5f) ? 10.f : 0.f; | |||||
lights[T2_LIGHT].setBrightnessSmooth(ramp_master[blockIndex] < 0.5f); | |||||
outputs[T3_OUTPUT].value = gates[blockIndex*2 + 1] ? 10.f : 0.f; | |||||
lights[T3_LIGHT].setBrightnessSmooth(gates[blockIndex*2 + 1]); | |||||
outputs[X1_OUTPUT].value = voltages[blockIndex*4 + 0]; | |||||
lights[X1_LIGHT].setBrightnessSmooth(voltages[blockIndex*4 + 0]); | |||||
outputs[X2_OUTPUT].value = voltages[blockIndex*4 + 1]; | |||||
lights[X2_LIGHT].setBrightnessSmooth(voltages[blockIndex*4 + 1]); | |||||
outputs[X3_OUTPUT].value = voltages[blockIndex*4 + 2]; | |||||
lights[X3_LIGHT].setBrightnessSmooth(voltages[blockIndex*4 + 2]); | |||||
outputs[Y_OUTPUT].value = voltages[blockIndex*4 + 3]; | |||||
lights[Y_LIGHT].setBrightnessSmooth(voltages[blockIndex*4 + 3]); | |||||
outputs[T1_OUTPUT].setVoltage(gates[blockIndex*2 + 0] ? 10.f : 0.f); | |||||
lights[T1_LIGHT].setSmoothBrightness(gates[blockIndex*2 + 0], args.sampleTime); | |||||
outputs[T2_OUTPUT].setVoltage((ramp_master[blockIndex] < 0.5f) ? 10.f : 0.f); | |||||
lights[T2_LIGHT].setSmoothBrightness(ramp_master[blockIndex] < 0.5f, args.sampleTime); | |||||
outputs[T3_OUTPUT].setVoltage(gates[blockIndex*2 + 1] ? 10.f : 0.f); | |||||
lights[T3_LIGHT].setSmoothBrightness(gates[blockIndex*2 + 1], args.sampleTime); | |||||
outputs[X1_OUTPUT].setVoltage(voltages[blockIndex*4 + 0]); | |||||
lights[X1_LIGHT].setSmoothBrightness(voltages[blockIndex*4 + 0], args.sampleTime); | |||||
outputs[X2_OUTPUT].setVoltage(voltages[blockIndex*4 + 1]); | |||||
lights[X2_LIGHT].setSmoothBrightness(voltages[blockIndex*4 + 1], args.sampleTime); | |||||
outputs[X3_OUTPUT].setVoltage(voltages[blockIndex*4 + 2]); | |||||
lights[X3_LIGHT].setSmoothBrightness(voltages[blockIndex*4 + 2], args.sampleTime); | |||||
outputs[Y_OUTPUT].setVoltage(voltages[blockIndex*4 + 3]); | |||||
lights[Y_LIGHT].setSmoothBrightness(voltages[blockIndex*4 + 3], args.sampleTime); | |||||
} | } | ||||
void stepBlock() { | void stepBlock() { | ||||
@@ -405,7 +422,7 @@ struct Marbles : Module { | |||||
ramps.slave[0] = ramp_slave[0]; | ramps.slave[0] = ramp_slave[0]; | ||||
ramps.slave[1] = ramp_slave[1]; | ramps.slave[1] = ramp_slave[1]; | ||||
float deja_vu = clamp(params[DEJA_VU_PARAM].value + inputs[DEJA_VU_INPUT].value / 5.f, 0.f, 1.f); | |||||
float deja_vu = clamp(params[DEJA_VU_PARAM].getValue() + inputs[DEJA_VU_INPUT].getVoltage() / 5.f, 0.f, 1.f); | |||||
static const int loop_length[] = { | static const int loop_length[] = { | ||||
1, 1, 1, 2, 2, | 1, 1, 1, 2, 2, | ||||
2, 2, 2, 3, 3, | 2, 2, 2, 3, 3, | ||||
@@ -416,20 +433,20 @@ struct Marbles : Module { | |||||
12, 12, 14, 14, 16, | 12, 12, 14, 14, 16, | ||||
16 | 16 | ||||
}; | }; | ||||
float deja_vu_length_index = params[DEJA_VU_LENGTH_PARAM].value * (LENGTHOF(loop_length) - 1); | |||||
float deja_vu_length_index = params[DEJA_VU_LENGTH_PARAM].getValue() * (LENGTHOF(loop_length) - 1); | |||||
int deja_vu_length = loop_length[(int) roundf(deja_vu_length_index)]; | int deja_vu_length = loop_length[(int) roundf(deja_vu_length_index)]; | ||||
// Set up TGenerator | // Set up TGenerator | ||||
bool t_external_clock = inputs[T_CLOCK_INPUT].active; | |||||
bool t_external_clock = inputs[T_CLOCK_INPUT].isConnected(); | |||||
t_generator.set_model((marbles::TGeneratorModel) t_mode); | t_generator.set_model((marbles::TGeneratorModel) t_mode); | ||||
t_generator.set_range((marbles::TGeneratorRange) t_range); | t_generator.set_range((marbles::TGeneratorRange) t_range); | ||||
float t_rate = 60.f * (params[T_RATE_PARAM].value + inputs[T_RATE_INPUT].value / 5.f); | |||||
float t_rate = 60.f * (params[T_RATE_PARAM].getValue() + inputs[T_RATE_INPUT].getVoltage() / 5.f); | |||||
t_generator.set_rate(t_rate); | t_generator.set_rate(t_rate); | ||||
float t_bias = clamp(params[T_BIAS_PARAM].value + inputs[T_BIAS_INPUT].value / 5.f, 0.f, 1.f); | |||||
float t_bias = clamp(params[T_BIAS_PARAM].getValue() + inputs[T_BIAS_INPUT].getVoltage() / 5.f, 0.f, 1.f); | |||||
t_generator.set_bias(t_bias); | t_generator.set_bias(t_bias); | ||||
float t_jitter = clamp(params[T_JITTER_PARAM].value + inputs[T_JITTER_INPUT].value / 5.f, 0.f, 1.f); | |||||
float t_jitter = clamp(params[T_JITTER_PARAM].getValue() + inputs[T_JITTER_INPUT].getVoltage() / 5.f, 0.f, 1.f); | |||||
t_generator.set_jitter(t_jitter); | t_generator.set_jitter(t_jitter); | ||||
t_generator.set_deja_vu(t_deja_vu ? deja_vu : 0.f); | t_generator.set_deja_vu(t_deja_vu ? deja_vu : 0.f); | ||||
t_generator.set_length(deja_vu_length); | t_generator.set_length(deja_vu_length); | ||||
@@ -442,23 +459,23 @@ struct Marbles : Module { | |||||
// Set up XYGenerator | // Set up XYGenerator | ||||
marbles::ClockSource x_clock_source = (marbles::ClockSource) x_clock_source_internal; | marbles::ClockSource x_clock_source = (marbles::ClockSource) x_clock_source_internal; | ||||
if (inputs[X_CLOCK_INPUT].active) | |||||
if (inputs[X_CLOCK_INPUT].isConnected()) | |||||
x_clock_source = marbles::CLOCK_SOURCE_EXTERNAL; | x_clock_source = marbles::CLOCK_SOURCE_EXTERNAL; | ||||
marbles::GroupSettings x; | marbles::GroupSettings x; | ||||
x.control_mode = (marbles::ControlMode) x_mode; | x.control_mode = (marbles::ControlMode) x_mode; | ||||
x.voltage_range = (marbles::VoltageRange) x_range; | x.voltage_range = (marbles::VoltageRange) x_range; | ||||
// TODO Fix the scaling | // TODO Fix the scaling | ||||
float note_cv = 0.5f * (params[X_SPREAD_PARAM].value + inputs[X_SPREAD_INPUT].value / 5.f); | |||||
float note_cv = 0.5f * (params[X_SPREAD_PARAM].getValue() + inputs[X_SPREAD_INPUT].getVoltage() / 5.f); | |||||
float u = note_filter.Process(0.5f * (note_cv + 1.f)); | float u = note_filter.Process(0.5f * (note_cv + 1.f)); | ||||
x.register_mode = external; | x.register_mode = external; | ||||
x.register_value = u; | x.register_value = u; | ||||
float x_spread = clamp(params[X_SPREAD_PARAM].value + inputs[X_SPREAD_INPUT].value / 5.f, 0.f, 1.f); | |||||
float x_spread = clamp(params[X_SPREAD_PARAM].getValue() + inputs[X_SPREAD_INPUT].getVoltage() / 5.f, 0.f, 1.f); | |||||
x.spread = x_spread; | x.spread = x_spread; | ||||
float x_bias = clamp(params[X_BIAS_PARAM].value + inputs[X_BIAS_INPUT].value / 5.f, 0.f, 1.f); | |||||
float x_bias = clamp(params[X_BIAS_PARAM].getValue() + inputs[X_BIAS_INPUT].getVoltage() / 5.f, 0.f, 1.f); | |||||
x.bias = x_bias; | x.bias = x_bias; | ||||
float x_steps = clamp(params[X_STEPS_PARAM].value + inputs[X_STEPS_INPUT].value / 5.f, 0.f, 1.f); | |||||
float x_steps = clamp(params[X_STEPS_PARAM].getValue() + inputs[X_STEPS_INPUT].getVoltage() / 5.f, 0.f, 1.f); | |||||
x.steps = x_steps; | x.steps = x_steps; | ||||
x.deja_vu = x_deja_vu ? deja_vu : 0.f; | x.deja_vu = x_deja_vu ? deja_vu : 0.f; | ||||
x.length = deja_vu_length; | x.length = deja_vu_length; | ||||
@@ -509,29 +526,30 @@ struct CKD6Light : BASE { | |||||
struct MarblesWidget : ModuleWidget { | struct MarblesWidget : ModuleWidget { | ||||
MarblesWidget(Marbles *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Marbles.svg"))); | |||||
MarblesWidget(Marbles *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Marbles.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); | addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | ||||
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | ||||
addParam(createParamCentered<CKD6>(mm2px(Vec(16.545, 17.794)), module, Marbles::T_DEJA_VU_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<CKD6>(mm2px(Vec(74.845, 17.794)), module, Marbles::X_DEJA_VU_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 22.244)), module, Marbles::DEJA_VU_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(23.467, 35.264)), module, Marbles::T_RATE_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(67.945, 35.243)), module, Marbles::X_SPREAD_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(6.945, 38.794)), module, Marbles::T_MODE_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(84.445, 38.793)), module, Marbles::X_MODE_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 51.144)), module, Marbles::DEJA_VU_LENGTH_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(9.545, 58.394)), module, Marbles::T_BIAS_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(81.844, 58.394)), module, Marbles::X_BIAS_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(26.644, 59.694)), module, Marbles::T_RANGE_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(64.744, 59.694)), module, Marbles::X_RANGE_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(45.694, 67.294)), module, Marbles::EXTERNAL_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(31.544, 73.694)), module, Marbles::T_JITTER_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(59.845, 73.694)), module, Marbles::X_STEPS_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParamCentered<CKD6>(mm2px(Vec(16.545, 17.794)), module, Marbles::T_DEJA_VU_PARAM)); | |||||
addParam(createParamCentered<CKD6>(mm2px(Vec(74.845, 17.794)), module, Marbles::X_DEJA_VU_PARAM)); | |||||
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 22.244)), module, Marbles::DEJA_VU_PARAM)); | |||||
addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(23.467, 35.264)), module, Marbles::T_RATE_PARAM)); | |||||
addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(67.945, 35.243)), module, Marbles::X_SPREAD_PARAM)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(6.945, 38.794)), module, Marbles::T_MODE_PARAM)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(84.445, 38.793)), module, Marbles::X_MODE_PARAM)); | |||||
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 51.144)), module, Marbles::DEJA_VU_LENGTH_PARAM)); | |||||
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(9.545, 58.394)), module, Marbles::T_BIAS_PARAM)); | |||||
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(81.844, 58.394)), module, Marbles::X_BIAS_PARAM)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(26.644, 59.694)), module, Marbles::T_RANGE_PARAM)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(64.744, 59.694)), module, Marbles::X_RANGE_PARAM)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(45.694, 67.294)), module, Marbles::EXTERNAL_PARAM)); | |||||
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(31.544, 73.694)), module, Marbles::T_JITTER_PARAM)); | |||||
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(59.845, 73.694)), module, Marbles::X_STEPS_PARAM)); | |||||
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(9.545, 81.944)), module, Marbles::T_BIAS_INPUT)); | addInput(createInputCentered<PJ301MPort>(mm2px(Vec(9.545, 81.944)), module, Marbles::T_BIAS_INPUT)); | ||||
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(81.844, 81.944)), module, Marbles::X_BIAS_INPUT)); | addInput(createInputCentered<PJ301MPort>(mm2px(Vec(81.844, 81.944)), module, Marbles::X_BIAS_INPUT)); | ||||
@@ -1,659 +0,0 @@ | |||||
#include <chrono> | |||||
#include "peaks/io_buffer.h" | |||||
#include "peaks/processors.h" | |||||
#include "AudibleInstruments.hpp" | |||||
enum SwitchIndex { | |||||
SWITCH_TWIN_MODE, | |||||
SWITCH_FUNCTION, | |||||
SWITCH_GATE_TRIG_1, | |||||
SWITCH_GATE_TRIG_2 | |||||
}; | |||||
enum EditMode { | |||||
EDIT_MODE_TWIN, | |||||
EDIT_MODE_SPLIT, | |||||
EDIT_MODE_FIRST, | |||||
EDIT_MODE_SECOND, | |||||
EDIT_MODE_LAST | |||||
}; | |||||
enum Function { | |||||
FUNCTION_ENVELOPE, | |||||
FUNCTION_LFO, | |||||
FUNCTION_TAP_LFO, | |||||
FUNCTION_DRUM_GENERATOR, | |||||
FUNCTION_MINI_SEQUENCER, | |||||
FUNCTION_PULSE_SHAPER, | |||||
FUNCTION_PULSE_RANDOMIZER, | |||||
FUNCTION_FM_DRUM_GENERATOR, | |||||
FUNCTION_LAST, | |||||
FUNCTION_FIRST_ALTERNATE_FUNCTION = FUNCTION_MINI_SEQUENCER | |||||
}; | |||||
struct Settings { | |||||
uint8_t edit_mode; | |||||
uint8_t function[2]; | |||||
uint8_t pot_value[8]; | |||||
bool snap_mode; | |||||
}; | |||||
static const int32_t kLongPressDuration = 600; | |||||
static const uint8_t kNumAdcChannels = 4; | |||||
static const uint16_t kAdcThresholdUnlocked = 1 << (16 - 10); // 10 bits | |||||
static const uint16_t kAdcThresholdLocked = 1 << (16 - 8); // 8 bits | |||||
// Global scope, so variables can be accessed by process() function. | |||||
int16_t gOutputBuffer[peaks::kBlockSize]; | |||||
int16_t gBrightness[2] = {0, 0}; | |||||
static void set_led_brightness(int channel, int16_t value) { | |||||
gBrightness[channel] = value; | |||||
} | |||||
// File scope because of IOBuffer function signature. | |||||
// It cannot refer to a member function of class Peaks(). | |||||
static void process(peaks::IOBuffer::Block* block, size_t size) { | |||||
for (size_t i = 0; i < peaks::kNumChannels; ++i) { | |||||
// TODO | |||||
// processors[i].Process(block->input[i], gOutputBuffer, size); | |||||
set_led_brightness(i, gOutputBuffer[0]); | |||||
for (size_t j = 0; j < size; ++j) { | |||||
// From calibration_data.h, shifting signed to unsigned values. | |||||
int32_t shifted_value = 32767 + static_cast<int32_t>(gOutputBuffer[j]); | |||||
CONSTRAIN(shifted_value, 0, 65535); | |||||
block->output[i][j] = static_cast<uint16_t>(shifted_value); | |||||
} | |||||
} | |||||
} | |||||
struct Peaks : Module { | |||||
enum ParamIds { | |||||
KNOB_1_PARAM, | |||||
KNOB_2_PARAM, | |||||
KNOB_3_PARAM, | |||||
KNOB_4_PARAM, | |||||
BUTTON_1_PARAM, | |||||
BUTTON_2_PARAM, | |||||
TRIG_1_PARAM, | |||||
TRIG_2_PARAM, | |||||
NUM_PARAMS | |||||
}; | |||||
enum InputIds { | |||||
GATE_1_INPUT, | |||||
GATE_2_INPUT, | |||||
NUM_INPUTS | |||||
}; | |||||
enum OutputIds { | |||||
OUT_1_OUTPUT, | |||||
OUT_2_OUTPUT, | |||||
NUM_OUTPUTS | |||||
}; | |||||
enum LightIds { | |||||
TRIG_1_LIGHT, | |||||
TRIG_2_LIGHT, | |||||
TWIN_MODE_LIGHT, | |||||
FUNC_1_LIGHT, | |||||
FUNC_2_LIGHT, | |||||
FUNC_3_LIGHT, | |||||
FUNC_4_LIGHT, | |||||
NUM_LIGHTS | |||||
}; | |||||
static const peaks::ProcessorFunction function_table_[FUNCTION_LAST][2]; | |||||
EditMode edit_mode_ = EDIT_MODE_TWIN; | |||||
Function function_[2] = {FUNCTION_ENVELOPE, FUNCTION_ENVELOPE}; | |||||
Settings settings_; | |||||
uint8_t pot_value_[8] = {0, 0, 0, 0, 0, 0, 0, 0}; | |||||
bool snap_mode_ = false; | |||||
bool snapped_[4] = {false, false, false, false}; | |||||
int32_t adc_lp_[kNumAdcChannels] = {0, 0, 0, 0}; | |||||
int32_t adc_value_[kNumAdcChannels] = {0, 0, 0, 0}; | |||||
int32_t adc_threshold_[kNumAdcChannels] = {0, 0, 0, 0}; | |||||
long long press_time_[2] = {0, 0}; | |||||
SchmittTrigger switches_[2]; | |||||
peaks::IOBuffer ioBuffer; | |||||
peaks::GateFlags gate_flags[2] = {0, 0}; | |||||
SampleRateConverter<2> outputSrc; | |||||
DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||||
bool initNumberStation = false; | |||||
peaks::Processors processors[2]; | |||||
Peaks() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
settings_.edit_mode = EDIT_MODE_TWIN; | |||||
settings_.function[0] = FUNCTION_ENVELOPE; | |||||
settings_.function[1] = FUNCTION_ENVELOPE; | |||||
settings_.snap_mode = false; | |||||
std::fill(&settings_.pot_value[0], &settings_.pot_value[8], 0); | |||||
memset(&ioBuffer, 0, sizeof(ioBuffer)); | |||||
memset(&processors[0], 0, sizeof(processors[0])); | |||||
memset(&processors[1], 0, sizeof(processors[1])); | |||||
ioBuffer.Init(); | |||||
processors[0].Init(0); | |||||
processors[1].Init(1); | |||||
} | |||||
void onReset() override { | |||||
init(); | |||||
} | |||||
void init() { | |||||
std::fill(&pot_value_[0], &pot_value_[8], 0); | |||||
std::fill(&press_time_[0], &press_time_[1], 0); | |||||
std::fill(&gBrightness[0], &gBrightness[1], 0); | |||||
std::fill(&adc_lp_[0], &adc_lp_[kNumAdcChannels], 0); | |||||
std::fill(&adc_value_[0], &adc_value_[kNumAdcChannels], 0); | |||||
std::fill(&adc_threshold_[0], &adc_threshold_[kNumAdcChannels], 0); | |||||
std::fill(&snapped_[0], &snapped_[kNumAdcChannels], false); | |||||
edit_mode_ = static_cast<EditMode>(settings_.edit_mode); | |||||
function_[0] = static_cast<Function>(settings_.function[0]); | |||||
function_[1] = static_cast<Function>(settings_.function[1]); | |||||
std::copy(&settings_.pot_value[0], &settings_.pot_value[8], &pot_value_[0]); | |||||
if (edit_mode_ == EDIT_MODE_FIRST || edit_mode_ == EDIT_MODE_SECOND) { | |||||
lockPots(); | |||||
for (uint8_t i = 0; i < 4; ++i) { | |||||
processors[0].set_parameter( | |||||
i, | |||||
static_cast<uint16_t>(pot_value_[i]) << 8); | |||||
processors[1].set_parameter( | |||||
i, | |||||
static_cast<uint16_t>(pot_value_[i + 4]) << 8); | |||||
} | |||||
} | |||||
snap_mode_ = settings_.snap_mode; | |||||
changeControlMode(); | |||||
setFunction(0, function_[0]); | |||||
setFunction(1, function_[1]); | |||||
} | |||||
json_t *dataToJson() override { | |||||
saveState(); | |||||
json_t *rootJ = json_object(); | |||||
json_object_set_new(rootJ, "edit_mode", json_integer((int)settings_.edit_mode)); | |||||
json_object_set_new(rootJ, "fcn_channel_1", json_integer((int)settings_.function[0])); | |||||
json_object_set_new(rootJ, "fcn_channel_2", json_integer((int)settings_.function[1])); | |||||
json_t *potValuesJ = json_array(); | |||||
for (int p : pot_value_) { | |||||
json_t *pJ = json_integer(p); | |||||
json_array_append_new(potValuesJ, pJ); | |||||
} | |||||
json_object_set_new(rootJ, "pot_values", potValuesJ); | |||||
json_object_set_new(rootJ, "snap_mode", json_boolean(settings_.snap_mode)); | |||||
return rootJ; | |||||
} | |||||
void dataFromJson(json_t *rootJ) override { | |||||
json_t *editModeJ = json_object_get(rootJ, "edit_mode"); | |||||
if (editModeJ) { | |||||
settings_.edit_mode = static_cast<EditMode>(json_integer_value(editModeJ)); | |||||
} | |||||
json_t *fcnChannel1J = json_object_get(rootJ, "fcn_channel_1"); | |||||
if (fcnChannel1J) { | |||||
settings_.function[0] = static_cast<Function>(json_integer_value(fcnChannel1J)); | |||||
} | |||||
json_t *fcnChannel2J = json_object_get(rootJ, "fcn_channel_2"); | |||||
if (fcnChannel2J) { | |||||
settings_.function[1] = static_cast<Function>(json_integer_value(fcnChannel2J)); | |||||
} | |||||
json_t *snapModeJ = json_object_get(rootJ, "snap_mode"); | |||||
if (snapModeJ) { | |||||
settings_.snap_mode = json_boolean_value(snapModeJ); | |||||
} | |||||
json_t *potValuesJ = json_object_get(rootJ, "pot_values"); | |||||
size_t potValueId; | |||||
json_t *pJ; | |||||
json_array_foreach(potValuesJ, potValueId, pJ) { | |||||
if (potValueId < sizeof(pot_value_) / sizeof(pot_value_)[0]) { | |||||
settings_.pot_value[potValueId] = json_integer_value(pJ); | |||||
} | |||||
} | |||||
// Update module internal state from settings. | |||||
init(); | |||||
} | |||||
void step() override { | |||||
poll(); | |||||
pollPots(); | |||||
// Initialize "secret" number station mode. | |||||
if (initNumberStation) { | |||||
processors[0].set_function(peaks::PROCESSOR_FUNCTION_NUMBER_STATION); | |||||
processors[1].set_function(peaks::PROCESSOR_FUNCTION_NUMBER_STATION); | |||||
initNumberStation = false; | |||||
} | |||||
if (outputBuffer.empty()) { | |||||
ioBuffer.Process(::process); | |||||
uint32_t external_gate_inputs = 0; | |||||
external_gate_inputs |= (inputs[GATE_1_INPUT].value ? 1 : 0); | |||||
external_gate_inputs |= (inputs[GATE_2_INPUT].value ? 2 : 0); | |||||
uint32_t buttons = 0; | |||||
buttons |= (params[TRIG_1_PARAM].value ? 1 : 0); | |||||
buttons |= (params[TRIG_2_PARAM].value ? 2 : 0); | |||||
uint32_t gate_inputs = external_gate_inputs | buttons; | |||||
// Prepare sample rate conversion. | |||||
// Peaks is sampling at 48kHZ. | |||||
outputSrc.setRates(48000, engineGetSampleRate()); | |||||
int inLen = peaks::kBlockSize; | |||||
int outLen = outputBuffer.capacity(); | |||||
Frame<2> f[peaks::kBlockSize]; | |||||
// Process an entire block of data from the IOBuffer. | |||||
for (size_t k = 0; k < peaks::kBlockSize; ++k) { | |||||
peaks::IOBuffer::Slice slice = ioBuffer.NextSlice(1); | |||||
for (size_t i = 0; i < peaks::kNumChannels; ++i) { | |||||
gate_flags[i] = peaks::ExtractGateFlags( | |||||
gate_flags[i], | |||||
gate_inputs & (1 << i)); | |||||
f[k].samples[i] = slice.block->output[i][slice.frame_index]; | |||||
} | |||||
// A hack to make channel 1 aware of what's going on in channel 2. Used to | |||||
// reset the sequencer. | |||||
slice.block->input[0][slice.frame_index] = gate_flags[0] | (gate_flags[1] << 4) | (buttons & 8 ? peaks::GATE_FLAG_FROM_BUTTON : 0); | |||||
slice.block->input[1][slice.frame_index] = gate_flags[1] | (buttons & 2 ? peaks::GATE_FLAG_FROM_BUTTON : 0); | |||||
} | |||||
outputSrc.process(f, &inLen, outputBuffer.endData(), &outLen); | |||||
outputBuffer.endIncr(outLen); | |||||
} | |||||
// Update outputs. | |||||
if (!outputBuffer.empty()) { | |||||
Frame<2> f = outputBuffer.shift(); | |||||
// Peaks manual says output spec is 0..8V for envelopes and 10Vpp for audio/CV. | |||||
// TODO Check the output values against an actual device. | |||||
outputs[OUT_1_OUTPUT].value = rescale(static_cast<float>(f.samples[0]), 0.0f, 65535.f, -8.0f, 8.0f); | |||||
outputs[OUT_2_OUTPUT].value = rescale(static_cast<float>(f.samples[1]), 0.0f, 65535.f, -8.0f, 8.0f); | |||||
} | |||||
} | |||||
inline Function function() const { | |||||
return edit_mode_ == EDIT_MODE_SECOND ? function_[1] : function_[0]; | |||||
} | |||||
void changeControlMode(); | |||||
void setFunction(uint8_t index, Function f); | |||||
void onPotChanged(uint16_t id, uint16_t value); | |||||
void onSwitchReleased(uint16_t id, uint16_t data); | |||||
void saveState(); | |||||
void lockPots(); | |||||
void poll(); | |||||
void pollPots(); | |||||
void refreshLeds(); | |||||
long long getSystemTimeMs(); | |||||
}; | |||||
const peaks::ProcessorFunction Peaks::function_table_[FUNCTION_LAST][2] = { | |||||
{ peaks::PROCESSOR_FUNCTION_ENVELOPE, peaks::PROCESSOR_FUNCTION_ENVELOPE }, | |||||
{ peaks::PROCESSOR_FUNCTION_LFO, peaks::PROCESSOR_FUNCTION_LFO }, | |||||
{ peaks::PROCESSOR_FUNCTION_TAP_LFO, peaks::PROCESSOR_FUNCTION_TAP_LFO }, | |||||
{ peaks::PROCESSOR_FUNCTION_BASS_DRUM, peaks::PROCESSOR_FUNCTION_SNARE_DRUM }, | |||||
{ peaks::PROCESSOR_FUNCTION_MINI_SEQUENCER, peaks::PROCESSOR_FUNCTION_MINI_SEQUENCER }, | |||||
{ peaks::PROCESSOR_FUNCTION_PULSE_SHAPER, peaks::PROCESSOR_FUNCTION_PULSE_SHAPER }, | |||||
{ peaks::PROCESSOR_FUNCTION_PULSE_RANDOMIZER, peaks::PROCESSOR_FUNCTION_PULSE_RANDOMIZER }, | |||||
{ peaks::PROCESSOR_FUNCTION_FM_DRUM, peaks::PROCESSOR_FUNCTION_FM_DRUM }, | |||||
}; | |||||
void Peaks::changeControlMode() { | |||||
uint16_t parameters[4]; | |||||
for (int i = 0; i < 4; ++i) { | |||||
parameters[i] = adc_value_[i]; | |||||
} | |||||
if (edit_mode_ == EDIT_MODE_SPLIT) { | |||||
processors[0].CopyParameters(¶meters[0], 2); | |||||
processors[1].CopyParameters(¶meters[2], 2); | |||||
processors[0].set_control_mode(peaks::CONTROL_MODE_HALF); | |||||
processors[1].set_control_mode(peaks::CONTROL_MODE_HALF); | |||||
} | |||||
else if (edit_mode_ == EDIT_MODE_TWIN) { | |||||
processors[0].CopyParameters(¶meters[0], 4); | |||||
processors[1].CopyParameters(¶meters[0], 4); | |||||
processors[0].set_control_mode(peaks::CONTROL_MODE_FULL); | |||||
processors[1].set_control_mode(peaks::CONTROL_MODE_FULL); | |||||
} | |||||
else { | |||||
processors[0].set_control_mode(peaks::CONTROL_MODE_FULL); | |||||
processors[1].set_control_mode(peaks::CONTROL_MODE_FULL); | |||||
} | |||||
} | |||||
void Peaks::setFunction(uint8_t index, Function f) { | |||||
if (edit_mode_ == EDIT_MODE_SPLIT || edit_mode_ == EDIT_MODE_TWIN) { | |||||
function_[0] = function_[1] = f; | |||||
processors[0].set_function(function_table_[f][0]); | |||||
processors[1].set_function(function_table_[f][1]); | |||||
} | |||||
else { | |||||
function_[index] = f; | |||||
processors[index].set_function(function_table_[f][index]); | |||||
} | |||||
} | |||||
void Peaks::onSwitchReleased(uint16_t id, uint16_t data) { | |||||
switch (id) { | |||||
case SWITCH_TWIN_MODE: | |||||
if (data > kLongPressDuration) { | |||||
edit_mode_ = static_cast<EditMode>( | |||||
(edit_mode_ + EDIT_MODE_FIRST) % EDIT_MODE_LAST); | |||||
function_[0] = function_[1]; | |||||
processors[0].set_function(function_table_[function_[0]][0]); | |||||
processors[1].set_function(function_table_[function_[0]][1]); | |||||
lockPots(); | |||||
} | |||||
else { | |||||
if (edit_mode_ <= EDIT_MODE_SPLIT) { | |||||
edit_mode_ = static_cast<EditMode>(EDIT_MODE_SPLIT - edit_mode_); | |||||
} | |||||
else { | |||||
edit_mode_ = static_cast<EditMode>(EDIT_MODE_SECOND - (edit_mode_ & 1)); | |||||
lockPots(); | |||||
} | |||||
} | |||||
changeControlMode(); | |||||
saveState(); | |||||
break; | |||||
case SWITCH_FUNCTION: { | |||||
Function f = function(); | |||||
if (data > kLongPressDuration) { | |||||
f = static_cast<Function>((f + FUNCTION_FIRST_ALTERNATE_FUNCTION) % FUNCTION_LAST); | |||||
} | |||||
else { | |||||
if (f <= FUNCTION_DRUM_GENERATOR) { | |||||
f = static_cast<Function>((f + 1) & 3); | |||||
} | |||||
else { | |||||
f = static_cast<Function>(((f + 1) & 3) + FUNCTION_FIRST_ALTERNATE_FUNCTION); | |||||
} | |||||
} | |||||
setFunction(edit_mode_ - EDIT_MODE_FIRST, f); | |||||
saveState(); | |||||
} | |||||
break; | |||||
case SWITCH_GATE_TRIG_1: | |||||
// no-op | |||||
break; | |||||
case SWITCH_GATE_TRIG_2: | |||||
// no-op | |||||
break; | |||||
} | |||||
} | |||||
void Peaks::lockPots() { | |||||
std::fill( | |||||
&adc_threshold_[0], | |||||
&adc_threshold_[kNumAdcChannels], | |||||
kAdcThresholdLocked); | |||||
std::fill(&snapped_[0], &snapped_[kNumAdcChannels], false); | |||||
} | |||||
void Peaks::pollPots() { | |||||
for (uint8_t i = 0; i < kNumAdcChannels; ++i) { | |||||
adc_lp_[i] = (int32_t(params[KNOB_1_PARAM + i].value) + adc_lp_[i] * 7) >> 3; | |||||
int32_t value = adc_lp_[i]; | |||||
int32_t current_value = adc_value_[i]; | |||||
if (value >= current_value + adc_threshold_[i] || | |||||
value <= current_value - adc_threshold_[i] || | |||||
!adc_threshold_[i]) { | |||||
onPotChanged(i, value); | |||||
adc_value_[i] = value; | |||||
adc_threshold_[i] = kAdcThresholdUnlocked; | |||||
} | |||||
} | |||||
} | |||||
void Peaks::onPotChanged(uint16_t id, uint16_t value) { | |||||
switch (edit_mode_) { | |||||
case EDIT_MODE_TWIN: | |||||
processors[0].set_parameter(id, value); | |||||
processors[1].set_parameter(id, value); | |||||
pot_value_[id] = value >> 8; | |||||
break; | |||||
case EDIT_MODE_SPLIT: | |||||
if (id < 2) { | |||||
processors[0].set_parameter(id, value); | |||||
} | |||||
else { | |||||
processors[1].set_parameter(id - 2, value); | |||||
} | |||||
pot_value_[id] = value >> 8; | |||||
break; | |||||
case EDIT_MODE_FIRST: | |||||
case EDIT_MODE_SECOND: { | |||||
uint8_t index = id + (edit_mode_ - EDIT_MODE_FIRST) * 4; | |||||
peaks::Processors* p = &processors[edit_mode_ - EDIT_MODE_FIRST]; | |||||
int16_t delta = static_cast<int16_t>(pot_value_[index]) - \ | |||||
static_cast<int16_t>(value >> 8); | |||||
if (delta < 0) { | |||||
delta = -delta; | |||||
} | |||||
if (!snap_mode_ || snapped_[id] || delta <= 2) { | |||||
p->set_parameter(id, value); | |||||
pot_value_[index] = value >> 8; | |||||
snapped_[id] = true; | |||||
} | |||||
} | |||||
break; | |||||
case EDIT_MODE_LAST: | |||||
break; | |||||
} | |||||
} | |||||
long long Peaks::getSystemTimeMs() { | |||||
return std::chrono::duration_cast<std::chrono::milliseconds>( | |||||
std::chrono::steady_clock::now().time_since_epoch() | |||||
).count(); | |||||
} | |||||
void Peaks::poll() { | |||||
for (uint8_t i = 0; i < 2; ++i) { | |||||
if (switches_[i].process(params[BUTTON_1_PARAM + i].value)) { | |||||
press_time_[i] = getSystemTimeMs(); | |||||
} | |||||
if (switches_[i].isHigh() && press_time_[i] != 0) { | |||||
int32_t pressed_time = getSystemTimeMs() - press_time_[i]; | |||||
if (pressed_time > kLongPressDuration) { | |||||
onSwitchReleased(SWITCH_TWIN_MODE + i, pressed_time); | |||||
press_time_[i] = 0; // Inhibit next release event | |||||
} | |||||
} | |||||
if (!switches_[i].isHigh() && press_time_[i] != 0) { | |||||
int32_t delta = getSystemTimeMs() - press_time_[i] + 1; | |||||
onSwitchReleased(SWITCH_TWIN_MODE + i, delta); | |||||
press_time_[i] = 0; // Not in original code! | |||||
} | |||||
} | |||||
refreshLeds(); | |||||
} | |||||
void Peaks::saveState() { | |||||
settings_.edit_mode = edit_mode_; | |||||
settings_.function[0] = function_[0]; | |||||
settings_.function[1] = function_[1]; | |||||
std::copy(&pot_value_[0], &pot_value_[8], &settings_.pot_value[0]); | |||||
settings_.snap_mode = snap_mode_; | |||||
} | |||||
void Peaks::refreshLeds() { | |||||
uint8_t flash = (getSystemTimeMs() >> 7) & 7; | |||||
switch (edit_mode_) { | |||||
case EDIT_MODE_FIRST: | |||||
lights[TWIN_MODE_LIGHT].value = (flash == 1) ? 1.0f : 0.0f; | |||||
break; | |||||
case EDIT_MODE_SECOND: | |||||
lights[TWIN_MODE_LIGHT].value = (flash == 1 || flash == 3) ? 1.0f : 0.0f; | |||||
break; | |||||
default: | |||||
lights[TWIN_MODE_LIGHT].value = (edit_mode_ & 1) ? 1.0f : 0.0f; | |||||
break; | |||||
} | |||||
if ((getSystemTimeMs() & 256) && function() >= FUNCTION_FIRST_ALTERNATE_FUNCTION) { | |||||
for (size_t i = 0; i < 4; ++i) { | |||||
lights[FUNC_1_LIGHT + i].value = 0.0f; | |||||
} | |||||
} | |||||
else { | |||||
for (size_t i = 0; i < 4; ++i) { | |||||
lights[FUNC_1_LIGHT + i].value = ((function() & 3) == i) ? 1.0f : 0.0f; | |||||
} | |||||
} | |||||
uint8_t b[2]; | |||||
for (uint8_t i = 0; i < 2; ++i) { | |||||
switch (function_[i]) { | |||||
case FUNCTION_DRUM_GENERATOR: | |||||
case FUNCTION_FM_DRUM_GENERATOR: | |||||
b[i] = (int16_t) std::abs(gBrightness[i]) >> 8; | |||||
b[i] = b[i] >= 255 ? 255 : b[i]; | |||||
break; | |||||
case FUNCTION_LFO: | |||||
case FUNCTION_TAP_LFO: | |||||
case FUNCTION_MINI_SEQUENCER: { | |||||
int32_t brightness = int32_t(gBrightness[i]) * 409 >> 8; | |||||
brightness += 32768; | |||||
brightness >>= 8; | |||||
CONSTRAIN(brightness, 0, 255); | |||||
b[i] = brightness; | |||||
} | |||||
break; | |||||
default: | |||||
b[i] = gBrightness[i] >> 7; | |||||
break; | |||||
} | |||||
} | |||||
if (processors[0].function() == peaks::PROCESSOR_FUNCTION_NUMBER_STATION) { | |||||
uint8_t pattern = processors[0].number_station().digit() | |||||
^ processors[1].number_station().digit(); | |||||
for (size_t i = 0; i < 4; ++i) { | |||||
lights[FUNC_1_LIGHT + i].value = (pattern & 1) ? 1.0f : 0.0f; | |||||
pattern = pattern >> 1; | |||||
} | |||||
b[0] = processors[0].number_station().gate() ? 255 : 0; | |||||
b[1] = processors[1].number_station().gate() ? 255 : 0; | |||||
} | |||||
lights[TRIG_1_LIGHT].value = rescale(static_cast<float>(b[0]), 0.0f, 255.0f, 0.0f, 1.0f); | |||||
lights[TRIG_2_LIGHT].value = rescale(static_cast<float>(b[1]), 0.0f, 255.0f, 0.0f, 1.0f); | |||||
} | |||||
struct PeaksWidget : ModuleWidget { | |||||
PeaksWidget(Peaks *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Peaks.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 0))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | |||||
addParam(createParam<TL1105>(Vec(8.5, 52), module, Peaks::BUTTON_1_PARAM, 0.0f, 1.0f, 0.0f)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 74), module, Peaks::TWIN_MODE_LIGHT)); | |||||
addParam(createParam<TL1105>(Vec(8.5, 89), module, Peaks::BUTTON_2_PARAM, 0.0f, 1.0f, 0.0f)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 111), module, Peaks::FUNC_1_LIGHT)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 126.75), module, Peaks::FUNC_2_LIGHT)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 142.5), module, Peaks::FUNC_3_LIGHT)); | |||||
addChild(createLight<MediumLight<GreenLight>>(Vec(11.88, 158), module, Peaks::FUNC_4_LIGHT)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(61, 51), module, Peaks::KNOB_1_PARAM, 0.0f, 65535.0f, 16384.0f)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(61, 115), module, Peaks::KNOB_2_PARAM, 0.0f, 65535.0f, 16384.0f)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(61, 179), module, Peaks::KNOB_3_PARAM, 0.0f, 65535.0f, 32678.0f)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(61, 244), module, Peaks::KNOB_4_PARAM, 0.0f, 65535.0f, 32678.0f)); | |||||
addParam(createParam<LEDBezel>(Vec(11, 188), module, Peaks::TRIG_1_PARAM, 0.0f, 1.0f, 0.0f)); | |||||
addParam(createParam<LEDBezel>(Vec(11, 273), module, Peaks::TRIG_2_PARAM, 0.0f, 1.0f, 0.0f)); | |||||
addChild(createLight<LEDBezelLight<GreenLight>>(Vec(11, 188).plus(mm2px(Vec(0.75, 0.75))), module, Peaks::TRIG_1_LIGHT)); | |||||
addChild(createLight<LEDBezelLight<GreenLight>>(Vec(11, 273).plus(mm2px(Vec(0.75, 0.75))), module, Peaks::TRIG_2_LIGHT)); | |||||
addInput(createPort<PJ301MPort>(Vec(10, 230), PortWidget::INPUT, module, Peaks::GATE_1_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(10, 315), PortWidget::INPUT, module, Peaks::GATE_2_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(53, 315), PortWidget::OUTPUT, module, Peaks::OUT_1_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(86, 315), PortWidget::OUTPUT, module, Peaks::OUT_2_OUTPUT)); | |||||
} | |||||
void appendContextMenu(Menu *menu) override { | |||||
Peaks *peaks = dynamic_cast<Peaks*>(this->module); | |||||
struct SnapModeItem : MenuItem { | |||||
Peaks *peaks; | |||||
void onAction(const event::Action &e) override { | |||||
peaks->snap_mode_ = !peaks->snap_mode_; | |||||
} | |||||
void step() override { | |||||
rightText = (peaks->snap_mode_) ? "âś”" : ""; | |||||
MenuItem::step(); | |||||
} | |||||
}; | |||||
struct NumberStationItem : MenuItem { | |||||
Peaks *peaks; | |||||
void onAction(const event::Action &e) override { | |||||
peaks->initNumberStation = true; | |||||
} | |||||
}; | |||||
menu->addChild(construct<MenuLabel>()); | |||||
menu->addChild(construct<SnapModeItem>(&SnapModeItem::text, "Snap Mode", &SnapModeItem::peaks, peaks)); | |||||
menu->addChild(construct<MenuLabel>()); | |||||
menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Secret Modes")); | |||||
menu->addChild(construct<NumberStationItem>(&NumberStationItem::text, "Number Station", &NumberStationItem::peaks, peaks)); | |||||
} | |||||
}; | |||||
Model *modelPeaks = createModel<Peaks, PeaksWidget>("Peaks"); |
@@ -1,5 +1,11 @@ | |||||
#include "AudibleInstruments.hpp" | #include "AudibleInstruments.hpp" | ||||
#pragma GCC diagnostic push | |||||
#ifndef __clang__ | |||||
#pragma GCC diagnostic ignored "-Wsuggest-override" | |||||
#endif | |||||
#include "plaits/dsp/voice.h" | #include "plaits/dsp/voice.h" | ||||
#pragma GCC diagnostic pop | |||||
struct Plaits : Module { | struct Plaits : Module { | ||||
@@ -42,15 +48,26 @@ struct Plaits : Module { | |||||
char shared_buffer[16384]; | char shared_buffer[16384]; | ||||
float triPhase = 0.f; | float triPhase = 0.f; | ||||
SampleRateConverter<2> outputSrc; | |||||
DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||||
dsp::SampleRateConverter<2> outputSrc; | |||||
dsp::DoubleRingBuffer<dsp::Frame<2>, 256> outputBuffer; | |||||
bool lowCpu = false; | bool lowCpu = false; | ||||
bool lpg = false; | bool lpg = false; | ||||
SchmittTrigger model1Trigger; | |||||
SchmittTrigger model2Trigger; | |||||
dsp::SchmittTrigger model1Trigger; | |||||
dsp::SchmittTrigger model2Trigger; | |||||
Plaits() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Plaits::MODEL1_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Plaits::MODEL2_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Plaits::FREQ_PARAM, -4.0, 4.0, 0.0); | |||||
configParam(Plaits::HARMONICS_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Plaits::TIMBRE_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Plaits::MORPH_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Plaits::TIMBRE_CV_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Plaits::FREQ_CV_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Plaits::MORPH_CV_PARAM, -1.0, 1.0, 0.0); | |||||
Plaits() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
memset(shared_buffer, 0, sizeof(shared_buffer)); | memset(shared_buffer, 0, sizeof(shared_buffer)); | ||||
stmlib::BufferAllocator allocator(shared_buffer, sizeof(shared_buffer)); | stmlib::BufferAllocator allocator(shared_buffer, sizeof(shared_buffer)); | ||||
voice.Init(&allocator); | voice.Init(&allocator); | ||||
@@ -67,7 +84,7 @@ struct Plaits : Module { | |||||
} | } | ||||
void onRandomize() override { | void onRandomize() override { | ||||
patch.engine = randomu32() % 16; | |||||
patch.engine = random::u32() % 16; | |||||
} | } | ||||
json_t *dataToJson() override { | json_t *dataToJson() override { | ||||
@@ -99,12 +116,12 @@ struct Plaits : Module { | |||||
patch.decay = json_number_value(decayJ); | patch.decay = json_number_value(decayJ); | ||||
} | } | ||||
void step() override { | |||||
void process(const ProcessArgs &args) override { | |||||
if (outputBuffer.empty()) { | if (outputBuffer.empty()) { | ||||
const int blockSize = 12; | const int blockSize = 12; | ||||
// Model buttons | // Model buttons | ||||
if (model1Trigger.process(params[MODEL1_PARAM].value)) { | |||||
if (model1Trigger.process(params[MODEL1_PARAM].getValue())) { | |||||
if (patch.engine >= 8) { | if (patch.engine >= 8) { | ||||
patch.engine -= 8; | patch.engine -= 8; | ||||
} | } | ||||
@@ -112,7 +129,7 @@ struct Plaits : Module { | |||||
patch.engine = (patch.engine + 1) % 8; | patch.engine = (patch.engine + 1) % 8; | ||||
} | } | ||||
} | } | ||||
if (model2Trigger.process(params[MODEL2_PARAM].value)) { | |||||
if (model2Trigger.process(params[MODEL2_PARAM].getValue())) { | |||||
if (patch.engine < 8) { | if (patch.engine < 8) { | ||||
patch.engine += 8; | patch.engine += 8; | ||||
} | } | ||||
@@ -123,7 +140,7 @@ struct Plaits : Module { | |||||
// Model lights | // Model lights | ||||
int activeEngine = voice.active_engine(); | int activeEngine = voice.active_engine(); | ||||
triPhase += 2.f * engineGetSampleTime() * blockSize; | |||||
triPhase += 2.f * args.sampleTime * blockSize; | |||||
if (triPhase >= 1.f) | if (triPhase >= 1.f) | ||||
triPhase -= 1.f; | triPhase -= 1.f; | ||||
float tri = (triPhase < 0.5f) ? triPhase * 2.f : (1.f - triPhase) * 2.f; | float tri = (triPhase < 0.5f) ? triPhase * 2.f : (1.f - triPhase) * 2.f; | ||||
@@ -134,47 +151,47 @@ struct Plaits : Module { | |||||
} | } | ||||
// Calculate pitch for lowCpu mode if needed | // Calculate pitch for lowCpu mode if needed | ||||
float pitch = params[FREQ_PARAM].value; | |||||
float pitch = params[FREQ_PARAM].getValue(); | |||||
if (lowCpu) | if (lowCpu) | ||||
pitch += log2f(48000.f * engineGetSampleTime()); | |||||
pitch += log2f(48000.f * args.sampleTime); | |||||
// Update patch | // Update patch | ||||
patch.note = 60.f + pitch * 12.f; | patch.note = 60.f + pitch * 12.f; | ||||
patch.harmonics = params[HARMONICS_PARAM].value; | |||||
patch.harmonics = params[HARMONICS_PARAM].getValue(); | |||||
if (!lpg) { | if (!lpg) { | ||||
patch.timbre = params[TIMBRE_PARAM].value; | |||||
patch.morph = params[MORPH_PARAM].value; | |||||
patch.timbre = params[TIMBRE_PARAM].getValue(); | |||||
patch.morph = params[MORPH_PARAM].getValue(); | |||||
} | } | ||||
else { | else { | ||||
patch.lpg_colour = params[TIMBRE_PARAM].value; | |||||
patch.decay = params[MORPH_PARAM].value; | |||||
patch.lpg_colour = params[TIMBRE_PARAM].getValue(); | |||||
patch.decay = params[MORPH_PARAM].getValue(); | |||||
} | } | ||||
patch.frequency_modulation_amount = params[FREQ_CV_PARAM].value; | |||||
patch.timbre_modulation_amount = params[TIMBRE_CV_PARAM].value; | |||||
patch.morph_modulation_amount = params[MORPH_CV_PARAM].value; | |||||
patch.frequency_modulation_amount = params[FREQ_CV_PARAM].getValue(); | |||||
patch.timbre_modulation_amount = params[TIMBRE_CV_PARAM].getValue(); | |||||
patch.morph_modulation_amount = params[MORPH_CV_PARAM].getValue(); | |||||
// Update modulations | // Update modulations | ||||
modulations.engine = inputs[ENGINE_INPUT].value / 5.f; | |||||
modulations.note = inputs[NOTE_INPUT].value * 12.f; | |||||
modulations.frequency = inputs[FREQ_INPUT].value * 6.f; | |||||
modulations.harmonics = inputs[HARMONICS_INPUT].value / 5.f; | |||||
modulations.timbre = inputs[TIMBRE_INPUT].value / 8.f; | |||||
modulations.morph = inputs[MORPH_INPUT].value / 8.f; | |||||
modulations.engine = inputs[ENGINE_INPUT].getVoltage() / 5.f; | |||||
modulations.note = inputs[NOTE_INPUT].getVoltage() * 12.f; | |||||
modulations.frequency = inputs[FREQ_INPUT].getVoltage() * 6.f; | |||||
modulations.harmonics = inputs[HARMONICS_INPUT].getVoltage() / 5.f; | |||||
modulations.timbre = inputs[TIMBRE_INPUT].getVoltage() / 8.f; | |||||
modulations.morph = inputs[MORPH_INPUT].getVoltage() / 8.f; | |||||
// Triggers at around 0.7 V | // Triggers at around 0.7 V | ||||
modulations.trigger = inputs[TRIGGER_INPUT].value / 3.f; | |||||
modulations.level = inputs[LEVEL_INPUT].value / 8.f; | |||||
modulations.trigger = inputs[TRIGGER_INPUT].getVoltage() / 3.f; | |||||
modulations.level = inputs[LEVEL_INPUT].getVoltage() / 8.f; | |||||
modulations.frequency_patched = inputs[FREQ_INPUT].active; | |||||
modulations.timbre_patched = inputs[TIMBRE_INPUT].active; | |||||
modulations.morph_patched = inputs[MORPH_INPUT].active; | |||||
modulations.trigger_patched = inputs[TRIGGER_INPUT].active; | |||||
modulations.level_patched = inputs[LEVEL_INPUT].active; | |||||
modulations.frequency_patched = inputs[FREQ_INPUT].isConnected(); | |||||
modulations.timbre_patched = inputs[TIMBRE_INPUT].isConnected(); | |||||
modulations.morph_patched = inputs[MORPH_INPUT].isConnected(); | |||||
modulations.trigger_patched = inputs[TRIGGER_INPUT].isConnected(); | |||||
modulations.level_patched = inputs[LEVEL_INPUT].isConnected(); | |||||
// Render frames | // Render frames | ||||
plaits::Voice::Frame output[blockSize]; | plaits::Voice::Frame output[blockSize]; | ||||
voice.Render(patch, modulations, output, blockSize); | voice.Render(patch, modulations, output, blockSize); | ||||
// Convert output to frames | // Convert output to frames | ||||
Frame<2> outputFrames[blockSize]; | |||||
dsp::Frame<2> outputFrames[blockSize]; | |||||
for (int i = 0; i < blockSize; i++) { | for (int i = 0; i < blockSize; i++) { | ||||
outputFrames[i].samples[0] = output[i].out / 32768.f; | outputFrames[i].samples[0] = output[i].out / 32768.f; | ||||
outputFrames[i].samples[1] = output[i].aux / 32768.f; | outputFrames[i].samples[1] = output[i].aux / 32768.f; | ||||
@@ -182,12 +199,12 @@ struct Plaits : Module { | |||||
// Convert output | // Convert output | ||||
if (lowCpu) { | if (lowCpu) { | ||||
int len = min(outputBuffer.capacity(), blockSize); | |||||
memcpy(outputBuffer.endData(), outputFrames, len * sizeof(Frame<2>)); | |||||
int len = std::min((int) outputBuffer.capacity(), blockSize); | |||||
memcpy(outputBuffer.endData(), outputFrames, len * sizeof(dsp::Frame<2>)); | |||||
outputBuffer.endIncr(len); | outputBuffer.endIncr(len); | ||||
} | } | ||||
else { | else { | ||||
outputSrc.setRates(48000, engineGetSampleRate()); | |||||
outputSrc.setRates(48000, args.sampleRate); | |||||
int inLen = blockSize; | int inLen = blockSize; | ||||
int outLen = outputBuffer.capacity(); | int outLen = outputBuffer.capacity(); | ||||
outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen); | outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen); | ||||
@@ -197,10 +214,10 @@ struct Plaits : Module { | |||||
// Set output | // Set output | ||||
if (!outputBuffer.empty()) { | if (!outputBuffer.empty()) { | ||||
Frame<2> outputFrame = outputBuffer.shift(); | |||||
dsp::Frame<2> outputFrame = outputBuffer.shift(); | |||||
// Inverting op-amp on outputs | // Inverting op-amp on outputs | ||||
outputs[OUT_OUTPUT].value = -outputFrame.samples[0] * 5.f; | |||||
outputs[AUX_OUTPUT].value = -outputFrame.samples[1] * 5.f; | |||||
outputs[OUT_OUTPUT].setVoltage(-outputFrame.samples[0] * 5.f); | |||||
outputs[AUX_OUTPUT].setVoltage(-outputFrame.samples[1] * 5.f); | |||||
} | } | ||||
} | } | ||||
}; | }; | ||||
@@ -227,35 +244,36 @@ static const std::string modelLabels[16] = { | |||||
struct PlaitsWidget : ModuleWidget { | struct PlaitsWidget : ModuleWidget { | ||||
PlaitsWidget(Plaits *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Plaits.svg"))); | |||||
PlaitsWidget(Plaits *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Plaits.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); | addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | ||||
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | ||||
addParam(createParam<TL1105>(mm2px(Vec(23.32685, 14.6539)), module, Plaits::MODEL1_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(32.22764, 14.6539)), module, Plaits::MODEL2_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan3PSWhite>(mm2px(Vec(3.1577, 20.21088)), module, Plaits::FREQ_PARAM, -4.0, 4.0, 0.0)); | |||||
addParam(createParam<Rogan3PSWhite>(mm2px(Vec(39.3327, 20.21088)), module, Plaits::HARMONICS_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSWhite>(mm2px(Vec(4.04171, 49.6562)), module, Plaits::TIMBRE_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSWhite>(mm2px(Vec(42.71716, 49.6562)), module, Plaits::MORPH_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(7.88712, 77.60705)), module, Plaits::TIMBRE_CV_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(27.2245, 77.60705)), module, Plaits::FREQ_CV_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(46.56189, 77.60705)), module, Plaits::MORPH_CV_PARAM, -1.0, 1.0, 0.0)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(3.31381, 92.48067)), PortWidget::INPUT, module, Plaits::ENGINE_INPUT)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(14.75983, 92.48067)), PortWidget::INPUT, module, Plaits::TIMBRE_INPUT)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(26.20655, 92.48067)), PortWidget::INPUT, module, Plaits::FREQ_INPUT)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(37.65257, 92.48067)), PortWidget::INPUT, module, Plaits::MORPH_INPUT)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(49.0986, 92.48067)), PortWidget::INPUT, module, Plaits::HARMONICS_INPUT)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(3.31381, 107.08103)), PortWidget::INPUT, module, Plaits::TRIGGER_INPUT)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(14.75983, 107.08103)), PortWidget::INPUT, module, Plaits::LEVEL_INPUT)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(26.20655, 107.08103)), PortWidget::INPUT, module, Plaits::NOTE_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(mm2px(Vec(37.65257, 107.08103)), PortWidget::OUTPUT, module, Plaits::OUT_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(mm2px(Vec(49.0986, 107.08103)), PortWidget::OUTPUT, module, Plaits::AUX_OUTPUT)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(23.32685, 14.6539)), module, Plaits::MODEL1_PARAM)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(32.22764, 14.6539)), module, Plaits::MODEL2_PARAM)); | |||||
addParam(createParam<Rogan3PSWhite>(mm2px(Vec(3.1577, 20.21088)), module, Plaits::FREQ_PARAM)); | |||||
addParam(createParam<Rogan3PSWhite>(mm2px(Vec(39.3327, 20.21088)), module, Plaits::HARMONICS_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(mm2px(Vec(4.04171, 49.6562)), module, Plaits::TIMBRE_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(mm2px(Vec(42.71716, 49.6562)), module, Plaits::MORPH_PARAM)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(7.88712, 77.60705)), module, Plaits::TIMBRE_CV_PARAM)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(27.2245, 77.60705)), module, Plaits::FREQ_CV_PARAM)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(46.56189, 77.60705)), module, Plaits::MORPH_CV_PARAM)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(3.31381, 92.48067)), module, Plaits::ENGINE_INPUT)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(14.75983, 92.48067)), module, Plaits::TIMBRE_INPUT)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(26.20655, 92.48067)), module, Plaits::FREQ_INPUT)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(37.65257, 92.48067)), module, Plaits::MORPH_INPUT)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(49.0986, 92.48067)), module, Plaits::HARMONICS_INPUT)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(3.31381, 107.08103)), module, Plaits::TRIGGER_INPUT)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(14.75983, 107.08103)), module, Plaits::LEVEL_INPUT)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(26.20655, 107.08103)), module, Plaits::NOTE_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(mm2px(Vec(37.65257, 107.08103)), module, Plaits::OUT_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(mm2px(Vec(49.0986, 107.08103)), module, Plaits::AUX_OUTPUT)); | |||||
addChild(createLight<MediumLight<GreenRedLight>>(mm2px(Vec(28.79498, 23.31649)), module, Plaits::MODEL_LIGHT + 0 * 2)); | addChild(createLight<MediumLight<GreenRedLight>>(mm2px(Vec(28.79498, 23.31649)), module, Plaits::MODEL_LIGHT + 0 * 2)); | ||||
addChild(createLight<MediumLight<GreenRedLight>>(mm2px(Vec(28.79498, 28.71704)), module, Plaits::MODEL_LIGHT + 1 * 2)); | addChild(createLight<MediumLight<GreenRedLight>>(mm2px(Vec(28.79498, 28.71704)), module, Plaits::MODEL_LIGHT + 1 * 2)); | ||||
@@ -45,10 +45,10 @@ struct Rings : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
SampleRateConverter<1> inputSrc; | |||||
SampleRateConverter<2> outputSrc; | |||||
DoubleRingBuffer<Frame<1>, 256> inputBuffer; | |||||
DoubleRingBuffer<Frame<2>, 256> outputBuffer; | |||||
dsp::SampleRateConverter<1> inputSrc; | |||||
dsp::SampleRateConverter<2> outputSrc; | |||||
dsp::DoubleRingBuffer<dsp::Frame<1>, 256> inputBuffer; | |||||
dsp::DoubleRingBuffer<dsp::Frame<2>, 256> outputBuffer; | |||||
uint16_t reverb_buffer[32768] = {}; | uint16_t reverb_buffer[32768] = {}; | ||||
rings::Part part; | rings::Part part; | ||||
@@ -57,14 +57,14 @@ struct Rings : Module { | |||||
bool strum = false; | bool strum = false; | ||||
bool lastStrum = false; | bool lastStrum = false; | ||||
SchmittTrigger polyphonyTrigger; | |||||
SchmittTrigger modelTrigger; | |||||
dsp::SchmittTrigger polyphonyTrigger; | |||||
dsp::SchmittTrigger modelTrigger; | |||||
int polyphonyMode = 0; | int polyphonyMode = 0; | ||||
rings::ResonatorModel resonatorModel = rings::RESONATOR_MODEL_MODAL; | rings::ResonatorModel resonatorModel = rings::RESONATOR_MODEL_MODAL; | ||||
bool easterEgg = false; | bool easterEgg = false; | ||||
Rings(); | Rings(); | ||||
void step() override; | |||||
void process(const ProcessArgs &args) override; | |||||
json_t *dataToJson() override { | json_t *dataToJson() override { | ||||
json_t *rootJ = json_object(); | json_t *rootJ = json_object(); | ||||
@@ -99,13 +99,27 @@ struct Rings : Module { | |||||
} | } | ||||
void onRandomize() override { | void onRandomize() override { | ||||
polyphonyMode = randomu32() % 3; | |||||
resonatorModel = (rings::ResonatorModel) (randomu32() % 3); | |||||
polyphonyMode = random::u32() % 3; | |||||
resonatorModel = (rings::ResonatorModel) (random::u32() % 3); | |||||
} | } | ||||
}; | }; | ||||
Rings::Rings() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
Rings::Rings() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Rings::POLYPHONY_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Rings::RESONATOR_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Rings::FREQUENCY_PARAM, 0.0, 60.0, 30.0); | |||||
configParam(Rings::STRUCTURE_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Rings::BRIGHTNESS_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Rings::DAMPING_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Rings::POSITION_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Rings::BRIGHTNESS_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Rings::FREQUENCY_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Rings::DAMPING_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Rings::STRUCTURE_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Rings::POSITION_MOD_PARAM, -1.0, 1.0, 0.0); | |||||
memset(&strummer, 0, sizeof(strummer)); | memset(&strummer, 0, sizeof(strummer)); | ||||
memset(&part, 0, sizeof(part)); | memset(&part, 0, sizeof(part)); | ||||
memset(&string_synth, 0, sizeof(string_synth)); | memset(&string_synth, 0, sizeof(string_synth)); | ||||
@@ -115,28 +129,28 @@ Rings::Rings() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
string_synth.Init(reverb_buffer); | string_synth.Init(reverb_buffer); | ||||
} | } | ||||
void Rings::step() { | |||||
void Rings::process(const ProcessArgs &args) { | |||||
// TODO | // TODO | ||||
// "Normalized to a pulse/burst generator that reacts to note changes on the V/OCT input." | // "Normalized to a pulse/burst generator that reacts to note changes on the V/OCT input." | ||||
// Get input | // Get input | ||||
if (!inputBuffer.full()) { | if (!inputBuffer.full()) { | ||||
Frame<1> f; | |||||
f.samples[0] = inputs[IN_INPUT].value / 5.0; | |||||
dsp::Frame<1> f; | |||||
f.samples[0] = inputs[IN_INPUT].getVoltage() / 5.0; | |||||
inputBuffer.push(f); | inputBuffer.push(f); | ||||
} | } | ||||
if (!strum) { | if (!strum) { | ||||
strum = inputs[STRUM_INPUT].value >= 1.0; | |||||
strum = inputs[STRUM_INPUT].getVoltage() >= 1.0; | |||||
} | } | ||||
// Polyphony / model | // Polyphony / model | ||||
if (polyphonyTrigger.process(params[POLYPHONY_PARAM].value)) { | |||||
if (polyphonyTrigger.process(params[POLYPHONY_PARAM].getValue())) { | |||||
polyphonyMode = (polyphonyMode + 1) % 3; | polyphonyMode = (polyphonyMode + 1) % 3; | ||||
} | } | ||||
lights[POLYPHONY_GREEN_LIGHT].value = (polyphonyMode == 0 || polyphonyMode == 1) ? 1.0 : 0.0; | lights[POLYPHONY_GREEN_LIGHT].value = (polyphonyMode == 0 || polyphonyMode == 1) ? 1.0 : 0.0; | ||||
lights[POLYPHONY_RED_LIGHT].value = (polyphonyMode == 1 || polyphonyMode == 2) ? 1.0 : 0.0; | lights[POLYPHONY_RED_LIGHT].value = (polyphonyMode == 1 || polyphonyMode == 2) ? 1.0 : 0.0; | ||||
if (modelTrigger.process(params[RESONATOR_PARAM].value)) { | |||||
if (modelTrigger.process(params[RESONATOR_PARAM].getValue())) { | |||||
resonatorModel = (rings::ResonatorModel) ((resonatorModel + 1) % 3); | resonatorModel = (rings::ResonatorModel) ((resonatorModel + 1) % 3); | ||||
} | } | ||||
int modelColor = resonatorModel % 3; | int modelColor = resonatorModel % 3; | ||||
@@ -148,10 +162,10 @@ void Rings::step() { | |||||
float in[24] = {}; | float in[24] = {}; | ||||
// Convert input buffer | // Convert input buffer | ||||
{ | { | ||||
inputSrc.setRates(engineGetSampleRate(), 48000); | |||||
inputSrc.setRates(args.sampleRate, 48000); | |||||
int inLen = inputBuffer.size(); | int inLen = inputBuffer.size(); | ||||
int outLen = 24; | int outLen = 24; | ||||
inputSrc.process(inputBuffer.startData(), &inLen, (Frame<1>*) in, &outLen); | |||||
inputSrc.process(inputBuffer.startData(), &inLen, (dsp::Frame<1>*) in, &outLen); | |||||
inputBuffer.startIncr(inLen); | inputBuffer.startIncr(inLen); | ||||
} | } | ||||
@@ -167,26 +181,26 @@ void Rings::step() { | |||||
// Patch | // Patch | ||||
rings::Patch patch; | rings::Patch patch; | ||||
float structure = params[STRUCTURE_PARAM].value + 3.3*quadraticBipolar(params[STRUCTURE_MOD_PARAM].value)*inputs[STRUCTURE_MOD_INPUT].value/5.0; | |||||
float structure = params[STRUCTURE_PARAM].getValue() + 3.3*dsp::quadraticBipolar(params[STRUCTURE_MOD_PARAM].getValue())*inputs[STRUCTURE_MOD_INPUT].getVoltage()/5.0; | |||||
patch.structure = clamp(structure, 0.0f, 0.9995f); | patch.structure = clamp(structure, 0.0f, 0.9995f); | ||||
patch.brightness = clamp(params[BRIGHTNESS_PARAM].value + 3.3*quadraticBipolar(params[BRIGHTNESS_MOD_PARAM].value)*inputs[BRIGHTNESS_MOD_INPUT].value/5.0, 0.0f, 1.0f); | |||||
patch.damping = clamp(params[DAMPING_PARAM].value + 3.3*quadraticBipolar(params[DAMPING_MOD_PARAM].value)*inputs[DAMPING_MOD_INPUT].value/5.0, 0.0f, 0.9995f); | |||||
patch.position = clamp(params[POSITION_PARAM].value + 3.3*quadraticBipolar(params[POSITION_MOD_PARAM].value)*inputs[POSITION_MOD_INPUT].value/5.0, 0.0f, 0.9995f); | |||||
patch.brightness = clamp(params[BRIGHTNESS_PARAM].getValue() + 3.3*dsp::quadraticBipolar(params[BRIGHTNESS_MOD_PARAM].getValue())*inputs[BRIGHTNESS_MOD_INPUT].getVoltage()/5.0, 0.0f, 1.0f); | |||||
patch.damping = clamp(params[DAMPING_PARAM].getValue() + 3.3*dsp::quadraticBipolar(params[DAMPING_MOD_PARAM].getValue())*inputs[DAMPING_MOD_INPUT].getVoltage()/5.0, 0.0f, 0.9995f); | |||||
patch.position = clamp(params[POSITION_PARAM].getValue() + 3.3*dsp::quadraticBipolar(params[POSITION_MOD_PARAM].getValue())*inputs[POSITION_MOD_INPUT].getVoltage()/5.0, 0.0f, 0.9995f); | |||||
// Performance | // Performance | ||||
rings::PerformanceState performance_state; | rings::PerformanceState performance_state; | ||||
performance_state.note = 12.0*inputs[PITCH_INPUT].normalize(1/12.0); | |||||
float transpose = params[FREQUENCY_PARAM].value; | |||||
performance_state.note = 12.0*inputs[PITCH_INPUT].getNormalVoltage(1/12.0); | |||||
float transpose = params[FREQUENCY_PARAM].getValue(); | |||||
// Quantize transpose if pitch input is connected | // Quantize transpose if pitch input is connected | ||||
if (inputs[PITCH_INPUT].active) { | |||||
if (inputs[PITCH_INPUT].isConnected()) { | |||||
transpose = roundf(transpose); | transpose = roundf(transpose); | ||||
} | } | ||||
performance_state.tonic = 12.0 + clamp(transpose, 0.0f, 60.0f); | performance_state.tonic = 12.0 + clamp(transpose, 0.0f, 60.0f); | ||||
performance_state.fm = clamp(48.0 * 3.3*quarticBipolar(params[FREQUENCY_MOD_PARAM].value) * inputs[FREQUENCY_MOD_INPUT].normalize(1.0)/5.0, -48.0f, 48.0f); | |||||
performance_state.fm = clamp(48.0 * 3.3*dsp::quarticBipolar(params[FREQUENCY_MOD_PARAM].getValue()) * inputs[FREQUENCY_MOD_INPUT].getNormalVoltage(1.0)/5.0, -48.0f, 48.0f); | |||||
performance_state.internal_exciter = !inputs[IN_INPUT].active; | |||||
performance_state.internal_strum = !inputs[STRUM_INPUT].active; | |||||
performance_state.internal_note = !inputs[PITCH_INPUT].active; | |||||
performance_state.internal_exciter = !inputs[IN_INPUT].isConnected(); | |||||
performance_state.internal_strum = !inputs[STRUM_INPUT].isConnected(); | |||||
performance_state.internal_note = !inputs[PITCH_INPUT].isConnected(); | |||||
// TODO | // TODO | ||||
// "Normalized to a step detector on the V/OCT input and a transient detector on the IN input." | // "Normalized to a step detector on the V/OCT input and a transient detector on the IN input." | ||||
@@ -210,13 +224,13 @@ void Rings::step() { | |||||
// Convert output buffer | // Convert output buffer | ||||
{ | { | ||||
Frame<2> outputFrames[24]; | |||||
dsp::Frame<2> outputFrames[24]; | |||||
for (int i = 0; i < 24; i++) { | for (int i = 0; i < 24; i++) { | ||||
outputFrames[i].samples[0] = out[i]; | outputFrames[i].samples[0] = out[i]; | ||||
outputFrames[i].samples[1] = aux[i]; | outputFrames[i].samples[1] = aux[i]; | ||||
} | } | ||||
outputSrc.setRates(48000, engineGetSampleRate()); | |||||
outputSrc.setRates(48000, args.sampleRate); | |||||
int inLen = 24; | int inLen = 24; | ||||
int outLen = outputBuffer.capacity(); | int outLen = outputBuffer.capacity(); | ||||
outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen); | outputSrc.process(outputFrames, &inLen, outputBuffer.endData(), &outLen); | ||||
@@ -226,57 +240,58 @@ void Rings::step() { | |||||
// Set output | // Set output | ||||
if (!outputBuffer.empty()) { | if (!outputBuffer.empty()) { | ||||
Frame<2> outputFrame = outputBuffer.shift(); | |||||
dsp::Frame<2> outputFrame = outputBuffer.shift(); | |||||
// "Note that you need to insert a jack into each output to split the signals: when only one jack is inserted, both signals are mixed together." | // "Note that you need to insert a jack into each output to split the signals: when only one jack is inserted, both signals are mixed together." | ||||
if (outputs[ODD_OUTPUT].active && outputs[EVEN_OUTPUT].active) { | |||||
outputs[ODD_OUTPUT].value = clamp(outputFrame.samples[0], -1.0, 1.0)*5.0; | |||||
outputs[EVEN_OUTPUT].value = clamp(outputFrame.samples[1], -1.0, 1.0)*5.0; | |||||
if (outputs[ODD_OUTPUT].isConnected() && outputs[EVEN_OUTPUT].isConnected()) { | |||||
outputs[ODD_OUTPUT].setVoltage(clamp(outputFrame.samples[0], -1.0, 1.0)*5.0); | |||||
outputs[EVEN_OUTPUT].setVoltage(clamp(outputFrame.samples[1], -1.0, 1.0)*5.0); | |||||
} | } | ||||
else { | else { | ||||
float v = clamp(outputFrame.samples[0] + outputFrame.samples[1], -1.0, 1.0)*5.0; | float v = clamp(outputFrame.samples[0] + outputFrame.samples[1], -1.0, 1.0)*5.0; | ||||
outputs[ODD_OUTPUT].value = v; | |||||
outputs[EVEN_OUTPUT].value = v; | |||||
outputs[ODD_OUTPUT].setVoltage(v); | |||||
outputs[EVEN_OUTPUT].setVoltage(v); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
struct RingsWidget : ModuleWidget { | struct RingsWidget : ModuleWidget { | ||||
RingsWidget(Rings *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Rings.svg"))); | |||||
RingsWidget(Rings *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Rings.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 0))); | addChild(createWidget<ScrewSilver>(Vec(15, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(180, 0))); | addChild(createWidget<ScrewSilver>(Vec(180, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addChild(createWidget<ScrewSilver>(Vec(180, 365))); | addChild(createWidget<ScrewSilver>(Vec(180, 365))); | ||||
addParam(createParam<TL1105>(Vec(14, 40), module, Rings::POLYPHONY_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<TL1105>(Vec(179, 40), module, Rings::RESONATOR_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan3PSWhite>(Vec(29, 72), module, Rings::FREQUENCY_PARAM, 0.0, 60.0, 30.0)); | |||||
addParam(createParam<Rogan3PSWhite>(Vec(126, 72), module, Rings::STRUCTURE_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(13, 158), module, Rings::BRIGHTNESS_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(83, 158), module, Rings::DAMPING_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(154, 158), module, Rings::POSITION_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Trimpot>(Vec(19, 229), module, Rings::BRIGHTNESS_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(57, 229), module, Rings::FREQUENCY_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(96, 229), module, Rings::DAMPING_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(134, 229), module, Rings::STRUCTURE_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(173, 229), module, Rings::POSITION_MOD_PARAM, -1.0, 1.0, 0.0)); | |||||
addInput(createPort<PJ301MPort>(Vec(15, 273), PortWidget::INPUT, module, Rings::BRIGHTNESS_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(54, 273), PortWidget::INPUT, module, Rings::FREQUENCY_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(92, 273), PortWidget::INPUT, module, Rings::DAMPING_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(131, 273), PortWidget::INPUT, module, Rings::STRUCTURE_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(169, 273), PortWidget::INPUT, module, Rings::POSITION_MOD_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(15, 316), PortWidget::INPUT, module, Rings::STRUM_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(54, 316), PortWidget::INPUT, module, Rings::PITCH_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(92, 316), PortWidget::INPUT, module, Rings::IN_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(131, 316), PortWidget::OUTPUT, module, Rings::ODD_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(169, 316), PortWidget::OUTPUT, module, Rings::EVEN_OUTPUT)); | |||||
addParam(createParam<TL1105>(Vec(14, 40), module, Rings::POLYPHONY_PARAM)); | |||||
addParam(createParam<TL1105>(Vec(179, 40), module, Rings::RESONATOR_PARAM)); | |||||
addParam(createParam<Rogan3PSWhite>(Vec(29, 72), module, Rings::FREQUENCY_PARAM)); | |||||
addParam(createParam<Rogan3PSWhite>(Vec(126, 72), module, Rings::STRUCTURE_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(13, 158), module, Rings::BRIGHTNESS_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(83, 158), module, Rings::DAMPING_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(154, 158), module, Rings::POSITION_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(19, 229), module, Rings::BRIGHTNESS_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(57, 229), module, Rings::FREQUENCY_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(96, 229), module, Rings::DAMPING_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(134, 229), module, Rings::STRUCTURE_MOD_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(173, 229), module, Rings::POSITION_MOD_PARAM)); | |||||
addInput(createInput<PJ301MPort>(Vec(15, 273), module, Rings::BRIGHTNESS_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(54, 273), module, Rings::FREQUENCY_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(92, 273), module, Rings::DAMPING_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(131, 273), module, Rings::STRUCTURE_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(169, 273), module, Rings::POSITION_MOD_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(15, 316), module, Rings::STRUM_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(54, 316), module, Rings::PITCH_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(92, 316), module, Rings::IN_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(131, 316), module, Rings::ODD_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(169, 316), module, Rings::EVEN_OUTPUT)); | |||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(37, 43), module, Rings::POLYPHONY_GREEN_LIGHT)); | addChild(createLight<MediumLight<GreenRedLight>>(Vec(37, 43), module, Rings::POLYPHONY_GREEN_LIGHT)); | ||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(162, 43), module, Rings::RESONATOR_GREEN_LIGHT)); | addChild(createLight<MediumLight<GreenRedLight>>(Vec(162, 43), module, Rings::RESONATOR_GREEN_LIGHT)); | ||||
@@ -30,29 +30,37 @@ struct Shades : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
Shades() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} | |||||
void step() override; | |||||
Shades() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Shades::GAIN1_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Shades::GAIN2_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Shades::GAIN3_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Shades::MODE1_PARAM, 0.0, 1.0, 1.0); | |||||
configParam(Shades::MODE2_PARAM, 0.0, 1.0, 1.0); | |||||
configParam(Shades::MODE3_PARAM, 0.0, 1.0, 1.0); | |||||
} | |||||
void process(const ProcessArgs &args) override; | |||||
}; | }; | ||||
void Shades::step() { | |||||
void Shades::process(const ProcessArgs &args) { | |||||
float out = 0.0; | float out = 0.0; | ||||
for (int i = 0; i < 3; i++) { | for (int i = 0; i < 3; i++) { | ||||
float in = inputs[IN1_INPUT + i].normalize(5.0); | float in = inputs[IN1_INPUT + i].normalize(5.0); | ||||
if ((int)params[MODE1_PARAM + i].value == 1) { | |||||
if ((int)params[MODE1_PARAM + i].getValue() == 1) { | |||||
// attenuverter | // attenuverter | ||||
in *= 2.0 * params[GAIN1_PARAM + i].value - 1.0; | |||||
in *= 2.0 * params[GAIN1_PARAM + i].getValue() - 1.0; | |||||
} | } | ||||
else { | else { | ||||
// attenuator | // attenuator | ||||
in *= params[GAIN1_PARAM + i].value; | |||||
in *= params[GAIN1_PARAM + i].getValue(); | |||||
} | } | ||||
out += in; | out += in; | ||||
lights[OUT1_POS_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, out / 5.0)); | lights[OUT1_POS_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, out / 5.0)); | ||||
lights[OUT1_NEG_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, -out / 5.0)); | lights[OUT1_NEG_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, -out / 5.0)); | ||||
if (outputs[OUT1_OUTPUT + i].active) { | |||||
outputs[OUT1_OUTPUT + i].value = out; | |||||
if (outputs[OUT1_OUTPUT + i].isConnected()) { | |||||
outputs[OUT1_OUTPUT + i].setVoltage(out); | |||||
out = 0.0; | out = 0.0; | ||||
} | } | ||||
} | } | ||||
@@ -60,27 +68,28 @@ void Shades::step() { | |||||
struct ShadesWidget : ModuleWidget { | struct ShadesWidget : ModuleWidget { | ||||
ShadesWidget(Shades *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Shades.svg"))); | |||||
ShadesWidget(Shades *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Shades.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 0))); | addChild(createWidget<ScrewSilver>(Vec(15, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addParam(createParam<Rogan1PSRed>(Vec(40, 40), module, Shades::GAIN1_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(40, 106), module, Shades::GAIN2_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(40, 172), module, Shades::GAIN3_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Rogan1PSRed>(Vec(40, 40), module, Shades::GAIN1_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(40, 106), module, Shades::GAIN2_PARAM)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(40, 172), module, Shades::GAIN3_PARAM)); | |||||
addParam(createParam<CKSS>(Vec(10, 51), module, Shades::MODE1_PARAM, 0.0, 1.0, 1.0)); | |||||
addParam(createParam<CKSS>(Vec(10, 117), module, Shades::MODE2_PARAM, 0.0, 1.0, 1.0)); | |||||
addParam(createParam<CKSS>(Vec(10, 183), module, Shades::MODE3_PARAM, 0.0, 1.0, 1.0)); | |||||
addParam(createParam<CKSS>(Vec(10, 51), module, Shades::MODE1_PARAM)); | |||||
addParam(createParam<CKSS>(Vec(10, 117), module, Shades::MODE2_PARAM)); | |||||
addParam(createParam<CKSS>(Vec(10, 183), module, Shades::MODE3_PARAM)); | |||||
addInput(createPort<PJ301MPort>(Vec(9, 245), PortWidget::INPUT, module, Shades::IN1_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(9, 281), PortWidget::INPUT, module, Shades::IN2_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(9, 317), PortWidget::INPUT, module, Shades::IN3_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(9, 245), module, Shades::IN1_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(9, 281), module, Shades::IN2_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(9, 317), module, Shades::IN3_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(56, 245), PortWidget::OUTPUT, module, Shades::OUT1_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(56, 281), PortWidget::OUTPUT, module, Shades::OUT2_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(56, 317), PortWidget::OUTPUT, module, Shades::OUT3_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(56, 245), module, Shades::OUT1_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(56, 281), module, Shades::OUT2_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(56, 317), module, Shades::OUT3_OUTPUT)); | |||||
addChild(createLight<SmallLight<GreenRedLight>>(Vec(41, 254), module, Shades::OUT1_POS_LIGHT)); | addChild(createLight<SmallLight<GreenRedLight>>(Vec(41, 254), module, Shades::OUT1_POS_LIGHT)); | ||||
addChild(createLight<SmallLight<GreenRedLight>>(Vec(41, 290), module, Shades::OUT2_POS_LIGHT)); | addChild(createLight<SmallLight<GreenRedLight>>(Vec(41, 290), module, Shades::OUT2_POS_LIGHT)); | ||||
@@ -15,14 +15,14 @@ struct LongPressButton { | |||||
}; | }; | ||||
float pressedTime = 0.f; | float pressedTime = 0.f; | ||||
BooleanTrigger trigger; | |||||
dsp::BooleanTrigger trigger; | |||||
Events step(Param ¶m) { | Events step(Param ¶m) { | ||||
Events result = NO_PRESS; | Events result = NO_PRESS; | ||||
bool pressed = param.value > 0.f; | bool pressed = param.value > 0.f; | ||||
if (pressed && pressedTime >= 0.f) { | if (pressed && pressedTime >= 0.f) { | ||||
pressedTime += engineGetSampleTime(); | |||||
pressedTime += APP->engine->getSampleTime(); | |||||
if (pressedTime >= 1.f) { | if (pressedTime >= 1.f) { | ||||
pressedTime = -1.f; | pressedTime = -1.f; | ||||
result = LONG_PRESS; | result = LONG_PRESS; | ||||
@@ -153,7 +153,27 @@ struct Stages : Module { | |||||
int blockIndex = 0; | int blockIndex = 0; | ||||
GroupBuilder groupBuilder; | GroupBuilder groupBuilder; | ||||
Stages() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
Stages() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Stages::SHAPE_PARAMS + 0, 0.0, 1.0, 0.5); | |||||
configParam(Stages::SHAPE_PARAMS + 1, 0.0, 1.0, 0.5); | |||||
configParam(Stages::SHAPE_PARAMS + 2, 0.0, 1.0, 0.5); | |||||
configParam(Stages::SHAPE_PARAMS + 3, 0.0, 1.0, 0.5); | |||||
configParam(Stages::SHAPE_PARAMS + 4, 0.0, 1.0, 0.5); | |||||
configParam(Stages::SHAPE_PARAMS + 5, 0.0, 1.0, 0.5); | |||||
configParam(Stages::TYPE_PARAMS + 0, 0.0, 1.0, 0.0); | |||||
configParam(Stages::TYPE_PARAMS + 1, 0.0, 1.0, 0.0); | |||||
configParam(Stages::TYPE_PARAMS + 2, 0.0, 1.0, 0.0); | |||||
configParam(Stages::TYPE_PARAMS + 3, 0.0, 1.0, 0.0); | |||||
configParam(Stages::TYPE_PARAMS + 4, 0.0, 1.0, 0.0); | |||||
configParam(Stages::TYPE_PARAMS + 5, 0.0, 1.0, 0.0); | |||||
configParam(Stages::LEVEL_PARAMS + 0, 0.0, 1.0, 0.5); | |||||
configParam(Stages::LEVEL_PARAMS + 1, 0.0, 1.0, 0.5); | |||||
configParam(Stages::LEVEL_PARAMS + 2, 0.0, 1.0, 0.5); | |||||
configParam(Stages::LEVEL_PARAMS + 3, 0.0, 1.0, 0.5); | |||||
configParam(Stages::LEVEL_PARAMS + 4, 0.0, 1.0, 0.5); | |||||
configParam(Stages::LEVEL_PARAMS + 5, 0.0, 1.0, 0.5); | |||||
onReset(); | onReset(); | ||||
} | } | ||||
@@ -203,7 +223,7 @@ struct Stages : Module { | |||||
void onSampleRateChange() override { | void onSampleRateChange() override { | ||||
for (int i = 0; i < NUM_CHANNELS; i++) { | for (int i = 0; i < NUM_CHANNELS; i++) { | ||||
segment_generator[i].SetSampleRate(engineGetSampleRate()); | |||||
segment_generator[i].SetSampleRate(APP->engine->getSampleRate()); | |||||
} | } | ||||
} | } | ||||
@@ -212,8 +232,8 @@ struct Stages : Module { | |||||
float primaries[NUM_CHANNELS]; | float primaries[NUM_CHANNELS]; | ||||
float secondaries[NUM_CHANNELS]; | float secondaries[NUM_CHANNELS]; | ||||
for (int i = 0; i < NUM_CHANNELS; i++) { | for (int i = 0; i < NUM_CHANNELS; i++) { | ||||
primaries[i] = clamp(params[LEVEL_PARAMS + i].value + inputs[LEVEL_INPUTS + i].value / 8.f, 0.f, 1.f); | |||||
secondaries[i] = params[SHAPE_PARAMS + i].value; | |||||
primaries[i] = clamp(params[LEVEL_PARAMS + i].getValue() + inputs[LEVEL_INPUTS + i].getVoltage() / 8.f, 0.f, 1.f); | |||||
secondaries[i] = params[SHAPE_PARAMS + i].getValue(); | |||||
} | } | ||||
// See if the group associations have changed since the last group | // See if the group associations have changed since the last group | ||||
@@ -309,9 +329,9 @@ struct Stages : Module { | |||||
} | } | ||||
} | } | ||||
void step() override { | |||||
void process(const ProcessArgs &args) override { | |||||
// Oscillate flashing the type lights | // Oscillate flashing the type lights | ||||
lightOscillatorPhase += 0.5f * engineGetSampleTime(); | |||||
lightOscillatorPhase += 0.5f * args.sampleTime; | |||||
if (lightOscillatorPhase >= 1.0f) | if (lightOscillatorPhase >= 1.0f) | ||||
lightOscillatorPhase -= 1.0f; | lightOscillatorPhase -= 1.0f; | ||||
@@ -327,7 +347,7 @@ struct Stages : Module { | |||||
// Input | // Input | ||||
for (int i = 0; i < NUM_CHANNELS; i++) { | for (int i = 0; i < NUM_CHANNELS; i++) { | ||||
bool gate = (inputs[GATE_INPUTS + i].value >= 1.7f); | |||||
bool gate = (inputs[GATE_INPUTS + i].getVoltage() >= 1.7f); | |||||
last_gate_flags[i] = stmlib::ExtractGateFlags(last_gate_flags[i], gate); | last_gate_flags[i] = stmlib::ExtractGateFlags(last_gate_flags[i], gate); | ||||
gate_flags[i][blockIndex] = last_gate_flags[i]; | gate_flags[i][blockIndex] = last_gate_flags[i]; | ||||
} | } | ||||
@@ -347,8 +367,8 @@ struct Stages : Module { | |||||
int segment = group.first_segment + j; | int segment = group.first_segment + j; | ||||
float envelope = envelopeBuffer[segment][blockIndex]; | float envelope = envelopeBuffer[segment][blockIndex]; | ||||
outputs[ENVELOPE_OUTPUTS + segment].value = envelope * 8.f; | |||||
lights[ENVELOPE_LIGHTS + segment].setBrightnessSmooth(envelope); | |||||
outputs[ENVELOPE_OUTPUTS + segment].setVoltage(envelope * 8.f); | |||||
lights[ENVELOPE_LIGHTS + segment].setSmoothBrightness(envelope, args.sampleTime); | |||||
numberOfLoopsInGroup += configurations[segment].loop ? 1 : 0; | numberOfLoopsInGroup += configurations[segment].loop ? 1 : 0; | ||||
float flashlevel = 1.f; | float flashlevel = 1.f; | ||||
@@ -373,52 +393,53 @@ struct Stages : Module { | |||||
struct StagesWidget : ModuleWidget { | struct StagesWidget : ModuleWidget { | ||||
StagesWidget(Stages *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Stages.svg"))); | |||||
StagesWidget(Stages *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Stages.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); | addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | ||||
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | ||||
addParam(createParam<Trimpot>(mm2px(Vec(3.72965, 13.98158)), module, Stages::SHAPE_PARAMS + 0, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(15.17012, 13.98158)), module, Stages::SHAPE_PARAMS + 1, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(26.6099, 13.98158)), module, Stages::SHAPE_PARAMS + 2, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(38.07174, 13.98158)), module, Stages::SHAPE_PARAMS + 3, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(49.51152, 13.98158)), module, Stages::SHAPE_PARAMS + 4, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(60.95199, 13.98158)), module, Stages::SHAPE_PARAMS + 5, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(4.17259, 32.37248)), module, Stages::TYPE_PARAMS + 0, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(15.61237, 32.37248)), module, Stages::TYPE_PARAMS + 1, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(27.05284, 32.37248)), module, Stages::TYPE_PARAMS + 2, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(38.51399, 32.37248)), module, Stages::TYPE_PARAMS + 3, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(49.95446, 32.37248)), module, Stages::TYPE_PARAMS + 4, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(61.39424, 32.37248)), module, Stages::TYPE_PARAMS + 5, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<LEDSliderGreen>(mm2px(Vec(3.36193, 43.06508)), module, Stages::LEVEL_PARAMS + 0, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<LEDSliderGreen>(mm2px(Vec(14.81619, 43.06508)), module, Stages::LEVEL_PARAMS + 1, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<LEDSliderGreen>(mm2px(Vec(26.26975, 43.06508)), module, Stages::LEVEL_PARAMS + 2, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<LEDSliderGreen>(mm2px(Vec(37.70265, 43.06508)), module, Stages::LEVEL_PARAMS + 3, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<LEDSliderGreen>(mm2px(Vec(49.15759, 43.06508)), module, Stages::LEVEL_PARAMS + 4, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<LEDSliderGreen>(mm2px(Vec(60.61184, 43.06508)), module, Stages::LEVEL_PARAMS + 5, 0.0, 1.0, 0.5)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(2.70756, 77.75277)), PortWidget::INPUT, module, Stages::LEVEL_INPUTS + 0)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(14.14734, 77.75277)), PortWidget::INPUT, module, Stages::LEVEL_INPUTS + 1)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(25.58781, 77.75277)), PortWidget::INPUT, module, Stages::LEVEL_INPUTS + 2)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(37.04896, 77.75277)), PortWidget::INPUT, module, Stages::LEVEL_INPUTS + 3)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(48.48943, 77.75277)), PortWidget::INPUT, module, Stages::LEVEL_INPUTS + 4)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(59.92921, 77.75277)), PortWidget::INPUT, module, Stages::LEVEL_INPUTS + 5)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(2.70756, 92.35239)), PortWidget::INPUT, module, Stages::GATE_INPUTS + 0)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(14.14734, 92.35239)), PortWidget::INPUT, module, Stages::GATE_INPUTS + 1)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(25.58781, 92.35239)), PortWidget::INPUT, module, Stages::GATE_INPUTS + 2)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(37.04896, 92.35239)), PortWidget::INPUT, module, Stages::GATE_INPUTS + 3)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(48.48943, 92.35239)), PortWidget::INPUT, module, Stages::GATE_INPUTS + 4)); | |||||
addInput(createPort<PJ301MPort>(mm2px(Vec(59.92921, 92.35239)), PortWidget::INPUT, module, Stages::GATE_INPUTS + 5)); | |||||
addOutput(createPort<PJ301MPort>(mm2px(Vec(2.70756, 106.95203)), PortWidget::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 0)); | |||||
addOutput(createPort<PJ301MPort>(mm2px(Vec(14.14734, 106.95203)), PortWidget::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 1)); | |||||
addOutput(createPort<PJ301MPort>(mm2px(Vec(25.58781, 106.95203)), PortWidget::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 2)); | |||||
addOutput(createPort<PJ301MPort>(mm2px(Vec(37.04896, 106.95203)), PortWidget::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 3)); | |||||
addOutput(createPort<PJ301MPort>(mm2px(Vec(48.48943, 106.95203)), PortWidget::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 4)); | |||||
addOutput(createPort<PJ301MPort>(mm2px(Vec(59.92921, 106.95203)), PortWidget::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 5)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(3.72965, 13.98158)), module, Stages::SHAPE_PARAMS + 0)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(15.17012, 13.98158)), module, Stages::SHAPE_PARAMS + 1)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(26.6099, 13.98158)), module, Stages::SHAPE_PARAMS + 2)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(38.07174, 13.98158)), module, Stages::SHAPE_PARAMS + 3)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(49.51152, 13.98158)), module, Stages::SHAPE_PARAMS + 4)); | |||||
addParam(createParam<Trimpot>(mm2px(Vec(60.95199, 13.98158)), module, Stages::SHAPE_PARAMS + 5)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(4.17259, 32.37248)), module, Stages::TYPE_PARAMS + 0)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(15.61237, 32.37248)), module, Stages::TYPE_PARAMS + 1)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(27.05284, 32.37248)), module, Stages::TYPE_PARAMS + 2)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(38.51399, 32.37248)), module, Stages::TYPE_PARAMS + 3)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(49.95446, 32.37248)), module, Stages::TYPE_PARAMS + 4)); | |||||
addParam(createParam<TL1105>(mm2px(Vec(61.39424, 32.37248)), module, Stages::TYPE_PARAMS + 5)); | |||||
addParam(createParam<LEDSliderGreen>(mm2px(Vec(3.36193, 43.06508)), module, Stages::LEVEL_PARAMS + 0)); | |||||
addParam(createParam<LEDSliderGreen>(mm2px(Vec(14.81619, 43.06508)), module, Stages::LEVEL_PARAMS + 1)); | |||||
addParam(createParam<LEDSliderGreen>(mm2px(Vec(26.26975, 43.06508)), module, Stages::LEVEL_PARAMS + 2)); | |||||
addParam(createParam<LEDSliderGreen>(mm2px(Vec(37.70265, 43.06508)), module, Stages::LEVEL_PARAMS + 3)); | |||||
addParam(createParam<LEDSliderGreen>(mm2px(Vec(49.15759, 43.06508)), module, Stages::LEVEL_PARAMS + 4)); | |||||
addParam(createParam<LEDSliderGreen>(mm2px(Vec(60.61184, 43.06508)), module, Stages::LEVEL_PARAMS + 5)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(2.70756, 77.75277)), module, Stages::LEVEL_INPUTS + 0)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(14.14734, 77.75277)), module, Stages::LEVEL_INPUTS + 1)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(25.58781, 77.75277)), module, Stages::LEVEL_INPUTS + 2)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(37.04896, 77.75277)), module, Stages::LEVEL_INPUTS + 3)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(48.48943, 77.75277)), module, Stages::LEVEL_INPUTS + 4)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(59.92921, 77.75277)), module, Stages::LEVEL_INPUTS + 5)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(2.70756, 92.35239)), module, Stages::GATE_INPUTS + 0)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(14.14734, 92.35239)), module, Stages::GATE_INPUTS + 1)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(25.58781, 92.35239)), module, Stages::GATE_INPUTS + 2)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(37.04896, 92.35239)), module, Stages::GATE_INPUTS + 3)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(48.48943, 92.35239)), module, Stages::GATE_INPUTS + 4)); | |||||
addInput(createInput<PJ301MPort>(mm2px(Vec(59.92921, 92.35239)), module, Stages::GATE_INPUTS + 5)); | |||||
addOutput(createOutput<PJ301MPort>(mm2px(Vec(2.70756, 106.95203)), module, Stages::ENVELOPE_OUTPUTS + 0)); | |||||
addOutput(createOutput<PJ301MPort>(mm2px(Vec(14.14734, 106.95203)), module, Stages::ENVELOPE_OUTPUTS + 1)); | |||||
addOutput(createOutput<PJ301MPort>(mm2px(Vec(25.58781, 106.95203)), module, Stages::ENVELOPE_OUTPUTS + 2)); | |||||
addOutput(createOutput<PJ301MPort>(mm2px(Vec(37.04896, 106.95203)), module, Stages::ENVELOPE_OUTPUTS + 3)); | |||||
addOutput(createOutput<PJ301MPort>(mm2px(Vec(48.48943, 106.95203)), module, Stages::ENVELOPE_OUTPUTS + 4)); | |||||
addOutput(createOutput<PJ301MPort>(mm2px(Vec(59.92921, 106.95203)), module, Stages::ENVELOPE_OUTPUTS + 5)); | |||||
addChild(createLight<MediumLight<GreenRedLight>>(mm2px(Vec(5.27737, 26.74447)), module, Stages::TYPE_LIGHTS + 0 * 2)); | addChild(createLight<MediumLight<GreenRedLight>>(mm2px(Vec(5.27737, 26.74447)), module, Stages::TYPE_LIGHTS + 0 * 2)); | ||||
addChild(createLight<MediumLight<GreenRedLight>>(mm2px(Vec(16.73784, 26.74447)), module, Stages::TYPE_LIGHTS + 1 * 2)); | addChild(createLight<MediumLight<GreenRedLight>>(mm2px(Vec(16.73784, 26.74447)), module, Stages::TYPE_LIGHTS + 1 * 2)); | ||||
@@ -47,11 +47,11 @@ struct Tides : Module { | |||||
tides::Generator generator; | tides::Generator generator; | ||||
int frame = 0; | int frame = 0; | ||||
uint8_t lastGate; | uint8_t lastGate; | ||||
SchmittTrigger modeTrigger; | |||||
SchmittTrigger rangeTrigger; | |||||
dsp::SchmittTrigger modeTrigger; | |||||
dsp::SchmittTrigger rangeTrigger; | |||||
Tides(); | Tides(); | ||||
void step() override; | |||||
void process(const ProcessArgs &args) override; | |||||
void onReset() override { | void onReset() override { | ||||
@@ -61,8 +61,8 @@ struct Tides : Module { | |||||
} | } | ||||
void onRandomize() override { | void onRandomize() override { | ||||
generator.set_range((tides::GeneratorRange) (randomu32() % 3)); | |||||
generator.set_mode((tides::GeneratorMode) (randomu32() % 3)); | |||||
generator.set_range((tides::GeneratorRange) (random::u32() % 3)); | |||||
generator.set_mode((tides::GeneratorMode) (random::u32() % 3)); | |||||
} | } | ||||
json_t *dataToJson() override { | json_t *dataToJson() override { | ||||
@@ -94,16 +94,25 @@ struct Tides : Module { | |||||
}; | }; | ||||
Tides::Tides() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
Tides::Tides() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Tides::MODE_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Tides::RANGE_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Tides::FREQUENCY_PARAM, -48.0, 48.0, 0.0); | |||||
configParam(Tides::FM_PARAM, -12.0, 12.0, 0.0); | |||||
configParam(Tides::SHAPE_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Tides::SLOPE_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Tides::SMOOTHNESS_PARAM, -1.0, 1.0, 0.0); | |||||
memset(&generator, 0, sizeof(generator)); | memset(&generator, 0, sizeof(generator)); | ||||
generator.Init(); | generator.Init(); | ||||
generator.set_sync(false); | generator.set_sync(false); | ||||
onReset(); | onReset(); | ||||
} | } | ||||
void Tides::step() { | |||||
void Tides::process(const ProcessArgs &args) { | |||||
tides::GeneratorMode mode = generator.mode(); | tides::GeneratorMode mode = generator.mode(); | ||||
if (modeTrigger.process(params[MODE_PARAM].value)) { | |||||
if (modeTrigger.process(params[MODE_PARAM].getValue())) { | |||||
mode = (tides::GeneratorMode) (((int)mode - 1 + 3) % 3); | mode = (tides::GeneratorMode) (((int)mode - 1 + 3) % 3); | ||||
generator.set_mode(mode); | generator.set_mode(mode); | ||||
} | } | ||||
@@ -111,7 +120,7 @@ void Tides::step() { | |||||
lights[MODE_RED_LIGHT].value = (mode == 0) ? 1.0 : 0.0; | lights[MODE_RED_LIGHT].value = (mode == 0) ? 1.0 : 0.0; | ||||
tides::GeneratorRange range = generator.range(); | tides::GeneratorRange range = generator.range(); | ||||
if (rangeTrigger.process(params[RANGE_PARAM].value)) { | |||||
if (rangeTrigger.process(params[RANGE_PARAM].getValue())) { | |||||
range = (tides::GeneratorRange) (((int)range - 1 + 3) % 3); | range = (tides::GeneratorRange) (((int)range - 1 + 3) % 3); | ||||
generator.set_range(range); | generator.set_range(range); | ||||
} | } | ||||
@@ -123,18 +132,18 @@ void Tides::step() { | |||||
frame = 0; | frame = 0; | ||||
// Pitch | // Pitch | ||||
float pitch = params[FREQUENCY_PARAM].value; | |||||
pitch += 12.0 * inputs[PITCH_INPUT].value; | |||||
pitch += params[FM_PARAM].value * inputs[FM_INPUT].normalize(0.1) / 5.0; | |||||
float pitch = params[FREQUENCY_PARAM].getValue(); | |||||
pitch += 12.0 * inputs[PITCH_INPUT].getVoltage(); | |||||
pitch += params[FM_PARAM].getValue() * inputs[FM_INPUT].getNormalVoltage(0.1) / 5.0; | |||||
pitch += 60.0; | pitch += 60.0; | ||||
// Scale to the global sample rate | // Scale to the global sample rate | ||||
pitch += log2f(48000.0 / engineGetSampleRate()) * 12.0; | |||||
pitch += log2f(48000.0 / args.sampleRate) * 12.0; | |||||
generator.set_pitch((int) clamp(pitch * 0x80, (float) -0x8000, (float) 0x7fff)); | generator.set_pitch((int) clamp(pitch * 0x80, (float) -0x8000, (float) 0x7fff)); | ||||
// Slope, smoothness, pitch | // Slope, smoothness, pitch | ||||
int16_t shape = clamp(params[SHAPE_PARAM].value + inputs[SHAPE_INPUT].value / 5.0f, -1.0f, 1.0f) * 0x7fff; | |||||
int16_t slope = clamp(params[SLOPE_PARAM].value + inputs[SLOPE_INPUT].value / 5.0f, -1.0f, 1.0f) * 0x7fff; | |||||
int16_t smoothness = clamp(params[SMOOTHNESS_PARAM].value + inputs[SMOOTHNESS_INPUT].value / 5.0f, -1.0f, 1.0f) * 0x7fff; | |||||
int16_t shape = clamp(params[SHAPE_PARAM].getValue() + inputs[SHAPE_INPUT].getVoltage() / 5.0f, -1.0f, 1.0f) * 0x7fff; | |||||
int16_t slope = clamp(params[SLOPE_PARAM].getValue() + inputs[SLOPE_INPUT].getVoltage() / 5.0f, -1.0f, 1.0f) * 0x7fff; | |||||
int16_t smoothness = clamp(params[SMOOTHNESS_PARAM].getValue() + inputs[SMOOTHNESS_INPUT].getVoltage() / 5.0f, -1.0f, 1.0f) * 0x7fff; | |||||
generator.set_shape(shape); | generator.set_shape(shape); | ||||
generator.set_slope(slope); | generator.set_slope(slope); | ||||
generator.set_smoothness(smoothness); | generator.set_smoothness(smoothness); | ||||
@@ -142,23 +151,23 @@ void Tides::step() { | |||||
// Sync | // Sync | ||||
// Slight deviation from spec here. | // Slight deviation from spec here. | ||||
// Instead of toggling sync by holding the range button, just enable it if the clock port is plugged in. | // Instead of toggling sync by holding the range button, just enable it if the clock port is plugged in. | ||||
generator.set_sync(inputs[CLOCK_INPUT].active && !sheep); | |||||
generator.set_sync(inputs[CLOCK_INPUT].isConnected() && !sheep); | |||||
// Generator | // Generator | ||||
generator.Process(sheep); | generator.Process(sheep); | ||||
} | } | ||||
// Level | // Level | ||||
uint16_t level = clamp(inputs[LEVEL_INPUT].normalize(8.0) / 8.0f, 0.0f, 1.0f) * 0xffff; | |||||
uint16_t level = clamp(inputs[LEVEL_INPUT].getNormalVoltage(8.0) / 8.0f, 0.0f, 1.0f) * 0xffff; | |||||
if (level < 32) | if (level < 32) | ||||
level = 0; | level = 0; | ||||
uint8_t gate = 0; | uint8_t gate = 0; | ||||
if (inputs[FREEZE_INPUT].value >= 0.7) | |||||
if (inputs[FREEZE_INPUT].getVoltage() >= 0.7) | |||||
gate |= tides::CONTROL_FREEZE; | gate |= tides::CONTROL_FREEZE; | ||||
if (inputs[TRIG_INPUT].value >= 0.7) | |||||
if (inputs[TRIG_INPUT].getVoltage() >= 0.7) | |||||
gate |= tides::CONTROL_GATE; | gate |= tides::CONTROL_GATE; | ||||
if (inputs[CLOCK_INPUT].value >= 0.7) | |||||
if (inputs[CLOCK_INPUT].getVoltage() >= 0.7) | |||||
gate |= tides::CONTROL_CLOCK; | gate |= tides::CONTROL_CLOCK; | ||||
if (!(lastGate & tides::CONTROL_CLOCK) && (gate & tides::CONTROL_CLOCK)) | if (!(lastGate & tides::CONTROL_CLOCK) && (gate & tides::CONTROL_CLOCK)) | ||||
gate |= tides::CONTROL_GATE_RISING; | gate |= tides::CONTROL_GATE_RISING; | ||||
@@ -177,33 +186,34 @@ void Tides::step() { | |||||
float unif = (float) uni / 0xffff; | float unif = (float) uni / 0xffff; | ||||
float bif = (float) bi / 0x8000; | float bif = (float) bi / 0x8000; | ||||
outputs[HIGH_OUTPUT].value = sample.flags & tides::FLAG_END_OF_ATTACK ? 0.0 : 5.0; | |||||
outputs[LOW_OUTPUT].value = sample.flags & tides::FLAG_END_OF_RELEASE ? 0.0 : 5.0; | |||||
outputs[UNI_OUTPUT].value = unif * 8.0; | |||||
outputs[BI_OUTPUT].value = bif * 5.0; | |||||
outputs[HIGH_OUTPUT].setVoltage(sample.flags & tides::FLAG_END_OF_ATTACK ? 0.0 : 5.0); | |||||
outputs[LOW_OUTPUT].setVoltage(sample.flags & tides::FLAG_END_OF_RELEASE ? 0.0 : 5.0); | |||||
outputs[UNI_OUTPUT].setVoltage(unif * 8.0); | |||||
outputs[BI_OUTPUT].setVoltage(bif * 5.0); | |||||
if (sample.flags & tides::FLAG_END_OF_ATTACK) | if (sample.flags & tides::FLAG_END_OF_ATTACK) | ||||
unif *= -1.0; | unif *= -1.0; | ||||
lights[PHASE_GREEN_LIGHT].setBrightnessSmooth(fmaxf(0.0, unif)); | |||||
lights[PHASE_RED_LIGHT].setBrightnessSmooth(fmaxf(0.0, -unif)); | |||||
lights[PHASE_GREEN_LIGHT].setSmoothBrightness(fmaxf(0.0, unif), args.sampleTime); | |||||
lights[PHASE_RED_LIGHT].setSmoothBrightness(fmaxf(0.0, -unif), args.sampleTime); | |||||
} | } | ||||
struct TidesWidget : ModuleWidget { | struct TidesWidget : ModuleWidget { | ||||
SVGPanel *tidesPanel; | |||||
SVGPanel *sheepPanel; | |||||
SvgPanel *tidesPanel; | |||||
SvgPanel *sheepPanel; | |||||
TidesWidget(Tides *module) : ModuleWidget(module) { | |||||
TidesWidget(Tides *module) { | |||||
setModule(module); | |||||
box.size = Vec(15*14, 380); | box.size = Vec(15*14, 380); | ||||
{ | { | ||||
tidesPanel = new SVGPanel(); | |||||
tidesPanel->setBackground(SVG::load(assetPlugin(pluginInstance, "res/Tides.svg"))); | |||||
tidesPanel = new SvgPanel(); | |||||
tidesPanel->setBackground(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Tides.svg"))); | |||||
tidesPanel->box.size = box.size; | tidesPanel->box.size = box.size; | ||||
addChild(tidesPanel); | addChild(tidesPanel); | ||||
} | } | ||||
{ | { | ||||
sheepPanel = new SVGPanel(); | |||||
sheepPanel->setBackground(SVG::load(assetPlugin(pluginInstance, "res/Sheep.svg"))); | |||||
sheepPanel = new SvgPanel(); | |||||
sheepPanel->setBackground(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Sheep.svg"))); | |||||
sheepPanel->box.size = box.size; | sheepPanel->box.size = box.size; | ||||
addChild(sheepPanel); | addChild(sheepPanel); | ||||
} | } | ||||
@@ -213,31 +223,31 @@ struct TidesWidget : ModuleWidget { | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addChild(createWidget<ScrewSilver>(Vec(180, 365))); | addChild(createWidget<ScrewSilver>(Vec(180, 365))); | ||||
addParam(createParam<CKD6>(Vec(19, 52), module, Tides::MODE_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<CKD6>(Vec(19, 93), module, Tides::RANGE_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<CKD6>(Vec(19, 52), module, Tides::MODE_PARAM)); | |||||
addParam(createParam<CKD6>(Vec(19, 93), module, Tides::RANGE_PARAM)); | |||||
addParam(createParam<Rogan3PSGreen>(Vec(78, 60), module, Tides::FREQUENCY_PARAM, -48.0, 48.0, 0.0)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(156, 66), module, Tides::FM_PARAM, -12.0, 12.0, 0.0)); | |||||
addParam(createParam<Rogan3PSGreen>(Vec(78, 60), module, Tides::FREQUENCY_PARAM)); | |||||
addParam(createParam<Rogan1PSGreen>(Vec(156, 66), module, Tides::FM_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(13, 155), module, Tides::SHAPE_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(85, 155), module, Tides::SLOPE_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(156, 155), module, Tides::SMOOTHNESS_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(13, 155), module, Tides::SHAPE_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(85, 155), module, Tides::SLOPE_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(156, 155), module, Tides::SMOOTHNESS_PARAM)); | |||||
addInput(createPort<PJ301MPort>(Vec(21, 219), PortWidget::INPUT, module, Tides::SHAPE_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(93, 219), PortWidget::INPUT, module, Tides::SLOPE_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(164, 219), PortWidget::INPUT, module, Tides::SMOOTHNESS_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(21, 219), module, Tides::SHAPE_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(93, 219), module, Tides::SLOPE_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(164, 219), module, Tides::SMOOTHNESS_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(21, 274), PortWidget::INPUT, module, Tides::TRIG_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(57, 274), PortWidget::INPUT, module, Tides::FREEZE_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(93, 274), PortWidget::INPUT, module, Tides::PITCH_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(128, 274), PortWidget::INPUT, module, Tides::FM_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(164, 274), PortWidget::INPUT, module, Tides::LEVEL_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(21, 274), module, Tides::TRIG_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(57, 274), module, Tides::FREEZE_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(93, 274), module, Tides::PITCH_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(128, 274), module, Tides::FM_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(164, 274), module, Tides::LEVEL_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(21, 316), PortWidget::INPUT, module, Tides::CLOCK_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(57, 316), PortWidget::OUTPUT, module, Tides::HIGH_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(93, 316), PortWidget::OUTPUT, module, Tides::LOW_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(128, 316), PortWidget::OUTPUT, module, Tides::UNI_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(164, 316), PortWidget::OUTPUT, module, Tides::BI_OUTPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(21, 316), module, Tides::CLOCK_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(57, 316), module, Tides::HIGH_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(93, 316), module, Tides::LOW_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(128, 316), module, Tides::UNI_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(164, 316), module, Tides::BI_OUTPUT)); | |||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(56, 61), module, Tides::MODE_GREEN_LIGHT)); | addChild(createLight<MediumLight<GreenRedLight>>(Vec(56, 61), module, Tides::MODE_GREEN_LIGHT)); | ||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(56, 82), module, Tides::PHASE_GREEN_LIGHT)); | addChild(createLight<MediumLight<GreenRedLight>>(Vec(56, 82), module, Tides::PHASE_GREEN_LIGHT)); | ||||
@@ -84,9 +84,9 @@ struct Tides2 : Module { | |||||
int range; | int range; | ||||
tides2::OutputMode output_mode; | tides2::OutputMode output_mode; | ||||
tides2::RampMode ramp_mode; | tides2::RampMode ramp_mode; | ||||
BooleanTrigger rangeTrigger; | |||||
BooleanTrigger modeTrigger; | |||||
BooleanTrigger rampTrigger; | |||||
dsp::BooleanTrigger rangeTrigger; | |||||
dsp::BooleanTrigger modeTrigger; | |||||
dsp::BooleanTrigger rampTrigger; | |||||
// Buffers | // Buffers | ||||
tides2::PolySlopeGenerator::OutputSample out[tides2::kBlockSize]; | tides2::PolySlopeGenerator::OutputSample out[tides2::kBlockSize]; | ||||
@@ -99,7 +99,22 @@ struct Tides2 : Module { | |||||
tides2::OutputMode previous_output_mode = tides2::OUTPUT_MODE_GATES; | tides2::OutputMode previous_output_mode = tides2::OUTPUT_MODE_GATES; | ||||
uint8_t frame = 0; | uint8_t frame = 0; | ||||
Tides2() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
Tides2() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Tides2::RANGE_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Tides2::MODE_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Tides2::FREQUENCY_PARAM, -48, 48, 0.0); | |||||
configParam(Tides2::SHAPE_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Tides2::RAMP_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Tides2::SMOOTHNESS_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Tides2::SLOPE_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Tides2::SHIFT_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Tides2::SLOPE_CV_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Tides2::FREQUENCY_CV_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Tides2::SMOOTHNESS_CV_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Tides2::SHAPE_CV_PARAM, -1.0, 1.0, 0.0); | |||||
configParam(Tides2::SHIFT_CV_PARAM, -1.0, 1.0, 0.0); | |||||
poly_slope_generator.Init(); | poly_slope_generator.Init(); | ||||
ratio_index_quantizer.Init(); | ratio_index_quantizer.Init(); | ||||
memset(&out, 0, sizeof(out)); | memset(&out, 0, sizeof(out)); | ||||
@@ -116,13 +131,13 @@ struct Tides2 : Module { | |||||
} | } | ||||
void onRandomize() override { | void onRandomize() override { | ||||
range = randomu32() % 3; | |||||
output_mode = (tides2::OutputMode) (randomu32() % 4); | |||||
ramp_mode = (tides2::RampMode) (randomu32() % 3); | |||||
range = random::u32() % 3; | |||||
output_mode = (tides2::OutputMode) (random::u32() % 4); | |||||
ramp_mode = (tides2::RampMode) (random::u32() % 3); | |||||
} | } | ||||
void onSampleRateChange() override { | void onSampleRateChange() override { | ||||
ramp_extractor.Init(engineGetSampleRate(), 40.f / engineGetSampleRate()); | |||||
ramp_extractor.Init(APP->engine->getSampleRate(), 40.f / APP->engine->getSampleRate()); | |||||
} | } | ||||
json_t *dataToJson() override { | json_t *dataToJson() override { | ||||
@@ -149,23 +164,23 @@ struct Tides2 : Module { | |||||
ramp_mode = (tides2::RampMode) json_integer_value(rampJ); | ramp_mode = (tides2::RampMode) json_integer_value(rampJ); | ||||
} | } | ||||
void step() override { | |||||
void process(const ProcessArgs &args) override { | |||||
// Switches | // Switches | ||||
if (rangeTrigger.process(params[RANGE_PARAM].value > 0.f)) { | |||||
if (rangeTrigger.process(params[RANGE_PARAM].getValue() > 0.f)) { | |||||
range = (range + 1) % 3; | range = (range + 1) % 3; | ||||
} | } | ||||
if (modeTrigger.process(params[MODE_PARAM].value > 0.f)) { | |||||
if (modeTrigger.process(params[MODE_PARAM].getValue() > 0.f)) { | |||||
output_mode = (tides2::OutputMode) ((output_mode + 1) % 4); | output_mode = (tides2::OutputMode) ((output_mode + 1) % 4); | ||||
} | } | ||||
if (rampTrigger.process(params[RAMP_PARAM].value > 0.f)) { | |||||
if (rampTrigger.process(params[RAMP_PARAM].getValue() > 0.f)) { | |||||
ramp_mode = (tides2::RampMode) ((ramp_mode + 1) % 3); | ramp_mode = (tides2::RampMode) ((ramp_mode + 1) % 3); | ||||
} | } | ||||
// Input gates | // Input gates | ||||
trig_flags[frame] = stmlib::ExtractGateFlags(previous_trig_flag, inputs[TRIG_INPUT].value >= 1.7f); | |||||
trig_flags[frame] = stmlib::ExtractGateFlags(previous_trig_flag, inputs[TRIG_INPUT].getVoltage() >= 1.7f); | |||||
previous_trig_flag = trig_flags[frame]; | previous_trig_flag = trig_flags[frame]; | ||||
clock_flags[frame] = stmlib::ExtractGateFlags(previous_clock_flag, inputs[CLOCK_INPUT].value >= 1.7f); | |||||
clock_flags[frame] = stmlib::ExtractGateFlags(previous_clock_flag, inputs[CLOCK_INPUT].getVoltage() >= 1.7f); | |||||
previous_clock_flag = clock_flags[frame]; | previous_clock_flag = clock_flags[frame]; | ||||
// Process block | // Process block | ||||
@@ -173,14 +188,14 @@ struct Tides2 : Module { | |||||
frame = 0; | frame = 0; | ||||
tides2::Range range_mode = (range < 2) ? tides2::RANGE_CONTROL : tides2::RANGE_AUDIO; | tides2::Range range_mode = (range < 2) ? tides2::RANGE_CONTROL : tides2::RANGE_AUDIO; | ||||
float note = clamp(params[FREQUENCY_PARAM].value + 12.f * inputs[V_OCT_INPUT].value, -96.f, 96.f); | |||||
float fm = clamp(params[FREQUENCY_CV_PARAM].value * inputs[FREQUENCY_INPUT].value * 12.f, -96.f, 96.f); | |||||
float note = clamp(params[FREQUENCY_PARAM].getValue() + 12.f * inputs[V_OCT_INPUT].getVoltage(), -96.f, 96.f); | |||||
float fm = clamp(params[FREQUENCY_CV_PARAM].getValue() * inputs[FREQUENCY_INPUT].getVoltage() * 12.f, -96.f, 96.f); | |||||
float transposition = note + fm; | float transposition = note + fm; | ||||
float ramp[tides2::kBlockSize]; | float ramp[tides2::kBlockSize]; | ||||
float frequency; | float frequency; | ||||
if (inputs[CLOCK_INPUT].active) { | |||||
if (inputs[CLOCK_INPUT].isConnected()) { | |||||
if (must_reset_ramp_extractor) { | if (must_reset_ramp_extractor) { | ||||
ramp_extractor.Reset(); | ramp_extractor.Reset(); | ||||
} | } | ||||
@@ -196,15 +211,15 @@ struct Tides2 : Module { | |||||
must_reset_ramp_extractor = false; | must_reset_ramp_extractor = false; | ||||
} | } | ||||
else { | else { | ||||
frequency = kRootScaled[range] / engineGetSampleRate() * stmlib::SemitonesToRatio(transposition); | |||||
frequency = kRootScaled[range] / args.sampleRate * stmlib::SemitonesToRatio(transposition); | |||||
must_reset_ramp_extractor = true; | must_reset_ramp_extractor = true; | ||||
} | } | ||||
// Get parameters | // Get parameters | ||||
float slope = clamp(params[SLOPE_PARAM].value + cubic(params[SLOPE_CV_PARAM].value) * inputs[SLOPE_INPUT].value / 10.f, 0.f, 1.f); | |||||
float shape = clamp(params[SHAPE_PARAM].value + cubic(params[SHAPE_CV_PARAM].value) * inputs[SHAPE_INPUT].value / 10.f, 0.f, 1.f); | |||||
float smoothness = clamp(params[SMOOTHNESS_PARAM].value + cubic(params[SMOOTHNESS_CV_PARAM].value) * inputs[SMOOTHNESS_INPUT].value / 10.f, 0.f, 1.f); | |||||
float shift = clamp(params[SHIFT_PARAM].value + cubic(params[SHIFT_CV_PARAM].value) * inputs[SHIFT_INPUT].value / 10.f, 0.f, 1.f); | |||||
float slope = clamp(params[SLOPE_PARAM].getValue() + dsp::cubic(params[SLOPE_CV_PARAM].getValue()) * inputs[SLOPE_INPUT].getVoltage() / 10.f, 0.f, 1.f); | |||||
float shape = clamp(params[SHAPE_PARAM].getValue() + dsp::cubic(params[SHAPE_CV_PARAM].getValue()) * inputs[SHAPE_INPUT].getVoltage() / 10.f, 0.f, 1.f); | |||||
float smoothness = clamp(params[SMOOTHNESS_PARAM].getValue() + dsp::cubic(params[SMOOTHNESS_CV_PARAM].getValue()) * inputs[SMOOTHNESS_INPUT].getVoltage() / 10.f, 0.f, 1.f); | |||||
float shift = clamp(params[SHIFT_PARAM].getValue() + dsp::cubic(params[SHIFT_CV_PARAM].getValue()) * inputs[SHIFT_INPUT].getVoltage() / 10.f, 0.f, 1.f); | |||||
if (output_mode != previous_output_mode) { | if (output_mode != previous_output_mode) { | ||||
poly_slope_generator.Reset(); | poly_slope_generator.Reset(); | ||||
@@ -222,7 +237,7 @@ struct Tides2 : Module { | |||||
smoothness, | smoothness, | ||||
shift, | shift, | ||||
trig_flags, | trig_flags, | ||||
!inputs[TRIG_INPUT].active && inputs[CLOCK_INPUT].active ? ramp : NULL, | |||||
!inputs[TRIG_INPUT].isConnected() && inputs[CLOCK_INPUT].isConnected() ? ramp : NULL, | |||||
out, | out, | ||||
tides2::kBlockSize); | tides2::kBlockSize); | ||||
@@ -238,35 +253,36 @@ struct Tides2 : Module { | |||||
// Outputs | // Outputs | ||||
for (int i = 0; i < 4; i++) { | for (int i = 0; i < 4; i++) { | ||||
float value = out[frame].channel[i]; | float value = out[frame].channel[i]; | ||||
outputs[OUT_OUTPUTS + i].value = value; | |||||
lights[OUTPUT_LIGHTS + i].setBrightnessSmooth(value); | |||||
outputs[OUT_OUTPUTS + i].setVoltage(value); | |||||
lights[OUTPUT_LIGHTS + i].setSmoothBrightness(value, args.sampleTime); | |||||
} | } | ||||
} | } | ||||
}; | }; | ||||
struct Tides2Widget : ModuleWidget { | struct Tides2Widget : ModuleWidget { | ||||
Tides2Widget(Tides2 *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Tides2.svg"))); | |||||
Tides2Widget(Tides2 *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Tides2.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); | addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | ||||
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | ||||
addParam(createParamCentered<TL1105>(mm2px(Vec(7.425, 16.15)), module, Tides2::RANGE_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(63.325, 16.15)), module, Tides2::MODE_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(16.325, 33.449)), module, Tides2::FREQUENCY_PARAM, -48, 48, 0.0)); | |||||
addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(54.425, 33.449)), module, Tides2::SHAPE_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(35.375, 38.699)), module, Tides2::RAMP_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(35.375, 55.549)), module, Tides2::SMOOTHNESS_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(11.575, 60.599)), module, Tides2::SLOPE_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(59.175, 60.599)), module, Tides2::SHIFT_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParamCentered<Trimpot>(mm2px(Vec(9.276, 80.599)), module, Tides2::SLOPE_CV_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<Trimpot>(mm2px(Vec(22.324, 80.599)), module, Tides2::FREQUENCY_CV_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<Trimpot>(mm2px(Vec(35.375, 80.599)), module, Tides2::SMOOTHNESS_CV_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<Trimpot>(mm2px(Vec(48.425, 80.599)), module, Tides2::SHAPE_CV_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<Trimpot>(mm2px(Vec(61.475, 80.599)), module, Tides2::SHIFT_CV_PARAM, -1.0, 1.0, 0.0)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(7.425, 16.15)), module, Tides2::RANGE_PARAM)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(63.325, 16.15)), module, Tides2::MODE_PARAM)); | |||||
addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(16.325, 33.449)), module, Tides2::FREQUENCY_PARAM)); | |||||
addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(54.425, 33.449)), module, Tides2::SHAPE_PARAM)); | |||||
addParam(createParamCentered<TL1105>(mm2px(Vec(35.375, 38.699)), module, Tides2::RAMP_PARAM)); | |||||
addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(35.375, 55.549)), module, Tides2::SMOOTHNESS_PARAM)); | |||||
addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(11.575, 60.599)), module, Tides2::SLOPE_PARAM)); | |||||
addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(59.175, 60.599)), module, Tides2::SHIFT_PARAM)); | |||||
addParam(createParamCentered<Trimpot>(mm2px(Vec(9.276, 80.599)), module, Tides2::SLOPE_CV_PARAM)); | |||||
addParam(createParamCentered<Trimpot>(mm2px(Vec(22.324, 80.599)), module, Tides2::FREQUENCY_CV_PARAM)); | |||||
addParam(createParamCentered<Trimpot>(mm2px(Vec(35.375, 80.599)), module, Tides2::SMOOTHNESS_CV_PARAM)); | |||||
addParam(createParamCentered<Trimpot>(mm2px(Vec(48.425, 80.599)), module, Tides2::SHAPE_CV_PARAM)); | |||||
addParam(createParamCentered<Trimpot>(mm2px(Vec(61.475, 80.599)), module, Tides2::SHIFT_CV_PARAM)); | |||||
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.775, 96.499)), module, Tides2::SLOPE_INPUT)); | addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.775, 96.499)), module, Tides2::SLOPE_INPUT)); | ||||
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.225, 96.499)), module, Tides2::FREQUENCY_INPUT)); | addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.225, 96.499)), module, Tides2::FREQUENCY_INPUT)); | ||||
@@ -39,28 +39,38 @@ struct Veils : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
Veils() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {} | |||||
void step() override; | |||||
Veils() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Veils::GAIN1_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Veils::GAIN2_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Veils::GAIN3_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Veils::GAIN4_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Veils::RESPONSE1_PARAM, 0.0, 1.0, 1.0); | |||||
configParam(Veils::RESPONSE2_PARAM, 0.0, 1.0, 1.0); | |||||
configParam(Veils::RESPONSE3_PARAM, 0.0, 1.0, 1.0); | |||||
configParam(Veils::RESPONSE4_PARAM, 0.0, 1.0, 1.0); | |||||
} | |||||
void process(const ProcessArgs &args) override; | |||||
}; | }; | ||||
void Veils::step() { | |||||
void Veils::process(const ProcessArgs &args) { | |||||
float out = 0.0; | float out = 0.0; | ||||
for (int i = 0; i < 4; i++) { | for (int i = 0; i < 4; i++) { | ||||
float in = inputs[IN1_INPUT + i].value * params[GAIN1_PARAM + i].value; | |||||
if (inputs[CV1_INPUT + i].active) { | |||||
float linear = fmaxf(inputs[CV1_INPUT + i].value / 5.0, 0.0); | |||||
float in = inputs[IN1_INPUT + i].getVoltage() * params[GAIN1_PARAM + i].getValue(); | |||||
if (inputs[CV1_INPUT + i].isConnected()) { | |||||
float linear = fmaxf(inputs[CV1_INPUT + i].getVoltage() / 5.0, 0.0); | |||||
linear = clamp(linear, 0.0f, 2.0f); | linear = clamp(linear, 0.0f, 2.0f); | ||||
const float base = 200.0; | const float base = 200.0; | ||||
float exponential = rescale(powf(base, linear / 2.0f), 1.0f, base, 0.0f, 10.0f); | float exponential = rescale(powf(base, linear / 2.0f), 1.0f, base, 0.0f, 10.0f); | ||||
in *= crossfade(exponential, linear, params[RESPONSE1_PARAM + i].value); | |||||
in *= crossfade(exponential, linear, params[RESPONSE1_PARAM + i].getValue()); | |||||
} | } | ||||
out += in; | out += in; | ||||
lights[OUT1_POS_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, out / 5.0)); | |||||
lights[OUT1_NEG_LIGHT + 2*i].setBrightnessSmooth(fmaxf(0.0, -out / 5.0)); | |||||
if (outputs[OUT1_OUTPUT + i].active) { | |||||
outputs[OUT1_OUTPUT + i].value = out; | |||||
lights[OUT1_POS_LIGHT + 2*i].setSmoothBrightness(fmaxf(0.0, out / 5.0), args.sampleTime); | |||||
lights[OUT1_NEG_LIGHT + 2*i].setSmoothBrightness(fmaxf(0.0, -out / 5.0), args.sampleTime); | |||||
if (outputs[OUT1_OUTPUT + i].isConnected()) { | |||||
outputs[OUT1_OUTPUT + i].setVoltage(out); | |||||
out = 0.0; | out = 0.0; | ||||
} | } | ||||
} | } | ||||
@@ -68,38 +78,39 @@ void Veils::step() { | |||||
struct VeilsWidget : ModuleWidget { | struct VeilsWidget : ModuleWidget { | ||||
VeilsWidget(Veils *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Veils.svg"))); | |||||
VeilsWidget(Veils *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Veils.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 0))); | addChild(createWidget<ScrewSilver>(Vec(15, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(150, 0))); | addChild(createWidget<ScrewSilver>(Vec(150, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addChild(createWidget<ScrewSilver>(Vec(150, 365))); | addChild(createWidget<ScrewSilver>(Vec(150, 365))); | ||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 52), module, Veils::GAIN1_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 131), module, Veils::GAIN2_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 210), module, Veils::GAIN3_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 288), module, Veils::GAIN4_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(72, 56), module, Veils::RESPONSE1_PARAM, 0.0, 1.0, 1.0)); | |||||
addParam(createParam<Trimpot>(Vec(72, 135), module, Veils::RESPONSE2_PARAM, 0.0, 1.0, 1.0)); | |||||
addParam(createParam<Trimpot>(Vec(72, 214), module, Veils::RESPONSE3_PARAM, 0.0, 1.0, 1.0)); | |||||
addParam(createParam<Trimpot>(Vec(72, 292), module, Veils::RESPONSE4_PARAM, 0.0, 1.0, 1.0)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 41), PortWidget::INPUT, module, Veils::IN1_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 120), PortWidget::INPUT, module, Veils::IN2_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 198), PortWidget::INPUT, module, Veils::IN3_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 277), PortWidget::INPUT, module, Veils::IN4_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 80), PortWidget::INPUT, module, Veils::CV1_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 159), PortWidget::INPUT, module, Veils::CV2_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 238), PortWidget::INPUT, module, Veils::CV3_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(110, 316), PortWidget::INPUT, module, Veils::CV4_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(144, 41), PortWidget::OUTPUT, module, Veils::OUT1_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(144, 120), PortWidget::OUTPUT, module, Veils::OUT2_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(144, 198), PortWidget::OUTPUT, module, Veils::OUT3_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(144, 277), PortWidget::OUTPUT, module, Veils::OUT4_OUTPUT)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 52), module, Veils::GAIN1_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 131), module, Veils::GAIN2_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 210), module, Veils::GAIN3_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(8, 288), module, Veils::GAIN4_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(72, 56), module, Veils::RESPONSE1_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(72, 135), module, Veils::RESPONSE2_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(72, 214), module, Veils::RESPONSE3_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(72, 292), module, Veils::RESPONSE4_PARAM)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 41), module, Veils::IN1_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 120), module, Veils::IN2_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 198), module, Veils::IN3_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 277), module, Veils::IN4_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 80), module, Veils::CV1_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 159), module, Veils::CV2_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 238), module, Veils::CV3_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(110, 316), module, Veils::CV4_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(144, 41), module, Veils::OUT1_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(144, 120), module, Veils::OUT2_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(144, 198), module, Veils::OUT3_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(144, 277), module, Veils::OUT4_OUTPUT)); | |||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(152, 87), module, Veils::OUT1_POS_LIGHT)); | addChild(createLight<MediumLight<GreenRedLight>>(Vec(152, 87), module, Veils::OUT1_POS_LIGHT)); | ||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(152, 166), module, Veils::OUT2_POS_LIGHT)); | addChild(createLight<MediumLight<GreenRedLight>>(Vec(152, 166), module, Veils::OUT2_POS_LIGHT)); | ||||
@@ -36,10 +36,10 @@ struct Warps : Module { | |||||
warps::Modulator modulator; | warps::Modulator modulator; | ||||
warps::ShortFrame inputFrames[60] = {}; | warps::ShortFrame inputFrames[60] = {}; | ||||
warps::ShortFrame outputFrames[60] = {}; | warps::ShortFrame outputFrames[60] = {}; | ||||
SchmittTrigger stateTrigger; | |||||
dsp::SchmittTrigger stateTrigger; | |||||
Warps(); | Warps(); | ||||
void step() override; | |||||
void process(const ProcessArgs &args) override; | |||||
json_t *dataToJson() override { | json_t *dataToJson() override { | ||||
json_t *rootJ = json_object(); | json_t *rootJ = json_object(); | ||||
@@ -63,20 +63,27 @@ struct Warps : Module { | |||||
void onRandomize() override { | void onRandomize() override { | ||||
warps::Parameters *p = modulator.mutable_parameters(); | warps::Parameters *p = modulator.mutable_parameters(); | ||||
p->carrier_shape = randomu32() % 4; | |||||
p->carrier_shape = random::u32() % 4; | |||||
} | } | ||||
}; | }; | ||||
Warps::Warps() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { | |||||
Warps::Warps() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
configParam(Warps::ALGORITHM_PARAM, 0.0, 8.0, 0.0); | |||||
configParam(Warps::TIMBRE_PARAM, 0.0, 1.0, 0.5); | |||||
configParam(Warps::STATE_PARAM, 0.0, 1.0, 0.0); | |||||
configParam(Warps::LEVEL1_PARAM, 0.0, 1.0, 1.0); | |||||
configParam(Warps::LEVEL2_PARAM, 0.0, 1.0, 1.0); | |||||
memset(&modulator, 0, sizeof(modulator)); | memset(&modulator, 0, sizeof(modulator)); | ||||
modulator.Init(96000.0f); | modulator.Init(96000.0f); | ||||
} | } | ||||
void Warps::step() { | |||||
void Warps::process(const ProcessArgs &args) { | |||||
// State trigger | // State trigger | ||||
warps::Parameters *p = modulator.mutable_parameters(); | warps::Parameters *p = modulator.mutable_parameters(); | ||||
if (stateTrigger.process(params[STATE_PARAM].value)) { | |||||
if (stateTrigger.process(params[STATE_PARAM].getValue())) { | |||||
p->carrier_shape = (p->carrier_shape + 1) % 4; | p->carrier_shape = (p->carrier_shape + 1) % 4; | ||||
} | } | ||||
lights[CARRIER_GREEN_LIGHT].value = (p->carrier_shape == 1 || p->carrier_shape == 2) ? 1.0 : 0.0; | lights[CARRIER_GREEN_LIGHT].value = (p->carrier_shape == 1 || p->carrier_shape == 2) ? 1.0 : 0.0; | ||||
@@ -86,9 +93,9 @@ void Warps::step() { | |||||
if (++frame >= 60) { | if (++frame >= 60) { | ||||
frame = 0; | frame = 0; | ||||
p->channel_drive[0] = clamp(params[LEVEL1_PARAM].value + inputs[LEVEL1_INPUT].value / 5.0f, 0.0f, 1.0f); | |||||
p->channel_drive[1] = clamp(params[LEVEL2_PARAM].value + inputs[LEVEL2_INPUT].value / 5.0f, 0.0f, 1.0f); | |||||
p->modulation_algorithm = clamp(params[ALGORITHM_PARAM].value / 8.0f + inputs[ALGORITHM_INPUT].value / 5.0f, 0.0f, 1.0f); | |||||
p->channel_drive[0] = clamp(params[LEVEL1_PARAM].getValue() + inputs[LEVEL1_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||||
p->channel_drive[1] = clamp(params[LEVEL2_PARAM].getValue() + inputs[LEVEL2_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||||
p->modulation_algorithm = clamp(params[ALGORITHM_PARAM].getValue() / 8.0f + inputs[ALGORITHM_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||||
{ | { | ||||
// TODO | // TODO | ||||
@@ -99,21 +106,21 @@ void Warps::step() { | |||||
lights[ALGORITHM_LIGHT + 2].setBrightness(algorithmColor.b); | lights[ALGORITHM_LIGHT + 2].setBrightness(algorithmColor.b); | ||||
} | } | ||||
p->modulation_parameter = clamp(params[TIMBRE_PARAM].value + inputs[TIMBRE_INPUT].value / 5.0f, 0.0f, 1.0f); | |||||
p->modulation_parameter = clamp(params[TIMBRE_PARAM].getValue() + inputs[TIMBRE_INPUT].getVoltage() / 5.0f, 0.0f, 1.0f); | |||||
p->frequency_shift_pot = params[ALGORITHM_PARAM].value / 8.0; | |||||
p->frequency_shift_cv = clamp(inputs[ALGORITHM_INPUT].value / 5.0f, -1.0f, 1.0f); | |||||
p->frequency_shift_pot = params[ALGORITHM_PARAM].getValue() / 8.0; | |||||
p->frequency_shift_cv = clamp(inputs[ALGORITHM_INPUT].getVoltage() / 5.0f, -1.0f, 1.0f); | |||||
p->phase_shift = p->modulation_algorithm; | p->phase_shift = p->modulation_algorithm; | ||||
p->note = 60.0 * params[LEVEL1_PARAM].value + 12.0 * inputs[LEVEL1_INPUT].normalize(2.0) + 12.0; | |||||
p->note += log2f(96000.0f * engineGetSampleTime()) * 12.0f; | |||||
p->note = 60.0 * params[LEVEL1_PARAM].getValue() + 12.0 * inputs[LEVEL1_INPUT].getNormalVoltage(2.0) + 12.0; | |||||
p->note += log2f(96000.0f * args.sampleTime) * 12.0f; | |||||
modulator.Process(inputFrames, outputFrames, 60); | modulator.Process(inputFrames, outputFrames, 60); | ||||
} | } | ||||
inputFrames[frame].l = clamp((int) (inputs[CARRIER_INPUT].value / 16.0 * 0x8000), -0x8000, 0x7fff); | |||||
inputFrames[frame].r = clamp((int) (inputs[MODULATOR_INPUT].value / 16.0 * 0x8000), -0x8000, 0x7fff); | |||||
outputs[MODULATOR_OUTPUT].value = (float)outputFrames[frame].l / 0x8000 * 5.0; | |||||
outputs[AUX_OUTPUT].value = (float)outputFrames[frame].r / 0x8000 * 5.0; | |||||
inputFrames[frame].l = clamp((int) (inputs[CARRIER_INPUT].getVoltage() / 16.0 * 0x8000), -0x8000, 0x7fff); | |||||
inputFrames[frame].r = clamp((int) (inputs[MODULATOR_INPUT].getVoltage() / 16.0 * 0x8000), -0x8000, 0x7fff); | |||||
outputs[MODULATOR_OUTPUT].setVoltage((float)outputFrames[frame].l / 0x8000 * 5.0); | |||||
outputs[AUX_OUTPUT].setVoltage((float)outputFrames[frame].r / 0x8000 * 5.0); | |||||
} | } | ||||
@@ -125,30 +132,31 @@ struct AlgorithmLight : RedGreenBlueLight { | |||||
struct WarpsWidget : ModuleWidget { | struct WarpsWidget : ModuleWidget { | ||||
WarpsWidget(Warps *module) : ModuleWidget(module) { | |||||
setPanel(SVG::load(assetPlugin(pluginInstance, "res/Warps.svg"))); | |||||
WarpsWidget(Warps *module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Warps.svg"))); | |||||
addChild(createWidget<ScrewSilver>(Vec(15, 0))); | addChild(createWidget<ScrewSilver>(Vec(15, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(120, 0))); | addChild(createWidget<ScrewSilver>(Vec(120, 0))); | ||||
addChild(createWidget<ScrewSilver>(Vec(15, 365))); | addChild(createWidget<ScrewSilver>(Vec(15, 365))); | ||||
addChild(createWidget<ScrewSilver>(Vec(120, 365))); | addChild(createWidget<ScrewSilver>(Vec(120, 365))); | ||||
addParam(createParam<Rogan6PSWhite>(Vec(29, 52), module, Warps::ALGORITHM_PARAM, 0.0, 8.0, 0.0)); | |||||
addParam(createParam<Rogan6PSWhite>(Vec(29, 52), module, Warps::ALGORITHM_PARAM)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(94, 173), module, Warps::TIMBRE_PARAM, 0.0, 1.0, 0.5)); | |||||
addParam(createParam<TL1105>(Vec(16, 182), module, Warps::STATE_PARAM, 0.0, 1.0, 0.0)); | |||||
addParam(createParam<Trimpot>(Vec(14, 213), module, Warps::LEVEL1_PARAM, 0.0, 1.0, 1.0)); | |||||
addParam(createParam<Trimpot>(Vec(53, 213), module, Warps::LEVEL2_PARAM, 0.0, 1.0, 1.0)); | |||||
addParam(createParam<Rogan1PSWhite>(Vec(94, 173), module, Warps::TIMBRE_PARAM)); | |||||
addParam(createParam<TL1105>(Vec(16, 182), module, Warps::STATE_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(14, 213), module, Warps::LEVEL1_PARAM)); | |||||
addParam(createParam<Trimpot>(Vec(53, 213), module, Warps::LEVEL2_PARAM)); | |||||
addInput(createPort<PJ301MPort>(Vec(8, 273), PortWidget::INPUT, module, Warps::LEVEL1_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(44, 273), PortWidget::INPUT, module, Warps::LEVEL2_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(80, 273), PortWidget::INPUT, module, Warps::ALGORITHM_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(116, 273), PortWidget::INPUT, module, Warps::TIMBRE_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(8, 273), module, Warps::LEVEL1_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(44, 273), module, Warps::LEVEL2_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(80, 273), module, Warps::ALGORITHM_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(116, 273), module, Warps::TIMBRE_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(8, 316), PortWidget::INPUT, module, Warps::CARRIER_INPUT)); | |||||
addInput(createPort<PJ301MPort>(Vec(44, 316), PortWidget::INPUT, module, Warps::MODULATOR_INPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(80, 316), PortWidget::OUTPUT, module, Warps::MODULATOR_OUTPUT)); | |||||
addOutput(createPort<PJ301MPort>(Vec(116, 316), PortWidget::OUTPUT, module, Warps::AUX_OUTPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(8, 316), module, Warps::CARRIER_INPUT)); | |||||
addInput(createInput<PJ301MPort>(Vec(44, 316), module, Warps::MODULATOR_INPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(80, 316), module, Warps::MODULATOR_OUTPUT)); | |||||
addOutput(createOutput<PJ301MPort>(Vec(116, 316), module, Warps::AUX_OUTPUT)); | |||||
addChild(createLight<SmallLight<GreenRedLight>>(Vec(21, 167), module, Warps::CARRIER_GREEN_LIGHT)); | addChild(createLight<SmallLight<GreenRedLight>>(Vec(21, 167), module, Warps::CARRIER_GREEN_LIGHT)); | ||||