Browse Source

Autoformat Streams.cpp. Clean up Streams. Add Mutable code to Makefile. Enable Streams in manifest.

v1
Andrew Belt 1 year ago
parent
commit
8ea69e536f
14 changed files with 434 additions and 477 deletions
  1. +9
    -0
      Makefile
  2. +0
    -1
      plugin.json
  3. +405
    -456
      src/Streams.cpp
  4. +1
    -1
      src/Streams/adc.hpp
  5. +1
    -1
      src/Streams/analog_engine.hpp
  6. +1
    -1
      src/Streams/audio_cv_meter.hpp
  7. +2
    -2
      src/Streams/cv_scaler.hpp
  8. +2
    -2
      src/Streams/digital_engine.hpp
  9. +1
    -1
      src/Streams/event_queue.hpp
  10. +1
    -1
      src/Streams/leds.hpp
  11. +1
    -1
      src/Streams/resampler.hpp
  12. +1
    -1
      src/Streams/streams.hpp
  13. +1
    -1
      src/Streams/switches.hpp
  14. +8
    -8
      src/Streams/ui.hpp

+ 9
- 0
Makefile View File

@@ -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



+ 0
- 1
plugin.json View File

@@ -248,7 +248,6 @@
"slug": "Streams",
"name": "Dual Dynamics Gate",
"description": "Based on Mutable Instruments Streams",
"disabled": true,
"tags": [
"Dynamics",
"Low-pass gate",


+ 405
- 456
src/Streams.cpp View File

@@ -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<ScrewSilver>(Vec(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(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(11.065, 128.75 - 107.695)), module, Streams::CH1_SHAPE_PARAM));
addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(11.065, 128.75 - 84.196)), module, Streams::CH1_MOD_PARAM));
addParam(createParamCentered<Rogan1PSRed> (mm2px(Vec(11.065, 128.75 - 60.706)), module, Streams::CH1_LEVEL_MOD_PARAM));
addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(49.785, 128.75 - 107.695)), module, Streams::CH2_SHAPE_PARAM));
addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(49.785, 128.75 - 84.196)), module, Streams::CH2_MOD_PARAM));
addParam(createParamCentered<Rogan1PSGreen>(mm2px(Vec(49.785, 128.75 - 60.706)), module, Streams::CH2_LEVEL_MOD_PARAM));

addParam(createParamCentered<Trimpot>(mm2px(Vec(30.425, 128.75 - 68.006)), module, Streams::CH1_RESPONSE_PARAM));
addParam(createParamCentered<Trimpot>(mm2px(Vec(30.425, 128.75 - 53.406)), module, Streams::CH2_RESPONSE_PARAM));

addParam(createParamCentered<TL1105>(mm2px(Vec(24.715, 128.75 - 113.726)), module, Streams::CH1_FUNCTION_BUTTON_PARAM));
addParam(createParamCentered<TL1105>(mm2px(Vec(36.135, 128.75 - 113.726)), module, Streams::CH2_FUNCTION_BUTTON_PARAM));
addParam(createParamCentered<TL1105>(mm2px(Vec(30.425, 128.75 - 81.976)), module, Streams::METERING_BUTTON_PARAM));

addInput(createInputCentered<PJ301MPort>(mm2px(Vec( 8.506, 128.75 - 32.136)), module, Streams::CH1_EXCITE_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(23.116, 128.75 - 32.136)), module, Streams::CH1_SIGNAL_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec( 8.506, 128.75 - 17.526)), module, Streams::CH1_LEVEL_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(52.335, 128.75 - 32.136)), module, Streams::CH2_EXCITE_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(37.726, 128.75 - 32.136)), module, Streams::CH2_SIGNAL_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(52.335, 128.75 - 17.526)), module, Streams::CH2_LEVEL_INPUT));

addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(23.116, 128.75 - 17.526)), module, Streams::CH1_SIGNAL_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(37.726, 128.75 - 17.526)), module, Streams::CH2_SIGNAL_OUTPUT));

addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(24.715, 128.75 - 106.746)), module, Streams::CH1_LIGHT_1_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(24.715, 128.75 - 101.026)), module, Streams::CH1_LIGHT_2_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(24.715, 128.75 - 95.305)), module, Streams::CH1_LIGHT_3_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(24.715, 128.75 - 89.585)), module, Streams::CH1_LIGHT_4_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(36.135, 128.75 - 106.746)), module, Streams::CH2_LIGHT_1_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(36.135, 128.75 - 101.026)), module, Streams::CH2_LIGHT_2_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(36.135, 128.75 - 95.305)), module, Streams::CH2_LIGHT_3_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(36.135, 128.75 - 89.585)), module, Streams::CH2_LIGHT_4_G));
}

void appendContextMenu(Menu* menu) override
{
Streams* module = dynamic_cast<Streams*>(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<LinkItem>(
"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<ChannelModeItem>(
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<ChannelModeItem>(
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<MonitorModeItem>(
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<ScrewSilver>(Vec(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(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(11.065, 128.75 - 107.695)), module, Streams::CH1_SHAPE_PARAM));
addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(11.065, 128.75 - 84.196)), module, Streams::CH1_MOD_PARAM));
addParam(createParamCentered<Rogan1PSRed> (mm2px(Vec(11.065, 128.75 - 60.706)), module, Streams::CH1_LEVEL_MOD_PARAM));
addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(49.785, 128.75 - 107.695)), module, Streams::CH2_SHAPE_PARAM));
addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(49.785, 128.75 - 84.196)), module, Streams::CH2_MOD_PARAM));
addParam(createParamCentered<Rogan1PSGreen>(mm2px(Vec(49.785, 128.75 - 60.706)), module, Streams::CH2_LEVEL_MOD_PARAM));

addParam(createParamCentered<Trimpot>(mm2px(Vec(30.425, 128.75 - 68.006)), module, Streams::CH1_RESPONSE_PARAM));
addParam(createParamCentered<Trimpot>(mm2px(Vec(30.425, 128.75 - 53.406)), module, Streams::CH2_RESPONSE_PARAM));

addParam(createParamCentered<TL1105>(mm2px(Vec(24.715, 128.75 - 113.726)), module, Streams::CH1_FUNCTION_BUTTON_PARAM));
addParam(createParamCentered<TL1105>(mm2px(Vec(36.135, 128.75 - 113.726)), module, Streams::CH2_FUNCTION_BUTTON_PARAM));
addParam(createParamCentered<TL1105>(mm2px(Vec(30.425, 128.75 - 81.976)), module, Streams::METERING_BUTTON_PARAM));

addInput(createInputCentered<PJ301MPort>(mm2px(Vec(8.506, 128.75 - 32.136)), module, Streams::CH1_EXCITE_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(23.116, 128.75 - 32.136)), module, Streams::CH1_SIGNAL_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(8.506, 128.75 - 17.526)), module, Streams::CH1_LEVEL_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(52.335, 128.75 - 32.136)), module, Streams::CH2_EXCITE_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(37.726, 128.75 - 32.136)), module, Streams::CH2_SIGNAL_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(52.335, 128.75 - 17.526)), module, Streams::CH2_LEVEL_INPUT));

addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(23.116, 128.75 - 17.526)), module, Streams::CH1_SIGNAL_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(37.726, 128.75 - 17.526)), module, Streams::CH2_SIGNAL_OUTPUT));

addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(24.715, 128.75 - 106.746)), module, Streams::CH1_LIGHT_1_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(24.715, 128.75 - 101.026)), module, Streams::CH1_LIGHT_2_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(24.715, 128.75 - 95.305)), module, Streams::CH1_LIGHT_3_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(24.715, 128.75 - 89.585)), module, Streams::CH1_LIGHT_4_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(36.135, 128.75 - 106.746)), module, Streams::CH2_LIGHT_1_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(36.135, 128.75 - 101.026)), module, Streams::CH2_LIGHT_2_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(36.135, 128.75 - 95.305)), module, Streams::CH2_LIGHT_3_G));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(36.135, 128.75 - 89.585)), module, Streams::CH2_LIGHT_4_G));
}

void appendContextMenu(Menu* menu) override {
Streams* module = dynamic_cast<Streams*>(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<LinkItem>(
"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<ChannelModeItem>(
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<ChannelModeItem>(
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<MonitorModeItem>(
streams::kMonitorModeTable[i].label, CHECKMARK(
module->monitorMode() == streams::kMonitorModeTable[i].mode));
modeItem->module = module;
modeItem->mode = i;
menu->addChild(modeItem);
}
}
};

Model* modelStreams = createModel<Streams, StreamsWidget>("Streams");

+ 1
- 1
src/Streams/adc.hpp View File

@@ -28,7 +28,7 @@

#pragma once

#include "stmlib/stmlib.h"
#include <stmlib/stmlib.h>

namespace streams
{


+ 1
- 1
src/Streams/analog_engine.hpp View File

@@ -16,7 +16,7 @@

#pragma once

#include "rack.hpp"
#include <rack.hpp>
#include "aafilter.hpp"

namespace streams


+ 1
- 1
src/Streams/audio_cv_meter.hpp View File

@@ -28,7 +28,7 @@

#pragma once

#include "stmlib/stmlib.h"
#include <stmlib/stmlib.h>

namespace streams
{


+ 2
- 2
src/Streams/cv_scaler.hpp View File

@@ -28,9 +28,9 @@

#pragma once

#include "stmlib/stmlib.h"
#include <stmlib/stmlib.h>

#include "streams/gain.h"
#include <streams/gain.h>

#include "adc.hpp"



+ 2
- 2
src/Streams/digital_engine.hpp View File

@@ -17,10 +17,10 @@
#pragma once

#include <cmath>
#include "rack.hpp"
#include <rack.hpp>
#include "cv_scaler.hpp"
#include "ui.hpp"
#include "eurorack/streams/processor.h"
#include <streams/processor.h>

namespace streams
{


+ 1
- 1
src/Streams/event_queue.hpp View File

@@ -19,7 +19,7 @@

#pragma once

#include "stmlib/utils/ring_buffer.h"
#include <stmlib/utils/ring_buffer.h>

namespace streams
{


+ 1
- 1
src/Streams/leds.hpp View File

@@ -28,7 +28,7 @@

#pragma once

#include "stmlib/stmlib.h"
#include <stmlib/stmlib.h>

namespace streams
{


+ 1
- 1
src/Streams/resampler.hpp View File

@@ -15,7 +15,7 @@

#pragma once

#include "rack.hpp"
#include <rack.hpp>

namespace streams
{


+ 1
- 1
src/Streams/streams.hpp View File

@@ -17,7 +17,7 @@
#pragma once

#include <cmath>
#include "rack.hpp"
#include <rack.hpp>
#include "resampler.hpp"
#include "analog_engine.hpp"
#include "digital_engine.hpp"


+ 1
- 1
src/Streams/switches.hpp View File

@@ -30,7 +30,7 @@

#include <algorithm>

#include "stmlib/stmlib.h"
#include <stmlib/stmlib.h>

namespace streams
{


+ 8
- 8
src/Streams/ui.hpp View File

@@ -30,16 +30,16 @@

#include <algorithm>

#include "stmlib/stmlib.h"
#include "src/Streams/event_queue.hpp"
#include <stmlib/stmlib.h>
#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 <streams/processor.h>

#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
{


Loading…
Cancel
Save