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.

165 lines
3.7KB

  1. //***********************************************************************************************
  2. //Impromptu Modular: Modules for VCV Rack by Marc Boulé
  3. //
  4. //This is code from the Fundamental plugin by Andrew Belt
  5. //See ./LICENSE.txt for all licenses and see below for the filter code license
  6. //***********************************************************************************************
  7. #include "rack.hpp"
  8. #include "dsp/functions.hpp"
  9. #include "dsp/resampler.hpp"
  10. #include "dsp/ode.hpp"
  11. #include "dsp/filter.hpp"
  12. #include "dsp/digital.hpp"
  13. using namespace rack;
  14. namespace rack_plugin_ImpromptuModular {
  15. extern float sawTable[2048];// see end of file
  16. extern float triTable[2048];// see end of file
  17. // From Fundamental VCF
  18. struct LadderFilter {
  19. float omega0;
  20. float resonance = 1.0f;
  21. float state[4];
  22. float input;
  23. float lowpass;
  24. float highpass;
  25. LadderFilter() {
  26. reset();
  27. setCutoff(0.f);
  28. }
  29. void reset() {
  30. for (int i = 0; i < 4; i++) {
  31. state[i] = 0.f;
  32. }
  33. }
  34. void setCutoff(float cutoff) {
  35. omega0 = 2.f*M_PI * cutoff;
  36. }
  37. void process(float input, float dt);
  38. };
  39. // From Fundamental VCO.cpp
  40. //template <int OVERSAMPLE, int QUALITY>
  41. static const int OVERSAMPLE = 8;
  42. static const int QUALITY = 8;
  43. struct VoltageControlledOscillator {
  44. bool analog = false;
  45. bool soft = false;
  46. float lastSyncValue = 0.0f;
  47. float phase = 0.0f;
  48. float freq;
  49. float pw = 0.5f;
  50. float pitch;
  51. bool syncEnabled = false;
  52. bool syncDirection = false;
  53. Decimator<OVERSAMPLE, QUALITY> sinDecimator;
  54. Decimator<OVERSAMPLE, QUALITY> triDecimator;
  55. Decimator<OVERSAMPLE, QUALITY> sawDecimator;
  56. Decimator<OVERSAMPLE, QUALITY> sqrDecimator;
  57. RCFilter sqrFilter;
  58. // For analog detuning effect
  59. float pitchSlew = 0.0f;
  60. int pitchSlewIndex = 0;
  61. float sinBuffer[OVERSAMPLE] = {};
  62. float triBuffer[OVERSAMPLE] = {};
  63. float sawBuffer[OVERSAMPLE] = {};
  64. float sqrBuffer[OVERSAMPLE] = {};
  65. void setPitch(float pitchKnob, float pitchCv);
  66. void setPulseWidth(float pulseWidth);
  67. void process(float deltaTime, float syncValue);
  68. float sin() {
  69. return sinDecimator.process(sinBuffer);
  70. }
  71. float tri() {
  72. return triDecimator.process(triBuffer);
  73. }
  74. float saw() {
  75. return sawDecimator.process(sawBuffer);
  76. }
  77. float sqr() {
  78. return sqrDecimator.process(sqrBuffer);
  79. }
  80. float light() {
  81. return sinf(2*M_PI * phase);
  82. }
  83. };
  84. // From Fundamental LFO.cpp
  85. struct LowFrequencyOscillator {
  86. float phase = 0.0f;
  87. float pw = 0.5f;
  88. float freq = 1.0f;
  89. bool offset = false;
  90. bool invert = false;
  91. SchmittTrigger resetTrigger;
  92. LowFrequencyOscillator() {}
  93. void setPitch(float pitch) {
  94. pitch = fminf(pitch, 8.0f);
  95. freq = powf(2.0f, pitch);
  96. }
  97. void setPulseWidth(float pw_) {
  98. const float pwMin = 0.01f;
  99. pw = clamp(pw_, pwMin, 1.0f - pwMin);
  100. }
  101. void setReset(float reset) {
  102. if (resetTrigger.process(reset / 0.01f)) {
  103. phase = 0.0f;
  104. }
  105. }
  106. void step(float dt) {
  107. float deltaPhase = fminf(freq * dt, 0.5f);
  108. phase += deltaPhase;
  109. if (phase >= 1.0f)
  110. phase -= 1.0f;
  111. }
  112. float sin() {
  113. if (offset)
  114. return 1.0f - cosf(2*M_PI * phase) * (invert ? -1.0f : 1.0f);
  115. else
  116. return sinf(2*M_PI * phase) * (invert ? -1.0f : 1.0f);
  117. }
  118. float tri(float x) {
  119. return 4.0f * fabsf(x - roundf(x));
  120. }
  121. float tri() {
  122. if (offset)
  123. return tri(invert ? phase - 0.5f : phase);
  124. else
  125. return -1.0f + tri(invert ? phase - 0.25f : phase - 0.75f);
  126. }
  127. float saw(float x) {
  128. return 2.0f * (x - roundf(x));
  129. }
  130. float saw() {
  131. if (offset)
  132. return invert ? 2.0f * (1.0f - phase) : 2.0f * phase;
  133. else
  134. return saw(phase) * (invert ? -1.0f : 1.0f);
  135. }
  136. float sqr() {
  137. float sqr = (phase < pw) ^ invert ? 1.0f : -1.0f;
  138. return offset ? sqr + 1.0f : sqr;
  139. }
  140. float light() {
  141. return sinf(2*M_PI * phase);
  142. }
  143. };
  144. } // namespace rack_plugin_ImpromptuModular