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.

88 lines
2.8KB

  1. #pragma once
  2. #include "AudioMath.h"
  3. #include "LookupTable.h"
  4. #include "ObjectCache.h"
  5. #include "SawOscillator.h"
  6. template<typename T> class SinOscillatorParams;
  7. template<typename T> class SinOscillatorState;
  8. /**
  9. * A simple sin oscillator based on lookup table.
  10. * Advantage:
  11. * fast.
  12. * frequency may be changed without phase discontinuity.
  13. * Optional quadrature output.
  14. * Disadvantage:
  15. * Not the best spectral purity (significant amount of phase jitter)
  16. */
  17. template<typename T, bool frequencyCanBeNegative>
  18. class SinOscillator
  19. {
  20. public:
  21. SinOscillator() = delete; // we are only static
  22. static void setFrequency(SinOscillatorParams<T>&, T frequency);
  23. static T run(SinOscillatorState<T>&, const SinOscillatorParams<T>&);
  24. static void runQuadrature(T& output, T& outputQuadrature, SinOscillatorState<T>&, const SinOscillatorParams<T>&);
  25. };
  26. template<typename T, bool frequencyCanBeNegative>
  27. inline void SinOscillator<T, frequencyCanBeNegative>::setFrequency(SinOscillatorParams<T>& params, T frequency)
  28. {
  29. std::function<double(double)> f = AudioMath::makeFunc_Sin();
  30. // TODO: figure out a better initialization strategy
  31. // and a better strategy for table size
  32. // with 4096 thd was -130 db. let's use less memory!
  33. // if (!params.lookupParams.isValid()) {
  34. // LookupTable<T>::init(params.lookupParams, 256, 0, 1, f);
  35. // }
  36. assert(params.lookupParams->isValid());
  37. SawOscillator<T, true>::setFrequency(params.sawParams, frequency);
  38. }
  39. template<typename T, bool frequencyCanBeNegative>
  40. inline T SinOscillator<T, frequencyCanBeNegative>::run(
  41. SinOscillatorState<T>& state, const SinOscillatorParams<T>& params)
  42. {
  43. const T temp = SawOscillator<T, frequencyCanBeNegative>::runSaw(state.sawState, params.sawParams);
  44. const T ret = LookupTable<T>::lookup(*params.lookupParams, temp);
  45. return ret;
  46. }
  47. template<typename T, bool frequencyCanBeNegative>
  48. inline void SinOscillator<T, frequencyCanBeNegative>::runQuadrature(
  49. T& output, T& outputQuadrature, SinOscillatorState<T>& state, const SinOscillatorParams<T>& params)
  50. {
  51. T saw, quadratureSaw;
  52. SawOscillator<T, frequencyCanBeNegative>::runQuadrature(saw, quadratureSaw, state.sawState, params.sawParams);
  53. output = LookupTable<T>::lookup(*params.lookupParams, saw);
  54. outputQuadrature = LookupTable<T>::lookup(*params.lookupParams, quadratureSaw);
  55. };
  56. template<typename T>
  57. class SinOscillatorParams
  58. {
  59. public:
  60. SawOscillatorParams<T> sawParams;
  61. // LookupTableParams<T> lookupParams;
  62. std::shared_ptr<LookupTableParams<T>> lookupParams;
  63. SinOscillatorParams()
  64. {
  65. lookupParams = ObjectCache<T>::getSinLookup();
  66. }
  67. SinOscillatorParams(const SinOscillatorParams&) = delete;
  68. };
  69. template<typename T>
  70. class SinOscillatorState
  71. {
  72. public:
  73. SawOscillatorState<T> sawState;
  74. };