36 template<
class FilterType>
37 void ComputeFilterResponse(
const FilterType& filter,
float sampleRate, std::vector<float>& outMagnitudes);
39 template<
class FilterType>
50 template<std::
floating_po
int T>
70 [[nodiscard]]
static JPL_INLINE
BiquadShelf From(
double normalizedFrequency);
90 [[nodiscard]]
static JPL_INLINE
OnePole MakeLowShelf(
float frequency,
float sampleRate,
float gain);
91 [[nodiscard]]
static JPL_INLINE
OnePole MakeHighShelf(
float frequency,
float sampleRate,
float gain);
93 [[nodiscard]]
static JPL_INLINE
OnePole MakeLowShelf(
float normalizedFrequency,
float gain);
107 [[nodiscard]]
inline std::complex<double>
CalculateResponse(
float normalizedFrequency)
const;
112 [[nodiscard]]
static JPL_INLINE
Biquad MakeHighShelf(
double normalizedFrequency,
double gainDb);
115 template<
class StateType>
118 template<
class StateType>
124 template<std::
size_t N>
129 [[nodiscard]] JPL_INLINE std::complex<double>
CalculateResponse(
double normalizedFrequency)
const;
188 s1 = biquad.
b1 * x - biquad.
a1 * y +
s2;
189 s2 = biquad.
b2 * x - biquad.
a2 * y;
194 template<std::
size_t N>
199 std::array<State::DirectFormI, N>
States;
220 namespace FilterUtils
223 template<std::
floating_po
int T>
244 return iterator(mMin, mMax, mMin > mMax);
252 [[nodiscard]]
constexpr std::size_t
size() const noexcept
260 if (std::is_constant_evaluated())
265 while (frequency <= mMax)
275 return static_cast<std::size_t
>(std::floor(T(12) * std::log2(mMax / mMin))) + 1;
289 constexpr iterator() : mCurrent(0), mMaxValue(0), bIsEnd(true) {}
291 : mCurrent(start), mMaxValue(
max), bIsEnd(
end)
295 constexpr T
operator*() const noexcept {
return mCurrent; }
302 bIsEnd = mCurrent - mMaxValue > T(1e-9);
316 if (bIsEnd and other.bIsEnd)
318 if (bIsEnd or other.bIsEnd)
337 template<
bool bDecibels,
class FilterType>
342 outMagnitudes.clear();
343 outMagnitudes.reserve(semitoneGrid.size());
345 const float invSampleRate = 1.0f / sampleRate;
347 auto projection = [](
auto&& v)
349 using Func =
decltype(&FilterType::CalculateResponse);
350 static constexpr bool bIsComplex =
351 std::same_as<std::invoke_result_t<Func, FilterType, float>, std::complex<double>> or
352 std::same_as<std::invoke_result_t<Func, FilterType, double>, std::complex<double>>;
354 if constexpr (bIsComplex)
364 for (
float frequency : semitoneGrid)
365 outMagnitudes.push_back(projection(filter.CalculateResponse(frequency * invSampleRate)));
367 if constexpr (bDecibels)
369 for (
float& magnitude : outMagnitudes)
376 template<
class FilterType>
382 template<
class FilterType>
392 const Sample omega = JPL_TWO_PI * normalizedFrequency;
393 const Sample cosOmega = ::cosf(omega);
394 const Sample numSq = (b0 * b0) + (b1 * b1) + (2.0f * b0 * b1 * cosOmega);
395 const Sample denSq = 1.0f + (a1 * a1) + (2.0f * a1 * cosOmega);
396 return ::sqrtf(numSq / denSq);
406 const float t = ::tanf(JPL_PI * normalizedFrequency);
407 const float sqrtK = ::sqrtf(gain);
408 return MakeLowShelf(
Cache::Shelf{ .t = t, .sqrtK = sqrtK, .gain = gain });
430 return MakeHighShelf(frequency / sampleRate, gain);
435 const float t = ::tanf(JPL_PI * normalizedFrequency);
436 const float sqrtK = ::sqrtf(gain);
437 return MakeHighShelf(
Cache::Shelf{ .t = t, .sqrtK = sqrtK, .gain = gain });
460 using Complex = std::complex<double>;
461 const double omega = 2 * std::numbers::pi_v<double> *normalizedFrequency;
462 const Complex czn1 = std::polar(1.0, -omega);
463 const Complex czn2 = std::polar(1.0, -2.0 * omega);
469 ct = ct +
static_cast<double>(b1) * czn1;
470 ct = ct +
static_cast<double>(b2) * czn2;
471 cb = cb +
static_cast<double>(a1) * czn1;
472 cb = cb +
static_cast<double>(a2) * czn2;
482 .b0 = broadbandGain * (low.
b0 * high.
b0),
483 .b1 = broadbandGain * (low.
b0 * high.
b1 + low.
b1 * high.
b0),
484 .b2 = broadbandGain * (low.
b1 * high.
b1),
485 .a1 = low.
a1 + high.
a1,
486 .a2 = low.
a1 * high.
a1
497 const double omega = 2.0 * std::numbers::pi_v<double> * normalizedFrequency;
505 static constexpr double log2_10_over40 = std::numbers::ln10 * std::numbers::log2e / 40.0;
506 const double A = std::exp2(gainDb * log2_10_over40);
511 const double A_plus_1 = A + 1.0;
512 const double A_minus_1 = A - 1.0;
513 const double A_minus_1_cos = A_minus_1 * cache.
cosOmega;
514 const double A_plus_1_cos = A_plus_1 * cache.
cosOmega;
516 const double b0 = A * (A_plus_1 + A_minus_1_cos + beta);
517 const double b1 = -2.0 * A * (A_minus_1 + A_plus_1_cos);
518 const double b2 = A * (A_plus_1 + A_minus_1_cos - beta);
519 const double a0 = A_plus_1 - A_minus_1_cos + beta;
520 const double a1 = 2.0 * (A_minus_1 - A_plus_1_cos);
521 const double a2 = A_plus_1 - A_minus_1_cos - beta;
523 const double inv_a0 = 1.0 / a0;
525 .b0 =
static_cast<float>(b0 * inv_a0),
526 .b1 =
static_cast<float>(b1 * inv_a0),
527 .b2 =
static_cast<float>(b2 * inv_a0),
528 .a1 =
static_cast<float>(a1 * inv_a0),
529 .a2 =
static_cast<float>(a2 * inv_a0)
533 template<
class StateType>
539 const Sample t = 1.0f / samples.size();
540 const Sample db0 = t * (b0 - previous.
b0);
541 const Sample db1 = t * (b1 - previous.
b1);
542 const Sample db2 = t * (b2 - previous.
b2);
543 const Sample da1 = t * (a1 - previous.
a1);
544 const Sample da2 = t * (a2 - previous.
a2);
546 for (
Sample& sample : samples)
553 sample = state.Process(sample, previous);
559 template<
class StateType>
565 const uint32 numFrames = 1 + (samples.size() - 1) / stride;
567 const Sample db0 = t * (b0 - previous.
b0);
568 const Sample db1 = t * (b1 - previous.
b1);
569 const Sample db2 = t * (b2 - previous.
b2);
570 const Sample da1 = t * (a1 - previous.
a1);
571 const Sample da2 = t * (a2 - previous.
a2);
573 for (
uint32 s = 0; s < samples.size(); s += stride)
580 samples[s] = state.Process(samples[s], previous);
592 template<std::
size_t N>
596 using Complex = std::complex<double>;
597 const double omega = 2.0f * std::numbers::pi_v<double> *normalizedFrequency;
598 const Complex czn1 = std::polar(1.0, -omega);
599 const Complex czn2 = std::polar(1.0, -2.0 * omega);
603 for (
const Biquad& stage : Stages)
606 Complex ct(stage.b0);
607 ct = ct +
static_cast<double>(stage.b1) * czn1;
608 ct = ct +
static_cast<double>(stage.b2) * czn2;
609 cb = cb +
static_cast<double>(stage.a1) * czn1;
610 cb = cb +
static_cast<double>(stage.a2) * czn2;
Definition FilterComponents.h:281
std::ptrdiff_t difference_type
Definition FilterComponents.h:286
constexpr iterator()
Definition FilterComponents.h:289
constexpr T operator*() const noexcept
Definition FilterComponents.h:295
T value_type
Definition FilterComponents.h:285
constexpr bool operator==(const iterator &other) const noexcept
Definition FilterComponents.h:314
constexpr iterator(T start, T max, bool end=false)
Definition FilterComponents.h:290
std::forward_iterator_tag iterator_concept
Definition FilterComponents.h:283
std::forward_iterator_tag iterator_category
Definition FilterComponents.h:284
constexpr iterator operator++(int) noexcept
Definition FilterComponents.h:307
constexpr iterator & operator++() noexcept
Definition FilterComponents.h:297
Definition FilterComponents.h:225
constexpr SemitoneGridView(T minFrequency, T maxFrequency)
Definition FilterComponents.h:231
static constexpr T cMinFrequency
Definition FilterComponents.h:228
constexpr iterator begin() const noexcept
Definition FilterComponents.h:242
constexpr SemitoneGridView(T maxFrequency)
Definition FilterComponents.h:235
constexpr std::size_t size() const noexcept
Definition FilterComponents.h:252
constexpr iterator end() const noexcept
Definition FilterComponents.h:247
static constexpr T cSemitoneRatio
Definition FilterComponents.h:227
void ComputeFilterResponse(const FilterType &filter, float sampleRate, std::vector< float > &outMagnitudes)
Definition FilterComponents.h:338
void ComputeFilterResponse_dB(const FilterType &filter, float sampleRate, std::vector< float > &outMagnitudes)
Definition FilterComponents.h:383
void ComputeFilterResponse(const FilterType &filter, float sampleRate, std::vector< float > &outMagnitudes)
Definition FilterComponents.h:377
JPL_INLINE constexpr T Sqrt(T x) noexcept
Definition Math.h:269
JPL_INLINE constexpr bool IsNearlyEqual(T a, T b, T tolerance=JPL_FLOAT_EPS_V< T >) noexcept
Definition Math.h:152
JPL_INLINE std::pair< T, T > SinCos(T value) noexcept
Definition Math.h:164
Definition AcousticMaterial.h:36
std::uint32_t uint32
Definition Core.h:311
JPL_INLINE T GainTodB(const T &gainFactor) noexcept
Definition DecibelsAndGain.h:75
JPL_INLINE simd max(const simd &a, const simd &b) noexcept
Element-wise max.
Definition SIMD.h:1799
Definition ChannelMap.h:281
Definition FilterComponents.h:66
double cosOmega
Definition FilterComponents.h:67
static JPL_INLINE BiquadShelf From(double normalizedFrequency)
Definition FilterComponents.h:495
double sqrt2SinOmega
Definition FilterComponents.h:68
Definition FilterComponents.h:59
float gain
Definition FilterComponents.h:62
float sqrtK
Definition FilterComponents.h:61
float t
Definition FilterComponents.h:60
Definition FilterComponents.h:196
std::array< State::DirectFormI, N > States
Definition FilterComponents.h:199
JPL_INLINE Sample Process(float x, const Topology::Cascade< N > &topo)
Definition FilterComponents.h:201
float Sample
Definition FilterComponents.h:197
Definition FilterComponents.h:101
Sample a2
Definition FilterComponents.h:105
float Sample
Definition FilterComponents.h:102
Sample b1
Definition FilterComponents.h:104
static JPL_INLINE Biquad MakeHighShelf(double normalizedFrequency, double gainDb)
Definition FilterComponents.h:490
Sample a1
Definition FilterComponents.h:105
Sample b0
Definition FilterComponents.h:104
JPL_INLINE void SetCoefficients(const Topology::Biquad &other)
Definition FilterComponents.h:586
Sample b2
Definition FilterComponents.h:104
std::complex< double > CalculateResponse(float normalizedFrequency) const
Definition FilterComponents.h:457
void ProcessInterpolating(std::span< Sample > samples, StateType &state, Biquad &previous) const
Definition FilterComponents.h:534
static Biquad Combine(const OnePole &low, const OnePole &high, float broadbandGain)
Definition FilterComponents.h:479
Definition FilterComponents.h:126
JPL_INLINE std::complex< double > CalculateResponse(double normalizedFrequency) const
Definition FilterComponents.h:593
std::array< Biquad, N > Stages
Definition FilterComponents.h:127
Definition FilterComponents.h:81
Sample b0
Definition FilterComponents.h:84
static JPL_INLINE OnePole MakeHighShelf(float frequency, float sampleRate, float gain)
Definition FilterComponents.h:428
Sample a1
Definition FilterComponents.h:85
float Sample
Definition FilterComponents.h:82
Sample CalculateResponse(float normalizedFrequency) const
Definition FilterComponents.h:390
static JPL_INLINE OnePole MakeLowShelf(float frequency, float sampleRate, float gain)
Definition FilterComponents.h:399
Sample b1
Definition FilterComponents.h:84