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.

234 lines
8.6KB

  1. ///////////////////////////////////////////////////
  2. //
  3. // Mixer VCV Module
  4. //
  5. // Strum 2017
  6. //
  7. ///////////////////////////////////////////////////
  8. #include "mental.hpp"
  9. #include "dsp/digital.hpp"
  10. namespace rack_plugin_mental {
  11. ///////////////////////////////////////////////////
  12. struct MentalMixer : Module {
  13. enum ParamIds {
  14. MIX_PARAM,
  15. AUX_SEND_1_PARAM,
  16. AUX_SEND_2_PARAM,
  17. AUX_RETURN_1_PARAM,
  18. AUX_RETURN_2_PARAM,
  19. VOL_PARAM,
  20. PAN_PARAM = VOL_PARAM + 12,
  21. AUX_1_PARAM = PAN_PARAM + 12 ,
  22. AUX_2_PARAM = AUX_1_PARAM + 12,
  23. MUTE_PARAM = AUX_2_PARAM + 12,
  24. NUM_PARAMS = MUTE_PARAM + 12
  25. };
  26. enum InputIds {
  27. CH_INPUT,
  28. CH_VOL_INPUT = CH_INPUT + 12,
  29. CH_PAN_INPUT = CH_VOL_INPUT + 12,
  30. CH_MUTE_INPUT = CH_PAN_INPUT + 12,
  31. RETURN_1_L_INPUT = CH_MUTE_INPUT + 12,
  32. RETURN_1_R_INPUT,
  33. RETURN_2_L_INPUT,
  34. RETURN_2_R_INPUT,
  35. NUM_INPUTS
  36. };
  37. enum OutputIds {
  38. MIX_OUTPUT_L,
  39. MIX_OUTPUT_R,
  40. SEND_1_OUTPUT,
  41. SEND_2_OUTPUT,
  42. NUM_OUTPUTS
  43. };
  44. enum LightIds {
  45. MUTE_LIGHTS,
  46. NUM_LIGHTS = MUTE_LIGHTS + 12
  47. };
  48. SchmittTrigger mute_triggers[12];
  49. bool mute_states[12]= {1,1,1,1,1,1,1,1,1,1,1,1};
  50. float channel_ins[12];
  51. float pan_cv_ins[12];
  52. float pan_positions[12];
  53. float channel_sends_1[12];
  54. float channel_sends_2[12];
  55. float channel_outs_l[12];
  56. float channel_outs_r[12];
  57. float send_1_sum = 0.0;
  58. float send_2_sum = 0.0;
  59. float left_sum = 0.0;
  60. float right_sum = 0.0;
  61. MentalMixer() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  62. void step() override;
  63. json_t *toJson() override
  64. {
  65. json_t *rootJ = json_object();
  66. // mute states
  67. json_t *mute_statesJ = json_array();
  68. for (int i = 0; i < 12; i++)
  69. {
  70. json_t *mute_stateJ = json_integer((int) mute_states[i]);
  71. json_array_append_new(mute_statesJ, mute_stateJ);
  72. }
  73. json_object_set_new(rootJ, "mutes", mute_statesJ);
  74. return rootJ;
  75. }
  76. void fromJson(json_t *rootJ) override
  77. {
  78. // mute states
  79. json_t *mute_statesJ = json_object_get(rootJ, "mutes");
  80. if (mute_statesJ)
  81. {
  82. for (int i = 0; i < 12; i++)
  83. {
  84. json_t *mute_stateJ = json_array_get(mute_statesJ, i);
  85. if (mute_stateJ)
  86. mute_states[i] = !!json_integer_value(mute_stateJ);
  87. }
  88. }
  89. }
  90. };
  91. ///////////////////////////////////////////////////////////////////
  92. void MentalMixer::step() {
  93. //clampf(inputs[CH1_CV_INPUT].normalize(10.0) / 10.0, 0.0, 1.0);
  94. send_1_sum = 0.0;
  95. send_2_sum = 0.0;
  96. left_sum = 0.0;
  97. right_sum = 0.0;
  98. for (int i = 0 ; i < 12; i++)
  99. {
  100. if (mute_triggers[i].process(params[MUTE_PARAM + i].value))
  101. {
  102. mute_states[i] = !mute_states[i];
  103. }
  104. lights[MUTE_LIGHTS + i ].value = mute_states[i] ? 1.0 : 0.0;
  105. }
  106. for (int i = 0 ; i < 12 ; i++)
  107. {
  108. channel_ins[i] = inputs[CH_INPUT + i].value * params[VOL_PARAM + i].value * clamp(inputs[CH_VOL_INPUT + i].normalize(10.0f) / 10.0f, 0.0f, 1.0f);
  109. if (!mute_states[i] || inputs[CH_MUTE_INPUT + i].value > 0.0 )
  110. {
  111. channel_ins[i] = 0.0;
  112. lights[MUTE_LIGHTS + i ].value = 0.0;
  113. }
  114. channel_sends_1[i] = channel_ins[i] * params[AUX_1_PARAM + i].value * clamp(inputs[CH_VOL_INPUT + i].normalize(10.0f) / 10.0f, 0.0f, 1.0f);
  115. channel_sends_2[i] = channel_ins[i] * params[AUX_2_PARAM + i].value * clamp(inputs[CH_VOL_INPUT + i].normalize(10.0f) / 10.0f, 0.0f, 1.0f);
  116. pan_cv_ins[i] = inputs[CH_PAN_INPUT + i].value/5;
  117. pan_positions[i] = pan_cv_ins[i] + params[PAN_PARAM+i].value;
  118. if (pan_positions[i] < 0) pan_positions[i] = 0;
  119. if (pan_positions[i] > 1) pan_positions[i] = 1;
  120. channel_outs_l[i]= channel_ins[i] * (1-pan_positions[i])* 2;
  121. channel_outs_r[i]= channel_ins[i] * pan_positions[i] * 2;
  122. send_1_sum += channel_sends_1[i];
  123. send_2_sum += channel_sends_2[i];
  124. left_sum += channel_outs_l[i];
  125. right_sum += channel_outs_r[i];
  126. }
  127. // get returns
  128. float return_1_l = inputs[RETURN_1_L_INPUT].value * params[AUX_RETURN_1_PARAM].value;
  129. float return_1_r = inputs[RETURN_1_R_INPUT].value * params[AUX_RETURN_1_PARAM].value;
  130. float return_2_l = inputs[RETURN_2_L_INPUT].value * params[AUX_RETURN_2_PARAM].value;
  131. float return_2_r = inputs[RETURN_2_R_INPUT].value * params[AUX_RETURN_2_PARAM].value;
  132. float mix_l = (left_sum + return_1_l + return_2_l) * params[MIX_PARAM].value;
  133. float mix_r = (right_sum + return_1_r + return_2_r) * params[MIX_PARAM].value;
  134. float send_1_mix = (send_1_sum) * params[AUX_SEND_1_PARAM].value;
  135. float send_2_mix = (send_2_sum) * params[AUX_SEND_2_PARAM].value;
  136. outputs[MIX_OUTPUT_L].value = mix_l;
  137. outputs[MIX_OUTPUT_R].value = mix_r;
  138. outputs[SEND_1_OUTPUT].value = send_1_mix;
  139. outputs[SEND_2_OUTPUT].value = send_2_mix;
  140. }
  141. /////////////////////////////////////////////////////////////////////////////
  142. struct MentalMixerWidget : ModuleWidget {
  143. MentalMixerWidget(MentalMixer *module);
  144. };
  145. MentalMixerWidget::MentalMixerWidget(MentalMixer *module) : ModuleWidget(module)
  146. {
  147. setPanel(SVG::load(assetPlugin(plugin, "res/Mixer.svg")));
  148. int port_col = 8;
  149. int pots_col = port_col + 3;
  150. int top_row = 117;
  151. int row_spacing = 28;
  152. int column_spacing = 29;
  153. // master volume
  154. addParam(ParamWidget::create<LrgKnob>(Vec(port_col + column_spacing * 8, 32), module, MentalMixer::MIX_PARAM, 0.0, 1.0, 0.5));
  155. addOutput(Port::create<OutPort>(Vec(port_col + column_spacing * 10, 30), Port::OUTPUT, module, MentalMixer::MIX_OUTPUT_L));
  156. addOutput(Port::create<OutPort>(Vec(port_col + column_spacing * 10, 58), Port::OUTPUT, module, MentalMixer::MIX_OUTPUT_R));
  157. // sends
  158. addOutput(Port::create<OutPort>(Vec(port_col + column_spacing , 30), Port::OUTPUT, module, MentalMixer::SEND_1_OUTPUT));
  159. addParam(ParamWidget::create<SmlKnob>(Vec(pots_col + column_spacing , 58), module, MentalMixer::AUX_SEND_1_PARAM, 0.0, 1.0, 0.0));
  160. addOutput(Port::create<OutPort>(Vec(port_col + column_spacing * 4, 30), Port::OUTPUT, module, MentalMixer::SEND_2_OUTPUT));
  161. addParam(ParamWidget::create<SmlKnob>(Vec(pots_col + column_spacing * 4, 58), module, MentalMixer::AUX_SEND_2_PARAM, 0.0, 1.0, 0.0));
  162. // returns
  163. addInput(Port::create<InPort>(Vec(port_col + column_spacing * 2, 30), Port::INPUT, module, MentalMixer::RETURN_1_L_INPUT));
  164. addInput(Port::create<InPort>(Vec(port_col + column_spacing * 2, 58), Port::INPUT, module, MentalMixer::RETURN_1_R_INPUT));
  165. addParam(ParamWidget::create<SmlKnob>(Vec(pots_col + column_spacing * 2, 86), module, MentalMixer::AUX_RETURN_1_PARAM, 0.0, 1.0, 0.0));
  166. addInput(Port::create<InPort>(Vec(port_col + column_spacing * 5, 30), Port::INPUT, module, MentalMixer::RETURN_2_L_INPUT));
  167. addInput(Port::create<InPort>(Vec(port_col + column_spacing * 5, 58), Port::INPUT, module, MentalMixer::RETURN_2_R_INPUT));
  168. addParam(ParamWidget::create<SmlKnob>(Vec(pots_col + column_spacing * 5, 86), module, MentalMixer::AUX_RETURN_2_PARAM, 0.0, 1.0, 0.0));
  169. // channel strips
  170. for (int i = 0 ; i < 12 ; i++)
  171. {
  172. addInput(Port::create<InPort>(Vec(port_col+column_spacing*i, top_row), Port::INPUT, module, MentalMixer::CH_INPUT + i));
  173. // volume
  174. addParam(ParamWidget::create<SmlKnob>(Vec(pots_col+column_spacing*i, top_row + row_spacing + 6), module, MentalMixer::VOL_PARAM + i, 0.0, 1.0, 0.0));
  175. addInput(Port::create<CVInPort>(Vec(port_col+column_spacing*i, top_row + row_spacing * 2), Port::INPUT, module, MentalMixer::CH_VOL_INPUT + i));
  176. // panning
  177. addParam(ParamWidget::create<SmlKnob>(Vec(pots_col+column_spacing*i, top_row + row_spacing * 3 + 6), module, MentalMixer::PAN_PARAM + i, 0.0, 1.0, 0.5));
  178. addInput(Port::create<CVInPort>(Vec(port_col+column_spacing*i, top_row + row_spacing * 4), Port::INPUT, module, MentalMixer::CH_PAN_INPUT + i));
  179. // sends
  180. addParam(ParamWidget::create<SmlKnob>(Vec(pots_col+column_spacing*i, top_row + row_spacing * 5 + 6), module, MentalMixer::AUX_1_PARAM + i, 0.0, 1.0, 0.0));
  181. addParam(ParamWidget::create<SmlKnob>(Vec(pots_col+column_spacing*i, top_row + row_spacing * 6 + 6), module, MentalMixer::AUX_2_PARAM + i, 0.0, 1.0, 0.0));
  182. // mutes
  183. addParam(ParamWidget::create<LEDButton>(Vec(pots_col+column_spacing*i,top_row + row_spacing * 7 + 6), module, MentalMixer::MUTE_PARAM + i, 0.0, 1.0, 0.0));
  184. addChild(ModuleLightWidget::create<MedLight<BlueLED>>(Vec(pots_col+column_spacing*i + 4.25, top_row + row_spacing * 7 + 10.25), module, MentalMixer::MUTE_LIGHTS + i));
  185. addInput(Port::create<GateInPort>(Vec(port_col+column_spacing*i, top_row + row_spacing * 8), Port::INPUT, module, MentalMixer::CH_MUTE_INPUT + i));
  186. }
  187. }
  188. } // namespace rack_plugin_mental
  189. using namespace rack_plugin_mental;
  190. RACK_PLUGIN_MODEL_INIT(mental, MentalMixer) {
  191. Model *modelMentalMixer = Model::create<MentalMixer, MentalMixerWidget>("mental", "MentalMixer", "Mixer", MIXER_TAG);
  192. return modelMentalMixer;
  193. }