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.

235 lines
7.0KB

  1. ///////////////////////////////////////////////////
  2. //
  3. //
  4. // Knobs - VCV Module outputs 3 constants of different types and ranges
  5. //
  6. // Strum 2017
  7. //
  8. ///////////////////////////////////////////////////
  9. #include "mental.hpp"
  10. #include "dsp/digital.hpp"
  11. #include <sstream>
  12. #include <iomanip>
  13. namespace rack_plugin_mental {
  14. struct MentalKnobs : Module {
  15. enum ParamIds {
  16. STEP_SWITCH,
  17. BI_SWITCH = STEP_SWITCH + 3,
  18. STEPSIZE_SWITCH = BI_SWITCH + 3,
  19. KNOB_PARAM = STEPSIZE_SWITCH + 3,
  20. SCALE_PARAM = KNOB_PARAM + 3,
  21. NUM_PARAMS = SCALE_PARAM + 3
  22. };
  23. enum InputIds {
  24. NUM_INPUTS
  25. };
  26. enum OutputIds {
  27. OUTPUT,
  28. NUM_OUTPUTS = OUTPUT + 3
  29. };
  30. enum LightIds {
  31. BUTTON_LEDS,
  32. NUM_LIGHTS = BUTTON_LEDS + 9
  33. };
  34. float knob_value[3] = {0.0,0.0,0.0};
  35. float scale_value[3] = {0.0,0.0,0.0};
  36. float output_value[3] = {0.0,0.0,0.0};
  37. int display_value[3] = {0,0,0};
  38. SchmittTrigger step_switch_trigger[3],bi_switch_trigger[3],stepsize_switch_trigger[3];
  39. bool switch_states[3][3] = {{0,0,0},
  40. {0,0,0},
  41. {0,0,0}};
  42. int octaves[3] = {0,0,0};
  43. int semitones[3] = {0,0,0};
  44. MentalKnobs() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  45. void step() override;
  46. json_t *toJson() override
  47. {
  48. json_t *rootJ = json_object();
  49. // button states
  50. json_t *switch_statesJ = json_array();
  51. for (int i = 0; i < 3; i++)
  52. {
  53. for (int j = 0 ; j < 3 ; j++)
  54. {
  55. json_t *switch_stateJ = json_integer((int) switch_states[i][j]);
  56. json_array_append_new(switch_statesJ, switch_stateJ);
  57. }
  58. }
  59. json_object_set_new(rootJ, "switches", switch_statesJ);
  60. return rootJ;
  61. }
  62. void fromJson(json_t *rootJ) override
  63. {
  64. // button states
  65. json_t *switch_statesJ = json_object_get(rootJ, "switches");
  66. if (switch_statesJ)
  67. {
  68. for (int i = 0; i < 3 ; i++)
  69. {
  70. for (int j = 0 ; j < 3 ; j++)
  71. {
  72. json_t *switch_stateJ = json_array_get(switch_statesJ, i * 3 + j);
  73. if (switch_stateJ)
  74. switch_states[i][j] = !!json_integer_value(switch_stateJ);
  75. }
  76. }
  77. }
  78. }
  79. };
  80. void MentalKnobs::step()
  81. {
  82. for ( int i = 0 ; i < 3 ; i++)
  83. {
  84. // button triggers
  85. if (step_switch_trigger[i].process(params[STEP_SWITCH + i].value))
  86. {
  87. switch_states[0][i] = !switch_states[0][i];
  88. }
  89. lights[BUTTON_LEDS + i].value = switch_states[0][i] ? 1.0 : 0.0;
  90. if (stepsize_switch_trigger[i].process(params[STEPSIZE_SWITCH + i].value))
  91. {
  92. switch_states[1][i] = !switch_states[1][i];
  93. }
  94. lights[BUTTON_LEDS + 6 + i].value = switch_states[1][i] ? 1.0 : 0.0;
  95. if (bi_switch_trigger[i].process(params[BI_SWITCH + i].value))
  96. {
  97. switch_states[2][i] = !switch_states[2][i];
  98. }
  99. lights[BUTTON_LEDS + 3 + i].value = switch_states[2][i] ? 1.0 : 0.0;
  100. knob_value[i] = params[KNOB_PARAM + i].value;
  101. scale_value[i] = params[SCALE_PARAM + i].value;
  102. if (!switch_states[2][i]) // bi switch
  103. {
  104. knob_value[i] = std::abs(knob_value[i]);
  105. }
  106. output_value[i] = knob_value[i] * scale_value[i];
  107. if (switch_states[0][i]) // step switch
  108. {
  109. if (switch_states[1][i]) // stepsize switch - quantise to semitones
  110. {
  111. octaves[i] = std::round(output_value[i]);
  112. semitones[i] = std::round((output_value[i] - octaves[i])*12);
  113. if (semitones[i] < 0)
  114. {
  115. semitones[i] +=12;
  116. octaves[i] -= 1;
  117. }
  118. output_value[i] = octaves[i] + semitones[i]/12.0;
  119. } else output_value[i] = std::round(output_value[i]);
  120. }
  121. display_value[i] = std::round(output_value[i]);
  122. outputs[OUTPUT + i].value = output_value[i];
  123. }
  124. }
  125. ////////////////////////////////////
  126. struct NumberDisplayWidget4 : TransparentWidget {
  127. int *value;
  128. std::shared_ptr<Font> font;
  129. NumberDisplayWidget4() {
  130. font = Font::load(assetPlugin(plugin, "res/Segment7Standard.ttf"));
  131. };
  132. void draw(NVGcontext *vg) override
  133. {
  134. // Background
  135. NVGcolor backgroundColor = nvgRGB(0x00, 0x00, 0x00);
  136. NVGcolor StrokeColor = nvgRGB(0x00, 0x47, 0x7e);
  137. nvgBeginPath(vg);
  138. nvgRoundedRect(vg, -1.0, -1.0, box.size.x+2, box.size.y+2, 4.0);
  139. nvgFillColor(vg, StrokeColor);
  140. nvgFill(vg);
  141. nvgBeginPath(vg);
  142. nvgRoundedRect(vg, 0.0, 0.0, box.size.x, box.size.y, 4.0);
  143. nvgFillColor(vg, backgroundColor);
  144. nvgFill(vg);
  145. // text
  146. nvgFontSize(vg, 18);
  147. nvgFontFaceId(vg, font->handle);
  148. nvgTextLetterSpacing(vg, 2.5);
  149. std::stringstream to_display;
  150. to_display << std::setw(3) << *value;
  151. Vec textPos = Vec(6.0f, 17.0f);
  152. NVGcolor textColor = nvgRGB(0x00, 0x47, 0x7e);
  153. nvgFillColor(vg, textColor);
  154. nvgText(vg, textPos.x, textPos.y, to_display.str().c_str(), NULL);
  155. }
  156. };
  157. //////////////////////////////////
  158. struct MentalKnobsWidget : ModuleWidget {
  159. MentalKnobsWidget(MentalKnobs *module);
  160. };
  161. MentalKnobsWidget::MentalKnobsWidget(MentalKnobs *module) : ModuleWidget(module)
  162. {
  163. setPanel(SVG::load(assetPlugin(plugin, "res/MentalKnobs.svg")));
  164. int group_offset = 120;
  165. for (int i = 0 ; i < 3 ; i++)
  166. {
  167. addParam(ParamWidget::create<MedKnob>(Vec(2, 20+group_offset*i), module, MentalKnobs::KNOB_PARAM + i, -1.0, 1.0, 0.0));
  168. addParam(ParamWidget::create<MedKnob>(Vec(32, 20+group_offset*i), module, MentalKnobs::SCALE_PARAM + i,0.0, 10.0, 1.0));
  169. addParam(ParamWidget::create<LEDButton>(Vec(5, 50+group_offset*i), module, MentalKnobs::STEP_SWITCH + i, 0.0, 1.0, 0.0));
  170. addChild(ModuleLightWidget::create<MedLight<BlueLED>>(Vec(10, 55+group_offset*i), module, MentalKnobs::BUTTON_LEDS + i ));
  171. addParam(ParamWidget::create<LEDButton>(Vec(5, 75+group_offset*i), module, MentalKnobs::BI_SWITCH + i, 0.0, 1.0, 0.0));
  172. addChild(ModuleLightWidget::create<MedLight<BlueLED>>(Vec(10, 80+group_offset*i), module, MentalKnobs::BUTTON_LEDS + 3 + i));
  173. addParam(ParamWidget::create<LEDButton>(Vec(35, 50+group_offset*i), module, MentalKnobs::STEPSIZE_SWITCH + i, 0.0, 1.0, 0.0));
  174. addChild(ModuleLightWidget::create<MedLight<BlueLED>>(Vec(40, 55+group_offset*i), module, MentalKnobs::BUTTON_LEDS + 6 + i));
  175. addOutput(Port::create<CVOutPort>(Vec(33, 75+group_offset*i), Port::OUTPUT, module, MentalKnobs::OUTPUT + i));
  176. }
  177. NumberDisplayWidget4 *display = new NumberDisplayWidget4();
  178. display->box.pos = Vec(5,105);
  179. display->box.size = Vec(50, 20);
  180. display->value = &module->display_value[0];
  181. addChild(display);
  182. NumberDisplayWidget4 *display2 = new NumberDisplayWidget4();
  183. display2->box.pos = Vec(5,105+group_offset);
  184. display2->box.size = Vec(50, 20);
  185. display2->value = &module->display_value[1];
  186. addChild(display2);
  187. NumberDisplayWidget4 *display3 = new NumberDisplayWidget4();
  188. display3->box.pos = Vec(5,105+group_offset * 2);
  189. display3->box.size = Vec(50, 20);
  190. display3->value = &module->display_value[2];
  191. addChild(display3);
  192. }
  193. } // namespace rack_plugin_mental
  194. using namespace rack_plugin_mental;
  195. RACK_PLUGIN_MODEL_INIT(mental, MentalKnobs) {
  196. Model *modelMentalKnobs = Model::create<MentalKnobs, MentalKnobsWidget>("mental", "MentalKnobs", "Knobs", CONTROLLER_TAG, UTILITY_TAG);
  197. return modelMentalKnobs;
  198. }