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.

109 lines
2.4KB

  1. #include "asserts.h"
  2. #include "poly.h"
  3. #include "Analyzer.h"
  4. #include "Shaper.h"
  5. #include "SinOscillator.h"
  6. #include "TestComposite.h"
  7. #include "TestSignal.h"
  8. static void test0()
  9. {
  10. Poly<float, 10> poly;
  11. float x = poly.run(0, 1);
  12. assertEQ(x, 0);
  13. x = poly.run(1, 1);
  14. assertEQ(x, 0);
  15. poly.setGain(0, 1);
  16. x = poly.run(0, 1);
  17. assertEQ(x, 0);
  18. }
  19. static void test1()
  20. {
  21. Poly<float, 10> poly;
  22. poly.setGain(0, 1);
  23. float x = poly.run(1, 0);
  24. assertNE(x, 0);
  25. }
  26. static void testPureTerm(int term)
  27. {
  28. float desiredFreq = 500.0f;
  29. int numSamples = 16 * 1024;
  30. const float sampleRate = 44100.0f;
  31. double actualFreq = Analyzer::makeEvenPeriod(desiredFreq, sampleRate, numSamples);
  32. SinOscillatorParams<float> sinParams;
  33. SinOscillatorState<float> sinState;
  34. SinOscillator<float, false>::setFrequency(sinParams, float(actualFreq / sampleRate));
  35. Poly<double, 10> poly;
  36. poly.setGain(term, 1);
  37. FFTDataCpx spectrum(numSamples);
  38. Analyzer::getSpectrum(spectrum, false, [&sinState, &sinParams, &poly]() {
  39. float sin = SinOscillator<float, false>::run(sinState, sinParams);
  40. const float x = poly.run(sin, 1);
  41. return x;
  42. });
  43. const int order = term + 1;
  44. Analyzer::assertSingleFreq(spectrum, float(actualFreq * order), sampleRate);
  45. }
  46. static void testTerms()
  47. {
  48. for (int i = 0; i < 10; ++i) {
  49. testPureTerm(i);
  50. }
  51. }
  52. static void _testDC(int term, float gain)
  53. {
  54. Poly<double, 10> poly;
  55. poly.setGain(term, 1);
  56. // Will generate sine at fs * .01 (around 400 Hz).
  57. SinOscillatorParams<float> sinp;
  58. SinOscillatorState<float> sins;
  59. SinOscillator<float, false>::setFrequency(sinp, .01f);
  60. // Run sin through Chebyshevs at specified gain
  61. auto func = [&sins, &sinp, &poly, gain]() {
  62. const float sin = gain * SinOscillator<float, false>::run(sins, sinp);
  63. const float x = poly.run(sin, gain);
  64. return x;
  65. };
  66. const int bufferSize = 16 * 1024;
  67. float buffer[bufferSize];
  68. for (int i = 0; i < bufferSize; ++i) {
  69. buffer[i] = func();
  70. }
  71. double dc = TestSignal<float>::getDC(buffer, bufferSize);
  72. assertClose(dc, 0, .001);
  73. }
  74. static void testDC()
  75. {
  76. for (int i = 0; i < 10; ++i) {
  77. _testDC(i, 1);
  78. }
  79. for (int i = 0; i < 10; ++i) {
  80. _testDC(i, .56f);
  81. _testDC(i, .83f);
  82. _testDC(i, .17f);
  83. }
  84. }
  85. void testPoly()
  86. {
  87. test0();
  88. test1();
  89. testDC();
  90. testTerms();
  91. }