From 8ea69e536fcda96e3476b13fd8ecc0f2a341bde2 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Fri, 6 Nov 2020 13:17:08 -0500 Subject: [PATCH] Autoformat Streams.cpp. Clean up Streams. Add Mutable code to Makefile. Enable Streams in manifest. --- Makefile | 9 + plugin.json | 1 - src/Streams.cpp | 861 ++++++++++++++++----------------- src/Streams/adc.hpp | 2 +- src/Streams/analog_engine.hpp | 2 +- src/Streams/audio_cv_meter.hpp | 2 +- src/Streams/cv_scaler.hpp | 4 +- src/Streams/digital_engine.hpp | 4 +- src/Streams/event_queue.hpp | 2 +- src/Streams/leds.hpp | 2 +- src/Streams/resampler.hpp | 2 +- src/Streams/streams.hpp | 2 +- src/Streams/switches.hpp | 2 +- src/Streams/ui.hpp | 16 +- 14 files changed, 434 insertions(+), 477 deletions(-) diff --git a/Makefile b/Makefile index 51794c7..bdbd9e5 100644 --- a/Makefile +++ b/Makefile @@ -90,6 +90,15 @@ SOURCES += eurorack/marbles/random/quantizer.cc SOURCES += eurorack/marbles/ramp/ramp_extractor.cc SOURCES += eurorack/marbles/resources.cc +SOURCES += eurorack/streams/resources.cc +SOURCES += eurorack/streams/processor.cc +SOURCES += eurorack/streams/follower.cc +SOURCES += eurorack/streams/lorenz_generator.cc +SOURCES += eurorack/streams/envelope.cc +SOURCES += eurorack/streams/svf.cc +SOURCES += eurorack/streams/vactrol.cc +SOURCES += eurorack/streams/compressor.cc + DISTRIBUTABLES += $(wildcard LICENSE*) res diff --git a/plugin.json b/plugin.json index 45a1429..5e08b33 100644 --- a/plugin.json +++ b/plugin.json @@ -248,7 +248,6 @@ "slug": "Streams", "name": "Dual Dynamics Gate", "description": "Based on Mutable Instruments Streams", - "disabled": true, "tags": [ "Dynamics", "Low-pass gate", diff --git a/src/Streams.cpp b/src/Streams.cpp index 38a87ac..1f1a095 100644 --- a/src/Streams.cpp +++ b/src/Streams.cpp @@ -19,478 +19,427 @@ #include "plugin.hpp" #include "Streams/streams.hpp" -namespace streams -{ - -struct StreamsChannelMode -{ - ProcessorFunction function; - bool alternate; - std::string label; +namespace streams { + +struct StreamsChannelMode { + ProcessorFunction function; + bool alternate; + std::string label; }; static constexpr int kNumChannelModes = 10; -static const StreamsChannelMode kChannelModeTable[kNumChannelModes] = -{ - {PROCESSOR_FUNCTION_ENVELOPE, false, "Envelope"}, - {PROCESSOR_FUNCTION_VACTROL, false, "Vactrol"}, - {PROCESSOR_FUNCTION_FOLLOWER, false, "Follower"}, - {PROCESSOR_FUNCTION_COMPRESSOR, false, "Compressor"}, - {PROCESSOR_FUNCTION_ENVELOPE, true, "AR envelope"}, - {PROCESSOR_FUNCTION_VACTROL, true, "Plucked vactrol"}, - {PROCESSOR_FUNCTION_FOLLOWER, true, "Cutoff controller"}, - {PROCESSOR_FUNCTION_COMPRESSOR, true, "Slow compressor"}, - {PROCESSOR_FUNCTION_FILTER_CONTROLLER, true, "Direct VCF controller"}, - {PROCESSOR_FUNCTION_LORENZ_GENERATOR, false, "Lorenz generator"}, +static const StreamsChannelMode kChannelModeTable[kNumChannelModes] = { + {PROCESSOR_FUNCTION_ENVELOPE, false, "Envelope"}, + {PROCESSOR_FUNCTION_VACTROL, false, "Vactrol"}, + {PROCESSOR_FUNCTION_FOLLOWER, false, "Follower"}, + {PROCESSOR_FUNCTION_COMPRESSOR, false, "Compressor"}, + {PROCESSOR_FUNCTION_ENVELOPE, true, "AR envelope"}, + {PROCESSOR_FUNCTION_VACTROL, true, "Plucked vactrol"}, + {PROCESSOR_FUNCTION_FOLLOWER, true, "Cutoff controller"}, + {PROCESSOR_FUNCTION_COMPRESSOR, true, "Slow compressor"}, + {PROCESSOR_FUNCTION_FILTER_CONTROLLER, true, "Direct VCF controller"}, + {PROCESSOR_FUNCTION_LORENZ_GENERATOR, false, "Lorenz generator"}, }; -struct StreamsMonitorMode -{ - MonitorMode mode; - std::string label; +struct StreamsMonitorMode { + MonitorMode mode; + std::string label; }; static constexpr int kNumMonitorModes = 4; -static const StreamsMonitorMode kMonitorModeTable[kNumMonitorModes] = -{ - {MONITOR_MODE_EXCITE_IN, "Excite"}, - {MONITOR_MODE_VCA_CV, "Level"}, - {MONITOR_MODE_AUDIO_IN, "In"}, - {MONITOR_MODE_OUTPUT, "Out"}, +static const StreamsMonitorMode kMonitorModeTable[kNumMonitorModes] = { + {MONITOR_MODE_EXCITE_IN, "Excite"}, + {MONITOR_MODE_VCA_CV, "Level"}, + {MONITOR_MODE_AUDIO_IN, "In"}, + {MONITOR_MODE_OUTPUT, "Out"}, }; } -struct Streams : Module -{ - enum ParamIds - { - CH1_SHAPE_PARAM, - CH1_MOD_PARAM, - CH1_LEVEL_MOD_PARAM, - CH1_RESPONSE_PARAM, - CH2_SHAPE_PARAM, - CH2_MOD_PARAM, - CH2_LEVEL_MOD_PARAM, - CH2_RESPONSE_PARAM, - CH1_FUNCTION_BUTTON_PARAM, - CH2_FUNCTION_BUTTON_PARAM, - METERING_BUTTON_PARAM, - NUM_PARAMS - }; - enum InputIds - { - CH1_EXCITE_INPUT, - CH1_SIGNAL_INPUT, - CH1_LEVEL_INPUT, - CH2_EXCITE_INPUT, - CH2_SIGNAL_INPUT, - CH2_LEVEL_INPUT, - NUM_INPUTS - }; - enum OutputIds - { - CH1_SIGNAL_OUTPUT, - CH2_SIGNAL_OUTPUT, - NUM_OUTPUTS - }; - enum LightIds - { - CH1_LIGHT_1_G, - CH1_LIGHT_1_R, - CH1_LIGHT_2_G, - CH1_LIGHT_2_R, - CH1_LIGHT_3_G, - CH1_LIGHT_3_R, - CH1_LIGHT_4_G, - CH1_LIGHT_4_R, - CH2_LIGHT_1_G, - CH2_LIGHT_1_R, - CH2_LIGHT_2_G, - CH2_LIGHT_2_R, - CH2_LIGHT_3_G, - CH2_LIGHT_3_R, - CH2_LIGHT_4_G, - CH2_LIGHT_4_R, - NUM_LIGHTS - }; - - static constexpr int kNumEngines = 16; - streams::StreamsEngine engine_[kNumEngines]; - float brightness_[NUM_LIGHTS][kNumEngines]; - int prev_num_channels_; - - Streams() - { - config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); - - configParam(CH1_SHAPE_PARAM, 0.f, 1.f, 0.f); - configParam(CH1_MOD_PARAM, 0.f, 1.f, 0.5f); - configParam(CH1_LEVEL_MOD_PARAM, 0.f, 1.f, 0.f); - configParam(CH2_SHAPE_PARAM, 0.f, 1.f, 0.f); - configParam(CH2_MOD_PARAM, 0.f, 1.f, 0.5f); - configParam(CH2_LEVEL_MOD_PARAM, 0.f, 1.f, 0.f); - configParam(CH1_RESPONSE_PARAM, 0.f, 1.f, 0.f); - configParam(CH2_RESPONSE_PARAM, 0.f, 1.f, 0.f); - - configParam(CH1_FUNCTION_BUTTON_PARAM, 0.f, 1.f, 0.f); - configParam(CH2_FUNCTION_BUTTON_PARAM, 0.f, 1.f, 0.f); - configParam(METERING_BUTTON_PARAM, 0.f, 1.f, 0.f); - - onReset(); - } - - void onReset() override - { - for (int c = 0; c < kNumEngines; c++) - { - engine_[c].Reset(); - - for (int i = 0; i < NUM_LIGHTS; i++) - { - brightness_[c][i] = 0.f; - } - } - - prev_num_channels_ = 1; - onSampleRateChange(); - } - - void onSampleRateChange() override - { - float sample_rate = APP->engine->getSampleRate(); - - for (int c = 0; c < kNumEngines; c++) - { - engine_[c].SetSampleRate(sample_rate); - } - } - - json_t* dataToJson() override - { - streams::UiSettings settings = engine_[0].ui_settings(); - json_t* root_j = json_object(); - json_object_set_new(root_j, "function1", json_integer(settings.function[0])); - json_object_set_new(root_j, "function2", json_integer(settings.function[1])); - json_object_set_new(root_j, "alternate1", json_integer(settings.alternate[0])); - json_object_set_new(root_j, "alternate2", json_integer(settings.alternate[1])); - json_object_set_new(root_j, "monitor_mode", json_integer(settings.monitor_mode)); - json_object_set_new(root_j, "linked", json_integer(settings.linked)); - return root_j; - } - - void dataFromJson(json_t* root_j) override - { - json_t* function1_j = json_object_get(root_j, "function1"); - json_t* function2_j = json_object_get(root_j, "function2"); - json_t* alternate1_j = json_object_get(root_j, "alternate1"); - json_t* alternate2_j = json_object_get(root_j, "alternate2"); - json_t* monitor_mode_j = json_object_get(root_j, "monitor_mode"); - json_t* linked_j = json_object_get(root_j, "linked"); - - streams::UiSettings settings = {}; - - if (function1_j) settings.function[0] = json_integer_value(function1_j); - if (function2_j) settings.function[1] = json_integer_value(function2_j); - if (alternate1_j) settings.alternate[0] = json_integer_value(alternate1_j); - if (alternate2_j) settings.alternate[1] = json_integer_value(alternate2_j); - if (monitor_mode_j) settings.monitor_mode = json_integer_value(monitor_mode_j); - if (linked_j) settings.linked = json_integer_value(linked_j); - - for (int c = 0; c < kNumEngines; c++) - { - engine_[c].ApplySettings(settings); - } - } - - void onRandomize() override - { - for (int c = 0; c < kNumEngines; c++) - { - engine_[c].Randomize(); - } - } - - void ToggleLink() - { - streams::UiSettings settings = engine_[0].ui_settings(); - settings.linked ^= 1; - - for (int c = 0; c < kNumEngines; c++) - { - engine_[c].ApplySettings(settings); - } - } - - void SetChannelMode(int channel, int mode_id) - { - streams::UiSettings settings = engine_[0].ui_settings(); - settings.function[channel] = streams::kChannelModeTable[mode_id].function; - settings.alternate[channel] = streams::kChannelModeTable[mode_id].alternate; - - for (int c = 0; c < kNumEngines; c++) - { - engine_[c].ApplySettings(settings); - } - } - - void SetMonitorMode(int mode_id) - { - streams::UiSettings settings = engine_[0].ui_settings(); - settings.monitor_mode = streams::kMonitorModeTable[mode_id].mode; - - for (int c = 0; c < kNumEngines; c++) - { - engine_[c].ApplySettings(settings); - } - } - - int function(int channel) - { - return engine_[0].ui_settings().function[channel]; - } - - int alternate(int channel) - { - return engine_[0].ui_settings().alternate[channel]; - } - - bool linked() - { - return engine_[0].ui_settings().linked; - } - - int monitor_mode() - { - return engine_[0].ui_settings().monitor_mode; - } - - void process(const ProcessArgs& args) override - { - int num_channels = std::max(inputs[CH1_SIGNAL_INPUT].getChannels(), - inputs[CH2_SIGNAL_INPUT].getChannels()); - num_channels = std::max(num_channels, 1); - - if (num_channels > prev_num_channels_) - { - for (int c = prev_num_channels_; c < num_channels; c++) - { - engine_[c].SyncUI(engine_[0]); - } - } - - prev_num_channels_ = num_channels; - - // Reuse the same frame object for multiple engines because the params - // aren't touched. - streams::StreamsEngine::Frame frame; - - frame.ch1.shape_knob = params[CH1_SHAPE_PARAM] .getValue(); - frame.ch1.mod_knob = params[CH1_MOD_PARAM] .getValue(); - frame.ch1.level_mod_knob = params[CH1_LEVEL_MOD_PARAM].getValue(); - frame.ch1.response_knob = params[CH1_RESPONSE_PARAM] .getValue(); - frame.ch2.shape_knob = params[CH2_SHAPE_PARAM] .getValue(); - frame.ch2.mod_knob = params[CH2_MOD_PARAM] .getValue(); - frame.ch2.level_mod_knob = params[CH2_LEVEL_MOD_PARAM].getValue(); - frame.ch2.response_knob = params[CH2_RESPONSE_PARAM] .getValue(); - - frame.ch1.signal_in_connected = inputs[CH1_SIGNAL_INPUT].isConnected(); - frame.ch1.level_cv_connected = inputs[CH1_LEVEL_INPUT] .isConnected(); - frame.ch2.signal_in_connected = inputs[CH2_SIGNAL_INPUT].isConnected(); - frame.ch2.level_cv_connected = inputs[CH2_LEVEL_INPUT] .isConnected(); - - frame.ch1.function_button = params[CH1_FUNCTION_BUTTON_PARAM].getValue(); - frame.ch2.function_button = params[CH2_FUNCTION_BUTTON_PARAM].getValue(); - frame.metering_button = params[METERING_BUTTON_PARAM].getValue(); - - bool lights_updated = false; - - for (int c = 0; c < num_channels; c++) - { - frame.ch1.excite_in = inputs[CH1_EXCITE_INPUT].getPolyVoltage(c); - frame.ch1.signal_in = inputs[CH1_SIGNAL_INPUT].getPolyVoltage(c); - frame.ch1.level_cv = inputs[CH1_LEVEL_INPUT] .getPolyVoltage(c); - frame.ch2.excite_in = inputs[CH2_EXCITE_INPUT].getPolyVoltage(c); - frame.ch2.signal_in = inputs[CH2_SIGNAL_INPUT].getPolyVoltage(c); - frame.ch2.level_cv = inputs[CH2_LEVEL_INPUT] .getPolyVoltage(c); - - engine_[c].Process(frame); - - outputs[CH1_SIGNAL_OUTPUT].setVoltage(frame.ch1.signal_out, c); - outputs[CH2_SIGNAL_OUTPUT].setVoltage(frame.ch2.signal_out, c); - - if (frame.lights_updated) - { - brightness_[CH1_LIGHT_1_G][c] = frame.ch1.led_green[0]; - brightness_[CH1_LIGHT_2_G][c] = frame.ch1.led_green[1]; - brightness_[CH1_LIGHT_3_G][c] = frame.ch1.led_green[2]; - brightness_[CH1_LIGHT_4_G][c] = frame.ch1.led_green[3]; - brightness_[CH1_LIGHT_1_R][c] = frame.ch1.led_red[0]; - brightness_[CH1_LIGHT_2_R][c] = frame.ch1.led_red[1]; - brightness_[CH1_LIGHT_3_R][c] = frame.ch1.led_red[2]; - brightness_[CH1_LIGHT_4_R][c] = frame.ch1.led_red[3]; - brightness_[CH2_LIGHT_1_G][c] = frame.ch2.led_green[0]; - brightness_[CH2_LIGHT_2_G][c] = frame.ch2.led_green[1]; - brightness_[CH2_LIGHT_3_G][c] = frame.ch2.led_green[2]; - brightness_[CH2_LIGHT_4_G][c] = frame.ch2.led_green[3]; - brightness_[CH2_LIGHT_1_R][c] = frame.ch2.led_red[0]; - brightness_[CH2_LIGHT_2_R][c] = frame.ch2.led_red[1]; - brightness_[CH2_LIGHT_3_R][c] = frame.ch2.led_red[2]; - brightness_[CH2_LIGHT_4_R][c] = frame.ch2.led_red[3]; - } - - lights_updated |= frame.lights_updated; - } - - outputs[CH1_SIGNAL_OUTPUT].setChannels(num_channels); - outputs[CH2_SIGNAL_OUTPUT].setChannels(num_channels); - - if (lights_updated) - { - // Drive lights according to maximum brightness across engines - for (int i = 0; i < NUM_LIGHTS; i++) - { - float brightness = 0.f; - - for (int c = 0; c < num_channels; c++) - { - brightness = std::max(brightness_[i][c], brightness); - } - - lights[i].setBrightness(brightness); - } - } - } +struct Streams : Module { + enum ParamIds { + CH1_SHAPE_PARAM, + CH1_MOD_PARAM, + CH1_LEVEL_MOD_PARAM, + CH1_RESPONSE_PARAM, + CH2_SHAPE_PARAM, + CH2_MOD_PARAM, + CH2_LEVEL_MOD_PARAM, + CH2_RESPONSE_PARAM, + CH1_FUNCTION_BUTTON_PARAM, + CH2_FUNCTION_BUTTON_PARAM, + METERING_BUTTON_PARAM, + NUM_PARAMS + }; + enum InputIds { + CH1_EXCITE_INPUT, + CH1_SIGNAL_INPUT, + CH1_LEVEL_INPUT, + CH2_EXCITE_INPUT, + CH2_SIGNAL_INPUT, + CH2_LEVEL_INPUT, + NUM_INPUTS + }; + enum OutputIds { + CH1_SIGNAL_OUTPUT, + CH2_SIGNAL_OUTPUT, + NUM_OUTPUTS + }; + enum LightIds { + CH1_LIGHT_1_G, + CH1_LIGHT_1_R, + CH1_LIGHT_2_G, + CH1_LIGHT_2_R, + CH1_LIGHT_3_G, + CH1_LIGHT_3_R, + CH1_LIGHT_4_G, + CH1_LIGHT_4_R, + CH2_LIGHT_1_G, + CH2_LIGHT_1_R, + CH2_LIGHT_2_G, + CH2_LIGHT_2_R, + CH2_LIGHT_3_G, + CH2_LIGHT_3_R, + CH2_LIGHT_4_G, + CH2_LIGHT_4_R, + NUM_LIGHTS + }; + + streams::StreamsEngine engines[PORT_MAX_CHANNELS]; + int prevNumChannels; + float brightnesses[NUM_LIGHTS][PORT_MAX_CHANNELS]; + + Streams() { + config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); + + configParam(CH1_SHAPE_PARAM, 0.f, 1.f, 0.5f, "Ch 1 shape"); + configParam(CH1_MOD_PARAM, 0.f, 1.f, 0.5f, "Ch 1 mod"); + configParam(CH1_LEVEL_MOD_PARAM, 0.f, 1.f, 0.5f, "Ch 1 level mod"); + configParam(CH2_SHAPE_PARAM, 0.f, 1.f, 0.5f, "Ch 2 shape"); + configParam(CH2_MOD_PARAM, 0.f, 1.f, 0.5f, "Ch 2 mod"); + configParam(CH2_LEVEL_MOD_PARAM, 0.f, 1.f, 0.5f, "Ch 2 level mod"); + configParam(CH1_RESPONSE_PARAM, 0.f, 1.f, 0.5f, "Ch 1 response"); + configParam(CH2_RESPONSE_PARAM, 0.f, 1.f, 0.5f, "Ch 2 response"); + + configParam(CH1_FUNCTION_BUTTON_PARAM, 0.f, 1.f, 0.f, "Ch 1 function"); + configParam(CH2_FUNCTION_BUTTON_PARAM, 0.f, 1.f, 0.f, "Ch 2 function"); + configParam(METERING_BUTTON_PARAM, 0.f, 1.f, 0.f, "Meter"); + + onReset(); + } + + void onReset() override { + for (int c = 0; c < PORT_MAX_CHANNELS; c++) { + engines[c].Reset(); + } + + prevNumChannels = 1; + onSampleRateChange(); + } + + void onSampleRateChange() override { + float sampleRate = APP->engine->getSampleRate(); + + for (int c = 0; c < PORT_MAX_CHANNELS; c++) { + engines[c].SetSampleRate(sampleRate); + } + } + + json_t* dataToJson() override { + streams::UiSettings settings = engines[0].ui_settings(); + json_t* rootJ = json_object(); + json_object_set_new(rootJ, "function1", json_integer(settings.function[0])); + json_object_set_new(rootJ, "function2", json_integer(settings.function[1])); + json_object_set_new(rootJ, "alternate1", json_integer(settings.alternate[0])); + json_object_set_new(rootJ, "alternate2", json_integer(settings.alternate[1])); + json_object_set_new(rootJ, "monitorMode", json_integer(settings.monitor_mode)); + json_object_set_new(rootJ, "linked", json_integer(settings.linked)); + return rootJ; + } + + void dataFromJson(json_t* rootJ) override { + json_t* function1J = json_object_get(rootJ, "function1"); + json_t* function2J = json_object_get(rootJ, "function2"); + json_t* alternate1J = json_object_get(rootJ, "alternate1"); + json_t* alternate2J = json_object_get(rootJ, "alternate2"); + json_t* monitorModeJ = json_object_get(rootJ, "monitorMode"); + json_t* linkedJ = json_object_get(rootJ, "linked"); + + streams::UiSettings settings = {}; + + if (function1J) + settings.function[0] = json_integer_value(function1J); + if (function2J) + settings.function[1] = json_integer_value(function2J); + if (alternate1J) + settings.alternate[0] = json_integer_value(alternate1J); + if (alternate2J) + settings.alternate[1] = json_integer_value(alternate2J); + if (monitorModeJ) + settings.monitor_mode = json_integer_value(monitorModeJ); + if (linkedJ) + settings.linked = json_integer_value(linkedJ); + + for (int c = 0; c < PORT_MAX_CHANNELS; c++) { + engines[c].ApplySettings(settings); + } + } + + void onRandomize() override { + for (int c = 0; c < PORT_MAX_CHANNELS; c++) { + engines[c].Randomize(); + } + } + + void toggleLink() { + streams::UiSettings settings = engines[0].ui_settings(); + settings.linked ^= 1; + + for (int c = 0; c < PORT_MAX_CHANNELS; c++) { + engines[c].ApplySettings(settings); + } + } + + void setChannelMode(int channel, int mode_id) { + streams::UiSettings settings = engines[0].ui_settings(); + settings.function[channel] = streams::kChannelModeTable[mode_id].function; + settings.alternate[channel] = streams::kChannelModeTable[mode_id].alternate; + + for (int c = 0; c < PORT_MAX_CHANNELS; c++) { + engines[c].ApplySettings(settings); + } + } + + void setMonitorMode(int mode_id) { + streams::UiSettings settings = engines[0].ui_settings(); + settings.monitor_mode = streams::kMonitorModeTable[mode_id].mode; + + for (int c = 0; c < PORT_MAX_CHANNELS; c++) { + engines[c].ApplySettings(settings); + } + } + + int function(int channel) { + return engines[0].ui_settings().function[channel]; + } + + int alternate(int channel) { + return engines[0].ui_settings().alternate[channel]; + } + + bool linked() { + return engines[0].ui_settings().linked; + } + + int monitorMode() { + return engines[0].ui_settings().monitor_mode; + } + + void process(const ProcessArgs& args) override { + int numChannels = std::max(inputs[CH1_SIGNAL_INPUT].getChannels(), inputs[CH2_SIGNAL_INPUT].getChannels()); + numChannels = std::max(numChannels, 1); + + if (numChannels > prevNumChannels) { + for (int c = prevNumChannels; c < numChannels; c++) { + engines[c].SyncUI(engines[0]); + } + } + + prevNumChannels = numChannels; + + // Reuse the same frame object for multiple engines because the params + // aren't touched. + streams::StreamsEngine::Frame frame; + + frame.ch1.shape_knob = params[CH1_SHAPE_PARAM] .getValue(); + frame.ch1.mod_knob = params[CH1_MOD_PARAM] .getValue(); + frame.ch1.level_mod_knob = params[CH1_LEVEL_MOD_PARAM].getValue(); + frame.ch1.response_knob = params[CH1_RESPONSE_PARAM] .getValue(); + frame.ch2.shape_knob = params[CH2_SHAPE_PARAM] .getValue(); + frame.ch2.mod_knob = params[CH2_MOD_PARAM] .getValue(); + frame.ch2.level_mod_knob = params[CH2_LEVEL_MOD_PARAM].getValue(); + frame.ch2.response_knob = params[CH2_RESPONSE_PARAM] .getValue(); + + frame.ch1.signal_in_connected = inputs[CH1_SIGNAL_INPUT].isConnected(); + frame.ch1.level_cv_connected = inputs[CH1_LEVEL_INPUT] .isConnected(); + frame.ch2.signal_in_connected = inputs[CH2_SIGNAL_INPUT].isConnected(); + frame.ch2.level_cv_connected = inputs[CH2_LEVEL_INPUT] .isConnected(); + + frame.ch1.function_button = params[CH1_FUNCTION_BUTTON_PARAM].getValue(); + frame.ch2.function_button = params[CH2_FUNCTION_BUTTON_PARAM].getValue(); + frame.metering_button = params[METERING_BUTTON_PARAM].getValue(); + + bool lights_updated = false; + + for (int c = 0; c < numChannels; c++) { + frame.ch1.excite_in = inputs[CH1_EXCITE_INPUT].getPolyVoltage(c); + frame.ch1.signal_in = inputs[CH1_SIGNAL_INPUT].getPolyVoltage(c); + frame.ch1.level_cv = inputs[CH1_LEVEL_INPUT] .getPolyVoltage(c); + frame.ch2.excite_in = inputs[CH2_EXCITE_INPUT].getPolyVoltage(c); + frame.ch2.signal_in = inputs[CH2_SIGNAL_INPUT].getPolyVoltage(c); + frame.ch2.level_cv = inputs[CH2_LEVEL_INPUT] .getPolyVoltage(c); + + engines[c].Process(frame); + + outputs[CH1_SIGNAL_OUTPUT].setVoltage(frame.ch1.signal_out, c); + outputs[CH2_SIGNAL_OUTPUT].setVoltage(frame.ch2.signal_out, c); + + if (frame.lights_updated) { + brightnesses[CH1_LIGHT_1_G][c] = frame.ch1.led_green[0]; + brightnesses[CH1_LIGHT_2_G][c] = frame.ch1.led_green[1]; + brightnesses[CH1_LIGHT_3_G][c] = frame.ch1.led_green[2]; + brightnesses[CH1_LIGHT_4_G][c] = frame.ch1.led_green[3]; + brightnesses[CH1_LIGHT_1_R][c] = frame.ch1.led_red[0]; + brightnesses[CH1_LIGHT_2_R][c] = frame.ch1.led_red[1]; + brightnesses[CH1_LIGHT_3_R][c] = frame.ch1.led_red[2]; + brightnesses[CH1_LIGHT_4_R][c] = frame.ch1.led_red[3]; + brightnesses[CH2_LIGHT_1_G][c] = frame.ch2.led_green[0]; + brightnesses[CH2_LIGHT_2_G][c] = frame.ch2.led_green[1]; + brightnesses[CH2_LIGHT_3_G][c] = frame.ch2.led_green[2]; + brightnesses[CH2_LIGHT_4_G][c] = frame.ch2.led_green[3]; + brightnesses[CH2_LIGHT_1_R][c] = frame.ch2.led_red[0]; + brightnesses[CH2_LIGHT_2_R][c] = frame.ch2.led_red[1]; + brightnesses[CH2_LIGHT_3_R][c] = frame.ch2.led_red[2]; + brightnesses[CH2_LIGHT_4_R][c] = frame.ch2.led_red[3]; + } + + lights_updated |= frame.lights_updated; + } + + outputs[CH1_SIGNAL_OUTPUT].setChannels(numChannels); + outputs[CH2_SIGNAL_OUTPUT].setChannels(numChannels); + + if (lights_updated) { + // Drive lights according to maximum brightness across engines + for (int i = 0; i < NUM_LIGHTS; i++) { + float brightness = 0.f; + + for (int c = 0; c < numChannels; c++) { + brightness = std::max(brightnesses[i][c], brightness); + } + + lights[i].setBrightness(brightness); + } + } + } }; -struct StreamsWidget : ModuleWidget -{ - StreamsWidget(Streams* module) - { - setModule(module); - setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Streams.svg"))); - - addChild(createWidget(Vec(RACK_GRID_WIDTH, 0))); - addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); - addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); - addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); - - addParam(createParamCentered(mm2px(Vec(11.065, 128.75 - 107.695)), module, Streams::CH1_SHAPE_PARAM)); - addParam(createParamCentered(mm2px(Vec(11.065, 128.75 - 84.196)), module, Streams::CH1_MOD_PARAM)); - addParam(createParamCentered (mm2px(Vec(11.065, 128.75 - 60.706)), module, Streams::CH1_LEVEL_MOD_PARAM)); - addParam(createParamCentered(mm2px(Vec(49.785, 128.75 - 107.695)), module, Streams::CH2_SHAPE_PARAM)); - addParam(createParamCentered(mm2px(Vec(49.785, 128.75 - 84.196)), module, Streams::CH2_MOD_PARAM)); - addParam(createParamCentered(mm2px(Vec(49.785, 128.75 - 60.706)), module, Streams::CH2_LEVEL_MOD_PARAM)); - - addParam(createParamCentered(mm2px(Vec(30.425, 128.75 - 68.006)), module, Streams::CH1_RESPONSE_PARAM)); - addParam(createParamCentered(mm2px(Vec(30.425, 128.75 - 53.406)), module, Streams::CH2_RESPONSE_PARAM)); - - addParam(createParamCentered(mm2px(Vec(24.715, 128.75 - 113.726)), module, Streams::CH1_FUNCTION_BUTTON_PARAM)); - addParam(createParamCentered(mm2px(Vec(36.135, 128.75 - 113.726)), module, Streams::CH2_FUNCTION_BUTTON_PARAM)); - addParam(createParamCentered(mm2px(Vec(30.425, 128.75 - 81.976)), module, Streams::METERING_BUTTON_PARAM)); - - addInput(createInputCentered(mm2px(Vec( 8.506, 128.75 - 32.136)), module, Streams::CH1_EXCITE_INPUT)); - addInput(createInputCentered(mm2px(Vec(23.116, 128.75 - 32.136)), module, Streams::CH1_SIGNAL_INPUT)); - addInput(createInputCentered(mm2px(Vec( 8.506, 128.75 - 17.526)), module, Streams::CH1_LEVEL_INPUT)); - addInput(createInputCentered(mm2px(Vec(52.335, 128.75 - 32.136)), module, Streams::CH2_EXCITE_INPUT)); - addInput(createInputCentered(mm2px(Vec(37.726, 128.75 - 32.136)), module, Streams::CH2_SIGNAL_INPUT)); - addInput(createInputCentered(mm2px(Vec(52.335, 128.75 - 17.526)), module, Streams::CH2_LEVEL_INPUT)); - - addOutput(createOutputCentered(mm2px(Vec(23.116, 128.75 - 17.526)), module, Streams::CH1_SIGNAL_OUTPUT)); - addOutput(createOutputCentered(mm2px(Vec(37.726, 128.75 - 17.526)), module, Streams::CH2_SIGNAL_OUTPUT)); - - addChild(createLightCentered>(mm2px(Vec(24.715, 128.75 - 106.746)), module, Streams::CH1_LIGHT_1_G)); - addChild(createLightCentered>(mm2px(Vec(24.715, 128.75 - 101.026)), module, Streams::CH1_LIGHT_2_G)); - addChild(createLightCentered>(mm2px(Vec(24.715, 128.75 - 95.305)), module, Streams::CH1_LIGHT_3_G)); - addChild(createLightCentered>(mm2px(Vec(24.715, 128.75 - 89.585)), module, Streams::CH1_LIGHT_4_G)); - addChild(createLightCentered>(mm2px(Vec(36.135, 128.75 - 106.746)), module, Streams::CH2_LIGHT_1_G)); - addChild(createLightCentered>(mm2px(Vec(36.135, 128.75 - 101.026)), module, Streams::CH2_LIGHT_2_G)); - addChild(createLightCentered>(mm2px(Vec(36.135, 128.75 - 95.305)), module, Streams::CH2_LIGHT_3_G)); - addChild(createLightCentered>(mm2px(Vec(36.135, 128.75 - 89.585)), module, Streams::CH2_LIGHT_4_G)); - } - - void appendContextMenu(Menu* menu) override - { - Streams* module = dynamic_cast(this->module); - - struct LinkItem : MenuItem - { - Streams* module; - void onAction(const event::Action & e) override - { - module->ToggleLink(); - } - }; - - struct ChannelModeItem : MenuItem - { - Streams* module; - int channel; - int mode; - void onAction(const event::Action& e) override - { - module->SetChannelMode(channel, mode); - } - }; - - struct MonitorModeItem : MenuItem - { - Streams* module; - int mode; - void onAction(const event::Action& e) override - { - module->SetMonitorMode(mode); - } - }; - - menu->addChild(new MenuSeparator); - LinkItem* link_item = createMenuItem( - "Link channels", CHECKMARK(module->linked())); - link_item->module = module; - menu->addChild(link_item); - - menu->addChild(new MenuSeparator); - menu->addChild(createMenuLabel("Channel 1")); - for (int i = 0; i < streams::kNumChannelModes; i++) - { - auto mode_item = createMenuItem( - streams::kChannelModeTable[i].label, CHECKMARK( - module->function(0) == streams::kChannelModeTable[i].function && - module->alternate(0) == streams::kChannelModeTable[i].alternate)); - mode_item->module = module; - mode_item->channel = 0; - mode_item->mode = i; - menu->addChild(mode_item); - } - - menu->addChild(new MenuSeparator); - menu->addChild(createMenuLabel("Channel 2")); - for (int i = 0; i < streams::kNumChannelModes; i++) - { - auto mode_item = createMenuItem( - streams::kChannelModeTable[i].label, CHECKMARK( - module->function(1) == streams::kChannelModeTable[i].function && - module->alternate(1) == streams::kChannelModeTable[i].alternate)); - mode_item->module = module; - mode_item->channel = 1; - mode_item->mode = i; - menu->addChild(mode_item); - } - - menu->addChild(new MenuSeparator); - menu->addChild(createMenuLabel("Meter")); - for (int i = 0; i < streams::kNumMonitorModes; i++) - { - auto mode_item = createMenuItem( - streams::kMonitorModeTable[i].label, CHECKMARK( - module->monitor_mode() == streams::kMonitorModeTable[i].mode)); - mode_item->module = module; - mode_item->mode = i; - menu->addChild(mode_item); - } - } +struct StreamsWidget : ModuleWidget { + StreamsWidget(Streams* module) { + setModule(module); + setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Streams.svg"))); + + addChild(createWidget(Vec(RACK_GRID_WIDTH, 0))); + addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); + addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + + addParam(createParamCentered(mm2px(Vec(11.065, 128.75 - 107.695)), module, Streams::CH1_SHAPE_PARAM)); + addParam(createParamCentered(mm2px(Vec(11.065, 128.75 - 84.196)), module, Streams::CH1_MOD_PARAM)); + addParam(createParamCentered (mm2px(Vec(11.065, 128.75 - 60.706)), module, Streams::CH1_LEVEL_MOD_PARAM)); + addParam(createParamCentered(mm2px(Vec(49.785, 128.75 - 107.695)), module, Streams::CH2_SHAPE_PARAM)); + addParam(createParamCentered(mm2px(Vec(49.785, 128.75 - 84.196)), module, Streams::CH2_MOD_PARAM)); + addParam(createParamCentered(mm2px(Vec(49.785, 128.75 - 60.706)), module, Streams::CH2_LEVEL_MOD_PARAM)); + + addParam(createParamCentered(mm2px(Vec(30.425, 128.75 - 68.006)), module, Streams::CH1_RESPONSE_PARAM)); + addParam(createParamCentered(mm2px(Vec(30.425, 128.75 - 53.406)), module, Streams::CH2_RESPONSE_PARAM)); + + addParam(createParamCentered(mm2px(Vec(24.715, 128.75 - 113.726)), module, Streams::CH1_FUNCTION_BUTTON_PARAM)); + addParam(createParamCentered(mm2px(Vec(36.135, 128.75 - 113.726)), module, Streams::CH2_FUNCTION_BUTTON_PARAM)); + addParam(createParamCentered(mm2px(Vec(30.425, 128.75 - 81.976)), module, Streams::METERING_BUTTON_PARAM)); + + addInput(createInputCentered(mm2px(Vec(8.506, 128.75 - 32.136)), module, Streams::CH1_EXCITE_INPUT)); + addInput(createInputCentered(mm2px(Vec(23.116, 128.75 - 32.136)), module, Streams::CH1_SIGNAL_INPUT)); + addInput(createInputCentered(mm2px(Vec(8.506, 128.75 - 17.526)), module, Streams::CH1_LEVEL_INPUT)); + addInput(createInputCentered(mm2px(Vec(52.335, 128.75 - 32.136)), module, Streams::CH2_EXCITE_INPUT)); + addInput(createInputCentered(mm2px(Vec(37.726, 128.75 - 32.136)), module, Streams::CH2_SIGNAL_INPUT)); + addInput(createInputCentered(mm2px(Vec(52.335, 128.75 - 17.526)), module, Streams::CH2_LEVEL_INPUT)); + + addOutput(createOutputCentered(mm2px(Vec(23.116, 128.75 - 17.526)), module, Streams::CH1_SIGNAL_OUTPUT)); + addOutput(createOutputCentered(mm2px(Vec(37.726, 128.75 - 17.526)), module, Streams::CH2_SIGNAL_OUTPUT)); + + addChild(createLightCentered>(mm2px(Vec(24.715, 128.75 - 106.746)), module, Streams::CH1_LIGHT_1_G)); + addChild(createLightCentered>(mm2px(Vec(24.715, 128.75 - 101.026)), module, Streams::CH1_LIGHT_2_G)); + addChild(createLightCentered>(mm2px(Vec(24.715, 128.75 - 95.305)), module, Streams::CH1_LIGHT_3_G)); + addChild(createLightCentered>(mm2px(Vec(24.715, 128.75 - 89.585)), module, Streams::CH1_LIGHT_4_G)); + addChild(createLightCentered>(mm2px(Vec(36.135, 128.75 - 106.746)), module, Streams::CH2_LIGHT_1_G)); + addChild(createLightCentered>(mm2px(Vec(36.135, 128.75 - 101.026)), module, Streams::CH2_LIGHT_2_G)); + addChild(createLightCentered>(mm2px(Vec(36.135, 128.75 - 95.305)), module, Streams::CH2_LIGHT_3_G)); + addChild(createLightCentered>(mm2px(Vec(36.135, 128.75 - 89.585)), module, Streams::CH2_LIGHT_4_G)); + } + + void appendContextMenu(Menu* menu) override { + Streams* module = dynamic_cast(this->module); + + struct LinkItem : MenuItem { + Streams* module; + void onAction(const event::Action& e) override { + module->toggleLink(); + } + }; + + struct ChannelModeItem : MenuItem { + Streams* module; + int channel; + int mode; + void onAction(const event::Action& e) override { + module->setChannelMode(channel, mode); + } + }; + + struct MonitorModeItem : MenuItem { + Streams* module; + int mode; + void onAction(const event::Action& e) override { + module->setMonitorMode(mode); + } + }; + + menu->addChild(new MenuSeparator); + LinkItem* linkItem = createMenuItem( + "Link channels", CHECKMARK(module->linked())); + linkItem->module = module; + menu->addChild(linkItem); + + menu->addChild(new MenuSeparator); + menu->addChild(createMenuLabel("Channel 1")); + for (int i = 0; i < streams::kNumChannelModes; i++) { + auto modeItem = createMenuItem( + streams::kChannelModeTable[i].label, CHECKMARK( + module->function(0) == streams::kChannelModeTable[i].function && + module->alternate(0) == streams::kChannelModeTable[i].alternate)); + modeItem->module = module; + modeItem->channel = 0; + modeItem->mode = i; + menu->addChild(modeItem); + } + + menu->addChild(new MenuSeparator); + menu->addChild(createMenuLabel("Channel 2")); + for (int i = 0; i < streams::kNumChannelModes; i++) { + auto modeItem = createMenuItem( + streams::kChannelModeTable[i].label, CHECKMARK( + module->function(1) == streams::kChannelModeTable[i].function && + module->alternate(1) == streams::kChannelModeTable[i].alternate)); + modeItem->module = module; + modeItem->channel = 1; + modeItem->mode = i; + menu->addChild(modeItem); + } + + menu->addChild(new MenuSeparator); + menu->addChild(createMenuLabel("Meter")); + for (int i = 0; i < streams::kNumMonitorModes; i++) { + auto modeItem = createMenuItem( + streams::kMonitorModeTable[i].label, CHECKMARK( + module->monitorMode() == streams::kMonitorModeTable[i].mode)); + modeItem->module = module; + modeItem->mode = i; + menu->addChild(modeItem); + } + } }; Model* modelStreams = createModel("Streams"); diff --git a/src/Streams/adc.hpp b/src/Streams/adc.hpp index 850fff1..0320dd3 100644 --- a/src/Streams/adc.hpp +++ b/src/Streams/adc.hpp @@ -28,7 +28,7 @@ #pragma once -#include "stmlib/stmlib.h" +#include namespace streams { diff --git a/src/Streams/analog_engine.hpp b/src/Streams/analog_engine.hpp index dee11fd..2a6b02f 100644 --- a/src/Streams/analog_engine.hpp +++ b/src/Streams/analog_engine.hpp @@ -16,7 +16,7 @@ #pragma once -#include "rack.hpp" +#include #include "aafilter.hpp" namespace streams diff --git a/src/Streams/audio_cv_meter.hpp b/src/Streams/audio_cv_meter.hpp index 9ecdec1..f6b31fa 100644 --- a/src/Streams/audio_cv_meter.hpp +++ b/src/Streams/audio_cv_meter.hpp @@ -28,7 +28,7 @@ #pragma once -#include "stmlib/stmlib.h" +#include namespace streams { diff --git a/src/Streams/cv_scaler.hpp b/src/Streams/cv_scaler.hpp index 2b92f85..1af9f68 100644 --- a/src/Streams/cv_scaler.hpp +++ b/src/Streams/cv_scaler.hpp @@ -28,9 +28,9 @@ #pragma once -#include "stmlib/stmlib.h" +#include -#include "streams/gain.h" +#include #include "adc.hpp" diff --git a/src/Streams/digital_engine.hpp b/src/Streams/digital_engine.hpp index 9f9e711..10b6520 100644 --- a/src/Streams/digital_engine.hpp +++ b/src/Streams/digital_engine.hpp @@ -17,10 +17,10 @@ #pragma once #include -#include "rack.hpp" +#include #include "cv_scaler.hpp" #include "ui.hpp" -#include "eurorack/streams/processor.h" +#include namespace streams { diff --git a/src/Streams/event_queue.hpp b/src/Streams/event_queue.hpp index 5a39734..bca61f0 100644 --- a/src/Streams/event_queue.hpp +++ b/src/Streams/event_queue.hpp @@ -19,7 +19,7 @@ #pragma once -#include "stmlib/utils/ring_buffer.h" +#include namespace streams { diff --git a/src/Streams/leds.hpp b/src/Streams/leds.hpp index 06715ba..2e93ef4 100644 --- a/src/Streams/leds.hpp +++ b/src/Streams/leds.hpp @@ -28,7 +28,7 @@ #pragma once -#include "stmlib/stmlib.h" +#include namespace streams { diff --git a/src/Streams/resampler.hpp b/src/Streams/resampler.hpp index dd63606..4c5c668 100644 --- a/src/Streams/resampler.hpp +++ b/src/Streams/resampler.hpp @@ -15,7 +15,7 @@ #pragma once -#include "rack.hpp" +#include namespace streams { diff --git a/src/Streams/streams.hpp b/src/Streams/streams.hpp index 7980245..cdf85ee 100644 --- a/src/Streams/streams.hpp +++ b/src/Streams/streams.hpp @@ -17,7 +17,7 @@ #pragma once #include -#include "rack.hpp" +#include #include "resampler.hpp" #include "analog_engine.hpp" #include "digital_engine.hpp" diff --git a/src/Streams/switches.hpp b/src/Streams/switches.hpp index 2ff2b35..c9d432a 100644 --- a/src/Streams/switches.hpp +++ b/src/Streams/switches.hpp @@ -30,7 +30,7 @@ #include -#include "stmlib/stmlib.h" +#include namespace streams { diff --git a/src/Streams/ui.hpp b/src/Streams/ui.hpp index 554941a..b5163f1 100644 --- a/src/Streams/ui.hpp +++ b/src/Streams/ui.hpp @@ -30,16 +30,16 @@ #include -#include "stmlib/stmlib.h" -#include "src/Streams/event_queue.hpp" +#include +#include "event_queue.hpp" -#include "src/Streams/audio_cv_meter.hpp" -#include "src/Streams/cv_scaler.hpp" -#include "streams/processor.h" +#include "audio_cv_meter.hpp" +#include "cv_scaler.hpp" +#include -#include "src/Streams/adc.hpp" -#include "src/Streams/leds.hpp" -#include "src/Streams/switches.hpp" +#include "adc.hpp" +#include "leds.hpp" +#include "switches.hpp" namespace streams {