Skip to content

Commit

Permalink
damc: fix equalizer at low frequencies
Browse files Browse the repository at this point in the history
Using +0.5 to avoid denormal was reducing the accuracy of float and low frequency EQ  (< 500Hz) was not working at all.

Use flush-to-zero instead.

Also use direct form 1 for biquad for a slight performance boost.
  • Loading branch information
amurzeau committed Apr 13, 2024
1 parent 415c4a5 commit b9489b0
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 17 deletions.
2 changes: 2 additions & 0 deletions Core/Src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ int main(void)

// memtester_stm32((void*)0x60000000, 512*1024, 10);

// Enable Flush-To-Zero to avoid denormals
FPU->FPDSCR |= FPU_FPDSCR_FZ_Msk;

DAMC_init();

Expand Down
27 changes: 13 additions & 14 deletions damc/damc_common/BiquadFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@ float BiquadFilter::put(float input) {
const float* const a = a_coefs;
const float* const b = b_coefs;

float y = b[0] * input + s1 - 0.5;
s1 = s2 + b[1] * input - a[0] * y;
s2 = b[2] * input - a[1] * y + 0.5;
// Direct form 1 implementation, leads to better performance than Transposed direct form 2. (18% cpu in audio
// processing vs 20% for 10 EqFilters (percentages without other processing))
float y = b[0] * input + b[1] * input1 + b[2] * input2 - a[0] * output1 - a[1] * output2;

input2 = input1;
input1 = input;
output2 = output1;
output1 = y;

return y;
}
Expand All @@ -37,14 +42,8 @@ std::complex<float> BiquadFilter::getResponse(float f0, float fs) {
return (b[0] + b[1] * z_1 + b[2] * z_2) / (std::complex<float>(1) + a[0] * z_1 + a[1] * z_2);
}

void BiquadFilter::computeFilter(bool enabled,
FilterType filterType,
float f0,
float fs,
float gain,
float Q,
float a_coefs[3],
float b_coefs[3]) {
void BiquadFilter::computeFilter(
bool enabled, FilterType filterType, float f0, float fs, float gain, float Q, float a_coefs[3], float b_coefs[3]) {
if(!enabled || Q == 0 || fs == 0) {
b_coefs[0] = 1;
b_coefs[1] = 0;
Expand All @@ -53,9 +52,9 @@ void BiquadFilter::computeFilter(bool enabled,
a_coefs[1] = 0;
a_coefs[2] = 0;
} else {
float A = pow(10, gain / 40);
float w0 = 2 * M_PI * f0 / fs;
float alpha = sin(w0) / (2 * Q);
double A = pow(10.0, gain / 40.0);
double w0 = 2.0 * M_PI * f0 / fs;
double alpha = sin(w0) / (2.0 * Q);

switch(filterType) {
default:
Expand Down
8 changes: 5 additions & 3 deletions damc/damc_common/BiquadFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ class BiquadFilter {
std::complex<float> getResponse(float f0, float fs);

private:
// Use offset of 0.5 to avoid denormals
float s1 = 0.5;
float s2 = 0.5;
float b_coefs[3] = {};
float a_coefs[2] = {};

float input1 = 0;
float input2 = 0;
float output1 = 0;
float output2 = 0;
};

0 comments on commit b9489b0

Please sign in to comment.