Sine.cpp (6068B)
1 2 #include "Sine.hpp" 3 4 #define WAVE "wave" 5 #define FM_MODE "fm_mode" 6 #define LINEAR_MODE "linear_mode" 7 8 json_t* Sine::saveToJson(json_t* root) { 9 root = VCOBase::saveToJson(root); 10 json_object_set_new(root, WAVE, json_integer((int)_wave)); 11 json_object_set_new(root, FM_MODE, json_boolean(_fmLinearMode)); 12 json_object_set_new(root, LINEAR_MODE, json_boolean(_linearMode)); 13 return root; 14 } 15 16 void Sine::loadFromJson(json_t* root) { 17 VCOBase::loadFromJson(root); 18 19 json_t* w = json_object_get(root, WAVE); 20 if (w) { 21 _wave = (Wave)json_integer_value(w); 22 if (!(_wave == TRIANGLE_WAVE || _wave == SAW_WAVE || _wave == RAMP_WAVE || _wave == SQUARE_WAVE || _wave == PULSE_25_WAVE || _wave == PULSE_10_WAVE)) { 23 _wave = SINE_WAVE; 24 } 25 } 26 27 json_t* fm = json_object_get(root, FM_MODE); 28 if (fm) { 29 _fmLinearMode = json_is_true(fm); 30 } 31 32 json_t* l = json_object_get(root, LINEAR_MODE); 33 if (l) { 34 _linearMode = json_is_true(l); 35 } 36 } 37 38 bool Sine::active() { 39 return outputs[OUT_OUTPUT].isConnected(); 40 } 41 42 void Sine::modulate() { 43 _slowMode = params[SLOW_PARAM].getValue() > 0.5f; 44 _fmDepth = params[FM_DEPTH_PARAM].getValue(); 45 } 46 47 void Sine::modulateChannel(int c) { 48 VCOBase::modulateChannel(c); 49 Engine& e = *_engines[c]; 50 51 _outputScale = 1.0f; 52 e.sawActive = false; 53 e.squareActive = false; 54 switch (_wave) { 55 case SAW_WAVE: { 56 e.sawActive = true; 57 break; 58 } 59 case RAMP_WAVE: { 60 e.sawActive = true; 61 _outputScale = -1.0f; 62 break; 63 } 64 case SQUARE_WAVE: { 65 e.squareActive = true; 66 e.square.setPulseWidth(e.squarePulseWidthSL.next(0.5f), _dcCorrection); 67 break; 68 } 69 case PULSE_25_WAVE: { 70 e.squareActive = true; 71 e.square.setPulseWidth(e.squarePulseWidthSL.next(0.25f), _dcCorrection); 72 break; 73 } 74 case PULSE_10_WAVE: { 75 e.squareActive = true; 76 e.square.setPulseWidth(e.squarePulseWidthSL.next(0.1f), _dcCorrection); 77 break; 78 } 79 default: { 80 } 81 } 82 e.triangleActive = _wave == TRIANGLE_WAVE; 83 e.sineActive = _wave == SINE_WAVE; 84 } 85 86 void Sine::processChannel(const ProcessArgs& args, int c) { 87 Engine& e = *_engines[c]; 88 89 float phaseOffset = params[PHASE_PARAM].getValue(); 90 if (inputs[PHASE_INPUT].isConnected()) { 91 phaseOffset *= clamp(inputs[PHASE_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f); 92 } 93 e.additionalPhaseOffset = -phaseOffset * 0.5f * Phasor::cyclePhase; 94 95 VCOBase::processChannel(args, c); 96 97 outputs[OUT_OUTPUT].setChannels(_channels); 98 outputs[OUT_OUTPUT].setVoltage(_outputScale * (e.squareOut + e.sawOut + e.triangleOut + e.sineOut), c); 99 } 100 101 struct SineWidget : VCOBaseModuleWidget { 102 static constexpr int hp = 3; 103 104 SineWidget(Sine* module) { 105 setModule(module); 106 box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); 107 setPanel(box.size, "Sine"); 108 createScrews(); 109 110 // generated by svg_widgets.rb 111 auto frequencyParamPosition = Vec(9.5, 27.0); 112 auto slowParamPosition = Vec(31.0, 62.0); 113 auto fmDepthParamPosition = Vec(14.5, 92.5); 114 auto phaseParamPosition = Vec(14.5, 134.5); 115 116 auto pitchInputPosition = Vec(10.5, 161.0); 117 auto fmInputPosition = Vec(10.5, 196.0); 118 auto phaseInputPosition = Vec(10.5, 231.0); 119 auto syncInputPosition = Vec(10.5, 266.0); 120 121 auto outOutputPosition = Vec(10.5, 304.0); 122 // end generated by svg_widgets.rb 123 124 addParam(createParam<Knob26>(frequencyParamPosition, module, Sine::FREQUENCY_PARAM)); 125 addParam(createParam<IndicatorButtonGreen9>(slowParamPosition, module, Sine::SLOW_PARAM)); 126 addParam(createParam<Knob16>(fmDepthParamPosition, module, Sine::FM_DEPTH_PARAM)); 127 addParam(createParam<Knob16>(phaseParamPosition, module, Sine::PHASE_PARAM)); 128 129 addInput(createInput<Port24>(pitchInputPosition, module, Sine::PITCH_INPUT)); 130 addInput(createInput<Port24>(fmInputPosition, module, Sine::FM_INPUT)); 131 addInput(createInput<Port24>(phaseInputPosition, module, Sine::PHASE_INPUT)); 132 addInput(createInput<Port24>(syncInputPosition, module, Sine::SYNC_INPUT)); 133 134 addOutput(createOutput<Port24>(outOutputPosition, module, Sine::OUT_OUTPUT)); 135 } 136 137 void contextMenu(Menu* menu) override { 138 auto m = dynamic_cast<Sine*>(module); 139 assert(m); 140 141 OptionsMenuItem* w = new OptionsMenuItem("Waveform"); 142 w->addItem(OptionMenuItem("Sine", [m]() { return m->_wave == Sine::SINE_WAVE; }, [m]() { m->_wave = Sine::SINE_WAVE; })); 143 w->addItem(OptionMenuItem("Triangle", [m]() { return m->_wave == Sine::TRIANGLE_WAVE; }, [m]() { m->_wave = Sine::TRIANGLE_WAVE; })); 144 w->addItem(OptionMenuItem("Saw", [m]() { return m->_wave == Sine::SAW_WAVE; }, [m]() { m->_wave = Sine::SAW_WAVE; })); 145 w->addItem(OptionMenuItem("Ramp", [m]() { return m->_wave == Sine::RAMP_WAVE; }, [m]() { m->_wave = Sine::RAMP_WAVE; })); 146 w->addItem(OptionMenuItem("Square", [m]() { return m->_wave == Sine::SQUARE_WAVE; }, [m]() { m->_wave = Sine::SQUARE_WAVE; })); 147 w->addItem(OptionMenuItem("25% pulse", [m]() { return m->_wave == Sine::PULSE_25_WAVE; }, [m]() { m->_wave = Sine::PULSE_25_WAVE; })); 148 w->addItem(OptionMenuItem("10% pulse", [m]() { return m->_wave == Sine::PULSE_10_WAVE; }, [m]() { m->_wave = Sine::PULSE_10_WAVE; })); 149 OptionsMenuItem::addToMenu(w, menu); 150 151 OptionsMenuItem* fm = new OptionsMenuItem("FM mode"); 152 fm->addItem(OptionMenuItem("Exponential", [m]() { return !m->_fmLinearMode; }, [m]() { m->_fmLinearMode = false; })); 153 fm->addItem(OptionMenuItem("Linear", [m]() { return m->_fmLinearMode; }, [m]() { m->_fmLinearMode = true; })); 154 OptionsMenuItem::addToMenu(fm, menu); 155 156 menu->addChild(new BoolOptionMenuItem("Linear frequency mode", [m]() { return &m->_linearMode; })); 157 158 OptionsMenuItem* p = new OptionsMenuItem("Polyphony channels from"); 159 p->addItem(OptionMenuItem("V/OCT input", [m]() { return m->_polyInputID == Sine::PITCH_INPUT; }, [m]() { m->_polyInputID = Sine::PITCH_INPUT; })); 160 p->addItem(OptionMenuItem("FM input", [m]() { return m->_polyInputID == Sine::FM_INPUT; }, [m]() { m->_polyInputID = Sine::FM_INPUT; })); 161 OptionsMenuItem::addToMenu(p, menu); 162 163 VCOBaseModuleWidget::contextMenu(menu); 164 } 165 }; 166 167 Model* modelSine = createModel<Sine, SineWidget>("Bogaudio-Sine", "SINE", "Sine oscillator with phase offset", "Oscillator", "Polyphonic");