VCO.cpp (4498B)
1 2 #include "VCO.hpp" 3 4 bool VCO::active() { 5 return ( 6 outputs[SQUARE_OUTPUT].isConnected() || 7 outputs[SAW_OUTPUT].isConnected() || 8 outputs[TRIANGLE_OUTPUT].isConnected() || 9 outputs[SINE_OUTPUT].isConnected() 10 ); 11 } 12 13 void VCO::modulate() { 14 _slowMode = params[SLOW_PARAM].getValue() > 0.5f; 15 _linearMode = params[LINEAR_PARAM].getValue() > 0.5f; 16 _fmLinearMode = params[FM_TYPE_PARAM].getValue() < 0.5f; 17 _fmDepth = params[FM_PARAM].getValue(); 18 } 19 20 void VCO::modulateChannel(int c) { 21 VCOBase::modulateChannel(c); 22 Engine& e = *_engines[c]; 23 24 e.squareActive = outputs[SQUARE_OUTPUT].isConnected(); 25 e.sawActive = outputs[SAW_OUTPUT].isConnected(); 26 e.triangleActive = outputs[TRIANGLE_OUTPUT].isConnected(); 27 e.sineActive = outputs[SINE_OUTPUT].isConnected(); 28 29 if (e.squareActive) { 30 float pw = params[PW_PARAM].getValue(); 31 if (inputs[PW_INPUT].isConnected()) { 32 pw *= clamp(inputs[PW_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f); 33 } 34 pw *= 1.0f - 2.0f * e.square.minPulseWidth; 35 pw *= 0.5f; 36 pw += 0.5f; 37 e.square.setPulseWidth(e.squarePulseWidthSL.next(pw), _dcCorrection); 38 } 39 } 40 41 void VCO::processChannel(const ProcessArgs& args, int c) { 42 VCOBase::processChannel(args, c); 43 Engine& e = *_engines[c]; 44 45 outputs[SQUARE_OUTPUT].setChannels(_channels); 46 outputs[SQUARE_OUTPUT].setVoltage(e.squareOut, c); 47 outputs[SAW_OUTPUT].setChannels(_channels); 48 outputs[SAW_OUTPUT].setVoltage(e.sawOut, c); 49 outputs[TRIANGLE_OUTPUT].setChannels(_channels); 50 outputs[TRIANGLE_OUTPUT].setVoltage(e.triangleOut, c); 51 outputs[SINE_OUTPUT].setChannels(_channels); 52 outputs[SINE_OUTPUT].setVoltage(e.sineOut, c); 53 } 54 55 struct VCOWidget : VCOBaseModuleWidget { 56 static constexpr int hp = 10; 57 58 VCOWidget(VCO* module) { 59 setModule(module); 60 box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); 61 setPanel(box.size, "VCO"); 62 createScrews(); 63 64 // generated by svg_widgets.rb 65 auto frequencyParamPosition = Vec(41.0, 45.0); 66 auto fineParamPosition = Vec(48.0, 153.0); 67 auto slowParamPosition = Vec(114.0, 149.7); 68 auto linearParamPosition = Vec(114.0, 162.7); 69 auto pwParamPosition = Vec(62.0, 188.0); 70 auto fmParamPosition = Vec(62.0, 230.0); 71 auto fmTypeParamPosition = Vec(100.5, 231.5); 72 73 auto pwInputPosition = Vec(15.0, 274.0); 74 auto fmInputPosition = Vec(47.0, 274.0); 75 auto pitchInputPosition = Vec(15.0, 318.0); 76 auto syncInputPosition = Vec(47.0, 318.0); 77 78 auto squareOutputPosition = Vec(79.0, 274.0); 79 auto sawOutputPosition = Vec(111.0, 274.0); 80 auto triangleOutputPosition = Vec(79.0, 318.0); 81 auto sineOutputPosition = Vec(111.0, 318.0); 82 // end generated by svg_widgets.rb 83 84 addParam(createParam<Knob68>(frequencyParamPosition, module, VCO::FREQUENCY_PARAM)); 85 addParam(createParam<Knob16>(fineParamPosition, module, VCO::FINE_PARAM)); 86 addParam(createParam<IndicatorButtonGreen9>(slowParamPosition, module, VCO::SLOW_PARAM)); 87 addParam(createParam<Knob26>(pwParamPosition, module, VCO::PW_PARAM)); 88 addParam(createParam<Knob26>(fmParamPosition, module, VCO::FM_PARAM)); 89 addParam(createParam<SliderSwitch2State14>(fmTypeParamPosition, module, VCO::FM_TYPE_PARAM)); 90 addParam(createParam<IndicatorButtonGreen9>(linearParamPosition, module, VCO::LINEAR_PARAM)); 91 92 addInput(createInput<Port24>(pitchInputPosition, module, VCO::PITCH_INPUT)); 93 addInput(createInput<Port24>(syncInputPosition, module, VCO::SYNC_INPUT)); 94 addInput(createInput<Port24>(pwInputPosition, module, VCO::PW_INPUT)); 95 addInput(createInput<Port24>(fmInputPosition, module, VCO::FM_INPUT)); 96 97 addOutput(createOutput<Port24>(squareOutputPosition, module, VCO::SQUARE_OUTPUT)); 98 addOutput(createOutput<Port24>(sawOutputPosition, module, VCO::SAW_OUTPUT)); 99 addOutput(createOutput<Port24>(triangleOutputPosition, module, VCO::TRIANGLE_OUTPUT)); 100 addOutput(createOutput<Port24>(sineOutputPosition, module, VCO::SINE_OUTPUT)); 101 } 102 103 void contextMenu(Menu* menu) override { 104 auto m = dynamic_cast<VCO*>(module); 105 assert(m); 106 OptionsMenuItem* p = new OptionsMenuItem("Polyphony channels from"); 107 p->addItem(OptionMenuItem("V/OCT input", [m]() { return m->_polyInputID == VCO::PITCH_INPUT; }, [m]() { m->_polyInputID = VCO::PITCH_INPUT; })); 108 p->addItem(OptionMenuItem("FM input", [m]() { return m->_polyInputID == VCO::FM_INPUT; }, [m]() { m->_polyInputID = VCO::FM_INPUT; })); 109 OptionsMenuItem::addToMenu(p, menu); 110 111 VCOBaseModuleWidget::contextMenu(menu); 112 } 113 }; 114 115 Model* modelVCO = bogaudio::createModel<VCO, VCOWidget>("Bogaudio-VCO", "VCO", "Oscillator", "Oscillator", "Polyphonic");