* make orange more vidid * draggable sliderspull/42/head
@@ -21,9 +21,11 @@ We have tried to make the VCV implementations as authentic as possible, however | |||
* The Noise Plethora filters self-oscillate on the hardware version but not the software version. | |||
* EvenVCO has the option (default true) to remove DC from the pulse waveform output (hardware contains DC for non-50% duty cycles) | |||
* EvenVCO has the option (default true) to remove DC from the pulse waveform output (hardware contains DC for non-50% duty cycles). | |||
* PonyVCO optionally allows the user: | |||
* to filter DC from the TZFM input signal (hardware filters below 15mHz) | |||
* to limit the pulsewidth from 5% to 95% (hardware is full range) | |||
* to remove DC from the pulse waveform output (hardware contains DC for non-50% duty cycles) | |||
* to remove DC from the pulse waveform output (hardware contains DC for non-50% duty cycles) | |||
* MotionMTR optionally doesn't use the 10V normalling on inputs if in audio mode to avoid acidentally adding unwanted DC to audio signals, see context menu. E.g. if you temporarily unpatch an audio source whilst using it it mixer mode, you get 10V DC suddenly and a nasty pop. |
@@ -0,0 +1,88 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> | |||
<svg | |||
version="1.0" | |||
id="svg258108" | |||
sodipodi:docname="CKSSThree_bg.svg" | |||
x="0px" | |||
y="0px" | |||
width="13.457px" | |||
height="28.34766px" | |||
viewBox="0 0 13.457 28.34766" | |||
enable-background="new 0 0 13.457 28.34766" | |||
xml:space="preserve" | |||
inkscape:version="1.2.1 (9c6d41e, 2022-07-14)" | |||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |||
xmlns="http://www.w3.org/2000/svg" | |||
xmlns:svg="http://www.w3.org/2000/svg"><defs | |||
id="defs158" /> | |||
<sodipodi:namedview | |||
bordercolor="#666666" | |||
borderopacity="1.0" | |||
fit-margin-bottom="0" | |||
fit-margin-left="0" | |||
fit-margin-right="0" | |||
fit-margin-top="0" | |||
id="base" | |||
inkscape:current-layer="svg258108" | |||
inkscape:cx="3.8392857" | |||
inkscape:cy="16.964286" | |||
inkscape:document-units="mm" | |||
inkscape:pageopacity="0.0" | |||
inkscape:pageshadow="2" | |||
inkscape:window-height="882" | |||
inkscape:window-maximized="0" | |||
inkscape:window-width="1600" | |||
inkscape:window-x="0" | |||
inkscape:window-y="25" | |||
inkscape:zoom="11.2" | |||
pagecolor="#ffffff" | |||
showgrid="false" | |||
inkscape:showpageshadow="2" | |||
inkscape:pagecheckerboard="0" | |||
inkscape:deskcolor="#d1d1d1"> | |||
</sodipodi:namedview> | |||
<path | |||
id="path243332" | |||
inkscape:connector-curvature="0" | |||
d="M0,1.41795c0-0.78124,0.6406-1.41797,1.41793-1.41797h10.62499 c0.77739,0,1.4141,0.63671,1.4141,1.41797v25.51173c0,0.77735-0.63669,1.41797-1.4141,1.41797H1.41793 C0.6406,28.34765,0,27.70702,0,26.92968V1.41795z" /> | |||
<linearGradient | |||
id="path243334_1_" | |||
gradientUnits="userSpaceOnUse" | |||
x1="6.73046" | |||
y1="1.26953" | |||
x2="6.73046" | |||
y2="27.07812"> | |||
<stop | |||
offset="0" | |||
style="stop-color:#3B3B3B" | |||
id="stop134" /> | |||
<stop | |||
offset="1" | |||
style="stop-color:#242424" | |||
id="stop136" /> | |||
</linearGradient> | |||
<path | |||
id="path243334" | |||
inkscape:connector-curvature="0" | |||
opacity="0.54" | |||
fill="url(#path243334_1_)" | |||
d="M11.3242,1.26953H2.13671 c-0.48326,0-0.87501,0.39176-0.87501,0.87501v24.05857c0,0.48326,0.39176,0.87501,0.87501,0.87501h9.18749 c0.48326,0,0.87501-0.39176,0.87501-0.87501V2.14454C12.19921,1.66128,11.80746,1.26953,11.3242,1.26953z" /> | |||
<rect | |||
x="-19.43386" | |||
y="19.77311" | |||
fill="none" | |||
width="0.6829" | |||
height="0.89523" | |||
id="rect140" /> | |||
<rect | |||
x="0.73033" | |||
y="0.80507" | |||
opacity="0.3" | |||
width="12.00026" | |||
height="1.71664" | |||
id="rect142" /> | |||
</svg> |
@@ -0,0 +1,148 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> | |||
<svg | |||
version="1.0" | |||
id="svg258108" | |||
sodipodi:docname="CKSSThree_fg.svg" | |||
x="0px" | |||
y="0px" | |||
width="10.94143" | |||
height="11.941" | |||
viewBox="0 0 10.94143 11.941" | |||
enable-background="new 0 0 13.457 28.34766" | |||
xml:space="preserve" | |||
inkscape:version="1.2.1 (9c6d41e, 2022-07-14)" | |||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |||
xmlns:xlink="http://www.w3.org/1999/xlink" | |||
xmlns="http://www.w3.org/2000/svg" | |||
xmlns:svg="http://www.w3.org/2000/svg"><defs | |||
id="defs3211"><linearGradient | |||
inkscape:collect="always" | |||
xlink:href="#linearGradient1577" | |||
id="linearGradient1579" | |||
x1="6.4409394" | |||
y1="10.29908" | |||
x2="6.4493213" | |||
y2="13.185839" | |||
gradientUnits="userSpaceOnUse" | |||
gradientTransform="matrix(1.003741,0,0,1,-0.03019806,-1.4171131)" /><linearGradient | |||
inkscape:collect="always" | |||
id="linearGradient1577"><stop | |||
style="stop-color:#000000;stop-opacity:0.38225257;" | |||
offset="0" | |||
id="stop1573" /><stop | |||
style="stop-color:#000000;stop-opacity:0;" | |||
offset="1" | |||
id="stop1575" /></linearGradient></defs> | |||
<sodipodi:namedview | |||
bordercolor="#666666" | |||
borderopacity="1.0" | |||
fit-margin-bottom="0" | |||
fit-margin-left="0" | |||
fit-margin-right="0" | |||
fit-margin-top="0" | |||
id="base" | |||
inkscape:current-layer="svg258108" | |||
inkscape:cx="1.0976869" | |||
inkscape:cy="8.2185788" | |||
inkscape:document-units="mm" | |||
inkscape:pageopacity="0.0" | |||
inkscape:pageshadow="2" | |||
inkscape:window-height="882" | |||
inkscape:window-maximized="0" | |||
inkscape:window-width="1600" | |||
inkscape:window-x="0" | |||
inkscape:window-y="25" | |||
inkscape:zoom="53.293886" | |||
pagecolor="#ffffff" | |||
showgrid="false" | |||
inkscape:showpageshadow="2" | |||
inkscape:pagecheckerboard="0" | |||
inkscape:deskcolor="#d1d1d1"> | |||
</sodipodi:namedview> | |||
<linearGradient | |||
id="path243334_1_" | |||
gradientUnits="userSpaceOnUse" | |||
x1="6.7304602" | |||
y1="1.2695301" | |||
x2="6.7304602" | |||
y2="27.078119"> | |||
<stop | |||
offset="0" | |||
style="stop-color:#3B3B3B" | |||
id="stop3187" /> | |||
<stop | |||
offset="1" | |||
style="stop-color:#242424" | |||
id="stop3189" /> | |||
</linearGradient> | |||
<rect | |||
x="-19.433861" | |||
y="19.773109" | |||
fill="none" | |||
width="0.68290001" | |||
height="0.89523" | |||
id="rect3193" /> | |||
<g | |||
id="g3208" | |||
transform="translate(-1.25778,-18.23161)"> | |||
<linearGradient | |||
id="path5815_2_" | |||
gradientUnits="userSpaceOnUse" | |||
x1="6.7284999" | |||
y1="18.231609" | |||
x2="6.7284999" | |||
y2="27.078119"> | |||
<stop | |||
offset="0.00559" | |||
style="stop-color:#3D3B3B" | |||
id="stop3197" /> | |||
<stop | |||
offset="1" | |||
style="stop-color:#2D2C2C" | |||
id="stop3199" /> | |||
</linearGradient> | |||
<path | |||
id="path5815_1_" | |||
inkscape:connector-curvature="0" | |||
fill="url(#path5815_2_)" | |||
d="m 1.25778,18.23161 h 10.94143 v 8.84652 H 1.25778 Z" | |||
style="fill:url(#path5815_2_)" /> | |||
<path | |||
id="path5817_1_" | |||
inkscape:connector-curvature="0" | |||
fill="#5e5e5e" | |||
d="m 1.25778,21.77853 h 10.94143 v 0.87738 H 1.25778 Z" /> | |||
<path | |||
id="path5819_1_" | |||
inkscape:connector-curvature="0" | |||
fill="#5e5e5e" | |||
d="m 1.25778,25.32545 h 10.94143 v 0.87738 H 1.25778 Z" /> | |||
<path | |||
id="path5821_1_" | |||
inkscape:connector-curvature="0" | |||
fill="#5e5e5e" | |||
d="m 1.25778,23.55285 h 10.94143 v 0.87738 H 1.25778 Z" /> | |||
<path | |||
id="path5823_1_" | |||
inkscape:connector-curvature="0" | |||
fill="#5e5e5e" | |||
d="m 1.25778,20.00513 h 10.94143 v 0.87738 H 1.25778 Z" /> | |||
<path | |||
id="path5825_1_" | |||
inkscape:connector-curvature="0" | |||
fill="#797979" | |||
d="m 1.25778,18.23161 h 10.94143 v 0.87738 H 1.25778 Z" /> | |||
</g> | |||
<rect | |||
style="fill:url(#linearGradient1579);fill-opacity:1;stroke:none;stroke-width:1.33393;stroke-linejoin:round;stroke-miterlimit:1.5" | |||
id="rect1517" | |||
width="13.160316" | |||
height="2.9625583" | |||
x="0" | |||
y="8.8440666" /></svg> |
@@ -57,20 +57,29 @@ struct MotionMTR : Module { | |||
bool startingUp = true; | |||
dsp::Timer startupTimer; | |||
bool break10VNormalForAudioMode = true; | |||
MotionMTR() { | |||
config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN); | |||
configSwitch(MODE1_PARAM, 0.f, 2.f, 1.f, "Channel 1 mode", modeLabels); | |||
auto mode1 = configSwitch(MODE1_PARAM, 0.f, 2.f, 1.f, "Channel 1 mode", modeLabels); | |||
mode1->snapEnabled = true; | |||
configParam(CTRL_1_PARAM, 0.f, 1.f, 0.f, "Channel 1 gain"); | |||
configSwitch(MODE2_PARAM, 0.f, 2.f, 1.f, "Channel 2 mode", modeLabels); | |||
auto mode2 = configSwitch(MODE2_PARAM, 0.f, 2.f, 1.f, "Channel 2 mode", modeLabels); | |||
mode2->snapEnabled = true; | |||
configParam(CTRL_2_PARAM, 0.f, 1.f, 0.f, "Channel 2 gain"); | |||
configSwitch(MODE3_PARAM, 0.f, 2.f, 1.f, "Channel 3 mode", modeLabels); | |||
auto mode3 = configSwitch(MODE3_PARAM, 0.f, 2.f, 1.f, "Channel 3 mode", modeLabels); | |||
mode3->snapEnabled = true; | |||
configParam(CTRL_3_PARAM, 0.f, 1.f, 0.f, "Channel 3 gain"); | |||
auto in1 = configInput(IN1_INPUT, "Channel 1"); | |||
in1->description = "Normalled to 10V (except in audio mode)"; | |||
in1->description = "Normalled to 10V (except optionally in audio mode)"; | |||
auto in2 = configInput(IN2_INPUT, "Channel 2"); | |||
in2->description = "Normalled to 10V (except in audio mode)"; | |||
in2->description = "Normalled to 10V (except optionally in audio mode)"; | |||
auto in3 = configInput(IN3_INPUT, "Channel 3"); | |||
in3->description = "Normalled to 10V (except in audio mode)"; | |||
in3->description = "Normalled to 10V (except optionally in audio mode)"; | |||
configOutput(OUT1_OUTPUT, "Channel 1"); | |||
configOutput(OUT2_OUTPUT, "Channel 2"); | |||
@@ -105,9 +114,9 @@ struct MotionMTR : Module { | |||
const LightDisplayType mode2 = (LightDisplayType) params[MODE2_PARAM].getValue(); | |||
const LightDisplayType mode3 = (LightDisplayType) params[MODE3_PARAM].getValue(); | |||
const float in1 = inputs[IN1_INPUT].getNormalVoltage(10.f * (mode1 != AUDIO)); | |||
const float in2 = inputs[IN2_INPUT].getNormalVoltage(10.f * (mode2 != AUDIO)); | |||
const float in3 = inputs[IN3_INPUT].getNormalVoltage(10.f * (mode3 != AUDIO)); | |||
const float in1 = inputs[IN1_INPUT].getNormalVoltage(10.f * (mode1 != AUDIO || !break10VNormalForAudioMode)); | |||
const float in2 = inputs[IN2_INPUT].getNormalVoltage(10.f * (mode2 != AUDIO || !break10VNormalForAudioMode)); | |||
const float in3 = inputs[IN3_INPUT].getNormalVoltage(10.f * (mode3 != AUDIO || !break10VNormalForAudioMode)); | |||
const float out1 = in1 * params[CTRL_1_PARAM].getValue() * (mode1 == CV_INV ? -1 : +1); | |||
const float out2 = in2 * params[CTRL_2_PARAM].getValue() * (mode2 == CV_INV ? -1 : +1); | |||
@@ -234,7 +243,7 @@ struct MotionMTR : Module { | |||
if (signal >= 0) { | |||
for (int i = 1; i < NUM_LIGHTS_PER_DIAL; ++i) { | |||
float value = 0.5f * (signal > (10 * (i + 1.) / (NUM_LIGHTS_PER_DIAL + 1))); | |||
float value = (signal > (10 * (i + 1.) / (NUM_LIGHTS_PER_DIAL + 1))); | |||
// purple | |||
setLightRGBSmooth(lightId + 3 * i, args, 0.82f * value, 0.0f, 0.82f * value); | |||
} | |||
@@ -242,12 +251,52 @@ struct MotionMTR : Module { | |||
else { | |||
for (int i = 1; i < NUM_LIGHTS_PER_DIAL; ++i) { | |||
float value = (signal < (-10 * (NUM_LIGHTS_PER_DIAL - i + 1.) / (NUM_LIGHTS_PER_DIAL + 1.))); | |||
setLightRGBSmooth(lightId + 3 * i, args, value, 0.65f * value, 0.f); | |||
// orange | |||
setLightRGBSmooth(lightId + 3 * i, args, value, 0.4f * value, 0.f); | |||
} | |||
} | |||
} | |||
} | |||
json_t* dataToJson() override { | |||
json_t* rootJ = json_object(); | |||
json_object_set_new(rootJ, "break10VNormalForAudioMode", json_boolean(break10VNormalForAudioMode)); | |||
return rootJ; | |||
} | |||
void dataFromJson(json_t* rootJ) override { | |||
json_t* break10VNormalAudioJ = json_object_get(rootJ, "break10VNormalForAudioMode"); | |||
if (break10VNormalAudioJ) { | |||
break10VNormalForAudioMode = json_boolean_value(break10VNormalAudioJ); | |||
} | |||
} | |||
}; | |||
struct CKSSThreeDragable : app::SvgSlider { | |||
CKSSThreeDragable() { | |||
math::Vec margin = math::Vec(0, 0); | |||
maxHandlePos = math::Vec(1, 1).plus(margin); | |||
minHandlePos = math::Vec(1, 18).plus(margin); | |||
setBackgroundSvg(Svg::load(asset::plugin(pluginInstance, "res/components/CKSSThree_bg.svg"))); | |||
setHandleSvg(Svg::load(asset::plugin(pluginInstance, "res/components/CKSSThree_fg.svg"))); | |||
background->box.pos = margin; | |||
box.size = background->box.size.plus(margin.mult(2)); | |||
} | |||
// disable double click as this messes with click to advance | |||
void onDoubleClick(const event::DoubleClick& e) override { } | |||
// cycle through the values (with reset) on click only (not drag) | |||
void onAction(const ActionEvent& e) override { | |||
ParamQuantity* paramQuantity = getParamQuantity(); | |||
float range = paramQuantity->maxValue - paramQuantity->minValue; | |||
float newValue = paramQuantity->getValue() + 1.f; | |||
if (newValue > paramQuantity->maxValue) { | |||
newValue -= range + 1.f; | |||
} | |||
paramQuantity->setValue(newValue); | |||
} | |||
}; | |||
@@ -259,11 +308,11 @@ struct MotionMTRWidget : ModuleWidget { | |||
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, 0))); | |||
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||
addParam(createParam<CKSSThree>(mm2px(Vec(1.298, 17.851)), module, MotionMTR::MODE1_PARAM)); | |||
addParam(createParam<CKSSThreeDragable>(mm2px(Vec(1.298, 17.851)), module, MotionMTR::MODE1_PARAM)); | |||
addParam(createParamCentered<Davies1900hBlackKnob>(mm2px(Vec(18.217, 22.18)), module, MotionMTR::CTRL_1_PARAM)); | |||
addParam(createParam<CKSSThree>(mm2px(Vec(23.762, 46.679)), module, MotionMTR::MODE2_PARAM)); | |||
addParam(createParam<CKSSThreeDragable>(mm2px(Vec(23.762, 46.679)), module, MotionMTR::MODE2_PARAM)); | |||
addParam(createParamCentered<Davies1900hBlackKnob>(mm2px(Vec(11.777, 50.761)), module, MotionMTR::CTRL_2_PARAM)); | |||
addParam(createParam<CKSSThree>(mm2px(Vec(1.34, 74.461)), module, MotionMTR::MODE3_PARAM)); | |||
addParam(createParam<CKSSThreeDragable>(mm2px(Vec(1.34, 74.461)), module, MotionMTR::MODE3_PARAM)); | |||
addParam(createParamCentered<Davies1900hBlackKnob>(mm2px(Vec(18.31, 78.89)), module, MotionMTR::CTRL_3_PARAM)); | |||
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(5.008, 100.315)), module, MotionMTR::IN1_INPUT)); | |||
@@ -296,6 +345,21 @@ struct MotionMTRWidget : ModuleWidget { | |||
} | |||
} | |||
} | |||
void appendContextMenu(Menu* menu) override { | |||
MotionMTR* module = dynamic_cast<MotionMTR*>(this->module); | |||
assert(module); | |||
menu->addChild(new MenuSeparator()); | |||
menu->addChild(createSubmenuItem("Hardware compatibility", "", | |||
[ = ](Menu * menu) { | |||
menu->addChild(createBoolPtrMenuItem("Disable 10V normal in audio mode", "", &module->break10VNormalForAudioMode)); | |||
} | |||
)); | |||
} | |||
}; | |||