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.

396 lines
13KB

  1. ///////////////////////////////////////////////////
  2. // dBiz revisited version of
  3. //
  4. // Chord Creator VCV Module
  5. //
  6. // Strum 2017
  7. //
  8. ///////////////////////////////////////////////////
  9. #include "dBiz.hpp"
  10. namespace rack_plugin_dBiz {
  11. /////////////////////////////////////////////////
  12. struct Chord : Module {
  13. enum ParamIds {
  14. OFFSET_PARAM,
  15. INVERSION_PARAM,
  16. VOICING_PARAM,
  17. OFFSET_AMT_PARAM,
  18. INVERSION_AMT_PARAM,
  19. VOICING_AMT_PARAM,
  20. FLAT_3RD_PARAM,
  21. FLAT_5TH_PARAM,
  22. FLAT_7TH_PARAM,
  23. SUS_2_PARAM,
  24. SUS_4_PARAM,
  25. SIX_FOR_5_PARAM,
  26. ONE_FOR_7_PARAM,
  27. FLAT_9_PARAM,
  28. SHARP_9_PARAM,
  29. SIX_FOR_7_PARAM,
  30. SHARP_5_PARAM,
  31. NUM_PARAMS
  32. };
  33. enum InputIds {
  34. INPUT,
  35. OFFSET_CV_INPUT,
  36. INVERSION_CV_INPUT,
  37. VOICING_CV_INPUT,
  38. FLAT_3RD_INPUT,
  39. FLAT_5TH_INPUT,
  40. FLAT_7TH_INPUT,
  41. SUS_2_INPUT,
  42. SUS_4_INPUT,
  43. SIX_FOR_5_INPUT,
  44. ONE_FOR_7_INPUT,
  45. FLAT_9_INPUT,
  46. SHARP_9_INPUT,
  47. SIX_FOR_7_INPUT,
  48. SHARP_5_INPUT,
  49. NUM_INPUTS
  50. };
  51. enum OutputIds {
  52. OUTPUT_1,
  53. OUTPUT_2,
  54. OUTPUT_3,
  55. OUTPUT_4,
  56. OUTPUT_ROOT,
  57. OUTPUT_THIRD,
  58. OUTPUT_FIFTH,
  59. OUTPUT_SEVENTH,
  60. NUM_OUTPUTS
  61. };
  62. enum LighIds {
  63. FLAT_3RD_LIGHT,
  64. FLAT_5TH_LIGHT,
  65. FLAT_7TH_LIGHT,
  66. SUS_2_LIGHT,
  67. SUS_4_LIGHT,
  68. SIX_FOR_5_LIGHT,
  69. ONE_FOR_7_LIGHT,
  70. FLAT_9_LIGHT,
  71. SHARP_9_LIGHT,
  72. SIX_FOR_7_LIGHT,
  73. SHARP_5_LIGHT,
  74. OUT_1_LIGHT,
  75. OUT_2_LIGHT,
  76. OUT_3_LIGHT,
  77. OUT_4_LIGHT,
  78. NUM_LIGHTS
  79. };
  80. Chord() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  81. void step() override ;
  82. };
  83. /////////////////////////////////////////////////////
  84. void Chord::step() {
  85. float in = inputs[INPUT].value;
  86. int octave = round(in);
  87. float offset_raw = (params[OFFSET_PARAM].value) * 12 - 6 + (inputs[OFFSET_CV_INPUT].value*params[OFFSET_AMT_PARAM].value) / 1.5;
  88. float pitch_offset = round(offset_raw) / 12;
  89. float root = in - 1.0*octave + pitch_offset;
  90. float root_or_2nd = root;
  91. float inversion_raw = (params[INVERSION_PARAM].value) * 4 - 1 + ((inputs[INVERSION_CV_INPUT].value*params[INVERSION_AMT_PARAM].value) / 3);
  92. int inversion = round(inversion_raw);
  93. if (inversion > 2) inversion = 2;
  94. if (inversion < -1) inversion = -1;
  95. float voicing_raw = (params[VOICING_PARAM].value) * 5 - 2 + ((inputs[VOICING_CV_INPUT].value*params[VOICING_AMT_PARAM].value) / 3);
  96. int voicing = round(voicing_raw);
  97. if (voicing > 2) voicing = 2;
  98. if (voicing < -2) voicing = -2;
  99. float voice_1 = 0.0;
  100. float voice_2 = 0.0;
  101. float voice_3 = 0.0;
  102. float voice_4 = 0.0;
  103. int third = 4;
  104. int fifth = 7;
  105. int seventh = 11;
  106. if (inputs[FLAT_3RD_INPUT].value+params[FLAT_3RD_PARAM].value > 0.0)
  107. {
  108. third = 3;
  109. lights[FLAT_3RD_LIGHT].value=1.0;
  110. }
  111. else lights[FLAT_3RD_LIGHT].value=0.0;
  112. if (inputs[FLAT_5TH_INPUT].value+params[FLAT_5TH_PARAM].value > 0.0)
  113. {
  114. fifth = 6;
  115. lights[FLAT_5TH_LIGHT].value=1.0;
  116. }
  117. else lights[FLAT_5TH_LIGHT].value=0.0;
  118. if (inputs[SHARP_5_INPUT].value+params[SHARP_5_PARAM].value > 0.0)
  119. {
  120. fifth = 8;
  121. lights[SHARP_5_LIGHT].value=1.0;
  122. }
  123. else lights[SHARP_5_LIGHT].value=0.0;
  124. if (inputs[FLAT_7TH_INPUT].value+params[FLAT_7TH_PARAM].value > 0.0)
  125. {
  126. seventh = 10;
  127. lights[FLAT_7TH_LIGHT].value=1.0;
  128. }
  129. else lights[FLAT_7TH_LIGHT].value=0.0;
  130. if (inputs[SUS_2_INPUT].value+params[SUS_2_PARAM].value > 0.0)
  131. {
  132. root_or_2nd = root + (2 * (1.0/12.0));
  133. lights[SUS_2_LIGHT].value=1.0;
  134. }
  135. else lights[SUS_2_LIGHT].value=0.0;
  136. if (inputs[SUS_4_INPUT].value+params[SUS_4_PARAM].value > 0.0)
  137. {
  138. third = 5;
  139. lights[SUS_4_LIGHT].value=1.0;
  140. }
  141. else lights[SUS_4_LIGHT].value=0.0;
  142. if (inputs[SIX_FOR_5_INPUT].value+params[SIX_FOR_5_PARAM].value > 0.0)
  143. {
  144. fifth = 9;
  145. lights[SIX_FOR_5_LIGHT].value=1.0;
  146. }
  147. else lights[SIX_FOR_5_LIGHT].value=0.0;
  148. if (inputs[SIX_FOR_7_INPUT].value+params[SIX_FOR_7_PARAM].value > 0.0)
  149. {
  150. seventh = 9;
  151. lights[SIX_FOR_7_LIGHT].value=1.0;
  152. }
  153. else lights[SIX_FOR_7_LIGHT].value=0.0;
  154. if (inputs[FLAT_9_INPUT].value+params[FLAT_9_PARAM].value > 0.0)
  155. {
  156. root_or_2nd = root + 1.0/12.0;
  157. lights[FLAT_9_LIGHT].value=1.0;
  158. }
  159. else lights[FLAT_9_LIGHT].value=0.0;
  160. if (inputs[SHARP_9_INPUT].value+params[SHARP_9_PARAM].value > 0.0)
  161. {
  162. root_or_2nd = root + (3 * (1.0/12.0));
  163. lights[SHARP_9_LIGHT].value=1.0;
  164. }
  165. else lights[SHARP_9_LIGHT].value=0.0;
  166. if (inputs[ONE_FOR_7_INPUT].value+params[ONE_FOR_7_PARAM].value > 0.0)
  167. {
  168. seventh = 12;
  169. lights[ONE_FOR_7_LIGHT].value=1.0;
  170. }
  171. else lights[ONE_FOR_7_LIGHT].value=0.0;
  172. outputs[OUTPUT_ROOT].value = root;
  173. outputs[OUTPUT_THIRD].value = root + third * (1.0/12.0);
  174. outputs[OUTPUT_FIFTH].value = root + fifth * (1.0/12.0);
  175. outputs[OUTPUT_SEVENTH].value = root + seventh * (1.0/12.0);
  176. if (inversion == -1 )
  177. {
  178. voice_1 = root_or_2nd;
  179. voice_2 = root + third * (1.0/12.0);
  180. voice_3 = root + fifth * (1.0/12.0);
  181. voice_4 = root + seventh * (1.0/12.0);
  182. }
  183. if (inversion == 0 )
  184. {
  185. voice_1 = root + third * (1.0/12.0);
  186. voice_2 = root + fifth * (1.0/12.0);
  187. voice_3 = root + seventh * (1.0/12.0);
  188. voice_4 = root_or_2nd + 1.0;
  189. }
  190. if (inversion == 1)
  191. {
  192. voice_1 = root + fifth * (1.0/12.0);
  193. voice_2 = root + seventh * (1.0/12.0);
  194. voice_3 = root_or_2nd + 1.0;
  195. voice_4 = root + 1.0 + third * (1.0/12.0);
  196. }
  197. if (inversion == 2 )
  198. {
  199. voice_1 = root + seventh * (1.0/12.0);
  200. voice_2 = root_or_2nd + 1.0;
  201. voice_3 = root + 1.0 + third * (1.0/12.0);
  202. voice_4 = root + 1.0 + fifth * (1.0/12.0);
  203. }
  204. if (voicing == -1) voice_2 -= 1.0;
  205. if (voicing == -0) voice_3 -= 1.0;
  206. if (voicing == 1)
  207. {
  208. voice_2 -= 1.0;
  209. voice_4 -= 1.0;
  210. }
  211. if (voicing == 2)
  212. {
  213. voice_2 += 1.0;
  214. voice_4 += 1.0;
  215. }
  216. outputs[OUTPUT_1].value = voice_1;
  217. outputs[OUTPUT_2].value = voice_2;
  218. outputs[OUTPUT_3].value = voice_3;
  219. outputs[OUTPUT_4].value = voice_4;
  220. }
  221. template <typename BASE>
  222. struct ChordLight : BASE
  223. {
  224. ChordLight()
  225. {
  226. this->box.size = mm2px(Vec(5, 5));
  227. }
  228. };
  229. //////////////////////////////////////////////////////////////////
  230. struct ChordWidget : ModuleWidget
  231. {
  232. ChordWidget(Chord *module) : ModuleWidget(module)
  233. {
  234. box.size = Vec(15*9, 380);
  235. {
  236. SVGPanel *panel = new SVGPanel();
  237. //Panel *panel = new LightPanel();
  238. panel->box.size = box.size;
  239. //panel->backgroundImage = Image::load(assetPlugin(plugin, "res/Chord.png"));
  240. panel->setBackground(SVG::load(assetPlugin(plugin,"res/Chord.svg")));
  241. addChild(panel);
  242. }
  243. //
  244. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  245. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  246. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  247. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  248. //
  249. int jacks = 27;
  250. int pot=22;
  251. int off =2.5;
  252. int space = 40;
  253. addInput(Port::create<PJ301MCPort>(Vec(off,60+jacks*1), Port::INPUT, module, Chord::OFFSET_CV_INPUT));
  254. addInput(Port::create<PJ301MCPort>(Vec(off,60+jacks*2), Port::INPUT, module, Chord::INVERSION_CV_INPUT));
  255. addInput(Port::create<PJ301MCPort>(Vec(off,60+jacks*3), Port::INPUT, module, Chord::VOICING_CV_INPUT));
  256. addParam(ParamWidget::create<Trimpot>(Vec(off*2,pot*1), module, Chord::OFFSET_AMT_PARAM, 0.0, 1.0, 0.0));
  257. addParam(ParamWidget::create<Trimpot>(Vec(off*2,pot*2), module, Chord::INVERSION_AMT_PARAM, 0.0, 1.0, 0.0));
  258. addParam(ParamWidget::create<Trimpot>(Vec(off*2,pot*3), module, Chord::VOICING_AMT_PARAM, 0.0, 1.0, 0.0));
  259. addParam(ParamWidget::create<FlatG>(Vec(off + 30 ,space*1-15), module, Chord::OFFSET_PARAM, 0.0, 1.0, 0.5));
  260. addParam(ParamWidget::create<FlatA>(Vec(off + 30 ,space*2-15), module, Chord::INVERSION_PARAM, 0.0, 1.0, 0.0));
  261. addParam(ParamWidget::create<FlatR>(Vec(off + 30 ,space*3-15), module, Chord::VOICING_PARAM, 0.0, 1.0, 0.0));
  262. //
  263. int right = 95 ;
  264. int left = 30;
  265. addInput(Port::create<PJ301MIPort>(Vec(left, 180), Port::INPUT, module, Chord::FLAT_3RD_INPUT));
  266. addInput(Port::create<PJ301MIPort>(Vec(left, 180+jacks*1), Port::INPUT, module, Chord::FLAT_5TH_INPUT));
  267. addInput(Port::create<PJ301MIPort>(Vec(left, 180+jacks*2), Port::INPUT, module, Chord::FLAT_7TH_INPUT));
  268. addInput(Port::create<PJ301MIPort>(Vec(left, 180+jacks*3), Port::INPUT, module, Chord::SIX_FOR_7_INPUT));
  269. addInput(Port::create<PJ301MIPort>(Vec(left, 180+jacks*4), Port::INPUT, module, Chord::SHARP_5_INPUT));
  270. //
  271. addInput(Port::create<PJ301MIPort>(Vec(right, 180), Port::INPUT, module, Chord::SUS_2_INPUT));
  272. addInput(Port::create<PJ301MIPort>(Vec(right, 180+jacks*1), Port::INPUT, module, Chord::SUS_4_INPUT));
  273. addInput(Port::create<PJ301MIPort>(Vec(right, 180+jacks*2), Port::INPUT, module, Chord::SIX_FOR_5_INPUT));
  274. addInput(Port::create<PJ301MIPort>(Vec(right, 180+jacks*3), Port::INPUT, module, Chord::ONE_FOR_7_INPUT));
  275. addInput(Port::create<PJ301MIPort>(Vec(right, 180+jacks*4), Port::INPUT, module, Chord::FLAT_9_INPUT));
  276. addInput(Port::create<PJ301MIPort>(Vec(right, 180+jacks*5), Port::INPUT, module, Chord::SHARP_9_INPUT));
  277. //
  278. addParam(ParamWidget::create<LEDB>(Vec(-22 + left, 3+ 180), module, Chord::FLAT_3RD_PARAM,0.0,1.0,0.0));
  279. addParam(ParamWidget::create<LEDB>(Vec(-22 + left, 3+ 180+jacks*1), module, Chord::FLAT_5TH_PARAM,0.0,1.0,0.0));
  280. addParam(ParamWidget::create<LEDB>(Vec(-22 + left, 3+ 180+jacks*2), module, Chord::FLAT_7TH_PARAM,0.0,1.0,0.0));
  281. addParam(ParamWidget::create<LEDB>(Vec(-22 + left, 3+ 180+jacks*3), module, Chord::SIX_FOR_7_PARAM,0.0,1.0,0.0));
  282. addParam(ParamWidget::create<LEDB>(Vec(-22 + left, 3+ 180+jacks*4), module, Chord::SHARP_5_PARAM,0.0,1.0,0.0));
  283. addParam(ParamWidget::create<LEDB>(Vec(-22 + right,3+ 180), module, Chord::SUS_2_PARAM,0.0,1.0,0.0));
  284. addParam(ParamWidget::create<LEDB>(Vec(-22 + right,3+ 180+jacks*1), module, Chord::SUS_4_PARAM,0.0,1.0,0.0));
  285. addParam(ParamWidget::create<LEDB>(Vec(-22 + right,3+ 180+jacks*2), module, Chord::SIX_FOR_5_PARAM,0.0,1.0,0.0));
  286. addParam(ParamWidget::create<LEDB>(Vec(-22 + right,3+ 180+jacks*3), module, Chord::ONE_FOR_7_PARAM,0.0,1.0,0.0));
  287. addParam(ParamWidget::create<LEDB>(Vec(-22 + right,3+ 180+jacks*4), module, Chord::FLAT_9_PARAM,0.0,1.0,0.0));
  288. addParam(ParamWidget::create<LEDB>(Vec(-22 + right,3+ 180+jacks*5), module, Chord::SHARP_9_PARAM,0.0,1.0,0.0));
  289. //
  290. addChild(GrayModuleLightWidget::create<ChordLight<OrangeLight>>(Vec(left-19.5,185.5), module, Chord::FLAT_3RD_LIGHT));
  291. addChild(GrayModuleLightWidget::create<ChordLight<OrangeLight>>(Vec(left-19.5,185.5+jacks*1), module, Chord::FLAT_5TH_LIGHT));
  292. addChild(GrayModuleLightWidget::create<ChordLight<OrangeLight>>(Vec(left-19.5,185.5+jacks*2), module, Chord::FLAT_7TH_LIGHT));
  293. addChild(GrayModuleLightWidget::create<ChordLight<OrangeLight>>(Vec(left-19.5,185.5+jacks*3), module, Chord::SIX_FOR_7_LIGHT));
  294. addChild(GrayModuleLightWidget::create<ChordLight<OrangeLight>>(Vec(left-19.5,185.5+jacks*4), module, Chord::SHARP_5_LIGHT));
  295. addChild(GrayModuleLightWidget::create<ChordLight<OrangeLight>>(Vec(right-19.5,185.5), module, Chord::SUS_2_LIGHT));
  296. addChild(GrayModuleLightWidget::create<ChordLight<OrangeLight>>(Vec(right-19.5,185.5+jacks*1), module, Chord::SUS_4_LIGHT));
  297. addChild(GrayModuleLightWidget::create<ChordLight<OrangeLight>>(Vec(right-19.5,185.5+jacks*2), module, Chord::SIX_FOR_5_LIGHT));
  298. addChild(GrayModuleLightWidget::create<ChordLight<OrangeLight>>(Vec(right-19.5,185.5+jacks*3), module, Chord::ONE_FOR_7_LIGHT));
  299. addChild(GrayModuleLightWidget::create<ChordLight<OrangeLight>>(Vec(right-19.5,185.5+jacks*4), module, Chord::FLAT_9_LIGHT));
  300. addChild(GrayModuleLightWidget::create<ChordLight<OrangeLight>>(Vec(right-19.5,185.5+jacks*5), module, Chord::SHARP_9_LIGHT));
  301. //
  302. //
  303. addOutput(Port::create<PJ301MOPort>(Vec(70,jacks*1), Port::OUTPUT, module, Chord::OUTPUT_ROOT));
  304. addOutput(Port::create<PJ301MOPort>(Vec(70,jacks*2), Port::OUTPUT, module, Chord::OUTPUT_THIRD));
  305. addOutput(Port::create<PJ301MOPort>(Vec(70,jacks*3), Port::OUTPUT, module, Chord::OUTPUT_FIFTH));
  306. addOutput(Port::create<PJ301MOPort>(Vec(70,jacks*4), Port::OUTPUT, module, Chord::OUTPUT_SEVENTH));
  307. addOutput(Port::create<PJ301MOPort>(Vec(97,jacks*1 ), Port::OUTPUT, module, Chord::OUTPUT_1));
  308. addOutput(Port::create<PJ301MOPort>(Vec(97,jacks*2 ), Port::OUTPUT, module, Chord::OUTPUT_2));
  309. addOutput(Port::create<PJ301MOPort>(Vec(97,jacks*3 ), Port::OUTPUT, module, Chord::OUTPUT_3));
  310. addOutput(Port::create<PJ301MOPort>(Vec(97,jacks*4 ), Port::OUTPUT, module, Chord::OUTPUT_4));
  311. //addChild(GrayModuleLightWidget::create<TinyLight<RedLight>>(Vec(97+22,jacks*1),module, Chord::OUT_1_LIGHT));
  312. //addChild(GrayModuleLightWidget::create<TinyLight<RedLight>>(Vec(97+22,jacks*2),module, Chord::OUT_1_LIGHT));
  313. //addChild(GrayModuleLightWidget::create<TinyLight<RedLight>>(Vec(97+22,jacks*3),module, Chord::OUT_1_LIGHT));
  314. //addChild(GrayModuleLightWidget::create<TinyLight<RedLight>>(Vec(97+22,jacks*4),module, Chord::OUT_1_LIGHT));
  315. addInput(Port::create<PJ301MIPort>(Vec(97,57+jacks*3), Port::INPUT, module, Chord::INPUT));
  316. }
  317. };
  318. } // namespace rack_plugin_dBiz
  319. using namespace rack_plugin_dBiz;
  320. RACK_PLUGIN_MODEL_INIT(dBiz, Chord) {
  321. Model *modelChord = Model::create<Chord, ChordWidget>("dBiz", "Chord", "Chord", QUANTIZER_TAG);
  322. return modelChord;
  323. }