From f40d3343fb00d612fd6c837df96ee7a0dcc64530 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Mon, 31 Dec 2018 15:41:28 -0500 Subject: [PATCH] Add polyphony to ports and wires --- include/engine/Input.hpp | 14 ++++---------- include/engine/Output.hpp | 9 ++------- include/engine/Port.hpp | 34 ++++++++++++++++++++++++++++++++++ src/app/WireWidget.cpp | 21 +++++++++++++++------ src/engine/Wire.cpp | 11 ++++++++--- 5 files changed, 63 insertions(+), 26 deletions(-) create mode 100644 include/engine/Port.hpp diff --git a/include/engine/Input.hpp b/include/engine/Input.hpp index 9a908b25..201f2c8a 100644 --- a/include/engine/Input.hpp +++ b/include/engine/Input.hpp @@ -1,21 +1,15 @@ #pragma once #include "common.hpp" -#include "engine/Light.hpp" +#include "engine/Port.hpp" namespace rack { -struct Input { - /** Voltage of the port, zero if not plugged in. Read-only by Module */ - float value = 0.f; - /** Whether a wire is plugged in */ - bool active = false; - Light plugLights[2]; - +struct Input : Port { /** Returns the value if a wire is plugged in, otherwise returns the given default value */ - float normalize(float normalValue) { - return active ? value : normalValue; + float normalize(float normalValue, int index = 0) { + return active ? getValue(index) : normalValue; } }; diff --git a/include/engine/Output.hpp b/include/engine/Output.hpp index b3084e40..db938435 100644 --- a/include/engine/Output.hpp +++ b/include/engine/Output.hpp @@ -1,17 +1,12 @@ #pragma once #include "common.hpp" -#include "engine/Light.hpp" +#include "engine/Port.hpp" namespace rack { -struct Output { - /** Voltage of the port. Write-only by Module */ - float value = 0.f; - /** Whether a wire is plugged in */ - bool active = false; - Light plugLights[2]; +struct Output : Port { }; diff --git a/include/engine/Port.hpp b/include/engine/Port.hpp new file mode 100644 index 00000000..2f2f146a --- /dev/null +++ b/include/engine/Port.hpp @@ -0,0 +1,34 @@ +#pragma once +#include "common.hpp" +#include "engine/Light.hpp" + + +namespace rack { + + +static const int PORT_MAX_CHANNELS = 16; + + +struct Port { + /** Voltage of the port */ + union { + float value; + float values[PORT_MAX_CHANNELS]; + }; + /** Number of polyphonic channels */ + int numChannels = 1; + /** Whether a wire is plugged in */ + bool active = false; + Light plugLights[2]; + + float getValue(int index = 0) { + return values[index]; + } + + void setValue(float value, int index = 0) { + this->values[index] = value; + } +}; + + +} // namespace rack diff --git a/src/app/WireWidget.cpp b/src/app/WireWidget.cpp index ee8510ea..d04cd560 100644 --- a/src/app/WireWidget.cpp +++ b/src/app/WireWidget.cpp @@ -31,14 +31,15 @@ static void drawPlug(NVGcontext *vg, math::Vec pos, NVGcolor color) { nvgFill(vg); } -static void drawWire(NVGcontext *vg, math::Vec pos1, math::Vec pos2, NVGcolor color, float tension, float opacity) { +static void drawWire(NVGcontext *vg, math::Vec pos1, math::Vec pos2, NVGcolor color, float width, float tension, float opacity) { NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.10); NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); // Wire if (opacity > 0.0) { nvgSave(vg); - nvgGlobalAlpha(vg, powf(opacity, 1.5)); + // This power scaling looks more linear than actual linear scaling + nvgGlobalAlpha(vg, std::pow(opacity, 1.5)); float dist = pos1.minus(pos2).norm(); math::Vec slump; @@ -53,7 +54,7 @@ static void drawWire(NVGcontext *vg, math::Vec pos1, math::Vec pos2, NVGcolor co nvgMoveTo(vg, pos1.x, pos1.y); nvgQuadTo(vg, pos4.x, pos4.y, pos2.x, pos2.y); nvgStrokeColor(vg, colorShadow); - nvgStrokeWidth(vg, 5); + nvgStrokeWidth(vg, width); nvgStroke(vg); // Wire outline @@ -61,12 +62,12 @@ static void drawWire(NVGcontext *vg, math::Vec pos1, math::Vec pos2, NVGcolor co nvgMoveTo(vg, pos1.x, pos1.y); nvgQuadTo(vg, pos3.x, pos3.y, pos2.x, pos2.y); nvgStrokeColor(vg, colorOutline); - nvgStrokeWidth(vg, 5); + nvgStrokeWidth(vg, width); nvgStroke(vg); // Wire solid nvgStrokeColor(vg, color); - nvgStrokeWidth(vg, 3); + nvgStrokeWidth(vg, width - 2); nvgStroke(vg); nvgRestore(vg); @@ -178,9 +179,17 @@ void WireWidget::draw(NVGcontext *vg) { opacity = 1.0; } + float width = 5; + if (wire && wire->outputModule) { + Output *output = &wire->outputModule->outputs[wire->outputId]; + if (output->numChannels != 1) { + width = 8; + } + } + math::Vec outputPos = getOutputPos(); math::Vec inputPos = getInputPos(); - drawWire(vg, outputPos, inputPos, color, tension, opacity); + drawWire(vg, outputPos, inputPos, color, width, tension, opacity); } void WireWidget::drawPlugs(NVGcontext *vg) { diff --git a/src/engine/Wire.cpp b/src/engine/Wire.cpp index 45d735d6..9dd9bb62 100644 --- a/src/engine/Wire.cpp +++ b/src/engine/Wire.cpp @@ -5,9 +5,14 @@ namespace rack { void Wire::step() { - // Copy output to input - float value = outputModule->outputs[outputId].value; - inputModule->inputs[inputId].value = value; + Output *output = &outputModule->outputs[outputId]; + Input *input = &inputModule->inputs[inputId]; + // Match number of polyphonic channels to output port + input->numChannels = output->numChannels; + // Copy values from output to input + for (int i = 0; i < output->numChannels; i++) { + input->values[i] = output->values[i]; + } }