mixer.cpp (5761B)
1 2 #include "mixer.hpp" 3 4 const float MixerChannel::maxDecibels = 6.0f; 5 const float MixerChannel::minDecibels = Amplifier::minDecibels; 6 const float MixerChannel::levelSlewTimeMS = 5.0f; 7 8 void MixerChannel::setSampleRate(float sampleRate) { 9 _levelSL.setParams(sampleRate, levelSlewTimeMS, maxDecibels - minDecibels); 10 _levelCVSL.setParams(sampleRate, levelSlewTimeMS, 1.0f); 11 _rms.setSampleRate(sampleRate); 12 } 13 14 void MixerChannel::reset() { 15 out = rms = 0.0f; 16 } 17 18 void MixerChannel::next(float sample, bool solo, int c, bool linearCV) { 19 float cv = 1.0f; 20 if (_levelInput.isConnected()) { 21 cv = clamp(_levelInput.getPolyVoltage(c) / 10.0f, 0.0f, 1.0f); 22 } 23 24 float mute = _muteParam.getValue(); 25 if (_muteInput) { 26 mute += clamp(_muteInput->getPolyVoltage(c), 0.0f, 10.0f); 27 } 28 bool muted = solo ? mute < 2.0f : mute > 0.5f; 29 if (muted) { 30 _amplifier.setLevel(_levelSL.next(minDecibels)); 31 } 32 else { 33 float level = clamp(_levelParam.getValue(), 0.0f, 1.0f); 34 if (!linearCV) { 35 level *= cv; 36 } 37 level *= maxDecibels - minDecibels; 38 level += minDecibels; 39 _amplifier.setLevel(_levelSL.next(level)); 40 } 41 42 out = _amplifier.next(sample); 43 if (linearCV) { 44 out *= _levelCVSL.next(cv); 45 } 46 rms = _rms.next(out / 5.0f); 47 } 48 49 50 #define LINEAR_CV "linear_cv" 51 52 json_t* LinearCVMixerModule::saveToJson(json_t* root) { 53 json_object_set_new(root, LINEAR_CV, json_boolean(_linearCV)); 54 return root; 55 } 56 57 void LinearCVMixerModule::loadFromJson(json_t* root) { 58 json_t* l = json_object_get(root, LINEAR_CV); 59 if (l) { 60 _linearCV = json_boolean_value(l); 61 } 62 } 63 64 65 void LinearCVMixerWidget::contextMenu(Menu* menu) { 66 auto m = dynamic_cast<LinearCVMixerModule*>(module); 67 assert(m); 68 menu->addChild(new BoolOptionMenuItem("Linear level CV response", [m]() { return &m->_linearCV; })); 69 } 70 71 72 #define DIM_DB "dim_decibels" 73 74 json_t* DimmableMixerModule::saveToJson(json_t* root) { 75 root = LinearCVMixerModule::saveToJson(root); 76 json_object_set_new(root, DIM_DB, json_real(_dimDb)); 77 return root; 78 } 79 80 void DimmableMixerModule::loadFromJson(json_t* root) { 81 LinearCVMixerModule::loadFromJson(root); 82 json_t* o = json_object_get(root, DIM_DB); 83 if (o) { 84 _dimDb = json_real_value(o); 85 } 86 } 87 88 89 void DimmableMixerWidget::contextMenu(Menu* menu) { 90 LinearCVMixerWidget::contextMenu(menu); 91 auto m = dynamic_cast<DimmableMixerModule*>(module); 92 assert(m); 93 OptionsMenuItem* da = new OptionsMenuItem("Dim amount"); 94 da->addItem(OptionMenuItem("-6 dB", [m]() { return m->_dimDb == 6.0f; }, [m]() { m->_dimDb = 6.0f; })); 95 da->addItem(OptionMenuItem("-12 dB", [m]() { return m->_dimDb == 12.0f; }, [m]() { m->_dimDb = 12.0f; })); 96 da->addItem(OptionMenuItem("-18 dB", [m]() { return m->_dimDb == 18.0f; }, [m]() { m->_dimDb = 18.0f; })); 97 da->addItem(OptionMenuItem("-24 dB", [m]() { return m->_dimDb == 24.0f; }, [m]() { m->_dimDb = 24.0f; })); 98 OptionsMenuItem::addToMenu(da, menu); 99 } 100 101 102 void MuteButton::onButton(const event::Button& e) { 103 if (!(e.action == GLFW_PRESS && (e.mods & RACK_MOD_MASK) == 0)) { 104 return; 105 } 106 107 if (e.button == GLFW_MOUSE_BUTTON_RIGHT) { 108 e.consume(this); 109 } 110 else { 111 ToggleButton::onButton(e); 112 } 113 } 114 115 bool MuteButton::isLit() { 116 return module && !module->isBypassed() && getParamQuantity() && getParamQuantity()->getValue() > 0.0f; 117 } 118 119 void MuteButton::draw(const DrawArgs& args) { 120 if (!isLit()) { 121 ToggleButton::draw(args); 122 } 123 } 124 125 void MuteButton::drawLit(const DrawArgs& args) { 126 ToggleButton::draw(args); 127 } 128 129 130 SoloMuteButton::SoloMuteButton() { 131 shadow = new CircularShadow(); 132 addChild(shadow); 133 134 _svgWidget = new SvgWidget(); 135 addChild(_svgWidget); 136 137 auto svg = APP->window->loadSvg(asset::plugin(pluginInstance, "res/button_18px_0.svg")); 138 _frames.push_back(svg); 139 _frames.push_back(APP->window->loadSvg(asset::plugin(pluginInstance, "res/button_18px_1_orange.svg"))); 140 _frames.push_back(APP->window->loadSvg(asset::plugin(pluginInstance, "res/button_18px_1_green.svg"))); 141 _frames.push_back(APP->window->loadSvg(asset::plugin(pluginInstance, "res/button_18px_1_green.svg"))); 142 143 _svgWidget->setSvg(svg); 144 box.size = _svgWidget->box.size; 145 shadow->box.size = _svgWidget->box.size; 146 shadow->blurRadius = 1.0; 147 shadow->box.pos = Vec(0.0, 1.0); 148 } 149 150 void SoloMuteButton::onButton(const event::Button& e) { 151 if (!getParamQuantity() || !(e.action == GLFW_PRESS && (e.mods & RACK_MOD_MASK) == 0)) { 152 ParamWidget::onButton(e); 153 return; 154 } 155 156 float value = getParamQuantity()->getValue(); 157 if (value >= 2.0f) { 158 getParamQuantity()->setValue(value - 2.0f); 159 } 160 else if (e.button == GLFW_MOUSE_BUTTON_RIGHT) { 161 getParamQuantity()->setValue(value + 2.0f); 162 } 163 else { 164 getParamQuantity()->setValue(value > 0.5f ? 0.0f : 1.0f); 165 } 166 167 if (e.button == GLFW_MOUSE_BUTTON_RIGHT) { 168 e.consume(this); 169 } else { 170 ParamWidget::onButton(e); 171 } 172 } 173 174 void SoloMuteButton::onChange(const event::Change& e) { 175 assert(_frames.size() == 4); 176 if (getParamQuantity()) { 177 float value = getParamQuantity()->getValue(); 178 assert(value >= 0.0f && value <= 3.0f); 179 _svgWidget->setSvg(_frames[(int)value]); 180 } 181 ParamWidget::onChange(e); 182 } 183 184 bool SoloMuteButton::isLit() { 185 return module && !module->isBypassed() && getParamQuantity() && getParamQuantity()->getValue() > 0.0f; 186 } 187 188 void SoloMuteButton::draw(const DrawArgs& args) { 189 if (!isLit() || !getParamQuantity() || getParamQuantity()->getValue() < 1.0f) { 190 ParamWidget::draw(args); 191 } 192 } 193 194 void SoloMuteButton::drawLit(const DrawArgs& args) { 195 if (getParamQuantity() && getParamQuantity()->getValue() >= 1.0f) { 196 ParamWidget::draw(args); 197 } 198 } 199 200 201 std::string DimSwitchQuantity::getDisplayValueString() { 202 if (!module || getValue() < 1.0f) { 203 return SwitchQuantity::getDisplayValueString(); 204 } 205 auto* m = static_cast<DimmableMixerModule*>(module); 206 assert(labels.size() == 2); 207 return format("%s (-%ddB)", labels[1].c_str(), (int)m->_dimDb); 208 }