| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 | #pragma once#include <stdint.h>       // for uint32_t#include <map>            // for map#include <memory>         // for unique_ptr, allocator#include <mutex>          // for scoped_lock#include <stdexcept>      // for invalid_argument#include <string>         // for string, operator<, hash, operator==#include <unordered_map>  // for operator!=, unordered_map, __hash_map_c...#include <utility>        // for pair#include <vector>         // for vector#include "AudioTransform.h"   // for AudioTransform#include "StreamInfo.h"       // for StreamInfo#include "TransformConfig.h"  // for TransformConfigextern "C" int dsps_biquad_f32_ae32(const float* input, float* output, int len,                                    float* coef, float* w);namespace bell {class Biquad : public bell::AudioTransform { public:  Biquad();  ~Biquad(){};  enum class Type {    Free,    Highpass,    Lowpass,    HighpassFO,    LowpassFO,    Peaking,    Highshelf,    HighshelfFO,    Lowshelf,    LowshelfFO,    Notch,    Bandpass,    Allpass,    AllpassFO  };  std::map<std::string, float> currentConfig;  std::unordered_map<std::string, Type> const strMapType = {      {"free", Type::Free},      {"highpass", Type::Highpass},      {"lowpass", Type::Lowpass},      {"highpass_fo", Type::HighpassFO},      {"lowpass_fo", Type::LowpassFO},      {"peaking", Type::Peaking},      {"highshelf", Type::Highshelf},      {"highshelf_fo", Type::HighpassFO},      {"lowshelf", Type::Lowshelf},      {"lowshelf_fo", Type::LowpassFO},      {"notch", Type::Notch},      {"bandpass", Type::Bandpass},      {"allpass", Type::Allpass},      {"allpass_fo", Type::AllpassFO},  };  float freq, q, gain;  int channel;  Biquad::Type type;  std::unique_ptr<StreamInfo> process(      std::unique_ptr<StreamInfo> data) override;  void configure(Type type, std::map<std::string, float>& config);  void sampleRateChanged(uint32_t sampleRate) override;  void reconfigure() override {    std::scoped_lock lock(this->accessMutex);    std::map<std::string, float> biquadConfig;    this->channel = config->getChannels()[0];    float invalid = -0x7C;    auto type = config->getString("biquad_type");    float bandwidth = config->getFloat("bandwidth", false, invalid);    float slope = config->getFloat("slope", false, invalid);    float gain = config->getFloat("gain", false, invalid);    float frequency = config->getFloat("frequency", false, invalid);    float q = config->getFloat("q", false, invalid);    if (currentConfig["bandwidth"] == bandwidth &&        currentConfig["slope"] == slope && currentConfig["gain"] == gain &&        currentConfig["frequency"] == frequency && currentConfig["q"] == q) {      return;    }    if (bandwidth != invalid)      biquadConfig["bandwidth"] = bandwidth;    if (slope != invalid)      biquadConfig["slope"] = slope;    if (gain != invalid)      biquadConfig["gain"] = gain;    if (frequency != invalid)      biquadConfig["freq"] = frequency;    if (q != invalid)      biquadConfig["q"] = q;    if (type == "free") {      biquadConfig["a1"] = config->getFloat("a1");      biquadConfig["a2"] = config->getFloat("a2");      biquadConfig["b0"] = config->getFloat("b0");      biquadConfig["b1"] = config->getFloat("b1");      biquadConfig["b2"] = config->getFloat("b2");    }    auto typeElement = strMapType.find(type);    if (typeElement != strMapType.end()) {      this->configure(typeElement->second, biquadConfig);    } else {      throw std::invalid_argument("No biquad of type " + type);    }  } private:  float coeffs[5];  float w[2] = {1.0, 1.0};  float sampleRate = 44100;  // Generator methods for different filter types  void highPassCoEffs(float f, float q);  void highPassFOCoEffs(float f);  void lowPassCoEffs(float f, float q);  void lowPassFOCoEffs(float f);  void peakCoEffs(float f, float gain, float q);  void peakCoEffsBandwidth(float f, float gain, float bandwidth);  void highShelfCoEffs(float f, float gain, float q);  void highShelfCoEffsSlope(float f, float gain, float slope);  void highShelfFOCoEffs(float f, float gain);  void lowShelfCoEffs(float f, float gain, float q);  void lowShelfCoEffsSlope(float f, float gain, float slope);  void lowShelfFOCoEffs(float f, float gain);  void notchCoEffs(float f, float gain, float q);  void notchCoEffsBandwidth(float f, float gain, float bandwidth);  void bandPassCoEffs(float f, float q);  void bandPassCoEffsBandwidth(float f, float bandwidth);  void allPassCoEffs(float f, float q);  void allPassCoEffsBandwidth(float f, float bandwidth);  void allPassFOCoEffs(float f);  void normalizeCoEffs(float a0, float a1, float a2, float b0, float b1,                       float b2);};}  // namespace bell
 |