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.

84 lines
2.0KB

  1. #pragma once
  2. /**
  3. * SawOscillator
  4. *
  5. * Generates a saw wave from 0..1
  6. * Good features:
  7. * frequency may be adjusted while running without glitches
  8. * can generate a quadrature output
  9. * can be configured to do positive and negative frequency
  10. */
  11. template<typename T> class SawOscillatorParams;
  12. template<typename T> class SawOscillatorState;
  13. template<typename T, bool frequencyCanBeNegative>
  14. class SawOscillator
  15. {
  16. public:
  17. static void setFrequency(SawOscillatorParams<T>& params, T freq);
  18. static T run(SawOscillatorState<T>& state, const SawOscillatorParams<T>& params);
  19. /**
  20. * gets the regular output and the quadrature output
  21. */
  22. static void runQuadrature(T& out, T& outQuad, SawOscillatorState<T>& state, const SawOscillatorParams<T>& params);
  23. };
  24. template<typename T, bool frequencyCanBeNegative>
  25. inline T SawOscillator<T, frequencyCanBeNegative>::run(SawOscillatorState<T>& state, const SawOscillatorParams<T>& params)
  26. {
  27. T ret = state.phase;
  28. state.phase += params.phaseIncrement;
  29. if (state.phase >= 1) {
  30. state.phase -= 1;
  31. }
  32. if (frequencyCanBeNegative && (state.phase < 0)) {
  33. state.phase += 1;
  34. }
  35. return ret;
  36. }
  37. template<typename T, bool frequencyCanBeNegative>
  38. inline void SawOscillator<T, frequencyCanBeNegative>::runQuadrature(T& out, T& outQuad, SawOscillatorState<T>& state, const SawOscillatorParams<T>& params)
  39. {
  40. out = run(state, params);
  41. T quad = out + T(.25);
  42. if (quad >= 1) {
  43. quad -= 1;
  44. }
  45. outQuad = quad;
  46. }
  47. template<typename T, bool frequencyCanBeNegative>
  48. inline void SawOscillator<T, frequencyCanBeNegative>::setFrequency(SawOscillatorParams<T>& params, T freq)
  49. {
  50. if (frequencyCanBeNegative) {
  51. assert(freq >= -.5 && freq < .5);
  52. } else {
  53. assert(freq >= 0 && freq < .5);
  54. }
  55. params.phaseIncrement = freq;
  56. }
  57. template<typename T>
  58. class SawOscillatorParams
  59. {
  60. public:
  61. T phaseIncrement = 0;
  62. };
  63. template<typename T>
  64. class SawOscillatorState
  65. {
  66. public:
  67. /**
  68. * phase increments from 0...1
  69. */
  70. T phase = 0;
  71. };