77 concept CDSFTopo = std::same_as<T, DualTopo> or std::same_as<T, Topology::Biquad>;
80 template<CDSFTopo TopoType>
84 static constexpr bool bDualTopo = std::same_as<TopoType, DualTopo>;
85 using StateType = std::conditional_t<bDualTopo, DualState, State::DirectFormI>;
88 [[nodiscard]] JPL_INLINE TopoType
BuildTopo(
float broadbandGain)
const;
105 template<Impl::CDSFTopo TopoType>
118 template<Impl::CDSFTopo TopoType>
126 [[nodiscard]] JPL_INLINE std::span<const float>
GetPrototypeLUT()
const {
return mProtoLUT; }
136 inline void SetGainsDb(
float Gl,
float Gm,
float Gh);
141 static inline void BuildProtoLUT(
float controlFrequency,
float sampleRate, std::vector<float>& outLUT);
144 [[nodiscard]]
static JPL_INLINE
int GetLUTOffset(
float frequency,
float controlFrequency);
147 [[nodiscard]]
inline float ReadPrototype(
int index)
const;
150 std::vector<float> mProtoLUT;
151 int mControlFrequencyIdx = 0;
154 float mInvSampleRate = -1.0f;
155 float mGl = 0.0f, mGm = 0.0f, mGh = 0.0f;
156 std::array<float, 9> mGinv;
171 template<Impl::CDSFTopo TopoType>
187 template<Impl::CDSFTopo TopoType>
216 float mInvSampleRate = 0.0f;
217 float mWeight = 0.0f;
218 float mEarlyGain = 0.0f;
232 template<Impl::CDSFTopo TopoType>
235 if constexpr (bDualTopo)
240 .BroadbandGain = broadbandGain
254 template<Impl::CDSFTopo TopoType>
268 SetFrequencies(params.
Fl, params.
Fm, params.
Fh);
271 template<Impl::CDSFTopo TopoType>
275 JPL_ASSERT(0.0f < Fl and Fl < Fm and Fm < Fh and Fh < (0.5f / mInvSampleRate));
278 Base::mLowShelfCache.t = ::tanf(JPL_PI * Fl * mInvSampleRate);
279 Base::mHighShelfCache.t = ::tanf(JPL_PI * Fh * mInvSampleRate);
281 const int center = mControlFrequencyIdx;
282 const float Glm = ReadPrototype(center + GetLUTOffset(Fm, Fl));
283 const float Glh = ReadPrototype(center + GetLUTOffset(Fh, Fl));
284 const float Ghl = ReadPrototype(center - GetLUTOffset(Fl, Fh));
285 const float Ghm = ReadPrototype(center - GetLUTOffset(Fm, Fh));
289 std::array<float, 9> G
297 std::array<float, 9> G1{
298 Glm - Ghm * Glh, Ghl * Glh - 1.0f, Ghm - Ghl * Glm,
299 Ghm - 1.0f, 1.0f - Ghl, Ghl - Ghm,
300 Glh - Glm, 1.0f - Glh, Glm - 1.0f
302 const float detG = (Glm + Ghm - Ghm * Glh + Ghl * Glh - Ghl * Glm - 1.0f);
304 JPL_ASSERT(std::isfinite(detG) and detG != 0.0f,
305 "Dual-shelf gain matrix is singular or non-finite. "
306 "Control frequencies must produce independent LUT constraints; "
307 "increase their spacing.");
309 const float invDetG = 1.0f / detG;
310 for (
uint32 i = 0; i < G1.size(); ++i)
311 mGinv[i] = G1[i] * invDetG;
314 SetGainsDb(mGl, mGm, mGh);
317 template<Impl::CDSFTopo TopoType>
326 std::array<float, 3> Ks = {
327 mGinv[0] * mGl + mGinv[1] * mGm + mGinv[2] * mGh,
328 mGinv[3] * mGl + mGinv[4] * mGm + mGinv[5] * mGh,
329 mGinv[6] * mGl + mGinv[7] * mGm + mGinv[8] * mGh
335 auto& [K, Kl, Kh] = Ks;
342 Base::mLowShelfCache.sqrtK = ::sqrtf(Kl);
343 Base::mLowShelfCache.gain = Kl;
345 Base::mHighShelfCache.sqrtK = ::sqrtf(Kh);
346 Base::mHighShelfCache.gain = Kh;
348 static_cast<TopoType&
>(*this) = Base::BuildTopo(K);
351 template<Impl::CDSFTopo TopoType>
354 static constexpr float cMinFrequency = 20.0f;
362 template<Impl::CDSFTopo TopoType>
363 JPL_INLINE
int DualShelfEQBase<TopoType>::GetLUTOffset(
float frequency,
float controlFrequency)
365 return static_cast<int>(std::lround(12.0 * std::log2(frequency / controlFrequency)));
368 template<Impl::CDSFTopo TopoType>
369 inline float DualShelfEQBase<TopoType>::ReadPrototype(
int index)
const
376 if (
static_cast<std::size_t
>(index) >= mProtoLUT.size())
379 return mProtoLUT[
static_cast<std::size_t
>(index)];
383 template<Impl::CDSFTopo TopoType>
387 PrepareLinear(params);
390 template<Impl::CDSFTopo TopoType>
401 Base::mLowShelfCache.t = ::tanf(JPL_PI * params.
Fl * mInvSampleRate);
402 Base::mHighShelfCache.t = ::tanf(JPL_PI * params.
Fh * mInvSampleRate);
404 SetGainLinear(params.
Gain);
407 template<Impl::CDSFTopo TopoType>
411 JPL_ASSERT(0.0f < Fl and Fl < Fh and Fh < (0.5f / mInvSampleRate));
413 Base::mLowShelfCache.t = ::tanf(JPL_PI * Fl * mInvSampleRate);
414 Base::mHighShelfCache.t = ::tanf(JPL_PI * Fh * mInvSampleRate);
416 static_cast<TopoType&
>(*this) = Base::BuildTopo(mEarlyGain);
419 template<Impl::CDSFTopo TopoType>
424 JPL_ASSERT(weight >= 0.0f and weight <= 1.0f);
430 template<Impl::CDSFTopo TopoType>
436 mEarlyGain = ::powf(gain, mWeight);
438 const float lowShelfGain = 1.0f / mEarlyGain;
439 const float highShelfGain = gain * lowShelfGain;
441 Base::mLowShelfCache.sqrtK = ::sqrtf(lowShelfGain);
442 Base::mLowShelfCache.gain = lowShelfGain;
444 Base::mHighShelfCache.sqrtK = ::sqrtf(highShelfGain);
445 Base::mHighShelfCache.gain = highShelfGain;
447 static_cast<TopoType&
>(*this) = Base::BuildTopo(mEarlyGain);
#define JPL_ASSERT(inExpression,...)
Main assert macro, usage: JPL_ASSERT(condition, message) or JPL_ASSERT(condition)
Definition ErrorReporting.h:80
Definition DualShelfFilter.h:120
void SetFrequencies(float Fl, float Fm, float Fh)
Set the desired frequencies of the control points.
Definition DualShelfFilter.h:272
typename Base::StateType StateType
Definition DualShelfFilter.h:123
void SetGainsDb(float Gl, float Gm, float Gh)
Set the desired gains at the control points.
Definition DualShelfFilter.h:318
JPL_INLINE void Prepare(const DualShelfEQParams ¶ms)
Definition DualShelfFilter.h:255
JPL_INLINE std::span< const float > GetPrototypeLUT() const
Definition DualShelfFilter.h:126
Definition DualShelfFilter.h:189
JPL_INLINE void SetGainLinear(float gain, float weight)
Definition DualShelfFilter.h:420
JPL_INLINE void SetFrequencies(float Fl, float Fh)
Set the desired frequencies of the control points.
Definition DualShelfFilter.h:408
JPL_INLINE void Prepare(DualShelfFilterParams params)
Definition DualShelfFilter.h:384
typename Base::StateType StateType
Definition DualShelfFilter.h:192
void PrepareLinear(const DualShelfFilterParams ¶ms)
Definition DualShelfFilter.h:391
Definition DualShelfFilter.h:82
Cache::Shelf mLowShelfCache
Definition DualShelfFilter.h:91
Cache::Shelf mHighShelfCache
Definition DualShelfFilter.h:92
static constexpr bool bDualTopo
Definition DualShelfFilter.h:84
JPL_INLINE TopoType BuildTopo(float broadbandGain) const
Definition DualShelfFilter.h:233
std::conditional_t< bDualTopo, DualState, State::DirectFormI > StateType
Definition DualShelfFilter.h:85
DSF (EQ) can be either Biquad, or DualTopo (Dual One-Pole)
Definition DualShelfFilter.h:77
void ComputeFilterResponse_dB(const FilterType &filter, float sampleRate, std::vector< float > &outMagnitudes)
Definition FilterComponents.h:383
Definition AcousticMaterial.h:36
std::uint32_t uint32
Definition Core.h:311
JPL_INLINE T dBToGain(const T &dB) noexcept
Definition DecibelsAndGain.h:40
Definition FilterComponents.h:59
Definition DualShelfFilter.h:98
float Gm
Definition DualShelfFilter.h:100
float Fh
Definition DualShelfFilter.h:99
float SampleRate
Definition DualShelfFilter.h:101
float Fm
Definition DualShelfFilter.h:99
float Gl
Definition DualShelfFilter.h:100
float PrototypeControlFrequency
Definition DualShelfFilter.h:102
float Fl
Definition DualShelfFilter.h:99
float Gh
Definition DualShelfFilter.h:100
Definition DualShelfFilter.h:161
float Weight
Definition DualShelfFilter.h:168
float Gain
Definition DualShelfFilter.h:163
float Fl
Definition DualShelfFilter.h:162
float SampleRate
Definition DualShelfFilter.h:164
float Fh
Definition DualShelfFilter.h:162
Definition DualShelfFilter.h:64
JPL_INLINE float Process(float x, const DualTopo &topo)
Definition DualShelfFilter.h:68
State::DirectFormIOnePole A
Definition DualShelfFilter.h:65
State::DirectFormIOnePole B
Definition DualShelfFilter.h:66
Definition DualShelfFilter.h:45
JPL_INLINE void SetCoefficients(const DualTopo &other)
Definition DualShelfFilter.h:55
Topology::OnePole A
Definition DualShelfFilter.h:46
float BroadbandGain
Definition DualShelfFilter.h:48
JPL_INLINE float CalculateResponse(float normalizedFrequency) const
Definition DualShelfFilter.h:50
Topology::OnePole B
Definition DualShelfFilter.h:47
static Biquad Combine(const OnePole &low, const OnePole &high, float broadbandGain)
Definition FilterComponents.h:479
Definition FilterComponents.h:81
static JPL_INLINE OnePole MakeHighShelf(float frequency, float sampleRate, float gain)
Definition FilterComponents.h:428
Sample CalculateResponse(float normalizedFrequency) const
Definition FilterComponents.h:390
static JPL_INLINE OnePole MakeLowShelf(float frequency, float sampleRate, float gain)
Definition FilterComponents.h:399