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.

89 lines
2.2KB

  1. #pragma once
  2. #include <cmath>
  3. #include <vector>
  4. /**
  5. * Utilities for generating and analyzing test signals.
  6. *
  7. * All test signals are +-1volt unless otherwise specified
  8. */
  9. template <typename T>
  10. class TestSignal
  11. {
  12. public:
  13. TestSignal() = delete; // we are only static
  14. // freq is normalized f / sr
  15. static void generateSin(T * output, int numSamples, T freq);
  16. static double getRMS(const T * signal, int numSamples);
  17. /**
  18. * Measure the gain of a processing lambda at a specificed frequency
  19. */
  20. static T measureGain(T freq, std::function<T(T)> func);
  21. /**
  22. * Measure the RMS output of a generator lambda
  23. */
  24. static double measureOutput(int samples, std::function<T()> func);
  25. };
  26. template <typename T>
  27. inline void TestSignal<T>::generateSin(T * output, int numSamples, T freq)
  28. {
  29. assert(freq < .5);
  30. assert(freq > 0);
  31. double phase = 0;
  32. for (int i = 0; i < numSamples; ++i) {
  33. const double phi = phase * 2 * AudioMath::Pi;
  34. output[i] = T(std::sin(phi));
  35. phase += freq;
  36. // should we normalize the phase here, instead of letting it grow?
  37. }
  38. }
  39. template <typename T>
  40. inline double TestSignal<T>::getRMS(const T * signal, int numSamples)
  41. {
  42. assert(numSamples > 0);
  43. double sumSq = 0;
  44. for (int i = 0; i < numSamples; ++i) {
  45. //printf("getRMS, i=%d, samp=%d\n")
  46. sumSq += double(signal[i]) * signal[i];
  47. }
  48. return std::sqrt(sumSq / numSamples);
  49. }
  50. template <typename T>
  51. inline T TestSignal<T>::measureGain(T freq, std::function<T(T)> func)
  52. {
  53. const int size = 60000;
  54. T input[size];
  55. T output[size];
  56. //generateSin(T * output, int numSamples, T freq);
  57. TestSignal<T>::generateSin(input, size, freq);
  58. for (int i = 0; i < size; ++i) {
  59. output[i] = func(input[i]);
  60. }
  61. T vo = T(TestSignal<T>::getRMS(output, size));
  62. T vi = T(TestSignal<T>::getRMS(input, size));
  63. return vo / vi;
  64. }
  65. template <typename T>
  66. inline double TestSignal<T>::measureOutput(int numSamples, std::function<T()> func)
  67. {
  68. //std::unique_ptr<T> buffer(new T[numSamples]);
  69. std::vector<T> buffer(numSamples);
  70. for (int i = 0; i < numSamples; ++i) {
  71. buffer[i] = func();
  72. }
  73. return getRMS(buffer.data(), numSamples);
  74. }