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.

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