ADSR.cpp (4809B)
1 2 #include "ADSR.hpp" 3 4 #define INVERT "invert" 5 6 void ADSR::Engine::reset() { 7 gateTrigger.reset(); 8 envelope.reset(); 9 } 10 11 void ADSR::Engine::sampleRateChange() { 12 envelope.setSampleRate(APP->engine->getSampleRate()); 13 } 14 15 void ADSR::reset() { 16 for (int c = 0; c < _channels; ++c) { 17 _engines[c]->reset(); 18 } 19 } 20 21 void ADSR::sampleRateChange() { 22 for (int c = 0; c < _channels; ++c) { 23 _engines[c]->sampleRateChange(); 24 } 25 } 26 27 json_t* ADSR::saveToJson(json_t* root) { 28 json_object_set_new(root, INVERT, json_real(_invert)); 29 return root; 30 } 31 32 void ADSR::loadFromJson(json_t* root) { 33 json_t* i = json_object_get(root, INVERT); 34 if (i) { 35 _invert = json_real_value(i); 36 } 37 } 38 39 bool ADSR::active() { 40 return inputs[GATE_INPUT].isConnected() || outputs[OUT_OUTPUT].isConnected(); 41 } 42 43 int ADSR::channels() { 44 return inputs[GATE_INPUT].getChannels(); 45 } 46 47 void ADSR::addChannel(int c) { 48 _engines[c] = new Engine(); 49 _engines[c]->reset(); 50 _engines[c]->sampleRateChange(); 51 } 52 53 void ADSR::removeChannel(int c) { 54 delete _engines[c]; 55 _engines[c] = NULL; 56 } 57 58 void ADSR::modulate() { 59 _linearMode = params[LINEAR_PARAM].getValue() > 0.5f; 60 } 61 62 void ADSR::modulateChannel(int c) { 63 Engine& e = *_engines[c]; 64 65 e.envelope.setAttack(powf(params[ATTACK_PARAM].getValue(), 2.0f) * 10.f); 66 e.envelope.setDecay(powf(params[DECAY_PARAM].getValue(), 2.0f) * 10.f); 67 e.envelope.setSustain(params[SUSTAIN_PARAM].getValue()); 68 e.envelope.setRelease(powf(params[RELEASE_PARAM].getValue(), 2.0f) * 10.f); 69 e.envelope.setLinearShape(_linearMode); 70 } 71 72 void ADSR::processAlways(const ProcessArgs& args) { 73 _attackLightSum = _decayLightSum = _sustainLightSum = _releaseLightSum = 0; 74 } 75 76 void ADSR::processChannel(const ProcessArgs& args, int c) { 77 Engine& e = *_engines[c]; 78 79 e.gateTrigger.process(inputs[GATE_INPUT].getVoltage(c)); 80 e.envelope.setGate(e.gateTrigger.isHigh()); 81 outputs[OUT_OUTPUT].setChannels(_channels); 82 outputs[OUT_OUTPUT].setVoltage(e.envelope.next() * 10.0f * _invert, c); 83 84 _attackLightSum += e.envelope.isStage(dsp::ADSR::ATTACK_STAGE); 85 _decayLightSum += e.envelope.isStage(dsp::ADSR::DECAY_STAGE); 86 _sustainLightSum += e.envelope.isStage(dsp::ADSR::SUSTAIN_STAGE); 87 _releaseLightSum += e.envelope.isStage(dsp::ADSR::RELEASE_STAGE); 88 } 89 90 void ADSR::postProcessAlways(const ProcessArgs& args) { 91 lights[ATTACK_LIGHT].value = _attackLightSum * _inverseChannels; 92 lights[DECAY_LIGHT].value = _decayLightSum * _inverseChannels; 93 lights[SUSTAIN_LIGHT].value = _sustainLightSum * _inverseChannels; 94 lights[RELEASE_LIGHT].value = _releaseLightSum * _inverseChannels; 95 } 96 97 struct ADSRWidget : BGModuleWidget { 98 static constexpr int hp = 3; 99 100 ADSRWidget(ADSR* module) { 101 setModule(module); 102 box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); 103 setPanel(box.size, "ADSR"); 104 createScrews(); 105 106 // generated by svg_widgets.rb 107 auto attackParamPosition = Vec(8.0, 33.0); 108 auto decayParamPosition = Vec(8.0, 90.0); 109 auto sustainParamPosition = Vec(8.0, 147.0); 110 auto releaseParamPosition = Vec(8.0, 204.0); 111 auto linearParamPosition = Vec(25.5, 246.0); 112 113 auto gateInputPosition = Vec(10.5, 265.0); 114 115 auto outOutputPosition = Vec(10.5, 303.0); 116 117 auto attackLightPosition = Vec(20.8, 65.0); 118 auto decayLightPosition = Vec(20.8, 122.0); 119 auto sustainLightPosition = Vec(20.8, 179.0); 120 auto releaseLightPosition = Vec(20.8, 236.0); 121 // end generated by svg_widgets.rb 122 123 addParam(createParam<Knob29>(attackParamPosition, module, ADSR::ATTACK_PARAM)); 124 addParam(createParam<Knob29>(decayParamPosition, module, ADSR::DECAY_PARAM)); 125 addParam(createParam<Knob29>(sustainParamPosition, module, ADSR::SUSTAIN_PARAM)); 126 addParam(createParam<Knob29>(releaseParamPosition, module, ADSR::RELEASE_PARAM)); 127 addParam(createParam<IndicatorButtonGreen9>(linearParamPosition, module, ADSR::LINEAR_PARAM)); 128 129 addInput(createInput<Port24>(gateInputPosition, module, ADSR::GATE_INPUT)); 130 131 addOutput(createOutput<Port24>(outOutputPosition, module, ADSR::OUT_OUTPUT)); 132 133 addChild(createLight<BGTinyLight<GreenLight>>(attackLightPosition, module, ADSR::ATTACK_LIGHT)); 134 addChild(createLight<BGTinyLight<GreenLight>>(decayLightPosition, module, ADSR::DECAY_LIGHT)); 135 addChild(createLight<BGTinyLight<GreenLight>>(sustainLightPosition, module, ADSR::SUSTAIN_LIGHT)); 136 addChild(createLight<BGTinyLight<GreenLight>>(releaseLightPosition, module, ADSR::RELEASE_LIGHT)); 137 } 138 139 void contextMenu(Menu* menu) override { 140 auto m = dynamic_cast<ADSR*>(module); 141 assert(m); 142 menu->addChild(new OptionMenuItem( 143 "Invert output", 144 [m]() { return m->_invert == -1.0f; }, 145 [m]() { 146 if (m->_invert < 0.0f) { 147 m->_invert = 1.0f; 148 } 149 else { 150 m->_invert = -1.0f; 151 } 152 } 153 )); 154 } 155 }; 156 157 Model* modelADSR = bogaudio::createModel<ADSR, ADSRWidget>("Bogaudio-ADSR", "ADSR", "ADSR envelope generator", "Envelope generator", "Polyphonic");