Browse Source

Make STMix polyphonic

* remove clipping from Morphader (according to voltage saturation part of voltage standard)
tags/v2.1.0
hemmer 3 years ago
parent
commit
ddd9ad94a4
4 changed files with 81 additions and 40 deletions
  1. +2
    -1
      plugin.json
  2. +7
    -7
      res/STMix.svg
  3. +3
    -2
      src/Morphader.cpp
  4. +69
    -30
      src/STMix.cpp

+ 2
- 1
plugin.json View File

@@ -200,7 +200,8 @@
"tags": [
"Hardware clone",
"Mixer",
"Stereo"
"Stereo",
"Polyphonic"
]
}
]

+ 7
- 7
res/STMix.svg View File

@@ -25,9 +25,9 @@
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="95.397589"
inkscape:cy="410.81889"
inkscape:cy="380.51432"
inkscape:document-units="mm"
inkscape:current-layer="components"
inkscape:current-layer="background"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="2560"
@@ -96,7 +96,7 @@
inkscape:export-filename="/home/diego/Escritorio/tirar kick all"
inkscape:label="Layer 1"
id="g73679"
transform="matrix(0.22493746,0,0,0.22493746,-41.377444,5.1830576)"
transform="matrix(0.22493746,0,0,0.22493746,-39.998259,5.1830576)"
style="display:inline">
<g
id="g73681"
@@ -107,7 +107,7 @@
style="fill:#ffffff">
<polygon
id="polygon73685"
points="606.316,298.069 640.94,298.069 640.94,259.056 537.067,259.056 537.067,362.929 640.94,362.929 640.94,328.304 606.315,328.304 571.691,328.304 571.691,305.222 571.691,289.29 606.315,289.29 "
points="640.94,259.056 537.067,259.056 537.067,362.929 640.94,362.929 640.94,328.304 606.315,328.304 571.691,328.304 571.691,305.222 571.691,289.29 606.315,289.29 606.316,298.069 640.94,298.069 "
style="fill:#ffffff"
transform="scale(1.0666667)" />
<path
@@ -127,12 +127,12 @@
style="fill:#ffffff;stroke-width:1.06667" />
<polygon
id="polygon73693"
points="272.366,311.113 294.698,289.29 294.698,259.056 190.825,259.056 190.825,289.29 253.516,289.29 231.128,310.993 254.394,332.696 190.825,332.696 190.825,362.929 294.698,362.929 294.698,332.696 "
points="294.698,259.056 190.825,259.056 190.825,289.29 253.516,289.29 231.128,310.993 254.394,332.696 190.825,332.696 190.825,362.929 294.698,362.929 294.698,332.696 272.366,311.113 294.698,289.29 "
style="fill:#ffffff"
transform="scale(1.0666667)" />
<polygon
id="polygon73695"
points="312.344,289.41 333.836,311.113 312.344,332.865 312.344,363.049 355.542,363.289 355.542,332.559 375.968,311.113 355.542,289.273 405.684,289.41 436.556,259.176 312.344,259.176 "
points="312.344,332.865 312.344,363.049 355.542,363.289 355.542,332.559 375.968,311.113 355.542,289.273 405.684,289.41 436.556,259.176 312.344,259.176 312.344,289.41 333.836,311.113 "
style="fill:#ffffff"
transform="scale(1.0666667)" />
</g>
@@ -548,7 +548,7 @@
inkscape:groupmode="layer"
id="components"
inkscape:label="components"
style="display:inline">
style="display:none">
<g
inkscape:export-ydpi="300"
inkscape:export-xdpi="300"


+ 3
- 2
src/Morphader.cpp View File

@@ -179,8 +179,9 @@ struct Morphader : Module {
}
case AUDIO_MODE: {
// in audio mode, close to the centre point it is possible to get large voltages
// (e.g. if A and B are both 10V const), so clip
out[c / 4] = clamp(equalPowerCrossfade(inA, inB, channelCrossfades[i]), -12.f, +12.f);
// (e.g. if A and B are both 10V const). however according to the standard, it is
// better not to clip this https://vcvrack.com/manual/VoltageStandards#Output-Saturation
out[c / 4] = equalPowerCrossfade(inA, inB, channelCrossfades[i]);
break;
}
default: assert(false);


+ 69
- 30
src/STMix.cpp View File

@@ -1,9 +1,10 @@
#include "plugin.hpp"

using simd::float_4;

struct STMix : Module {

// NOTE: not including auxilary channel
// NOTE: not including auxiliary channel
static const int numMixerChannels = 4;

enum ParamIds {
@@ -22,8 +23,8 @@ struct STMix : Module {
NUM_OUTPUTS
};
enum LightIds {
LEFT_LED,
RIGHT_LED,
ENUMS(LEFT_LED, 3),
ENUMS(RIGHT_LED, 3),
NUM_LIGHTS
};

@@ -32,27 +33,65 @@ struct STMix : Module {
for (int i = 0; i < numMixerChannels; ++i) {
configParam(GAIN_PARAM + i, 0.f, 1.f, 0.f, string::f("Gain %d", i + 1));
}

}

void process(const ProcessArgs& args) override {
float out[2] = {};
float_4 out_left[4] = {};
float_4 out_right[4] = {};

int numActivePolyphonyEngines = 1;
for (int i = 0; i < numMixerChannels + 1; ++i) {
const int stereoPolyChannels = std::max(inputs[LEFT_INPUT + i].getChannels(),
inputs[RIGHT_INPUT + i].getChannels());
numActivePolyphonyEngines = std::max(numActivePolyphonyEngines, stereoPolyChannels);
}

for (int i = 0; i < numMixerChannels + 1; ++i) {

for (int c = 0; c < numActivePolyphonyEngines; c += 4) {
const float_4 in_left = inputs[LEFT_INPUT + i].getNormalPolyVoltageSimd<float_4>(0.f, c);
const float_4 in_right = inputs[RIGHT_INPUT + i].getNormalPolyVoltageSimd<float_4>(in_left, c);

const float in_left = inputs[LEFT_INPUT + i].getNormalVoltage(0.f);
const float in_right = inputs[RIGHT_INPUT + i].getNormalVoltage(in_left);
const float gain = (i < numMixerChannels) ? params[GAIN_PARAM + i].getValue() : 1.f;
const float gain = (i < numMixerChannels) ? params[GAIN_PARAM + i].getValue() : 1.f;

out[0] += in_left * gain;
out[1] += in_right * gain;
out_left[c / 4] += in_left * gain;
out_right[c / 4] += in_right * gain;
}
}

outputs[LEFT_OUTPUT].setVoltage(out[0]);
outputs[RIGHT_OUTPUT].setVoltage(out[1]);
outputs[LEFT_OUTPUT].setChannels(numActivePolyphonyEngines);
outputs[RIGHT_OUTPUT].setChannels(numActivePolyphonyEngines);

lights[LEFT_LED].setSmoothBrightness(outputs[LEFT_OUTPUT].getVoltage() / 5.f, args.sampleTime);
lights[RIGHT_LED].setSmoothBrightness(outputs[RIGHT_OUTPUT].getVoltage() / 5.f, args.sampleTime);
for (int c = 0; c < numActivePolyphonyEngines; c += 4) {
outputs[LEFT_OUTPUT].setVoltageSimd(out_left[c / 4], c);
outputs[RIGHT_OUTPUT].setVoltageSimd(out_right[c / 4], c);
}

if (numActivePolyphonyEngines == 1) {
lights[LEFT_LED + 0].setSmoothBrightness(outputs[LEFT_OUTPUT].getVoltage() / 5.f, args.sampleTime);
lights[RIGHT_LED + 0].setSmoothBrightness(outputs[RIGHT_OUTPUT].getVoltage() / 5.f, args.sampleTime);
lights[LEFT_LED + 1].setBrightness(0.f);
lights[RIGHT_LED + 1].setBrightness(0.f);
lights[LEFT_LED + 2].setBrightness(0.f);
lights[RIGHT_LED + 2].setBrightness(0.f);
}
else {
lights[LEFT_LED + 0].setBrightness(0.f);
lights[RIGHT_LED + 0].setBrightness(0.f);
lights[LEFT_LED + 1].setBrightness(0.f);
lights[RIGHT_LED + 1].setBrightness(0.f);

float b_left = 0.f;
float b_right = 0.f;
for (int c = 0; c < numActivePolyphonyEngines; c++) {
b_left += std::pow(out_left[c / 4][c % 4], 2);
b_right += std::pow(out_right[c / 4][c % 4], 2);
}
b_left = std::sqrt(b_left) / 5.f;
b_right = std::sqrt(b_right) / 5.f;
lights[LEFT_LED + 2].setSmoothBrightness(b_left, args.sampleTime);
lights[RIGHT_LED + 2].setSmoothBrightness(b_right, args.sampleTime);
}
}
};

@@ -65,28 +104,28 @@ struct STMixWidget : ModuleWidget {
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

addParam(createParamCentered<Davies1900hWhiteKnob>(mm2px(Vec(20.892, 18.141)), module, STMix::GAIN_PARAM + 0));
addParam(createParamCentered<Davies1900hWhiteKnob>(mm2px(Vec(20.982, 41.451)), module, STMix::GAIN_PARAM + 1));
addParam(createParamCentered<Davies1900hWhiteKnob>(mm2px(Vec(20.927, 64.318)), module, STMix::GAIN_PARAM + 2));
addParam(createParamCentered<Davies1900hWhiteKnob>(mm2px(Vec(21.0, 18.141)), module, STMix::GAIN_PARAM + 0));
addParam(createParamCentered<Davies1900hWhiteKnob>(mm2px(Vec(21.0, 41.451)), module, STMix::GAIN_PARAM + 1));
addParam(createParamCentered<Davies1900hWhiteKnob>(mm2px(Vec(21.0, 64.318)), module, STMix::GAIN_PARAM + 2));
addParam(createParamCentered<Davies1900hWhiteKnob>(mm2px(Vec(21.0, 87.124)), module, STMix::GAIN_PARAM + 3));

addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.308, 13.108)), module, STMix::LEFT_INPUT + 0));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.308, 36.175)), module, STMix::LEFT_INPUT + 1));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 13.108)), module, STMix::LEFT_INPUT + 0));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 36.175)), module, STMix::LEFT_INPUT + 1));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 59.243)), module, STMix::LEFT_INPUT + 2));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.279, 82.311)), module, STMix::LEFT_INPUT + 3));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.287, 105.378)), module, STMix::LEFT_INPUT + 4));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 82.311)), module, STMix::LEFT_INPUT + 3));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 105.378)), module, STMix::LEFT_INPUT + 4));

addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.308, 23.108)), module, STMix::RIGHT_INPUT + 0));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.313, 46.354)), module, STMix::RIGHT_INPUT + 1));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.308, 69.237)), module, STMix::RIGHT_INPUT + 2));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.308, 92.132)), module, STMix::RIGHT_INPUT + 3));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.279, 115.379)), module, STMix::RIGHT_INPUT + 4));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 23.108)), module, STMix::RIGHT_INPUT + 0));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 46.354)), module, STMix::RIGHT_INPUT + 1));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 69.237)), module, STMix::RIGHT_INPUT + 2));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 92.132)), module, STMix::RIGHT_INPUT + 3));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(6.3, 115.379)), module, STMix::RIGHT_INPUT + 4));

addOutput(createOutputCentered<BefacoOutputPort>(mm2px(Vec(23.813, 105.422)), module, STMix::LEFT_OUTPUT));
addOutput(createOutputCentered<BefacoOutputPort>(mm2px(Vec(23.792, 115.392)), module, STMix::RIGHT_OUTPUT));
addOutput(createOutputCentered<BefacoOutputPort>(mm2px(Vec(23.8, 105.422)), module, STMix::LEFT_OUTPUT));
addOutput(createOutputCentered<BefacoOutputPort>(mm2px(Vec(23.8, 115.392)), module, STMix::RIGHT_OUTPUT));

addChild(createLightCentered<MediumLight<RedLight>>(mm2px(Vec(16.8, 103.0)), module, STMix::LEFT_LED));
addChild(createLightCentered<MediumLight<RedLight>>(mm2px(Vec(16.8, 113.0)), module, STMix::RIGHT_LED));
addChild(createLightCentered<MediumLight<RedGreenBlueLight>>(mm2px(Vec(16.8, 103.0)), module, STMix::LEFT_LED));
addChild(createLightCentered<MediumLight<RedGreenBlueLight>>(mm2px(Vec(16.8, 113.0)), module, STMix::RIGHT_LED));
}
};



Loading…
Cancel
Save