commit 0f248d0263e23d4cc421d586d190790d821cc3d1
parent ba169d3695bf1e68e5203576542969eecdc20a60
Author: Matt Demanett <matt@demanett.net>
Date: Sat, 4 May 2019 22:49:05 -0400
UMIX: add "cv mode" as context menu option: disables saturation for precision adding. #42
Diffstat:
3 files changed, 47 insertions(+), 6 deletions(-)
diff --git a/README.md b/README.md
@@ -218,10 +218,12 @@ By default, the output is hard clipped at +/-12 volts (this is a standard in Rac
#### UMIX
-A 3HP unity mixer, usable with CV (e.g. combining triggers) or audio. Up to 8 inputs are summed to the output. Saturation (soft clipping) is applied to the output at +/-12 volts; the LEVEL knob allows attenuation of the mix before the saturation is applied.
+A 3HP unity mixer, usable with CV (e.g. combining triggers) or audio. Up to 8 inputs are summed to the output. Saturation (soft clipping) is applied to the output, which limits it to around +/-11V; the LEVEL knob allows attenuation of the mix before the saturation is applied.
The context (right-click) menu has an option to average, rather than sum, the inputs.
+A second context menu option, "CV mode", disables the saturation, which allows for precise summing (or averaging) of CVs. In this case the output is hard-clipped at +/-12V.
+
#### MATRIX88
An 8x8 channel matrix mixer. Each input can be sent with an independent level to each of the eight output mixes.
diff --git a/src/UMix.cpp b/src/UMix.cpp
@@ -2,17 +2,24 @@
#include "UMix.hpp"
#define SUM "sum"
+#define CVMODE "cv_mode"
json_t* UMix::toJson() {
json_t* root = json_object();
json_object_set_new(root, SUM, json_boolean(_sum));
+ json_object_set_new(root, CVMODE, json_boolean(_cvMode));
return root;
}
void UMix::fromJson(json_t* root) {
- json_t* ll = json_object_get(root, SUM);
- if (ll) {
- _sum = json_is_true(ll);
+ json_t* s = json_object_get(root, SUM);
+ if (s) {
+ _sum = json_is_true(s);
+ }
+
+ json_t* c = json_object_get(root, CVMODE);
+ if (c) {
+ _cvMode = json_is_true(c);
}
}
@@ -25,7 +32,13 @@ void UMix::step() {
for (int i = 0; i < 8; ++i) {
out += inputs[IN1_INPUT + i].value;
}
- outputs[OUT_OUTPUT].value = _saturator.next(params[LEVEL_PARAM].value * out);
+ out *= params[LEVEL_PARAM].value;
+ if (_cvMode) {
+ outputs[OUT_OUTPUT].value = clamp(out, -12.0f, 12.0f);
+ }
+ else {
+ outputs[OUT_OUTPUT].value = _saturator.next(out);
+ }
}
else {
float out = 0.0f;
@@ -38,7 +51,13 @@ void UMix::step() {
}
if (active > 0) {
out /= (float)active;
- outputs[OUT_OUTPUT].value = _saturator.next(params[LEVEL_PARAM].value * out);
+ out *= params[LEVEL_PARAM].value;
+ if (_cvMode) {
+ outputs[OUT_OUTPUT].value = clamp(out, -12.0f, 12.0f);
+ }
+ else {
+ outputs[OUT_OUTPUT].value = _saturator.next(out);
+ }
}
else {
outputs[OUT_OUTPUT].value = 0.0f;
@@ -64,6 +83,24 @@ struct AverageMenuItem : MenuItem {
}
};
+struct CVModeMenuItem : MenuItem {
+ UMix* _module;
+
+ CVModeMenuItem(UMix* module, const char* label)
+ : _module(module)
+ {
+ this->text = label;
+ }
+
+ void onAction(EventAction &e) override {
+ _module->_cvMode = !_module->_cvMode;
+ }
+
+ void step() override {
+ rightText = _module->_cvMode ? "✔" : "";
+ }
+};
+
struct UMixWidget : ModuleWidget {
static constexpr int hp = 3;
@@ -114,6 +151,7 @@ struct UMixWidget : ModuleWidget {
assert(umix);
menu->addChild(new MenuLabel());
menu->addChild(new AverageMenuItem(umix, "Average"));
+ menu->addChild(new CVModeMenuItem(umix, "CV mode"));
}
};
diff --git a/src/UMix.hpp b/src/UMix.hpp
@@ -37,6 +37,7 @@ struct UMix : Module {
};
bool _sum = true;
+ bool _cvMode = false;
Saturator _saturator;
UMix() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {