SpectrumNormalizer.cpp 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #include <catch2/catch_approx.hpp>
  2. #include <catch2/catch_test_macros.hpp>
  3. #include "WallpaperEngine/Audio/SpectrumNormalizer.h"
  4. using Catch::Approx;
  5. using WallpaperEngine::Audio::SpectrumNormalizer;
  6. namespace {
  7. // a frame whose loudest fifth of the bands sit at the given level, and the rest well below it
  8. void settle (SpectrumNormalizer& normalizer, float peak, float seconds) {
  9. constexpr float frame = 0.023f;
  10. float levels[64] = {};
  11. for (int i = 0; i < 13; i++) {
  12. levels[i] = peak;
  13. }
  14. for (float t = 0.0f; t < seconds; t += frame) {
  15. normalizer.update (levels, 64, frame);
  16. }
  17. }
  18. } // namespace
  19. TEST_CASE ("Silence and capture noise stay flat") {
  20. SpectrumNormalizer normalizer;
  21. settle (normalizer, 0.0f, 2.0f);
  22. CHECK (normalizer.apply (0.0f) == 0.0f);
  23. CHECK (normalizer.apply (0.1f) == 0.0f);
  24. }
  25. TEST_CASE ("Loud music does not push every band to the top") {
  26. SpectrumNormalizer normalizer;
  27. settle (normalizer, 2.5f, 3.0f);
  28. CHECK (normalizer.apply (2.5f) == Approx (1.0f).margin (0.02f));
  29. // a band a little below the peak is clearly below the top, not locked to it
  30. CHECK (normalizer.apply (2.1f) < 0.7f);
  31. CHECK (normalizer.apply (2.1f) > 0.2f);
  32. CHECK (normalizer.apply (1.0f) == 0.0f);
  33. }
  34. TEST_CASE ("The same shape looks the same at any volume") {
  35. SpectrumNormalizer loud;
  36. SpectrumNormalizer louder;
  37. settle (loud, 2.0f, 3.0f);
  38. settle (louder, 3.0f, 3.0f);
  39. // 0.3 below the peak in both
  40. CHECK (loud.apply (1.7f) == Approx (louder.apply (2.7f)).margin (0.02f));
  41. }
  42. TEST_CASE ("Faint sounds are stretched to fill the range but not below the gate") {
  43. SpectrumNormalizer normalizer;
  44. settle (normalizer, 0.6f, 3.0f);
  45. CHECK (normalizer.apply (0.6f) == Approx (1.0f).margin (0.02f));
  46. CHECK (normalizer.apply (0.15f) == 0.0f);
  47. }
  48. TEST_CASE ("The reference follows the music back down over a few seconds") {
  49. SpectrumNormalizer normalizer;
  50. settle (normalizer, 3.0f, 2.0f);
  51. CHECK (normalizer.getReference () == Approx (3.0f).margin (0.05f));
  52. settle (normalizer, 1.0f, 0.5f);
  53. CHECK (normalizer.getReference () > 2.0f);
  54. settle (normalizer, 1.0f, 10.0f);
  55. CHECK (normalizer.getReference () < 1.2f);
  56. }
  57. TEST_CASE ("One outlier band does not flatten the rest of the spectrum") {
  58. SpectrumNormalizer normalizer;
  59. float levels[64];
  60. for (float& level : levels) {
  61. level = 1.5f;
  62. }
  63. levels[10] = 4.0f;
  64. for (int i = 0; i < 200; i++) {
  65. normalizer.update (levels, 64, 0.023f);
  66. }
  67. CHECK (normalizer.getReference () < 2.2f);
  68. CHECK (normalizer.apply (1.5f) > 0.5f);
  69. }