Chirp.cpp (5021B)
1 2 #include "Chirp.hpp" 3 #include "vco_base.hpp" 4 #include "dsp/pitch.hpp" 5 6 void Chirp::Engine::reset() { 7 trigger.reset(); 8 eocPulseGen.process(10.0f); 9 } 10 11 void Chirp::Engine::sampleRateChange(float sr) { 12 chirp.setSampleRate(sr); 13 ampSL.setParams(sr, Chirp::cycleSlewSeconds * 1000.0f, -Amplifier::minDecibels); 14 } 15 16 void Chirp::reset() { 17 for (int c = 0; c < _channels; ++c) { 18 _engines[c]->reset(); 19 } 20 } 21 22 void Chirp::sampleRateChange() { 23 float sr = APP->engine->getSampleRate(); 24 _sampleTime = 1.0f / sr; 25 for (int c = 0; c < _channels; ++c) { 26 _engines[c]->sampleRateChange(sr); 27 } 28 } 29 30 bool Chirp::active() { 31 return outputs[OUT_OUTPUT].isConnected() || outputs[EOC_OUTPUT].isConnected(); 32 } 33 34 int Chirp::channels() { 35 return inputs[FREQUENCY1_INPUT].getChannels(); 36 } 37 38 void Chirp::addChannel(int c) { 39 _engines[c] = new Engine(); 40 _engines[c]->reset(); 41 _engines[c]->sampleRateChange(APP->engine->getSampleRate()); 42 } 43 44 void Chirp::removeChannel(int c) { 45 delete _engines[c]; 46 _engines[c] = NULL; 47 } 48 49 void Chirp::modulate() { 50 _exponential = params[EXPONENTIAL_PARAM].getValue() > 0.5f; 51 _loop = params[LOOP_PARAM].getValue() > 0.5f; 52 } 53 54 void Chirp::modulateChannel(int c) { 55 Engine& e = *_engines[c]; 56 57 float time = clamp(params[TIME_PARAM].getValue(), 0.0f, 1.0f); 58 if (inputs[TIME_INPUT].isConnected()) { 59 time *= clamp(inputs[TIME_INPUT].getPolyVoltage(c) / 10.0f, 0.0f, 1.0f); 60 } 61 time *= time; 62 time *= maxTimeSeconds - minTimeSeconds; 63 time += minTimeSeconds; 64 65 float maxF = roundf(maxFrequencyNyquistRatio * APP->engine->getSampleRate()); 66 float f1 = params[FREQUENCY1_PARAM].getValue(); 67 if (inputs[FREQUENCY1_INPUT].isConnected()) { 68 f1 += clamp(inputs[FREQUENCY1_INPUT].getPolyVoltage(c), -5.0f, 5.0f); 69 } 70 f1 = cvToFrequency(f1); 71 f1 = clamp(f1, minFrequency, maxF); 72 73 float f2 = params[FREQUENCY2_PARAM].getValue(); 74 if (inputs[FREQUENCY2_INPUT].isConnected()) { 75 f2 += clamp(inputs[FREQUENCY2_INPUT].getPolyVoltage(c), -5.0f, 5.0f); 76 } 77 f2 = cvToFrequency(f2); 78 f2 = clamp(f2, minFrequency, maxF); 79 80 e.chirp.setParams(f1, f2, time, !_exponential); 81 } 82 83 void Chirp::processChannel(const ProcessArgs& args, int c) { 84 Engine& e = *_engines[c]; 85 86 bool triggered = e.trigger.process(params[TRIGGER_PARAM].getValue()*5.0f + inputs[TRIGGER_INPUT].getPolyVoltage(c)); 87 if (!_run) { 88 if (triggered || _loop) { 89 _run = true; 90 e.chirp.reset(); 91 } 92 } 93 94 float out = 0.0f; 95 if (_run) { 96 out = e.chirp.next() * 5.0f; 97 if (e.chirp.isCycleComplete()) { 98 _run = false; 99 e.eocPulseGen.trigger(0.001f); 100 e.targetAmplitude = 0.0f; 101 } 102 else if (e.chirp.isCycleNearlyComplete(cycleSlewSeconds)) { 103 e.targetAmplitude = Amplifier::minDecibels; 104 } 105 106 e.amp.setLevel(e.ampSL.next(e.targetAmplitude)); 107 out = e.amp.next(out); 108 } 109 110 outputs[OUT_OUTPUT].setChannels(_channels); 111 outputs[OUT_OUTPUT].setVoltage(out, c); 112 outputs[EOC_OUTPUT].setChannels(_channels); 113 outputs[EOC_OUTPUT].setVoltage(e.eocPulseGen.process(_sampleTime) * 5.0f, c); 114 } 115 116 struct ChirpWidget : BGModuleWidget { 117 static constexpr int hp = 5; 118 119 ChirpWidget(Chirp* module) { 120 setModule(module); 121 box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); 122 setPanel(box.size, "Chirp"); 123 createScrews(); 124 125 // generated by svg_widgets.rb 126 auto timeParamPosition = Vec(18.5, 46.0); 127 auto frequency1ParamPosition = Vec(24.5, 122.0); 128 auto frequency2ParamPosition = Vec(24.5, 179.0); 129 auto triggerParamPosition = Vec(10.0, 216.0); 130 auto exponentialParamPosition = Vec(59.5, 218.0); 131 auto loopParamPosition = Vec(59.5, 232.0); 132 133 auto frequency1InputPosition = Vec(10.5, 251.0); 134 auto frequency2InputPosition = Vec(40.5, 251.0); 135 auto timeInputPosition = Vec(10.5, 288.0); 136 auto triggerInputPosition = Vec(10.5, 325.0); 137 138 auto eocOutputPosition = Vec(40.5, 288.0); 139 auto outOutputPosition = Vec(40.5, 325.0); 140 // end generated by svg_widgets.rb 141 142 addParam(createParam<Knob38>(timeParamPosition, module, Chirp::TIME_PARAM)); 143 addParam(createParam<Knob26>(frequency1ParamPosition, module, Chirp::FREQUENCY1_PARAM)); 144 addParam(createParam<Knob26>(frequency2ParamPosition, module, Chirp::FREQUENCY2_PARAM)); 145 addParam(createParam<Button18>(triggerParamPosition, module, Chirp::TRIGGER_PARAM)); 146 addParam(createParam<IndicatorButtonGreen9>(exponentialParamPosition, module, Chirp::EXPONENTIAL_PARAM)); 147 addParam(createParam<IndicatorButtonGreen9>(loopParamPosition, module, Chirp::LOOP_PARAM)); 148 149 addInput(createInput<Port24>(frequency1InputPosition, module, Chirp::FREQUENCY1_INPUT)); 150 addInput(createInput<Port24>(frequency2InputPosition, module, Chirp::FREQUENCY2_INPUT)); 151 addInput(createInput<Port24>(timeInputPosition, module, Chirp::TIME_INPUT)); 152 addInput(createInput<Port24>(triggerInputPosition, module, Chirp::TRIGGER_INPUT)); 153 154 addOutput(createOutput<Port24>(eocOutputPosition, module, Chirp::EOC_OUTPUT)); 155 addOutput(createOutput<Port24>(outOutputPosition, module, Chirp::OUT_OUTPUT)); 156 } 157 }; 158 159 Model* modelChirp = createModel<Chirp, ChirpWidget>("Bogaudio-Chirp", "CHIRP", "Swept-sine oscillator", "Oscillator", "Polyphonic");