You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

266 lines
12KB

  1. #include "plugin.hpp"
  2. #include "Shelves/shelves.hpp"
  3. static const float freqMin = std::log2(shelves::kFreqKnobMin);
  4. static const float freqMax = std::log2(shelves::kFreqKnobMax);
  5. static const float freqInit = (freqMin + freqMax) / 2;
  6. static const float gainMin = -shelves::kGainKnobRange;
  7. static const float gainMax = shelves::kGainKnobRange;
  8. static const float qMin = std::log2(shelves::kQKnobMin);
  9. static const float qMax = std::log2(shelves::kQKnobMax);
  10. static const float qInit = (qMin + qMax) / 2;
  11. struct Shelves : Module {
  12. enum ParamIds {
  13. HS_FREQ_PARAM,
  14. HS_GAIN_PARAM,
  15. P1_FREQ_PARAM,
  16. P1_GAIN_PARAM,
  17. P1_Q_PARAM,
  18. P2_FREQ_PARAM,
  19. P2_GAIN_PARAM,
  20. P2_Q_PARAM,
  21. LS_FREQ_PARAM,
  22. LS_GAIN_PARAM,
  23. NUM_PARAMS
  24. };
  25. enum InputIds {
  26. HS_FREQ_INPUT,
  27. HS_GAIN_INPUT,
  28. P1_FREQ_INPUT,
  29. P1_GAIN_INPUT,
  30. P1_Q_INPUT,
  31. P2_FREQ_INPUT,
  32. P2_GAIN_INPUT,
  33. P2_Q_INPUT,
  34. LS_FREQ_INPUT,
  35. LS_GAIN_INPUT,
  36. FREQ_INPUT,
  37. GAIN_INPUT,
  38. IN_INPUT,
  39. NUM_INPUTS
  40. };
  41. enum OutputIds {
  42. P1_HP_OUTPUT,
  43. P1_BP_OUTPUT,
  44. P1_LP_OUTPUT,
  45. P2_HP_OUTPUT,
  46. P2_BP_OUTPUT,
  47. P2_LP_OUTPUT,
  48. OUT_OUTPUT,
  49. NUM_OUTPUTS
  50. };
  51. enum LightIds {
  52. CLIP_LIGHT,
  53. NUM_LIGHTS
  54. };
  55. shelves::ShelvesEngine engines[16];
  56. bool preGain;
  57. Shelves() {
  58. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  59. configParam(HS_FREQ_PARAM, freqMin, freqMax, freqInit, "High-shelf frequency", " Hz", 2.f);
  60. configParam(P1_FREQ_PARAM, freqMin, freqMax, freqInit, "Parametric 1 frequency", " Hz", 2.f);
  61. configParam(P2_FREQ_PARAM, freqMin, freqMax, freqInit, "Parametric 2 frequency", " Hz", 2.f);
  62. configParam(LS_FREQ_PARAM, freqMin, freqMax, freqInit, "Low-shelf frequency", " Hz", 2.f);
  63. configParam(HS_GAIN_PARAM, gainMin, gainMax, 0.f, "High-shelf gain", " dB");
  64. configParam(P1_GAIN_PARAM, gainMin, gainMax, 0.f, "Parametric 1 gain", " dB");
  65. configParam(P2_GAIN_PARAM, gainMin, gainMax, 0.f, "Parametric 2 gain", " dB");
  66. configParam(LS_GAIN_PARAM, gainMin, gainMax, 0.f, "Low-shelf gain", " dB");
  67. configParam(P1_Q_PARAM, qMin, qMax, qInit, "Parametric 1 quality", "", 2.f);
  68. configParam(P2_Q_PARAM, qMin, qMax, qInit, "Parametric 2 quality", "", 2.f);
  69. configInput(HS_FREQ_INPUT, "High-shelf frequency");
  70. configInput(HS_GAIN_INPUT, "High-shelf gain");
  71. configInput(P1_FREQ_INPUT, "Parametric 1 frequency");
  72. configInput(P1_GAIN_INPUT, "Parametric 1 gain");
  73. configInput(P1_Q_INPUT, "Parametric 1 quality");
  74. configInput(P2_FREQ_INPUT, "Parametric 2 frequency");
  75. configInput(P2_GAIN_INPUT, "Parametric 2 gain");
  76. configInput(P2_Q_INPUT, "Parametric 2 quality");
  77. configInput(LS_FREQ_INPUT, "Low-shelf frequency");
  78. configInput(LS_GAIN_INPUT, "Low-shelf gain");
  79. configInput(FREQ_INPUT, "All frequency");
  80. configInput(GAIN_INPUT, "All gain");
  81. configInput(IN_INPUT, "Audio");
  82. configOutput(P1_HP_OUTPUT, "Parametric 1 high-pass");
  83. configOutput(P1_BP_OUTPUT, "Parametric 1 band-pass");
  84. configOutput(P1_LP_OUTPUT, "Parametric 1 low-pass");
  85. configOutput(P2_HP_OUTPUT, "Parametric 2 high-pass");
  86. configOutput(P2_BP_OUTPUT, "Parametric 2 band-pass");
  87. configOutput(P2_LP_OUTPUT, "Parametric 2 low-pass");
  88. configOutput(OUT_OUTPUT, "Audio");
  89. onReset();
  90. }
  91. void onReset() override {
  92. preGain = false;
  93. onSampleRateChange();
  94. }
  95. void onSampleRateChange() override {
  96. // TODO In Rack v2, replace with args.sampleRate
  97. for (int c = 0; c < 16; c++) {
  98. engines[c].setSampleRate(APP->engine->getSampleRate());
  99. }
  100. }
  101. void process(const ProcessArgs& args) override {
  102. int channels = std::max(inputs[IN_INPUT].getChannels(), 1);
  103. // Reuse the same frame object for multiple engines because the params aren't touched.
  104. shelves::ShelvesEngine::Frame frame;
  105. frame.pre_gain = preGain;
  106. frame.hs_freq_knob = rescale(params[HS_FREQ_PARAM].getValue(), freqMin, freqMax, 0.f, 1.f);
  107. frame.p1_freq_knob = rescale(params[P1_FREQ_PARAM].getValue(), freqMin, freqMax, 0.f, 1.f);
  108. frame.p2_freq_knob = rescale(params[P2_FREQ_PARAM].getValue(), freqMin, freqMax, 0.f, 1.f);
  109. frame.ls_freq_knob = rescale(params[LS_FREQ_PARAM].getValue(), freqMin, freqMax, 0.f, 1.f);
  110. frame.hs_gain_knob = params[HS_GAIN_PARAM].getValue() / shelves::kGainKnobRange;
  111. frame.p1_gain_knob = params[P1_GAIN_PARAM].getValue() / shelves::kGainKnobRange;
  112. frame.p2_gain_knob = params[P2_GAIN_PARAM].getValue() / shelves::kGainKnobRange;
  113. frame.ls_gain_knob = params[LS_GAIN_PARAM].getValue() / shelves::kGainKnobRange;
  114. frame.p1_q_knob = rescale(params[P1_Q_PARAM].getValue(), qMin, qMax, 0.f, 1.f);
  115. frame.p2_q_knob = rescale(params[P2_Q_PARAM].getValue(), qMin, qMax, 0.f, 1.f);
  116. frame.hs_freq_cv_connected = inputs[HS_FREQ_INPUT].isConnected();
  117. frame.hs_gain_cv_connected = inputs[HS_GAIN_INPUT].isConnected();
  118. frame.p1_freq_cv_connected = inputs[P1_FREQ_INPUT].isConnected();
  119. frame.p1_gain_cv_connected = inputs[P1_GAIN_INPUT].isConnected();
  120. frame.p1_q_cv_connected = inputs[P1_Q_INPUT].isConnected();
  121. frame.p2_freq_cv_connected = inputs[P2_FREQ_INPUT].isConnected();
  122. frame.p2_gain_cv_connected = inputs[P2_GAIN_INPUT].isConnected();
  123. frame.p2_q_cv_connected = inputs[P2_Q_INPUT].isConnected();
  124. frame.ls_freq_cv_connected = inputs[LS_FREQ_INPUT].isConnected();
  125. frame.ls_gain_cv_connected = inputs[LS_GAIN_INPUT].isConnected();
  126. frame.global_freq_cv_connected = inputs[FREQ_INPUT].isConnected();
  127. frame.global_gain_cv_connected = inputs[GAIN_INPUT].isConnected();
  128. frame.p1_hp_out_connected = outputs[P1_HP_OUTPUT].isConnected();
  129. frame.p1_bp_out_connected = outputs[P1_BP_OUTPUT].isConnected();
  130. frame.p1_lp_out_connected = outputs[P1_LP_OUTPUT].isConnected();
  131. frame.p2_hp_out_connected = outputs[P2_HP_OUTPUT].isConnected();
  132. frame.p2_bp_out_connected = outputs[P2_BP_OUTPUT].isConnected();
  133. frame.p2_lp_out_connected = outputs[P2_LP_OUTPUT].isConnected();
  134. float clipLight = 0.f;
  135. for (int c = 0; c < channels; c++) {
  136. frame.main_in = inputs[IN_INPUT].getVoltage(c);
  137. frame.hs_freq_cv = inputs[HS_FREQ_INPUT].getPolyVoltage(c);
  138. frame.hs_gain_cv = inputs[HS_GAIN_INPUT].getPolyVoltage(c);
  139. frame.p1_freq_cv = inputs[P1_FREQ_INPUT].getPolyVoltage(c);
  140. frame.p1_gain_cv = inputs[P1_GAIN_INPUT].getPolyVoltage(c);
  141. frame.p1_q_cv = inputs[P1_Q_INPUT].getPolyVoltage(c);
  142. frame.p2_freq_cv = inputs[P2_FREQ_INPUT].getPolyVoltage(c);
  143. frame.p2_gain_cv = inputs[P2_GAIN_INPUT].getPolyVoltage(c);
  144. frame.p2_q_cv = inputs[P2_Q_INPUT].getPolyVoltage(c);
  145. frame.ls_freq_cv = inputs[LS_FREQ_INPUT].getPolyVoltage(c);
  146. frame.ls_gain_cv = inputs[LS_GAIN_INPUT].getPolyVoltage(c);
  147. frame.global_freq_cv = inputs[FREQ_INPUT].getPolyVoltage(c);
  148. frame.global_gain_cv = inputs[GAIN_INPUT].getPolyVoltage(c);
  149. engines[c].process(frame);
  150. outputs[P1_HP_OUTPUT].setVoltage(frame.p1_hp_out, c);
  151. outputs[P1_BP_OUTPUT].setVoltage(frame.p1_bp_out, c);
  152. outputs[P1_LP_OUTPUT].setVoltage(frame.p1_lp_out, c);
  153. outputs[P2_HP_OUTPUT].setVoltage(frame.p2_hp_out, c);
  154. outputs[P2_BP_OUTPUT].setVoltage(frame.p2_bp_out, c);
  155. outputs[P2_LP_OUTPUT].setVoltage(frame.p2_lp_out, c);
  156. outputs[OUT_OUTPUT].setVoltage(frame.main_out, c);
  157. clipLight += frame.clip;
  158. }
  159. outputs[P1_HP_OUTPUT].setChannels(channels);
  160. outputs[P1_BP_OUTPUT].setChannels(channels);
  161. outputs[P1_LP_OUTPUT].setChannels(channels);
  162. outputs[P2_HP_OUTPUT].setChannels(channels);
  163. outputs[P2_BP_OUTPUT].setChannels(channels);
  164. outputs[P2_LP_OUTPUT].setChannels(channels);
  165. outputs[OUT_OUTPUT].setChannels(channels);
  166. lights[CLIP_LIGHT].setSmoothBrightness(clipLight, args.sampleTime);
  167. }
  168. json_t* dataToJson() override {
  169. json_t* root_j = json_object();
  170. json_object_set_new(root_j, "preGain", json_boolean(preGain));
  171. return root_j;
  172. }
  173. void dataFromJson(json_t* root_j) override {
  174. json_t* preGainJ = json_object_get(root_j, "preGain");
  175. if (preGainJ)
  176. preGain = json_boolean_value(preGainJ);
  177. }
  178. };
  179. struct ShelvesWidget : ModuleWidget {
  180. ShelvesWidget(Shelves* module) {
  181. setModule(module);
  182. setPanel(Svg::load(asset::plugin(pluginInstance, "res/Shelves.svg")));
  183. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  184. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  185. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  186. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  187. addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(41.582, 19.659)), module, Shelves::HS_FREQ_PARAM));
  188. addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(65.699, 19.659)), module, Shelves::HS_GAIN_PARAM));
  189. addParam(createParamCentered<Rogan1PSRed>(mm2px(Vec(41.582, 43.473)), module, Shelves::P1_FREQ_PARAM));
  190. addParam(createParamCentered<Rogan1PSRed>(mm2px(Vec(65.699, 43.473)), module, Shelves::P1_GAIN_PARAM));
  191. addParam(createParamCentered<Trimpot>(mm2px(Vec(20.632, 48.111)), module, Shelves::P1_Q_PARAM));
  192. addParam(createParamCentered<Rogan1PSGreen>(mm2px(Vec(41.582, 67.286)), module, Shelves::P2_FREQ_PARAM));
  193. addParam(createParamCentered<Rogan1PSGreen>(mm2px(Vec(65.699, 67.286)), module, Shelves::P2_GAIN_PARAM));
  194. addParam(createParamCentered<Trimpot>(mm2px(Vec(20.632, 63.447)), module, Shelves::P2_Q_PARAM));
  195. addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(41.582, 91.099)), module, Shelves::LS_FREQ_PARAM));
  196. addParam(createParamCentered<Rogan1PSWhite>(mm2px(Vec(65.699, 91.099)), module, Shelves::LS_GAIN_PARAM));
  197. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.983, 17.329)), module, Shelves::HS_FREQ_INPUT));
  198. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20.619, 17.329)), module, Shelves::HS_GAIN_INPUT));
  199. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.983, 33.824)), module, Shelves::P1_FREQ_INPUT));
  200. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20.619, 33.824)), module, Shelves::P1_GAIN_INPUT));
  201. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.983, 48.111)), module, Shelves::P1_Q_INPUT));
  202. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.983, 77.733)), module, Shelves::P2_FREQ_INPUT));
  203. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20.619, 77.733)), module, Shelves::P2_GAIN_INPUT));
  204. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.983, 63.447)), module, Shelves::P2_Q_INPUT));
  205. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.983, 94.228)), module, Shelves::LS_FREQ_INPUT));
  206. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20.619, 94.228)), module, Shelves::LS_GAIN_INPUT));
  207. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.983, 109.475)), module, Shelves::FREQ_INPUT));
  208. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(20.619, 109.475)), module, Shelves::GAIN_INPUT));
  209. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(41.565, 109.475)), module, Shelves::IN_INPUT));
  210. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(84.418, 17.329)), module, Shelves::P1_HP_OUTPUT));
  211. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(84.418, 32.725)), module, Shelves::P1_BP_OUTPUT));
  212. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(84.431, 48.111)), module, Shelves::P1_LP_OUTPUT));
  213. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(84.431, 63.447)), module, Shelves::P2_HP_OUTPUT));
  214. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(84.418, 78.832)), module, Shelves::P2_BP_OUTPUT));
  215. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(84.418, 94.228)), module, Shelves::P2_LP_OUTPUT));
  216. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(65.682, 109.475)), module, Shelves::OUT_OUTPUT));
  217. addChild(createLightCentered<MediumLight<RedLight>>(mm2px(Vec(53.629, 109.475)), module, Shelves::CLIP_LIGHT));
  218. }
  219. void appendContextMenu(Menu* menu) override {
  220. Shelves* module = dynamic_cast<Shelves*>(this->module);
  221. menu->addChild(new MenuSeparator);
  222. menu->addChild(createBoolPtrMenuItem("Pad input by -6dB", &module->preGain));
  223. }
  224. };
  225. Model* modelShelves = createModel<Shelves, ShelvesWidget>("Shelves");