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.

104 lines
2.7KB

  1. #pragma once
  2. /**
  3. * SawOscillator
  4. *
  5. * Good features:
  6. * frequency may be adjusted while running without glitches
  7. * can generate a quadrature output
  8. * can be configured to do positive and negative frequency
  9. */
  10. template<typename T> class SawOscillatorParams;
  11. template<typename T> class SawOscillatorState;
  12. template<typename T, bool frequencyCanBeNegative>
  13. class SawOscillator
  14. {
  15. public:
  16. SawOscillator() = delete; // we are only static
  17. static void setFrequency(SawOscillatorParams<T>& params, T freq); // TODO: so we want setters on params?
  18. // Generates a saw wave from 0..1
  19. static T runSaw(SawOscillatorState<T>& state, const SawOscillatorParams<T>& params);
  20. // Generates a triangle wave from -1..1
  21. static T runTri(SawOscillatorState<T>& state, const SawOscillatorParams<T>& params);
  22. /**
  23. * gets the regular output and the quadrature output
  24. */
  25. static void runQuadrature(T& out, T& outQuad, SawOscillatorState<T>& state, const SawOscillatorParams<T>& params);
  26. };
  27. template<typename T, bool frequencyCanBeNegative>
  28. inline T SawOscillator<T, frequencyCanBeNegative>::runSaw(SawOscillatorState<T>& state, const SawOscillatorParams<T>& params)
  29. {
  30. T ret = state.phase;
  31. state.phase += params.phaseIncrement;
  32. if (state.phase >= 1) {
  33. state.phase -= 1;
  34. }
  35. if (frequencyCanBeNegative && (state.phase < 0)) {
  36. state.phase += 1;
  37. }
  38. return ret;
  39. }
  40. template<typename T, bool frequencyCanBeNegative>
  41. inline T SawOscillator<T, frequencyCanBeNegative>::runTri(SawOscillatorState<T>& state, const SawOscillatorParams<T>& params)
  42. {
  43. T output = 4 * runSaw(state, params); // Saw 0...4
  44. // printf("in tri, 4x = %f ", output);
  45. if (output > 3) {
  46. output -= 4;
  47. } else if (output > 1) {
  48. output = 2 - output;
  49. }
  50. // printf("final = %f \n", output);
  51. return output;
  52. }
  53. template<typename T, bool frequencyCanBeNegative>
  54. inline void SawOscillator<T, frequencyCanBeNegative>::runQuadrature(T& out, T& outQuad, SawOscillatorState<T>& state, const SawOscillatorParams<T>& params)
  55. {
  56. out = runSaw(state, params);
  57. T quad = out + T(.25);
  58. if (quad >= 1) {
  59. quad -= 1;
  60. }
  61. outQuad = quad;
  62. }
  63. template<typename T, bool frequencyCanBeNegative>
  64. inline void SawOscillator<T, frequencyCanBeNegative>::setFrequency(SawOscillatorParams<T>& params, T freq)
  65. {
  66. if (frequencyCanBeNegative) {
  67. assert(freq >= -.5 && freq < .5);
  68. } else {
  69. assert(freq >= 0 && freq < .5);
  70. }
  71. params.phaseIncrement = freq;
  72. }
  73. template<typename T>
  74. class SawOscillatorParams
  75. {
  76. public:
  77. T phaseIncrement = 0;
  78. };
  79. template<typename T>
  80. class SawOscillatorState
  81. {
  82. public:
  83. /**
  84. * phase increments from 0...1
  85. */
  86. T phase = 0;
  87. };