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.

277 lines
8.4KB

  1. #include "cf.hpp"
  2. #include "dsp/digital.hpp"
  3. namespace rack_plugin_cf {
  4. struct STEREO : Module {
  5. enum ParamIds {
  6. PAN_PARAM,
  7. GAIN_PARAM,
  8. SOLO_PARAM,
  9. ON_PARAM,
  10. NUM_PARAMS
  11. };
  12. enum InputIds {
  13. SOLOT_INPUT,
  14. ONT_INPUT,
  15. PAN_INPUT,
  16. GAIN_INPUT,
  17. EXTSOLO_INPUT,
  18. LEFT_INPUT,
  19. RIGHT_INPUT,
  20. PANPOT_INPUT,
  21. IN1_INPUT,
  22. IN2_INPUT,
  23. NUM_INPUTS
  24. };
  25. enum OutputIds {
  26. EXTSOLO_OUTPUT,
  27. LEFT_OUTPUT,
  28. RIGHT_OUTPUT,
  29. TLEFT_OUTPUT,
  30. TRIGHT_OUTPUT,
  31. NUM_OUTPUTS
  32. };
  33. enum LightIds {
  34. SOLO_LIGHT,
  35. ON_LIGHT,
  36. LEVEL_LIGHTS,
  37. NUM_LIGHTS = LEVEL_LIGHTS +11
  38. };
  39. float SIGNAL1 = 0.0 ;
  40. float SIGNAL2 = 0.0 ;
  41. bool ON_STATE = false ;
  42. bool SOLO_STATE = false ;
  43. bool soloed = false;
  44. int lightState[11] = {};
  45. int cligno =0;
  46. int retard =0;
  47. int retard2 =0;
  48. SchmittTrigger onTrigger;
  49. SchmittTrigger oninTrigger;
  50. SchmittTrigger soloTrigger;
  51. SchmittTrigger soloinTrigger;
  52. float or_gain ;
  53. int or_affi ;
  54. float orp_gain ;
  55. int orp_affi ;
  56. STEREO() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {onReset();}
  57. void step() override;
  58. void onReset() override {
  59. ON_STATE = true;
  60. SOLO_STATE = false;
  61. }
  62. json_t *toJson() override {
  63. json_t *rootJ = json_object();
  64. // solo
  65. json_object_set_new(rootJ, "solostate", json_integer(SOLO_STATE));
  66. // solo
  67. json_object_set_new(rootJ, "onstate", json_integer(ON_STATE));
  68. return rootJ;
  69. }
  70. void fromJson(json_t *rootJ) override {
  71. // solo
  72. json_t *solostateJ = json_object_get(rootJ, "solostate");
  73. if (solostateJ)
  74. SOLO_STATE = json_integer_value(solostateJ);
  75. // solo
  76. json_t *onstateJ = json_object_get(rootJ, "onstate");
  77. if (onstateJ)
  78. ON_STATE = json_integer_value(onstateJ);
  79. }
  80. };
  81. void STEREO::step() {
  82. SIGNAL1 = inputs[IN1_INPUT].value ;
  83. SIGNAL2 = inputs[IN2_INPUT].value ;
  84. if (!inputs[GAIN_INPUT].active) {
  85. SIGNAL1 = SIGNAL1 * params[GAIN_PARAM].value/5.0 ;
  86. SIGNAL2 = SIGNAL2 * params[GAIN_PARAM].value/5.0 ;
  87. or_affi =0;
  88. }
  89. else {
  90. SIGNAL1 = SIGNAL1 * clamp(inputs[GAIN_INPUT].value/5.0,0.0f,2.0f) ;
  91. SIGNAL2 = SIGNAL2 * clamp(inputs[GAIN_INPUT].value/5.0,0.0f,2.0f) ;
  92. or_affi=1;or_gain=clamp(inputs[GAIN_INPUT].value,0.0f,10.0f);
  93. }
  94. if (onTrigger.process(params[ON_PARAM].value)+oninTrigger.process(inputs[ONT_INPUT].value))
  95. {if (ON_STATE == 0) ON_STATE = 1; else ON_STATE = 0;}
  96. if (inputs[EXTSOLO_INPUT].value == 0) soloed = 0;
  97. if (inputs[EXTSOLO_INPUT].value == 10) soloed = 1;
  98. if (soloTrigger.process(params[SOLO_PARAM].value)+soloinTrigger.process(inputs[SOLOT_INPUT].value))
  99. {if (SOLO_STATE == 0) {SOLO_STATE = 1;} else {SOLO_STATE = 0;soloed=0;}}
  100. #define and &&
  101. if ((!SOLO_STATE and !soloed) and (retard > 0)) retard = 0; else if (retard < 1000) retard = retard + 1;
  102. #undef and
  103. outputs[EXTSOLO_OUTPUT].value=round(10*retard/1000);
  104. if (!SOLO_STATE) {SIGNAL1 = SIGNAL1 * ON_STATE ; SIGNAL2 = SIGNAL2 * ON_STATE ;}
  105. #define and &&
  106. if (soloed and !SOLO_STATE) {SIGNAL1 = 0; SIGNAL2 = 0;}
  107. #undef and
  108. if (!inputs[PAN_INPUT].active) {
  109. outputs[LEFT_OUTPUT].value = inputs[LEFT_INPUT].value + SIGNAL1*(1-clamp(params[PAN_PARAM].value,0.0f,1.0f));
  110. outputs[RIGHT_OUTPUT].value = inputs[RIGHT_INPUT].value + SIGNAL2*(1-clamp(-params[PAN_PARAM].value,0.0f,1.0f));
  111. outputs[TLEFT_OUTPUT].value = SIGNAL1*(1-clamp(params[PAN_PARAM].value,0.0f,1.0f));
  112. outputs[TRIGHT_OUTPUT].value = SIGNAL2*(1-clamp(-params[PAN_PARAM].value,0.0f,1.0f));
  113. orp_affi = 0;
  114. } else {
  115. outputs[LEFT_OUTPUT].value = inputs[LEFT_INPUT].value + SIGNAL1*(1-(clamp(inputs[PAN_INPUT].value,5.0f,10.0f)-5)/5);
  116. outputs[RIGHT_OUTPUT].value = inputs[RIGHT_INPUT].value + SIGNAL2*(1-(clamp(inputs[PAN_INPUT].value,0.0f,5.0f)+5)/5);
  117. outputs[TLEFT_OUTPUT].value = SIGNAL1*(1-(clamp(inputs[PAN_INPUT].value,5.0f,10.0f)-5)/5);
  118. outputs[TRIGHT_OUTPUT].value = SIGNAL2*(1-(clamp(inputs[PAN_INPUT].value,0.0f,5.0f)+5)/5);
  119. orp_affi = 1;orp_gain = clamp(inputs[PAN_INPUT].value,0.0f,10.0f);
  120. }
  121. if (ON_STATE==1) lights[ON_LIGHT].value=true; else lights[ON_LIGHT].value=false;
  122. if (SOLO_STATE==1) {if (cligno == 0) cligno =20000; else cligno=cligno-1;} else cligno = 0;
  123. if (cligno>5000) lights[SOLO_LIGHT].value =1; else lights[SOLO_LIGHT].value =0;
  124. for (int i = 0; i < 11; i++) {
  125. #ifdef _MSC_VER
  126. #define sMAX(a,b) (((a)>(b))?(a):(b))
  127. if (sMAX(SIGNAL1,SIGNAL2)> i) {if (i<10) lightState[i]=5000;else lightState[i]=20000;}
  128. #else
  129. if (std::max(SIGNAL1,SIGNAL2)> i) {if (i<10) lightState[i]=5000;else lightState[i]=20000;}
  130. #endif
  131. }
  132. for (int i = 0; i < 11; i++) {
  133. if (lightState[i]> 0) {lightState[i]=lightState[i]-1;lights[LEVEL_LIGHTS + i].value=true;} else lights[LEVEL_LIGHTS + i].value=false;
  134. }
  135. }
  136. struct MOTORPOTDisplay : TransparentWidget {
  137. float d;
  138. float *gainX ;
  139. int *affich;
  140. MOTORPOTDisplay() {
  141. }
  142. void draw(NVGcontext *vg) {
  143. if (*affich==1) {
  144. float xx = d*sin(-(*gainX*0.17+0.15)*M_PI) ;
  145. float yy = d*cos((*gainX*0.17+0.15)*M_PI) ;
  146. nvgBeginPath(vg);
  147. nvgCircle(vg, 0,0, d);
  148. nvgFillColor(vg, nvgRGBA(0x00, 0x00, 0x00, 0xff));
  149. nvgFill(vg);
  150. nvgStrokeWidth(vg,1.2);
  151. nvgStrokeColor(vg, nvgRGBA(0xff, 0xff, 0xff, 0xff));
  152. {
  153. nvgBeginPath(vg);
  154. nvgMoveTo(vg, 0,0);
  155. nvgLineTo(vg, xx,yy);
  156. nvgClosePath(vg);
  157. }
  158. nvgStroke(vg);
  159. }
  160. }
  161. };
  162. struct STEREOWidget : ModuleWidget {
  163. STEREOWidget(STEREO *module);
  164. };
  165. STEREOWidget::STEREOWidget(STEREO *module) : ModuleWidget(module) {
  166. setPanel(SVG::load(assetPlugin(plugin, "res/STEREO.svg")));
  167. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  168. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  169. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  170. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  171. addParam(ParamWidget::create<Trimpot>(Vec(38, 127), module, STEREO::PAN_PARAM, -1.0f, 1.0f, 0.0f));
  172. addInput(Port::create<PJ301MPort>(Vec(11, 131), Port::INPUT, module, STEREO::PAN_INPUT));
  173. {
  174. MOTORPOTDisplay *pdisplay = new MOTORPOTDisplay();
  175. pdisplay->box.pos = Vec(47, 136);
  176. pdisplay->d = 9.2;
  177. pdisplay->gainX = &module->orp_gain;
  178. pdisplay->affich = &module->orp_affi;
  179. addChild(pdisplay);
  180. }
  181. addParam(ParamWidget::create<RoundLargeBlackKnob>(Vec(27, 247), module, STEREO::GAIN_PARAM, 0.0f, 10.0f, 5.0f));
  182. addInput(Port::create<PJ301MPort>(Vec(11, 281), Port::INPUT, module, STEREO::GAIN_INPUT));
  183. {
  184. MOTORPOTDisplay *display = new MOTORPOTDisplay();
  185. display->box.pos = Vec(46, 266);
  186. display->d = 19.1;
  187. display->gainX = &module->or_gain;
  188. display->affich = &module->or_affi;
  189. addChild(display);
  190. }
  191. addParam(ParamWidget::create<LEDButton>(Vec(38, 167), module, STEREO::SOLO_PARAM, 0.0f, 1.0f, 0.0f));
  192. addChild(ModuleLightWidget::create<MediumLight<BlueLight>>(Vec(42.4, 171.4), module, STEREO::SOLO_LIGHT));
  193. addInput(Port::create<PJ301MPort>(Vec(11, 171), Port::INPUT, module, STEREO::SOLOT_INPUT));
  194. addParam(ParamWidget::create<LEDButton>(Vec(38, 208), module, STEREO::ON_PARAM, 0.0f, 1.0f, 0.0f));
  195. addChild(ModuleLightWidget::create<MediumLight<BlueLight>>(Vec(42.4, 212.4), module, STEREO::ON_LIGHT));
  196. addInput(Port::create<PJ301MPort>(Vec(11, 211), Port::INPUT, module, STEREO::ONT_INPUT));
  197. addInput(Port::create<PJ301MPort>(Vec(11, 308), Port::INPUT, module, STEREO::IN1_INPUT));
  198. addInput(Port::create<PJ301MPort>(Vec(11, 334), Port::INPUT, module, STEREO::IN2_INPUT));
  199. addOutput(Port::create<PJ301MPort>(Vec(54, 31), Port::OUTPUT, module, STEREO::EXTSOLO_OUTPUT));
  200. addOutput(Port::create<PJ301MPort>(Vec(54, 61), Port::OUTPUT, module, STEREO::LEFT_OUTPUT));
  201. addOutput(Port::create<PJ301MPort>(Vec(54, 91), Port::OUTPUT, module, STEREO::RIGHT_OUTPUT));
  202. addInput(Port::create<PJ301MPort>(Vec(11, 31), Port::INPUT, module, STEREO::EXTSOLO_INPUT));
  203. addInput(Port::create<PJ301MPort>(Vec(11, 61), Port::INPUT, module, STEREO::LEFT_INPUT));
  204. addInput(Port::create<PJ301MPort>(Vec(11, 91), Port::INPUT, module, STEREO::RIGHT_INPUT));
  205. addOutput(Port::create<PJ301MPort>(Vec(54, 308), Port::OUTPUT, module, STEREO::TLEFT_OUTPUT));
  206. addOutput(Port::create<PJ301MPort>(Vec(54, 334), Port::OUTPUT, module, STEREO::TRIGHT_OUTPUT));
  207. for (int i = 0; i < 11; i++) {
  208. if (i<10) addChild(ModuleLightWidget::create<MediumLight<BlueLight>>(Vec(70, 242-i*12), module, STEREO::LEVEL_LIGHTS + i));
  209. else addChild(ModuleLightWidget::create<MediumLight<RedLight>>(Vec(70, 242-i*12), module, STEREO::LEVEL_LIGHTS + i));
  210. }
  211. }
  212. } // namespace rack_plugin_cf
  213. using namespace rack_plugin_cf;
  214. RACK_PLUGIN_MODEL_INIT(cf, STEREO) {
  215. Model *modelSTEREO = Model::create<STEREO, STEREOWidget>("cf", "STEREO", "Stereo", MIXER_TAG);
  216. return modelSTEREO;
  217. }