## Build your own noise shaping filters!

#####
Reply #13 –

I just thought you might be interested in a filter that I computed some time ago for 44kHz. This is what I did:- used LAME's ATH-curve formula (high quality setting)
- clipped the magnitude response below 200 Hz and above 18 kHz (so the max gain is limited to +20 dB)
- ran a non-linear least squares fitter that minimized the log magnitude errors to get a 4th order IIR filter close to LAME's ATH curve.

Here's the result:

SOS FILE VERSION 1

size = 2x6

1.0 0.43661 0.43995 1.0 1.21968 0.67167

1.0 -1.58404 0.78993 1.0 -0.16099 -0.40768

# newly designed filter according to LAME's ATH curve

# for a sampling frequency of 44100 Hz

# max gain (limited) : +20 dB at 18-22 kHz

# min gain : -23 dB at 3400 Hz

Save the above text to "lameath44.sos" and the filter is ready to be used by REQUANT.

Note: This filter is NOT compatible to IIIRDSGN. It has a pair of distinct real poles and IIIRDSGN only supports complex conjugate roots. IIIRDSGN will simply ignore 2nd order polynomials with distinct real roots, print out a warning and show you a *different* magnitude response.

This given 2x6 matrix is in fact a MATLAB compatible second-order-section matrix. The corresponding numerator and denominator coefficients are [b,a]=sos2tf(sos_matrix):

b = [1.0000 -1.1474 0.5383 -0.3520 0.3475]; % the numerator

a = [1.0000 1.0587 0.0676 -0.6054 -0.2738]; % the denominator

edit:

In case your noise shaping implementation follows this popular signal flow graph and you require the coefficients b_h & a_h for H(z) then you need to derive these from the noise shaper's transfer function G(z) (given by b & a) like this:

b_h = remove_leading_zero(a-b);

a_h = a;

due to the relationship G(z) = 1 - z^-1 H(z). So, for the above example b_h would be

b_h = [2.20610 -0.47070 -0.25340 -0.62130];

For FIR filters this boils down to removing the leading one and negating the remaining coefficients.

Cheers,

SG