Biquad.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #pragma once
  2. #include <stdint.h> // for uint32_t
  3. #include <map> // for map
  4. #include <memory> // for unique_ptr, allocator
  5. #include <mutex> // for scoped_lock
  6. #include <stdexcept> // for invalid_argument
  7. #include <string> // for string, operator<, hash, operator==
  8. #include <unordered_map> // for operator!=, unordered_map, __hash_map_c...
  9. #include <utility> // for pair
  10. #include <vector> // for vector
  11. #include "AudioTransform.h" // for AudioTransform
  12. #include "StreamInfo.h" // for StreamInfo
  13. #include "TransformConfig.h" // for TransformConfig
  14. extern "C" int dsps_biquad_f32_ae32(const float* input, float* output, int len,
  15. float* coef, float* w);
  16. namespace bell {
  17. class Biquad : public bell::AudioTransform {
  18. public:
  19. Biquad();
  20. ~Biquad(){};
  21. enum class Type {
  22. Free,
  23. Highpass,
  24. Lowpass,
  25. HighpassFO,
  26. LowpassFO,
  27. Peaking,
  28. Highshelf,
  29. HighshelfFO,
  30. Lowshelf,
  31. LowshelfFO,
  32. Notch,
  33. Bandpass,
  34. Allpass,
  35. AllpassFO
  36. };
  37. std::map<std::string, float> currentConfig;
  38. std::unordered_map<std::string, Type> const strMapType = {
  39. {"free", Type::Free},
  40. {"highpass", Type::Highpass},
  41. {"lowpass", Type::Lowpass},
  42. {"highpass_fo", Type::HighpassFO},
  43. {"lowpass_fo", Type::LowpassFO},
  44. {"peaking", Type::Peaking},
  45. {"highshelf", Type::Highshelf},
  46. {"highshelf_fo", Type::HighpassFO},
  47. {"lowshelf", Type::Lowshelf},
  48. {"lowshelf_fo", Type::LowpassFO},
  49. {"notch", Type::Notch},
  50. {"bandpass", Type::Bandpass},
  51. {"allpass", Type::Allpass},
  52. {"allpass_fo", Type::AllpassFO},
  53. };
  54. float freq, q, gain;
  55. int channel;
  56. Biquad::Type type;
  57. std::unique_ptr<StreamInfo> process(
  58. std::unique_ptr<StreamInfo> data) override;
  59. void configure(Type type, std::map<std::string, float>& config);
  60. void sampleRateChanged(uint32_t sampleRate) override;
  61. void reconfigure() override {
  62. std::scoped_lock lock(this->accessMutex);
  63. std::map<std::string, float> biquadConfig;
  64. this->channel = config->getChannels()[0];
  65. float invalid = -0x7C;
  66. auto type = config->getString("biquad_type");
  67. float bandwidth = config->getFloat("bandwidth", false, invalid);
  68. float slope = config->getFloat("slope", false, invalid);
  69. float gain = config->getFloat("gain", false, invalid);
  70. float frequency = config->getFloat("frequency", false, invalid);
  71. float q = config->getFloat("q", false, invalid);
  72. if (currentConfig["bandwidth"] == bandwidth &&
  73. currentConfig["slope"] == slope && currentConfig["gain"] == gain &&
  74. currentConfig["frequency"] == frequency && currentConfig["q"] == q) {
  75. return;
  76. }
  77. if (bandwidth != invalid)
  78. biquadConfig["bandwidth"] = bandwidth;
  79. if (slope != invalid)
  80. biquadConfig["slope"] = slope;
  81. if (gain != invalid)
  82. biquadConfig["gain"] = gain;
  83. if (frequency != invalid)
  84. biquadConfig["freq"] = frequency;
  85. if (q != invalid)
  86. biquadConfig["q"] = q;
  87. if (type == "free") {
  88. biquadConfig["a1"] = config->getFloat("a1");
  89. biquadConfig["a2"] = config->getFloat("a2");
  90. biquadConfig["b0"] = config->getFloat("b0");
  91. biquadConfig["b1"] = config->getFloat("b1");
  92. biquadConfig["b2"] = config->getFloat("b2");
  93. }
  94. auto typeElement = strMapType.find(type);
  95. if (typeElement != strMapType.end()) {
  96. this->configure(typeElement->second, biquadConfig);
  97. } else {
  98. throw std::invalid_argument("No biquad of type " + type);
  99. }
  100. }
  101. private:
  102. float coeffs[5];
  103. float w[2] = {1.0, 1.0};
  104. float sampleRate = 44100;
  105. // Generator methods for different filter types
  106. void highPassCoEffs(float f, float q);
  107. void highPassFOCoEffs(float f);
  108. void lowPassCoEffs(float f, float q);
  109. void lowPassFOCoEffs(float f);
  110. void peakCoEffs(float f, float gain, float q);
  111. void peakCoEffsBandwidth(float f, float gain, float bandwidth);
  112. void highShelfCoEffs(float f, float gain, float q);
  113. void highShelfCoEffsSlope(float f, float gain, float slope);
  114. void highShelfFOCoEffs(float f, float gain);
  115. void lowShelfCoEffs(float f, float gain, float q);
  116. void lowShelfCoEffsSlope(float f, float gain, float slope);
  117. void lowShelfFOCoEffs(float f, float gain);
  118. void notchCoEffs(float f, float gain, float q);
  119. void notchCoEffsBandwidth(float f, float gain, float bandwidth);
  120. void bandPassCoEffs(float f, float q);
  121. void bandPassCoEffsBandwidth(float f, float bandwidth);
  122. void allPassCoEffs(float f, float q);
  123. void allPassCoEffsBandwidth(float f, float bandwidth);
  124. void allPassFOCoEffs(float f);
  125. void normalizeCoEffs(float a0, float a1, float a2, float b0, float b1,
  126. float b2);
  127. };
  128. } // namespace bell