MegaGate.cpp (17842B)
1 2 #include "MegaGate.hpp" 3 #include "dsp/pitch.hpp" 4 5 #define VELOCITY_MINIMUM_DECIBELS "velocity_minimum_decibels" 6 7 void MegaGate::Engine::reset() { 8 trigger.reset(); 9 gatePulseGen.process(10.0); 10 } 11 12 void MegaGate::Engine::setSampleRate(float sr) { 13 velocitySL.setParams(sr, 5.0f, 1.0f); 14 tiltSL.setParams(sr, 10.0f, 2.0f); 15 leftVcaSL.setParams(sr, 5.0f, 1.0f); 16 rightVcaSL.setParams(sr, 5.0f, 1.0f); 17 leftFinalHP.setParams(sr, MultimodeFilter::BUTTERWORTH_TYPE, 2, MultimodeFilter::HIGHPASS_MODE, 80.0f, MultimodeFilter::minQbw, MultimodeFilter::LINEAR_BANDWIDTH_MODE, MultimodeFilter::MINIMUM_DELAY_MODE); 18 rightFinalHP.setParams(sr, MultimodeFilter::BUTTERWORTH_TYPE, 2, MultimodeFilter::HIGHPASS_MODE, 80.0f, MultimodeFilter::minQbw, MultimodeFilter::LINEAR_BANDWIDTH_MODE, MultimodeFilter::MINIMUM_DELAY_MODE); 19 } 20 21 void MegaGate::reset() { 22 for (int c = 0; c < _channels; ++c) { 23 _engines[c]->reset(); 24 } 25 } 26 27 void MegaGate::sampleRateChange() { 28 _sampleRate = APP->engine->getSampleRate(); 29 _sampleTime = APP->engine->getSampleTime(); 30 for (int i = 0; i < _channels; ++i) { 31 _engines[i]->setSampleRate(_sampleRate); 32 } 33 } 34 35 json_t* MegaGate::saveToJson(json_t* root) { 36 root = LPGEnvBaseModule::saveToJson(root); 37 json_object_set_new(root, VELOCITY_MINIMUM_DECIBELS, json_real(_minVelocityDb)); 38 return root; 39 } 40 41 void MegaGate::loadFromJson(json_t* root) { 42 LPGEnvBaseModule::loadFromJson(root); 43 json_t* mdb = json_object_get(root, VELOCITY_MINIMUM_DECIBELS); 44 if (mdb) { 45 _minVelocityDb = json_real_value(mdb); 46 } 47 } 48 49 bool MegaGate::active() { 50 return outputs[LEFT_OUTPUT].isConnected() || outputs[RIGHT_OUTPUT].isConnected() || outputs[ENV_OUTPUT].isConnected(); 51 } 52 53 int MegaGate::channels() { 54 return inputs[GATE_INPUT].getChannels(); 55 } 56 57 void MegaGate::addChannel(int c) { 58 _engines[c] = new Engine(); 59 _engines[c]->reset(); 60 _engines[c]->setSampleRate(_sampleRate); 61 } 62 63 void MegaGate::removeChannel(int c) { 64 delete _engines[c]; 65 _engines[c] = NULL; 66 } 67 68 void MegaGate::modulateChannel(int c) { 69 _engines[c]->slew.modulate( 70 _sampleRate, 71 params[RISE_PARAM], 72 &inputs[RISE_INPUT], 73 300.0f * _timeScale, 74 params[RISE_SHAPE_PARAM], 75 params[FALL_PARAM], 76 &inputs[FALL_INPUT], 77 1000.0f * _timeScale, 78 params[FALL_SHAPE_PARAM], 79 c, 80 false, 81 &inputs[SHAPE_INPUT], 82 _riseShapeMode, 83 _fallShapeMode 84 ); 85 } 86 87 void MegaGate::processChannel(const ProcessArgs& args, int c) { 88 Engine& e = *_engines[c]; 89 90 float in = inputs[GATE_INPUT].getPolyVoltage(c); 91 if (e.trigger.process(in)) { 92 float time = clamp(params[MINIMUM_GATE_PARAM].getValue(), 0.0f, 1.0f); 93 if (inputs[MINIMUM_GATE_INPUT].isConnected()) { 94 time *= clamp(inputs[MINIMUM_GATE_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f); 95 } 96 time *= time; 97 time *= _timeScale; 98 e.gateSeconds = time; 99 100 e.gateElapsedSeconds = 0.0f; 101 if (_gateToTrigger) { 102 e.gateSeconds = std::max(0.01f, time); 103 } 104 else { 105 e.gateSeconds = time; 106 } 107 } 108 else { 109 e.gateElapsedSeconds += _sampleTime; 110 } 111 112 float gate = 0.0f; 113 if (e.gateElapsedSeconds < e.gateSeconds) { 114 gate = 10.0f; 115 } 116 else if (!_gateToTrigger) { 117 gate = in; 118 } 119 120 float velocity = 1.0f; 121 if (inputs[VELOCITY_INPUT].isConnected()) { 122 velocity = clamp(inputs[VELOCITY_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f); 123 } 124 velocity = e.velocitySL.next(velocity); 125 e.velocityAmp.setLevel(_minVelocityDb + velocity * (_maxVelocityDb - _minVelocityDb)); 126 float env = e.velocityAmp.next(e.slew.next(gate)); 127 env /= 10.0f; 128 129 float tilt = clamp(params[TILT_PARAM].getValue(), -1.0f, 1.0f); 130 if (inputs[TILT_INPUT].isConnected()) { 131 tilt *= clamp(inputs[TILT_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f); 132 } 133 tilt = e.tiltSL.next(tilt); 134 135 float leftEnv = env; 136 float rightEnv = env; 137 if (tilt < 0.0f) { 138 rightEnv *= 1.0f + tilt; 139 } 140 else { 141 leftEnv *= 1.0f - tilt; 142 } 143 144 float lpfEnv = clamp(params[LPF_ENV_PARAM].getValue(), -1.0f, 1.0f); 145 if (inputs[LPF_ENV_INPUT].isConnected()) { 146 float cv = clamp(params[LPF_ENV_ATTENUATOR_PARAM].getValue(), -1.0f, 1.0f); 147 cv *= clamp(inputs[LPF_ENV_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f); 148 lpfEnv = clamp(lpfEnv + cv, -1.0f, 1.0f); 149 } 150 float lpfBias = clamp(params[LPF_BIAS_PARAM].getValue(), -1.0f, 1.0f); 151 if (inputs[LPF_BIAS_INPUT].isConnected()) { 152 float cv = clamp(params[LPF_BIAS_ATTENUATOR_PARAM].getValue(), -1.0f, 1.0f); 153 cv *= clamp(inputs[LPF_BIAS_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f); 154 lpfBias = clamp(lpfBias + cv, -1.0f, 1.0f); 155 } 156 lpfBias *= lpfBias; 157 int lpfPoles = 1 + roundf(clamp(params[LPF_POLES_PARAM].getValue(), 0.0f, 3.0f)); 158 159 float hpfEnv = clamp(params[HPF_ENV_PARAM].getValue(), -1.0f, 1.0f); 160 if (inputs[HPF_ENV_INPUT].isConnected()) { 161 float cv = clamp(params[HPF_ENV_ATTENUATOR_PARAM].getValue(), -1.0f, 1.0f); 162 cv *= clamp(inputs[HPF_ENV_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f); 163 hpfEnv = clamp(hpfEnv + cv, -1.0f, 1.0f); 164 } 165 float hpfBias = clamp(params[HPF_BIAS_PARAM].getValue(), -1.0f, 1.0f); 166 if (inputs[HPF_BIAS_INPUT].isConnected()) { 167 float cv = clamp(params[HPF_BIAS_ATTENUATOR_PARAM].getValue(), -1.0f, 1.0f); 168 cv *= clamp(inputs[HPF_BIAS_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f); 169 hpfBias = clamp(hpfBias + cv, -1.0f, 1.0f); 170 } 171 hpfBias *= hpfBias; 172 int hpfPoles = 1 + roundf(clamp(params[HPF_POLES_PARAM].getValue(), 0.0f, 3.0f)); 173 174 bool serial = params[FILTERS_SERIAL_PARAM].getValue() > 0.5f; 175 bool linear = params[LINEAR_VCA_PARAM].getValue() > 0.5f; 176 177 float vcaEnv = clamp(params[VCA_ENV_PARAM].getValue(), -1.0f, 1.0f); 178 if (inputs[VCA_ENV_INPUT].isConnected()) { 179 float cv = clamp(params[VCA_ENV_ATTENUATOR_PARAM].getValue(), -1.0f, 1.0f); 180 cv *= clamp(inputs[VCA_ENV_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f); 181 vcaEnv = clamp(vcaEnv + cv, -1.0f, 1.0f); 182 } 183 float vcaBias = clamp(params[VCA_BIAS_PARAM].getValue(), 0.0f, 1.0f); 184 if (inputs[VCA_ENV_INPUT].isConnected()) { 185 float cv = clamp(params[VCA_BIAS_ATTENUATOR_PARAM].getValue(), -1.0f, 1.0f); 186 cv *= clamp(inputs[VCA_BIAS_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f); 187 vcaBias = clamp(vcaBias + cv, 0.0f, 1.0f); 188 } 189 190 { 191 float f = clamp(lpfBias + leftEnv * lpfEnv, 0.0f, 1.0f); 192 f *= maxFilterCutoff; 193 f = std::max(f, MultimodeFilter4::minFrequency); 194 e.leftLpf.setParams( 195 _sampleRate, 196 MultimodeFilter::BUTTERWORTH_TYPE, 197 lpfPoles, 198 MultimodeFilter::LOWPASS_MODE, 199 f, 200 0.0f 201 ); 202 } 203 { 204 float f = clamp(hpfBias - leftEnv * hpfEnv, 0.0f, 1.0f); 205 f *= maxFilterCutoff; 206 f = std::max(f, MultimodeFilter4::minFrequency); 207 e.leftHpf.setParams( 208 _sampleRate, 209 MultimodeFilter::BUTTERWORTH_TYPE, 210 hpfPoles, 211 MultimodeFilter::HIGHPASS_MODE, 212 f, 213 0.0f 214 ); 215 } 216 float level = clamp(vcaBias + leftEnv * vcaEnv, 0.0f, 1.0f); 217 level = e.leftVcaSL.next(level); 218 219 float leftIn = inputs[LEFT_INPUT].getPolyVoltage(c); 220 float leftOut = 0.0f; 221 if (serial) { 222 leftOut = e.leftHpf.next(e.leftLpf.next(leftIn)); 223 } 224 else { 225 leftOut = e.leftLpf.next(leftIn) + e.leftHpf.next(leftIn); 226 } 227 leftOut = e.leftFinalHP.next(leftOut); 228 if (linear) { 229 leftOut *= level; 230 } 231 else { 232 e.leftVca.setLevel(Amplifier::minDecibels * (1.0f - level)); 233 leftOut = e.leftVca.next(leftOut); 234 } 235 236 float rightOut = 0.0f; 237 if (outputs[RIGHT_OUTPUT].isConnected()) { 238 float rightIn = leftIn; 239 if (inputs[RIGHT_INPUT].isConnected()) { 240 rightIn = inputs[RIGHT_INPUT].getPolyVoltage(c); 241 } 242 243 { 244 float f = clamp(lpfBias + rightEnv * lpfEnv, 0.0f, 1.0f); 245 f *= maxFilterCutoff; 246 f = std::max(f, MultimodeFilter4::minFrequency); 247 e.rightLpf.setParams( 248 _sampleRate, 249 MultimodeFilter::BUTTERWORTH_TYPE, 250 lpfPoles, 251 MultimodeFilter::LOWPASS_MODE, 252 f, 253 0.0f 254 ); 255 } 256 { 257 float f = clamp(hpfBias - rightEnv * hpfEnv, 0.0f, 1.0f); 258 f *= maxFilterCutoff; 259 f = std::max(f, MultimodeFilter4::minFrequency); 260 e.rightHpf.setParams( 261 _sampleRate, 262 MultimodeFilter::BUTTERWORTH_TYPE, 263 hpfPoles, 264 MultimodeFilter::HIGHPASS_MODE, 265 f, 266 0.0f 267 ); 268 } 269 float level = clamp(vcaBias + rightEnv * vcaEnv, 0.0f, 1.0f); 270 level = e.rightVcaSL.next(level); 271 272 if (serial) { 273 rightOut = e.rightHpf.next(e.rightLpf.next(rightIn)); 274 } 275 else { 276 rightOut = e.rightLpf.next(rightIn) + e.rightHpf.next(rightIn); 277 } 278 rightOut = e.rightFinalHP.next(rightOut); 279 if (linear) { 280 rightOut *= level; 281 } 282 else { 283 e.rightVca.setLevel(Amplifier::minDecibels * (1.0f - level)); 284 rightOut = e.rightVca.next(rightOut); 285 } 286 } 287 288 outputs[ENV_OUTPUT].setChannels(_channels); 289 outputs[ENV_OUTPUT].setVoltage(env * 10.0f, c); 290 outputs[LEFT_OUTPUT].setChannels(_channels); 291 outputs[LEFT_OUTPUT].setVoltage(leftOut, c); 292 outputs[RIGHT_OUTPUT].setChannels(_channels); 293 outputs[RIGHT_OUTPUT].setVoltage(rightOut, c); 294 } 295 296 void MegaGate::processAlways(const ProcessArgs& args) { 297 { 298 int poles = params[LPF_POLES_PARAM].getValue(); 299 lights[LPF_POLES_1_LIGHT].value = poles == 0; 300 lights[LPF_POLES_2_LIGHT].value = poles == 1; 301 lights[LPF_POLES_3_LIGHT].value = poles == 2; 302 lights[LPF_POLES_4_LIGHT].value = poles == 3; 303 } 304 { 305 int poles = params[HPF_POLES_PARAM].getValue(); 306 lights[HPF_POLES_1_LIGHT].value = poles == 0; 307 lights[HPF_POLES_2_LIGHT].value = poles == 1; 308 lights[HPF_POLES_3_LIGHT].value = poles == 2; 309 lights[HPF_POLES_4_LIGHT].value = poles == 3; 310 } 311 } 312 313 struct MegaGateWidget : LPGEnvBaseWidget { 314 static constexpr int hp = 18; 315 316 MegaGateWidget(MegaGate* module) { 317 setModule(module); 318 box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); 319 setPanel(box.size, "MegaGate"); 320 createScrews(); 321 322 // generated by svg_widgets.rb 323 auto riseParamPosition = Vec(17.5, 41.5); 324 auto riseShapeParamPosition = Vec(24.0, 89.0); 325 auto fallParamPosition = Vec(72.5, 41.5); 326 auto fallShapeParamPosition = Vec(79.0, 89.0); 327 auto minimumGateParamPosition = Vec(17.5, 176.0); 328 auto tiltParamPosition = Vec(72.5, 176.0); 329 auto gateToTriggerParamPosition = Vec(20.0, 255.0); 330 auto times10xParamPosition = Vec(20.0, 269.0); 331 auto filtersSerialParamPosition = Vec(90.0, 255.0); 332 auto linearVcaParamPosition = Vec(90.0, 269.0); 333 auto lpfEnvParamPosition = Vec(136.5, 42.0); 334 auto lpfEnvAttenuatorParamPosition = Vec(143.0, 81.0); 335 auto lpfBiasParamPosition = Vec(186.5, 42.0); 336 auto lpfBiasAttenuatorParamPosition = Vec(193.0, 81.0); 337 auto lpfPolesParamPosition = Vec(241.0, 87.0); 338 auto hpfEnvParamPosition = Vec(136.5, 157.0); 339 auto hpfEnvAttenuatorParamPosition = Vec(143.0, 196.0); 340 auto hpfBiasParamPosition = Vec(186.5, 157.0); 341 auto hpfBiasAttenuatorParamPosition = Vec(193.0, 196.0); 342 auto hpfPolesParamPosition = Vec(239.0, 202.0); 343 auto vcaEnvParamPosition = Vec(163.5, 271.0); 344 auto vcaEnvAttenuatorParamPosition = Vec(170.0, 310.0); 345 auto vcaBiasParamPosition = Vec(213.5, 271.0); 346 auto vcaBiasAttenuatorParamPosition = Vec(220.0, 310.0); 347 348 auto riseInputPosition = Vec(20.5, 118.0); 349 auto fallInputPosition = Vec(75.5, 118.0); 350 auto minimumGateInputPosition = Vec(20.5, 220.0); 351 auto tiltInputPosition = Vec(75.5, 220.0); 352 auto velocityInputPosition = Vec(8.5, 287.0); 353 auto shapeInputPosition = Vec(38.5, 287.0); 354 auto leftInputPosition = Vec(68.5, 287.0); 355 auto rightInputPosition = Vec(98.5, 287.0); 356 auto gateInputPosition = Vec(8.5, 324.0); 357 auto lpfEnvInputPosition = Vec(139.0, 106.0); 358 auto lpfBiasInputPosition = Vec(189.0, 106.0); 359 auto hpfEnvInputPosition = Vec(139.0, 221.0); 360 auto hpfBiasInputPosition = Vec(189.0, 221.0); 361 auto vcaEnvInputPosition = Vec(166.0, 335.0); 362 auto vcaBiasInputPosition = Vec(216.0, 335.0); 363 364 auto envOutputPosition = Vec(38.5, 324.0); 365 auto leftOutputPosition = Vec(68.5, 324.0); 366 auto rightOutputPosition = Vec(98.5, 324.0); 367 368 auto lpfPoles1LightPosition = Vec(239.0, 40.0); 369 auto lpfPoles2LightPosition = Vec(239.0, 52.0); 370 auto lpfPoles3LightPosition = Vec(239.0, 64.0); 371 auto lpfPoles4LightPosition = Vec(239.0, 76.0); 372 auto hpfPoles1LightPosition = Vec(237.0, 155.0); 373 auto hpfPoles2LightPosition = Vec(237.0, 167.0); 374 auto hpfPoles3LightPosition = Vec(237.0, 179.0); 375 auto hpfPoles4LightPosition = Vec(237.0, 191.0); 376 // end generated by svg_widgets.rb 377 378 addParam(createParam<Knob29>(riseParamPosition, module, MegaGate::RISE_PARAM)); 379 addParam(createParam<Knob16>(riseShapeParamPosition, module, MegaGate::RISE_SHAPE_PARAM)); 380 addParam(createParam<Knob29>(fallParamPosition, module, MegaGate::FALL_PARAM)); 381 addParam(createParam<Knob16>(fallShapeParamPosition, module, MegaGate::FALL_SHAPE_PARAM)); 382 addParam(createParam<Knob29>(minimumGateParamPosition, module, MegaGate::MINIMUM_GATE_PARAM)); 383 addParam(createParam<Knob29>(tiltParamPosition, module, MegaGate::TILT_PARAM)); 384 addParam(createParam<IndicatorButtonGreen9>(gateToTriggerParamPosition, module, MegaGate::GATE_TO_TRIGGER_PARAM)); 385 addParam(createParam<IndicatorButtonGreen9>(times10xParamPosition, module, MegaGate::TIMES_10X_PARAM)); 386 addParam(createParam<IndicatorButtonGreen9>(filtersSerialParamPosition, module, MegaGate::FILTERS_SERIAL_PARAM)); 387 addParam(createParam<IndicatorButtonGreen9>(linearVcaParamPosition, module, MegaGate::LINEAR_VCA_PARAM)); 388 addParam(createParam<Knob29>(lpfEnvParamPosition, module, MegaGate::LPF_ENV_PARAM)); 389 addParam(createParam<Knob16>(lpfEnvAttenuatorParamPosition, module, MegaGate::LPF_ENV_ATTENUATOR_PARAM)); 390 addParam(createParam<Knob29>(lpfBiasParamPosition, module, MegaGate::LPF_BIAS_PARAM)); 391 addParam(createParam<Knob16>(lpfBiasAttenuatorParamPosition, module, MegaGate::LPF_BIAS_ATTENUATOR_PARAM)); 392 addParam(createParam<StatefulButton9>(lpfPolesParamPosition, module, MegaGate::LPF_POLES_PARAM)); 393 addParam(createParam<Knob29>(hpfEnvParamPosition, module, MegaGate::HPF_ENV_PARAM)); 394 addParam(createParam<Knob16>(hpfEnvAttenuatorParamPosition, module, MegaGate::HPF_ENV_ATTENUATOR_PARAM)); 395 addParam(createParam<Knob29>(hpfBiasParamPosition, module, MegaGate::HPF_BIAS_PARAM)); 396 addParam(createParam<Knob16>(hpfBiasAttenuatorParamPosition, module, MegaGate::HPF_BIAS_ATTENUATOR_PARAM)); 397 addParam(createParam<StatefulButton9>(hpfPolesParamPosition, module, MegaGate::HPF_POLES_PARAM)); 398 addParam(createParam<Knob29>(vcaEnvParamPosition, module, MegaGate::VCA_ENV_PARAM)); 399 addParam(createParam<Knob16>(vcaEnvAttenuatorParamPosition, module, MegaGate::VCA_ENV_ATTENUATOR_PARAM)); 400 addParam(createParam<Knob29>(vcaBiasParamPosition, module, MegaGate::VCA_BIAS_PARAM)); 401 addParam(createParam<Knob16>(vcaBiasAttenuatorParamPosition, module, MegaGate::VCA_BIAS_ATTENUATOR_PARAM)); 402 403 addInput(createInput<Port24>(riseInputPosition, module, MegaGate::RISE_INPUT)); 404 addInput(createInput<Port24>(fallInputPosition, module, MegaGate::FALL_INPUT)); 405 addInput(createInput<Port24>(minimumGateInputPosition, module, MegaGate::MINIMUM_GATE_INPUT)); 406 addInput(createInput<Port24>(tiltInputPosition, module, MegaGate::TILT_INPUT)); 407 addInput(createInput<Port24>(velocityInputPosition, module, MegaGate::VELOCITY_INPUT)); 408 addInput(createInput<Port24>(shapeInputPosition, module, MegaGate::SHAPE_INPUT)); 409 addInput(createInput<Port24>(leftInputPosition, module, MegaGate::LEFT_INPUT)); 410 addInput(createInput<Port24>(rightInputPosition, module, MegaGate::RIGHT_INPUT)); 411 addInput(createInput<Port24>(gateInputPosition, module, MegaGate::GATE_INPUT)); 412 addInput(createInput<Port24>(lpfEnvInputPosition, module, MegaGate::LPF_ENV_INPUT)); 413 addInput(createInput<Port24>(lpfBiasInputPosition, module, MegaGate::LPF_BIAS_INPUT)); 414 addInput(createInput<Port24>(hpfEnvInputPosition, module, MegaGate::HPF_ENV_INPUT)); 415 addInput(createInput<Port24>(hpfBiasInputPosition, module, MegaGate::HPF_BIAS_INPUT)); 416 addInput(createInput<Port24>(vcaEnvInputPosition, module, MegaGate::VCA_ENV_INPUT)); 417 addInput(createInput<Port24>(vcaBiasInputPosition, module, MegaGate::VCA_BIAS_INPUT)); 418 419 addOutput(createOutput<Port24>(envOutputPosition, module, MegaGate::ENV_OUTPUT)); 420 addOutput(createOutput<Port24>(leftOutputPosition, module, MegaGate::LEFT_OUTPUT)); 421 addOutput(createOutput<Port24>(rightOutputPosition, module, MegaGate::RIGHT_OUTPUT)); 422 423 addChild(createLight<BGSmallLight<GreenLight>>(lpfPoles1LightPosition, module, MegaGate::LPF_POLES_1_LIGHT)); 424 addChild(createLight<BGSmallLight<GreenLight>>(lpfPoles2LightPosition, module, MegaGate::LPF_POLES_2_LIGHT)); 425 addChild(createLight<BGSmallLight<GreenLight>>(lpfPoles3LightPosition, module, MegaGate::LPF_POLES_3_LIGHT)); 426 addChild(createLight<BGSmallLight<GreenLight>>(lpfPoles4LightPosition, module, MegaGate::LPF_POLES_4_LIGHT)); 427 addChild(createLight<BGSmallLight<GreenLight>>(hpfPoles1LightPosition, module, MegaGate::HPF_POLES_1_LIGHT)); 428 addChild(createLight<BGSmallLight<GreenLight>>(hpfPoles2LightPosition, module, MegaGate::HPF_POLES_2_LIGHT)); 429 addChild(createLight<BGSmallLight<GreenLight>>(hpfPoles3LightPosition, module, MegaGate::HPF_POLES_3_LIGHT)); 430 addChild(createLight<BGSmallLight<GreenLight>>(hpfPoles4LightPosition, module, MegaGate::HPF_POLES_4_LIGHT)); 431 } 432 433 void contextMenu(Menu* menu) override { 434 LPGEnvBaseWidget::contextMenu(menu); 435 auto m = dynamic_cast<MegaGate*>(module); 436 assert(m); 437 OptionsMenuItem* mi = new OptionsMenuItem("Minimum velocity output gain"); 438 mi->addItem(OptionMenuItem("-3db", [m]() { return m->_minVelocityDb == -3.0f; }, [m]() { m->_minVelocityDb = -3.0f; })); 439 mi->addItem(OptionMenuItem("-6db", [m]() { return m->_minVelocityDb == -6.0f; }, [m]() { m->_minVelocityDb = -6.0f; })); 440 mi->addItem(OptionMenuItem("-12db", [m]() { return m->_minVelocityDb == -12.0f; }, [m]() { m->_minVelocityDb = -12.0f; })); 441 mi->addItem(OptionMenuItem("-24db", [m]() { return m->_minVelocityDb == -24.0f; }, [m]() { m->_minVelocityDb = -24.0f; })); 442 mi->addItem(OptionMenuItem("-60db", [m]() { return m->_minVelocityDb == -60.0f; }, [m]() { m->_minVelocityDb = -60.0f; })); 443 OptionsMenuItem::addToMenu(mi, menu); 444 } 445 }; 446 447 Model* modelMegaGate = createModel<MegaGate, MegaGateWidget>("Bogaudio-MegaGate", "MEGAGATE", "Low- and high-pass gate", "Low-pass gate", "Dual", "Polyphonic");