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.

220 lines
5.1KB

  1. #include "Cmp.hpp"
  2. void Cmp::onReset() {
  3. _thresholdState = LOW;
  4. _windowState = LOW;
  5. }
  6. void Cmp::step() {
  7. if (!(
  8. outputs[GREATER_OUTPUT].active ||
  9. outputs[LESS_OUTPUT].active ||
  10. outputs[EQUAL_OUTPUT].active ||
  11. outputs[NOT_EQUAL_OUTPUT].active
  12. )) {
  13. return;
  14. }
  15. float a = params[A_PARAM].value * 10.0f;
  16. if (inputs[A_INPUT].active) {
  17. a = clamp(a + inputs[A_INPUT].value, -12.0f, 12.0f);
  18. }
  19. float b = params[B_PARAM].value * 10.0f;
  20. if (inputs[B_INPUT].active) {
  21. b = clamp(b + inputs[B_INPUT].value, -12.0f, 12.0f);
  22. }
  23. float window = params[WINDOW_PARAM].value;
  24. if (inputs[WINDOW_INPUT].active) {
  25. window *= clamp(inputs[WINDOW_INPUT].value / 10.0f, 0.0f, 1.0f);
  26. }
  27. window *= 10.0f;
  28. float high = 10.0f;
  29. float low = 0.0f;
  30. if (params[OUTPUT_PARAM].value > 0.5f) {
  31. high = 5.0f;
  32. low = -5.0f;
  33. }
  34. int lag = -1;
  35. stepChannel(
  36. a >= b,
  37. high,
  38. low,
  39. _thresholdState,
  40. _thresholdLag,
  41. lag,
  42. outputs[GREATER_OUTPUT],
  43. outputs[LESS_OUTPUT]
  44. );
  45. stepChannel(
  46. fabsf(a - b) <= window,
  47. high,
  48. low,
  49. _windowState,
  50. _windowLag,
  51. lag,
  52. outputs[EQUAL_OUTPUT],
  53. outputs[NOT_EQUAL_OUTPUT]
  54. );
  55. }
  56. void Cmp::stepChannel(
  57. bool high,
  58. float highValue,
  59. float lowValue,
  60. State& state,
  61. int& channelLag,
  62. int& lag,
  63. Output& highOutput,
  64. Output& lowOutput
  65. ) {
  66. switch (state) {
  67. case LOW: {
  68. if (high) {
  69. if (lag < 0) {
  70. lag = lagInSamples();
  71. }
  72. if (lag < 1) {
  73. state = HIGH;
  74. }
  75. else {
  76. state = LAG_HIGH;
  77. channelLag = lag;
  78. }
  79. }
  80. break;
  81. }
  82. case HIGH: {
  83. if (!high) {
  84. if (lag < 0) {
  85. lag = lagInSamples();
  86. }
  87. if (lag < 1) {
  88. state = LOW;
  89. }
  90. else {
  91. state = LAG_LOW;
  92. channelLag = lag;
  93. }
  94. }
  95. break;
  96. }
  97. case LAG_LOW: {
  98. if (!high) {
  99. --channelLag;
  100. if(channelLag == 0) {
  101. state = LOW;
  102. }
  103. }
  104. else {
  105. state = HIGH;
  106. }
  107. break;
  108. }
  109. case LAG_HIGH: {
  110. if (high) {
  111. --channelLag;
  112. if(channelLag == 0) {
  113. state = HIGH;
  114. }
  115. }
  116. else {
  117. state = LOW;
  118. }
  119. break;
  120. }
  121. };
  122. switch (state) {
  123. case LOW:
  124. case LAG_HIGH: {
  125. highOutput.value = lowValue;
  126. lowOutput.value = highValue;
  127. break;
  128. }
  129. case HIGH:
  130. case LAG_LOW: {
  131. highOutput.value = highValue;
  132. lowOutput.value = lowValue;
  133. break;
  134. }
  135. }
  136. }
  137. int Cmp::lagInSamples() {
  138. float lag = params[LAG_PARAM].value;
  139. if (inputs[LAG_INPUT].active) {
  140. lag *= clamp(inputs[LAG_INPUT].value / 10.0f, 0.0f, 1.0f);
  141. }
  142. return lag * lag * engineGetSampleRate();
  143. }
  144. struct CmpWidget : ModuleWidget {
  145. static constexpr int hp = 6;
  146. CmpWidget(Cmp* module) : ModuleWidget(module) {
  147. box.size = Vec(RACK_GRID_WIDTH * hp, RACK_GRID_HEIGHT);
  148. {
  149. SVGPanel *panel = new SVGPanel();
  150. panel->box.size = box.size;
  151. panel->setBackground(SVG::load(assetPlugin(plugin, "res/Cmp.svg")));
  152. addChild(panel);
  153. }
  154. addChild(Widget::create<ScrewSilver>(Vec(0, 0)));
  155. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 15, 365)));
  156. // generated by svg_widgets.rb
  157. auto aParamPosition = Vec(8.0, 46.0);
  158. auto bParamPosition = Vec(53.0, 46.0);
  159. auto windowParamPosition = Vec(8.0, 151.0);
  160. auto lagParamPosition = Vec(53.0, 151.0);
  161. auto outputParamPosition = Vec(25.5, 251.0);
  162. auto aInputPosition = Vec(10.5, 87.0);
  163. auto bInputPosition = Vec(55.5, 87.0);
  164. auto windowInputPosition = Vec(10.5, 192.0);
  165. auto lagInputPosition = Vec(55.5, 192.0);
  166. auto greaterOutputPosition = Vec(16.0, 283.0);
  167. auto lessOutputPosition = Vec(50.0, 283.0);
  168. auto equalOutputPosition = Vec(16.0, 319.0);
  169. auto notEqualOutputPosition = Vec(50.0, 319.0);
  170. // end generated by svg_widgets.rb
  171. addParam(ParamWidget::create<Knob29>(aParamPosition, module, Cmp::A_PARAM, -1.0, 1.0, 0.0));
  172. addParam(ParamWidget::create<Knob29>(bParamPosition, module, Cmp::B_PARAM, -1.0, 1.0, 0.0));
  173. addParam(ParamWidget::create<Knob29>(windowParamPosition, module, Cmp::WINDOW_PARAM, 0.0, 1.0, 0.5));
  174. addParam(ParamWidget::create<Knob29>(lagParamPosition, module, Cmp::LAG_PARAM, 0.0, 1.0, 0.1));
  175. {
  176. auto w = ParamWidget::create<Knob16>(outputParamPosition, module, Cmp::OUTPUT_PARAM, 0.0, 1.0, 0.0);
  177. auto k = dynamic_cast<SVGKnob*>(w);
  178. k->snap = true;
  179. k->minAngle = 3.0f * (M_PI / 8.0f);
  180. k->maxAngle = 5.0f * (M_PI / 8.0f);
  181. k->speed = 3.0;
  182. addParam(w);
  183. }
  184. addInput(Port::create<Port24>(aInputPosition, Port::INPUT, module, Cmp::A_INPUT));
  185. addInput(Port::create<Port24>(bInputPosition, Port::INPUT, module, Cmp::B_INPUT));
  186. addInput(Port::create<Port24>(windowInputPosition, Port::INPUT, module, Cmp::WINDOW_INPUT));
  187. addInput(Port::create<Port24>(lagInputPosition, Port::INPUT, module, Cmp::LAG_INPUT));
  188. addOutput(Port::create<Port24>(greaterOutputPosition, Port::OUTPUT, module, Cmp::GREATER_OUTPUT));
  189. addOutput(Port::create<Port24>(lessOutputPosition, Port::OUTPUT, module, Cmp::LESS_OUTPUT));
  190. addOutput(Port::create<Port24>(equalOutputPosition, Port::OUTPUT, module, Cmp::EQUAL_OUTPUT));
  191. addOutput(Port::create<Port24>(notEqualOutputPosition, Port::OUTPUT, module, Cmp::NOT_EQUAL_OUTPUT));
  192. }
  193. };
  194. RACK_PLUGIN_MODEL_INIT(Bogaudio, Cmp) {
  195. Model *modelCmp = createModel<Cmp, CmpWidget>("Bogaudio-Cmp", "CMP", "comparator", LOGIC_TAG);
  196. return modelCmp;
  197. }