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
6.6KB

  1. #include "HetrickCV.hpp"
  2. namespace rack_plugin_HetrickCV {
  3. #ifdef USE_VST2
  4. #define plugin "HetrickCV"
  5. #endif // USE_VST2
  6. struct GateJunction : Module
  7. {
  8. enum ParamIds
  9. {
  10. MUTE1_PARAM,
  11. MUTE2_PARAM,
  12. MUTE3_PARAM,
  13. MUTE4_PARAM,
  14. MUTE5_PARAM,
  15. MUTE6_PARAM,
  16. MUTE7_PARAM,
  17. MUTE8_PARAM,
  18. INV1_PARAM,
  19. INV2_PARAM,
  20. INV3_PARAM,
  21. INV4_PARAM,
  22. INV5_PARAM,
  23. INV6_PARAM,
  24. INV7_PARAM,
  25. INV8_PARAM,
  26. NUM_PARAMS
  27. };
  28. enum InputIds
  29. {
  30. IN1_INPUT,
  31. IN2_INPUT,
  32. IN3_INPUT,
  33. IN4_INPUT,
  34. IN5_INPUT,
  35. IN6_INPUT,
  36. IN7_INPUT,
  37. IN8_INPUT,
  38. NUM_INPUTS
  39. };
  40. enum OutputIds
  41. {
  42. OUT1_OUTPUT,
  43. OUT2_OUTPUT,
  44. OUT3_OUTPUT,
  45. OUT4_OUTPUT,
  46. OUT5_OUTPUT,
  47. OUT6_OUTPUT,
  48. OUT7_OUTPUT,
  49. OUT8_OUTPUT,
  50. NUM_OUTPUTS
  51. };
  52. enum LightIds
  53. {
  54. MUTE1_LIGHT,
  55. MUTE2_LIGHT,
  56. MUTE3_LIGHT,
  57. MUTE4_LIGHT,
  58. MUTE5_LIGHT,
  59. MUTE6_LIGHT,
  60. MUTE7_LIGHT,
  61. MUTE8_LIGHT,
  62. INV1_LIGHT,
  63. INV2_LIGHT,
  64. INV3_LIGHT,
  65. INV4_LIGHT,
  66. INV5_LIGHT,
  67. INV6_LIGHT,
  68. INV7_LIGHT,
  69. INV8_LIGHT,
  70. OUT1_LIGHT,
  71. OUT2_LIGHT,
  72. OUT3_LIGHT,
  73. OUT4_LIGHT,
  74. OUT5_LIGHT,
  75. OUT6_LIGHT,
  76. OUT7_LIGHT,
  77. OUT8_LIGHT,
  78. NUM_LIGHTS
  79. };
  80. float ins[8] = {};
  81. float outs[8] = {};
  82. bool muteState[8] = {};
  83. SchmittTrigger muteTrigger[8];
  84. bool invState[8] = {};
  85. SchmittTrigger invTrigger[8];
  86. GateJunction() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS)
  87. {
  88. reset();
  89. }
  90. void step() override;
  91. void reset() override
  92. {
  93. for (int i = 0; i < 8; i++)
  94. {
  95. muteState[i] = false;
  96. invState[i] = false;
  97. }
  98. }
  99. void randomize() override
  100. {
  101. for (int i = 0; i < 8; i++)
  102. {
  103. muteState[i] = (randomf() < 0.5);
  104. invState[i] = (randomf() < 0.5);
  105. }
  106. }
  107. json_t *toJson() override
  108. {
  109. json_t *rootJ = json_object();
  110. // states
  111. json_t *muteStatesJ = json_array();
  112. json_t *invStatesJ = json_array();
  113. for (int i = 0; i < 8; i++)
  114. {
  115. json_t *muteStateJ = json_boolean(muteState[i]);
  116. json_array_append_new(muteStatesJ, muteStateJ);
  117. json_t *invStateJ = json_boolean(invState[i]);
  118. json_array_append_new(invStatesJ, invStateJ);
  119. }
  120. json_object_set_new(rootJ, "muteStates", muteStatesJ);
  121. json_object_set_new(rootJ, "invStates", invStatesJ);
  122. return rootJ;
  123. }
  124. void fromJson(json_t *rootJ) override
  125. {
  126. // states
  127. json_t *muteStatesJ = json_object_get(rootJ, "muteStates");
  128. json_t *invStatesJ = json_object_get(rootJ, "invStates");
  129. if (muteStatesJ)
  130. {
  131. for (int i = 0; i < 8; i++)
  132. {
  133. json_t *stateJ = json_array_get(muteStatesJ, i);
  134. if (stateJ)
  135. muteState[i] = json_boolean_value(stateJ);
  136. }
  137. }
  138. if (invStatesJ)
  139. {
  140. for (int i = 0; i < 8; i++)
  141. {
  142. json_t *stateJ = json_array_get(invStatesJ, i);
  143. if (stateJ)
  144. invState[i] = json_boolean_value(stateJ);
  145. }
  146. }
  147. }
  148. // For more advanced Module features, read Rack's engine.hpp header file
  149. // - toJson, fromJson: serialization of internal data
  150. // - onSampleRateChange: event triggered by a change of sample rate
  151. // - reset, randomize: implements special behavior when user clicks these from the context menu
  152. };
  153. void GateJunction::step()
  154. {
  155. ins[0] = (inputs[IN1_INPUT].value >= 1.0f) ? 5.0f : 0.0f;
  156. for(int i = 1; i < 8; i++)
  157. {
  158. const int thisInput = IN1_INPUT + i;
  159. if(inputs[thisInput].active)
  160. {
  161. ins[i] = (inputs[thisInput].value >= 1.0f) ? 5.0f : 0.0f;
  162. }
  163. else
  164. {
  165. ins[i] = ins[thisInput - 1];
  166. }
  167. }
  168. for(int i = 0; i < 8; i++)
  169. {
  170. if (muteTrigger[i].process(params[MUTE1_PARAM + i].value)) muteState[i] ^= true;
  171. if (invTrigger[i].process(params[INV1_PARAM + i].value)) invState[i] ^= true;
  172. if(invState[i]) ins[i] = 5.0f - ins[i];
  173. if(muteState[i]) ins[i] = 0.0f;
  174. outputs[OUT1_OUTPUT + i].value = ins[i];
  175. lights[OUT1_LIGHT + i].value = ins[i];
  176. lights[MUTE1_LIGHT + i].setBrightness(muteState[i] ? 0.9 : 0.0);
  177. lights[INV1_LIGHT + i].setBrightness(invState[i] ? 0.9 : 0.0);
  178. }
  179. }
  180. template <typename BASE>
  181. struct MuteLight : BASE {
  182. MuteLight() {
  183. this->box.size = mm2px(Vec(6.0, 6.0));
  184. }
  185. };
  186. struct GateJunctionWidget : ModuleWidget { GateJunctionWidget(GateJunction *module); };
  187. GateJunctionWidget::GateJunctionWidget(GateJunction *module) : ModuleWidget(module)
  188. {
  189. box.size = Vec(12 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
  190. {
  191. auto *panel = new SVGPanel();
  192. panel->box.size = box.size;
  193. panel->setBackground(SVG::load(assetPlugin(plugin, "res/GateJunction.svg")));
  194. addChild(panel);
  195. }
  196. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  197. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0)));
  198. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  199. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365)));
  200. //////PARAMS//////
  201. const int inXPos = 10;
  202. const int outXPos = 145;
  203. //const int inLightX = 50;
  204. const int outLightX = 120;
  205. for(int i = 0; i < 8; i++)
  206. {
  207. const int yPos = 50 + (40 * i);
  208. const int lightY = 59 + (40 * i);
  209. //////INPUTS//////
  210. addInput(Port::create<PJ301MPort>(Vec(inXPos, yPos), Port::INPUT, module, GateJunction::IN1_INPUT + i));
  211. //////OUTPUTS//////
  212. addOutput(Port::create<PJ301MPort>(Vec(outXPos, yPos), Port::OUTPUT, module, GateJunction::OUT1_OUTPUT + i));
  213. //////BLINKENLIGHTS//////
  214. addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(outLightX, lightY), module, GateJunction::OUT1_LIGHT + i));
  215. addParam(ParamWidget::create<LEDBezel>(Vec(50, 1 + yPos), module, GateJunction::MUTE1_PARAM + i, 0.0, 1.0, 0.0));
  216. addParam(ParamWidget::create<LEDBezel>(Vec(85, 1 + yPos), module, GateJunction::INV1_PARAM + i, 0.0, 1.0, 0.0));
  217. addChild(ModuleLightWidget::create<MuteLight<RedLight>>(Vec(52.2, 3 + yPos), module, GateJunction::MUTE1_LIGHT + i));
  218. addChild(ModuleLightWidget::create<MuteLight<BlueLight>>(Vec(87.2, 3 + yPos), module, GateJunction::INV1_LIGHT + i));
  219. }
  220. }
  221. } // namespace rack_plugin_HetrickCV
  222. using namespace rack_plugin_HetrickCV;
  223. RACK_PLUGIN_MODEL_INIT(HetrickCV, GateJunction) {
  224. Model *modelGateJunction = Model::create<GateJunction, GateJunctionWidget>("HetrickCV", "Gate Junction", "Gate Junction", SWITCH_TAG, LOGIC_TAG);
  225. return modelGateJunction;
  226. }