LVCF.cpp (8133B)
1 2 #include "LVCF.hpp" 3 #include "dsp/pitch.hpp" 4 5 #define POLES_KEY "poles" 6 #define BANDWIDTH_MODE_KEY "bandwidthMode" 7 #define LINEAR_BANDWIDTH_MODE_KEY "linear" 8 #define PITCH_BANDWIDTH_MODE_KEY "pitched" 9 10 void LVCF::Engine::setParams( 11 int poles, 12 MultimodeFilter::Mode mode, 13 float frequency, 14 float qbw, 15 MultimodeFilter::BandwidthMode bwm 16 ) { 17 frequency = semitoneToFrequency(_frequencySL.next(frequencyToSemitone(frequency))); 18 frequency = clamp(semitoneToFrequency(_frequencySL.next(frequencyToSemitone(frequency))), LVCF::minFrequency, LVCF::maxFrequency); 19 20 _filter.setParams( 21 _sampleRate, 22 MultimodeFilter::BUTTERWORTH_TYPE, 23 poles, 24 mode, 25 frequency, 26 qbw, 27 bwm 28 ); 29 } 30 31 void LVCF::Engine::sampleRateChange() { 32 _sampleRate = APP->engine->getSampleRate(); 33 _frequencySL.setParams(_sampleRate, 0.5f, frequencyToSemitone(maxFrequency - minFrequency)); 34 _finalHP.setParams(_sampleRate, MultimodeFilter::BUTTERWORTH_TYPE, 2, MultimodeFilter::HIGHPASS_MODE, 80.0f, MultimodeFilter::minQbw, MultimodeFilter::LINEAR_BANDWIDTH_MODE, MultimodeFilter::MINIMUM_DELAY_MODE); 35 } 36 37 void LVCF::Engine::reset() { 38 _filter.reset(); 39 } 40 41 float LVCF::Engine::next(float sample) { 42 return _finalHP.next(_filter.next(sample)); 43 } 44 45 json_t* LVCF::saveToJson(json_t* root) { 46 json_object_set_new(root, POLES_KEY, json_integer(_polesSetting)); 47 48 switch (_bandwidthMode) { 49 case MultimodeFilter::LINEAR_BANDWIDTH_MODE: { 50 json_object_set_new(root, BANDWIDTH_MODE_KEY, json_string(LINEAR_BANDWIDTH_MODE_KEY)); 51 break; 52 } 53 case MultimodeFilter::PITCH_BANDWIDTH_MODE: { 54 json_object_set_new(root, BANDWIDTH_MODE_KEY, json_string(PITCH_BANDWIDTH_MODE_KEY)); 55 break; 56 } 57 default: {} 58 } 59 60 return root; 61 } 62 63 void LVCF::loadFromJson(json_t* root) { 64 json_t* p = json_object_get(root, POLES_KEY); 65 if (p) { 66 _polesSetting = clamp(json_integer_value(p), 1, 12); 67 } 68 69 json_t* bwm = json_object_get(root, BANDWIDTH_MODE_KEY); 70 if (bwm) { 71 if (strcmp(json_string_value(bwm), LINEAR_BANDWIDTH_MODE_KEY) == 0) { 72 _bandwidthMode = MultimodeFilter::LINEAR_BANDWIDTH_MODE; 73 } 74 else { 75 _bandwidthMode = MultimodeFilter::PITCH_BANDWIDTH_MODE; 76 } 77 } 78 } 79 80 void LVCF::sampleRateChange() { 81 for (int c = 0; c < _channels; ++c) { 82 _engines[c]->sampleRateChange(); 83 } 84 } 85 86 bool LVCF::active() { 87 return outputs[OUT_OUTPUT].isConnected(); 88 } 89 90 int LVCF::channels() { 91 return inputs[IN_INPUT].getChannels(); 92 } 93 94 void LVCF::addChannel(int c) { 95 _engines[c] = new Engine(); 96 } 97 98 void LVCF::removeChannel(int c) { 99 delete _engines[c]; 100 _engines[c] = NULL; 101 } 102 103 MultimodeFilter::Mode LVCF::modeParamValue() { 104 return (MultimodeFilter::Mode)(1 + clamp((int)params[MODE_PARAM].getValue(), 0, 4)); 105 } 106 107 void LVCF::modulate() { 108 MultimodeFilter::Mode mode = modeParamValue(); 109 if (_mode != mode || _poles != _polesSetting) { 110 _mode = mode; 111 _poles = _polesSetting; 112 for (int c = 0; c < _channels; ++c) { 113 _engines[c]->reset(); 114 } 115 } 116 117 _q = clamp(params[Q_PARAM].getValue(), 0.0f, 1.0f); 118 } 119 120 void LVCF::modulateChannel(int c) { 121 Engine& e = *_engines[c]; 122 123 float q = _q; 124 float f = clamp(params[FREQUENCY_PARAM].getValue(), 0.0f, 1.0f); 125 if (inputs[FREQUENCY_CV_INPUT].isConnected()) { 126 float fcv = clamp(inputs[FREQUENCY_CV_INPUT].getPolyVoltage(c) / 5.0f, -1.0f, 1.0f); 127 fcv *= clamp(params[FREQUENCY_CV_PARAM].getValue(), -1.0f, 1.0f); 128 f = std::max(0.0f, f + fcv); 129 } 130 f *= f; 131 f *= maxFrequency; 132 f = clamp(f, minFrequency, maxFrequency); 133 134 e.setParams( 135 _poles, 136 _mode, 137 f, 138 q, 139 _bandwidthMode 140 ); 141 } 142 143 void LVCF::processAlways(const ProcessArgs& args) { 144 MultimodeFilter::Mode mode = modeParamValue(); 145 lights[LOWPASS_LIGHT].value = mode == MultimodeFilter::LOWPASS_MODE; 146 lights[HIGHPASS_LIGHT].value = mode == MultimodeFilter::HIGHPASS_MODE; 147 lights[BANDPASS_LIGHT].value = mode == MultimodeFilter::BANDPASS_MODE; 148 lights[BANDREJECT_LIGHT].value = mode == MultimodeFilter::BANDREJECT_MODE; 149 } 150 151 void LVCF::processAll(const ProcessArgs& args) { 152 outputs[OUT_OUTPUT].setChannels(_channels); 153 } 154 155 void LVCF::processChannel(const ProcessArgs& args, int c) { 156 outputs[OUT_OUTPUT].setVoltage(_engines[c]->next(inputs[IN_INPUT].getVoltage(c)), c); 157 } 158 159 struct LVCFWidget : BGModuleWidget { 160 static constexpr int hp = 3; 161 162 LVCFWidget(LVCF* module) { 163 setModule(module); 164 box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); 165 setPanel(box.size, "LVCF"); 166 createScrews(); 167 168 // generated by svg_widgets.rb 169 auto frequencyParamPosition = Vec(9.5, 39.0); 170 auto frequencyCvParamPosition = Vec(14.5, 93.5); 171 auto qParamPosition = Vec(9.5, 138.0); 172 auto modeParamPosition = Vec(18.0, 204.0); 173 174 auto inInputPosition = Vec(10.5, 228.0); 175 auto frequencyCvInputPosition = Vec(10.5, 263.0); 176 177 auto outOutputPosition = Vec(10.5, 301.0); 178 179 auto lowpassLightPosition = Vec(3.0, 181.0); 180 auto bandpassLightPosition = Vec(3.0, 194.0); 181 auto highpassLightPosition = Vec(25.0, 181.0); 182 auto bandrejectLightPosition = Vec(25.0, 194.0); 183 // end generated by svg_widgets.rb 184 185 addParam(createParam<Knob26>(frequencyParamPosition, module, LVCF::FREQUENCY_PARAM)); 186 addParam(createParam<Knob16>(frequencyCvParamPosition, module, LVCF::FREQUENCY_CV_PARAM)); 187 addParam(createParam<Knob26>(qParamPosition, module, LVCF::Q_PARAM)); 188 addParam(createParam<StatefulButton9>(modeParamPosition, module, LVCF::MODE_PARAM)); 189 190 addInput(createInput<Port24>(inInputPosition, module, LVCF::IN_INPUT)); 191 addInput(createInput<Port24>(frequencyCvInputPosition, module, LVCF::FREQUENCY_CV_INPUT)); 192 193 addOutput(createOutput<Port24>(outOutputPosition, module, LVCF::OUT_OUTPUT)); 194 195 addChild(createLight<BGSmallLight<GreenLight>>(lowpassLightPosition, module, LVCF::LOWPASS_LIGHT)); 196 addChild(createLight<BGSmallLight<GreenLight>>(bandpassLightPosition, module, LVCF::BANDPASS_LIGHT)); 197 addChild(createLight<BGSmallLight<GreenLight>>(highpassLightPosition, module, LVCF::HIGHPASS_LIGHT)); 198 addChild(createLight<BGSmallLight<GreenLight>>(bandrejectLightPosition, module, LVCF::BANDREJECT_LIGHT)); 199 } 200 201 void contextMenu(Menu* menu) override { 202 auto m = dynamic_cast<LVCF*>(module); 203 assert(m); 204 205 OptionsMenuItem* s = new OptionsMenuItem("Slope"); 206 s->addItem(OptionMenuItem("1 pole", [m]() { return m->_polesSetting == 1; }, [m]() { m->_polesSetting = 1; })); 207 s->addItem(OptionMenuItem("2 poles", [m]() { return m->_polesSetting == 2; }, [m]() { m->_polesSetting = 2; })); 208 s->addItem(OptionMenuItem("3 poles", [m]() { return m->_polesSetting == 3; }, [m]() { m->_polesSetting = 3; })); 209 s->addItem(OptionMenuItem("4 poles", [m]() { return m->_polesSetting == 4; }, [m]() { m->_polesSetting = 4; })); 210 s->addItem(OptionMenuItem("5 poles", [m]() { return m->_polesSetting == 5; }, [m]() { m->_polesSetting = 5; })); 211 s->addItem(OptionMenuItem("6 poles", [m]() { return m->_polesSetting == 6; }, [m]() { m->_polesSetting = 6; })); 212 s->addItem(OptionMenuItem("7 poles", [m]() { return m->_polesSetting == 7; }, [m]() { m->_polesSetting = 7; })); 213 s->addItem(OptionMenuItem("8 poles", [m]() { return m->_polesSetting == 8; }, [m]() { m->_polesSetting = 8; })); 214 s->addItem(OptionMenuItem("9 poles", [m]() { return m->_polesSetting == 9; }, [m]() { m->_polesSetting = 9; })); 215 s->addItem(OptionMenuItem("10 poles", [m]() { return m->_polesSetting == 10; }, [m]() { m->_polesSetting = 10; })); 216 s->addItem(OptionMenuItem("11 poles", [m]() { return m->_polesSetting == 11; }, [m]() { m->_polesSetting = 11; })); 217 s->addItem(OptionMenuItem("12 poles", [m]() { return m->_polesSetting == 12; }, [m]() { m->_polesSetting = 12; })); 218 OptionsMenuItem::addToMenu(s, menu); 219 220 OptionsMenuItem* bwm = new OptionsMenuItem("Bandwidth mode"); 221 bwm->addItem(OptionMenuItem("Pitched", [m]() { return m->_bandwidthMode == MultimodeFilter::PITCH_BANDWIDTH_MODE; }, [m]() { m->_bandwidthMode = MultimodeFilter::PITCH_BANDWIDTH_MODE; })); 222 bwm->addItem(OptionMenuItem("Linear", [m]() { return m->_bandwidthMode == MultimodeFilter::LINEAR_BANDWIDTH_MODE; }, [m]() { m->_bandwidthMode = MultimodeFilter::LINEAR_BANDWIDTH_MODE; })); 223 OptionsMenuItem::addToMenu(bwm, menu); 224 } 225 }; 226 227 Model* modelLVCF = createModel<LVCF, LVCFWidget>("Bogaudio-LVCF", "LVCF", "Multimode filter", "Filter", "Polyphonic");