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.

171 lines
4.9KB

  1. #include "Befaco.hpp"
  2. #include "dsp.hpp"
  3. struct EvenVCO : Module {
  4. enum ParamIds {
  5. OCTAVE_PARAM,
  6. TUNE_PARAM,
  7. PWM_PARAM,
  8. NUM_PARAMS
  9. };
  10. enum InputIds {
  11. PITCH1_INPUT,
  12. PITCH2_INPUT,
  13. FM_INPUT,
  14. SYNC_INPUT,
  15. PWM_INPUT,
  16. NUM_INPUTS
  17. };
  18. enum OutputIds {
  19. TRI_OUTPUT,
  20. SINE_OUTPUT,
  21. EVEN_OUTPUT,
  22. SAW_OUTPUT,
  23. SQUARE_OUTPUT,
  24. NUM_OUTPUTS
  25. };
  26. float phase = 0.0;
  27. /** The value of the last sync input */
  28. float sync = 0.0;
  29. /** The outputs */
  30. float tri = 0.0;
  31. /** Whether we are past the pulse width already */
  32. bool halfPhase = false;
  33. MinBLEP<16> triSquareMinBLEP;
  34. MinBLEP<16> triMinBLEP;
  35. MinBLEP<16> sineMinBLEP;
  36. MinBLEP<16> doubleSawMinBLEP;
  37. MinBLEP<16> sawMinBLEP;
  38. MinBLEP<16> squareMinBLEP;
  39. RCFilter triFilter;
  40. EvenVCO();
  41. void step();
  42. };
  43. EvenVCO::EvenVCO() {
  44. params.resize(NUM_PARAMS);
  45. inputs.resize(NUM_INPUTS);
  46. outputs.resize(NUM_OUTPUTS);
  47. triSquareMinBLEP.minblep = minblep_16_32;
  48. triSquareMinBLEP.oversample = 32;
  49. triMinBLEP.minblep = minblep_16_32;
  50. triMinBLEP.oversample = 32;
  51. sineMinBLEP.minblep = minblep_16_32;
  52. sineMinBLEP.oversample = 32;
  53. doubleSawMinBLEP.minblep = minblep_16_32;
  54. doubleSawMinBLEP.oversample = 32;
  55. sawMinBLEP.minblep = minblep_16_32;
  56. sawMinBLEP.oversample = 32;
  57. squareMinBLEP.minblep = minblep_16_32;
  58. squareMinBLEP.oversample = 32;
  59. }
  60. void EvenVCO::step() {
  61. // Compute frequency, pitch is 1V/oct
  62. float pitch = 1.0 + roundf(params[OCTAVE_PARAM]) + params[TUNE_PARAM] / 12.0;
  63. pitch += getf(inputs[PITCH1_INPUT]) + getf(inputs[PITCH2_INPUT]);
  64. pitch += getf(inputs[FM_INPUT]) / 4.0;
  65. float freq = 261.626 * powf(2.0, pitch);
  66. freq = clampf(freq, 0.0, 20000.0);
  67. // Pulse width
  68. float pw = params[PWM_PARAM] + getf(inputs[PWM_INPUT]) / 5.0;
  69. const float minPw = 0.05;
  70. pw = rescalef(clampf(pw, -1.0, 1.0), -1.0, 1.0, minPw, 1.0-minPw);
  71. // Advance phase
  72. float deltaPhase = clampf(freq / gSampleRate, 1e-6, 0.5);
  73. float oldPhase = phase;
  74. phase += deltaPhase;
  75. if (oldPhase < 0.5 && phase >= 0.5) {
  76. float crossing = -(phase - 0.5) / deltaPhase;
  77. triSquareMinBLEP.jump(crossing, 2.0);
  78. doubleSawMinBLEP.jump(crossing, -2.0);
  79. }
  80. if (!halfPhase && phase >= pw) {
  81. float crossing = -(phase - pw) / deltaPhase;
  82. squareMinBLEP.jump(crossing, 2.0);
  83. halfPhase = true;
  84. }
  85. // Reset phase if at end of cycle
  86. if (phase >= 1.0) {
  87. phase -= 1.0;
  88. float crossing = -phase / deltaPhase;
  89. triSquareMinBLEP.jump(crossing, -2.0);
  90. doubleSawMinBLEP.jump(crossing, -2.0);
  91. squareMinBLEP.jump(crossing, -2.0);
  92. sawMinBLEP.jump(crossing, -2.0);
  93. halfPhase = false;
  94. }
  95. // Outputs
  96. float triSquare = (phase < 0.5) ? -1.0 : 1.0;
  97. triSquare += triSquareMinBLEP.shift();
  98. // Integrate square for triangle
  99. tri += 4.0 * triSquare * freq / gSampleRate;
  100. tri *= (1.0 - 40.0 / gSampleRate);
  101. float sine = -cosf(2*M_PI * phase);
  102. float doubleSaw = (phase < 0.5) ? (-1.0 + 4.0*phase) : (-1.0 + 4.0*(phase - 0.5));
  103. doubleSaw += doubleSawMinBLEP.shift();
  104. float even = 0.55 * (doubleSaw + 1.27 * sine);
  105. float saw = -1.0 + 2.0*phase;
  106. saw += sawMinBLEP.shift();
  107. float square = (phase < pw) ? -1.0 : 1.0;
  108. square += squareMinBLEP.shift();
  109. // Set outputs
  110. setf(outputs[TRI_OUTPUT], 5.0*tri);
  111. setf(outputs[SINE_OUTPUT], 5.0*sine);
  112. setf(outputs[EVEN_OUTPUT], 5.0*even);
  113. setf(outputs[SAW_OUTPUT], 5.0*saw);
  114. setf(outputs[SQUARE_OUTPUT], 5.0*square);
  115. }
  116. EvenVCOWidget::EvenVCOWidget() {
  117. EvenVCO *module = new EvenVCO();
  118. setModule(module);
  119. box.size = Vec(15*8, 380);
  120. {
  121. Panel *panel = new DarkPanel();
  122. panel->box.size = box.size;
  123. panel->backgroundImage = Image::load("plugins/Befaco/res/EvenVCO.png");
  124. addChild(panel);
  125. }
  126. addChild(createScrew<ScrewBlack>(Vec(15, 0)));
  127. addChild(createScrew<ScrewBlack>(Vec(15, 365)));
  128. addChild(createScrew<ScrewBlack>(Vec(15*6, 0)));
  129. addChild(createScrew<ScrewBlack>(Vec(15*6, 365)));
  130. addParam(createParam<BefacoBigSnapKnob>(Vec(24-4+2, 35-4+1), module, EvenVCO::OCTAVE_PARAM, -5.0, 4.0, 0.0));
  131. addParam(createParam<BefacoTinyKnob>(Vec(72, 131), module, EvenVCO::TUNE_PARAM, -7.0, 7.0, 0.0));
  132. addParam(createParam<Davies1900hRedKnob>(Vec(16, 230), module, EvenVCO::PWM_PARAM, -1.0, 1.0, 0.0));
  133. addInput(createInput<PJ3410Port>(Vec(13-7-1, 124-7), module, EvenVCO::PITCH1_INPUT));
  134. addInput(createInput<PJ3410Port>(Vec(22-7, 162-7-1), module, EvenVCO::PITCH2_INPUT));
  135. addInput(createInput<PJ3410Port>(Vec(51-7, 188-7-1), module, EvenVCO::FM_INPUT));
  136. addInput(createInput<PJ3410Port>(Vec(88-7, 193-7), module, EvenVCO::SYNC_INPUT));
  137. addInput(createInput<PJ3410Port>(Vec(76-7, 240-7), module, EvenVCO::PWM_INPUT));
  138. addOutput(createOutput<PJ3410Port>(Vec(12-7, 285-7), module, EvenVCO::TRI_OUTPUT));
  139. addOutput(createOutput<PJ3410Port>(Vec(88-7+1, 285-7), module, EvenVCO::SINE_OUTPUT));
  140. addOutput(createOutput<PJ3410Port>(Vec(50-7+1, 308-7), module, EvenVCO::EVEN_OUTPUT));
  141. addOutput(createOutput<PJ3410Port>(Vec(12-7, 329-7), module, EvenVCO::SAW_OUTPUT));
  142. addOutput(createOutput<PJ3410Port>(Vec(88-7+1, 329-7), module, EvenVCO::SQUARE_OUTPUT));
  143. }