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.

181 lines
3.7KB

  1. #pragma once
  2. #include "ButterworthLookup.h"
  3. #include "BiquadState.h"
  4. #include "BiquadFilter.h"
  5. #include "ObjectCache.h"
  6. template <class TBase>
  7. class Super : public TBase
  8. {
  9. public:
  10. Super(struct Module * module) : TBase(module)
  11. {
  12. }
  13. Super() : TBase()
  14. {
  15. }
  16. /**
  17. * re-calc everything that changes with sample
  18. * rate. Also everything that depends on baseFrequency.
  19. *
  20. * Only needs to be called once.
  21. */
  22. void init();
  23. enum ParamIds
  24. {
  25. OCTAVE_PARAM,
  26. SEMI_PARAM,
  27. FINE_PARAM,
  28. DETUNE_PARAM,
  29. MIX_PARAM,
  30. NUM_PARAMS
  31. };
  32. enum InputIds
  33. {
  34. CV_INPUT,
  35. GATE_INPUT,
  36. DEBUG_INPUT,
  37. NUM_INPUTS
  38. };
  39. enum OutputIds
  40. {
  41. MAIN_OUTPUT,
  42. DEBUG_OUTPUT,
  43. NUM_OUTPUTS
  44. };
  45. enum LightIds
  46. {
  47. NUM_LIGHTS
  48. };
  49. /**
  50. * Main processing entry point. Called every sample
  51. */
  52. void step() override;
  53. private:
  54. static const int numSaws = 7;
  55. float phase[numSaws] = {0};
  56. float phaseInc[numSaws] = {0};
  57. float globalPhaseInc = 0;
  58. std::function<float(float)> expLookup =
  59. ObjectCache<float>::getExp2Ex();
  60. std::shared_ptr<LookupTableParams<float>> audioTaper =
  61. ObjectCache<float>::getAudioTaper();
  62. void updatePhaseInc();
  63. void updateAudio();
  64. // TODO: make static
  65. float const detuneFactors[numSaws] = {
  66. .89f,
  67. .94f,
  68. .98f,
  69. 1.f,
  70. 1.02f,
  71. 1.06f,
  72. 1.107f
  73. };
  74. // For debugging filters
  75. BiquadState<float, 2> filterState;
  76. BiquadParams<float, 2> filterParams;
  77. void updateHPFilters();
  78. ButterworthLookup4PHP filterLookup;
  79. };
  80. template <class TBase>
  81. inline void Super<TBase>::init()
  82. {
  83. }
  84. template <class TBase>
  85. inline void Super<TBase>::updatePhaseInc()
  86. {
  87. const float cv = TBase::inputs[CV_INPUT].value;
  88. const float finePitch = TBase::params[FINE_PARAM].value / 12.0f;
  89. const float semiPitch = TBase::params[SEMI_PARAM].value / 12.0f;
  90. float pitch = 1.0f + roundf(TBase::params[OCTAVE_PARAM].value) +
  91. semiPitch +
  92. finePitch;
  93. pitch += cv;
  94. const float q = float(log2(261.626)); // move up to pitch range of even vco
  95. pitch += q;
  96. const float freq = expLookup(pitch);
  97. globalPhaseInc = TBase::engineGetSampleTime() * freq;
  98. for (int i=0; i<numSaws; ++i) {
  99. float detune = (detuneFactors[i] - 1) * .1f;
  100. detune += 1;
  101. phaseInc[i] = globalPhaseInc * detune;
  102. // printf("phaseINc[%d] = %f\n", i, phaseInc[i]); fflush(stdout);
  103. }
  104. }
  105. template <class TBase>
  106. inline void Super<TBase>::updateAudio()
  107. {
  108. float mix = 0;
  109. for (int i=0; i<numSaws; ++i) {
  110. phase[i] += phaseInc[i];
  111. if (phase[i] > 1) {
  112. phase[i] -= 1;
  113. }
  114. if (phase[i] > 1) {
  115. printf("hey, phase too big %f\n", phase[i]); fflush(stdout);
  116. }
  117. if (phase[i] < 0) {
  118. printf("hey, phase too bismallg %f\n", phase[i]); fflush(stdout);
  119. }
  120. mix += phase[i];
  121. }
  122. // mix = phase[3]; // just for test
  123. mix *= 2;
  124. const float output = BiquadFilter<float>::run(mix, filterState, filterParams);
  125. TBase::outputs[MAIN_OUTPUT].value = output;
  126. }
  127. template <class TBase>
  128. inline void Super<TBase>::updateHPFilters()
  129. {
  130. filterLookup.get(filterParams, globalPhaseInc);
  131. #if 0
  132. const float input = TBase::inputs[DEBUG_INPUT].value;
  133. filterLookup.get(filterParams, globalPhaseInc);
  134. const float output = BiquadFilter<float>::run(input, filterState, filterParams);
  135. TBase::outputs[DEBUG_OUTPUT].value = output * 10;
  136. #endif
  137. }
  138. template <class TBase>
  139. inline void Super<TBase>::step()
  140. {
  141. updatePhaseInc();
  142. updateHPFilters();
  143. updateAudio();
  144. }