Mix2.cpp (5566B)
1 2 #include "Mix2.hpp" 3 4 #define POLY_OFFSET "poly_channel_offset" 5 6 json_t* Mix2::saveToJson(json_t* root) { 7 json_object_set_new(root, POLY_OFFSET, json_integer(_polyChannelOffset)); 8 return root; 9 } 10 11 void Mix2::loadFromJson(json_t* root) { 12 json_t* o = json_object_get(root, POLY_OFFSET); 13 if (o) { 14 _polyChannelOffset = json_integer_value(o); 15 } 16 } 17 18 void Mix2::sampleRateChange() { 19 float sr = APP->engine->getSampleRate(); 20 for (int c = 0; c < _channels; ++c) { 21 _engines[c]->left.setSampleRate(sr); 22 _engines[c]->right.setSampleRate(sr); 23 } 24 } 25 26 bool Mix2::active() { 27 return outputs[L_OUTPUT].isConnected() || outputs[R_OUTPUT].isConnected(); 28 } 29 30 int Mix2::channels() { 31 if (_polyChannelOffset >= 0) { 32 return 1; 33 } 34 return inputs[L_INPUT].getChannels(); 35 } 36 37 void Mix2::addChannel(int c) { 38 _engines[c] = new Engine( 39 params[LEVEL_PARAM], 40 params[MUTE_PARAM], 41 inputs[LEVEL_INPUT], 42 inputs[MUTE_INPUT] 43 ); 44 } 45 46 void Mix2::removeChannel(int c) { 47 delete _engines[c]; 48 _engines[c] = NULL; 49 } 50 51 void Mix2::processAlways(const ProcessArgs& args) { 52 _leftRmsSum = 0.0f; 53 _rightRmsSum = 0.0f; 54 } 55 56 void Mix2::processChannel(const ProcessArgs& args, int c) { 57 Engine& e = *_engines[c]; 58 59 float left = 0.0f; 60 if (_polyChannelOffset >= 0) { 61 left = inputs[L_INPUT].getPolyVoltage(_polyChannelOffset); 62 } 63 else { 64 left = inputs[L_INPUT].getVoltage(c); 65 } 66 e.left.next(left, false, c, _linearCV); 67 _leftRmsSum += e.left.rms; 68 outputs[L_OUTPUT].setChannels(_channels); 69 outputs[L_OUTPUT].setVoltage(e.left.out, c); 70 71 float right = left; 72 if (inputs[R_INPUT].isConnected()) { 73 right = inputs[R_INPUT].getVoltage(c); 74 } 75 else if (_polyChannelOffset >= 0) { 76 right = inputs[L_INPUT].getPolyVoltage(_polyChannelOffset + 1); 77 } 78 e.right.next(right, false, c, _linearCV); 79 _rightRmsSum += e.right.rms; 80 outputs[R_OUTPUT].setChannels(_channels); 81 outputs[R_OUTPUT].setVoltage(e.right.out, c); 82 } 83 84 void Mix2::postProcessAlways(const ProcessArgs& args) { 85 _leftRms = _leftRmsSum * _inverseChannels; 86 _rightRms = _rightRmsSum * _inverseChannels; 87 } 88 89 void Mix2::processBypass(const ProcessArgs& args) { 90 outputs[L_OUTPUT].setChannels(inputs[L_INPUT].getChannels()); 91 outputs[L_OUTPUT].writeVoltages(inputs[L_INPUT].getVoltages()); 92 if (inputs[R_INPUT].isConnected()) { 93 outputs[R_OUTPUT].setChannels(inputs[R_INPUT].getChannels()); 94 outputs[R_OUTPUT].writeVoltages(inputs[R_INPUT].getVoltages()); 95 } 96 else { 97 outputs[R_OUTPUT].setChannels(inputs[L_INPUT].getChannels()); 98 outputs[R_OUTPUT].writeVoltages(inputs[L_INPUT].getVoltages()); 99 } 100 } 101 102 struct Mix2Widget : LinearCVMixerWidget { 103 static constexpr int hp = 5; 104 105 Mix2Widget(Mix2* module) { 106 setModule(module); 107 box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT); 108 setPanel(box.size, "Mix2"); 109 createScrews(); 110 111 // generated by svg_widgets.rb 112 auto levelParamPosition = Vec(28.5, 32.0); 113 auto muteParamPosition = Vec(28.5, 197.0); 114 115 auto levelInputPosition = Vec(10.5, 244.0); 116 auto muteInputPosition = Vec(40.5, 244.0); 117 auto lInputPosition = Vec(10.5, 280.0); 118 auto rInputPosition = Vec(40.5, 280.0); 119 120 auto lOutputPosition = Vec(10.5, 320.0); 121 auto rOutputPosition = Vec(40.5, 320.0); 122 // end generated by svg_widgets.rb 123 124 { 125 auto slider = createParam<VUSlider151>(levelParamPosition, module, Mix2::LEVEL_PARAM); 126 if (module) { 127 dynamic_cast<VUSlider*>(slider)->setVULevel(&module->_leftRms); 128 dynamic_cast<VUSlider*>(slider)->setStereoVULevel(&module->_rightRms); 129 } 130 addParam(slider); 131 } 132 addParam(createParam<MuteButton>(muteParamPosition, module, Mix2::MUTE_PARAM)); 133 134 addInput(createInput<Port24>(levelInputPosition, module, Mix2::LEVEL_INPUT)); 135 addInput(createInput<Port24>(muteInputPosition, module, Mix2::MUTE_INPUT)); 136 addInput(createInput<Port24>(lInputPosition, module, Mix2::L_INPUT)); 137 addInput(createInput<Port24>(rInputPosition, module, Mix2::R_INPUT)); 138 139 addOutput(createOutput<Port24>(lOutputPosition, module, Mix2::L_OUTPUT)); 140 addOutput(createOutput<Port24>(rOutputPosition, module, Mix2::R_OUTPUT)); 141 } 142 143 void contextMenu(Menu* menu) override { 144 auto m = dynamic_cast<Mix2*>(module); 145 assert(m); 146 OptionsMenuItem* mi = new OptionsMenuItem("Input 1 poly spread"); 147 mi->addItem(OptionMenuItem("None (normal polyphonic)", [m]() { return m->_polyChannelOffset == -1; }, [m]() { m->_polyChannelOffset = -1; })); 148 mi->addItem(OptionMenuItem("Channels 1-2", [m]() { return m->_polyChannelOffset == 0; }, [m]() { m->_polyChannelOffset = 0; })); 149 mi->addItem(OptionMenuItem("Channels 3-4", [m]() { return m->_polyChannelOffset == 2; }, [m]() { m->_polyChannelOffset = 2; })); 150 mi->addItem(OptionMenuItem("Channels 5-6", [m]() { return m->_polyChannelOffset == 4; }, [m]() { m->_polyChannelOffset = 4; })); 151 mi->addItem(OptionMenuItem("Channels 7-8", [m]() { return m->_polyChannelOffset == 6; }, [m]() { m->_polyChannelOffset = 6; })); 152 mi->addItem(OptionMenuItem("Channels 9-10", [m]() { return m->_polyChannelOffset == 8; }, [m]() { m->_polyChannelOffset = 8; })); 153 mi->addItem(OptionMenuItem("Channels 11-12", [m]() { return m->_polyChannelOffset == 10; }, [m]() { m->_polyChannelOffset = 10; })); 154 mi->addItem(OptionMenuItem("Channels 13-14", [m]() { return m->_polyChannelOffset == 12; }, [m]() { m->_polyChannelOffset = 12; })); 155 mi->addItem(OptionMenuItem("Channels 15-16", [m]() { return m->_polyChannelOffset == 14; }, [m]() { m->_polyChannelOffset = 14; })); 156 OptionsMenuItem::addToMenu(mi, menu); 157 } 158 }; 159 160 Model* modelMix2 = createModel<Mix2, Mix2Widget>("Bogaudio-Mix2", "MIX2", "Stereo fader/amplifier with CV-controllable mute", "VCA", "Polyphonic");