DSP

音频EQ系数的生成

2019-07-13 15:54发布

版权声明

本文翻译自 http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
原标题为:Cookbook formulae for audio EQ biquad filter coefficients
by Robert Bristow-Johnson rbj@audioimagination.com

前言

后面所有滤波器都是从对应的模拟滤波器原型中推导得到的(每个模拟滤波器原型在后面都会讲到),并且是用双线性变换(BLT: Bilinear Transform)来数字化模拟滤波器原型而得到数字滤波器的。BLT的频率变形也考虑到了:频率选择和带宽选择(这一句翻译不准确,望高手指点,不过,对后面理解主要核心没有太大影响)。 首先,给出双二阶滤波器的传输函数: b0 + b1*z^-1 + b2*z^-2 H(z) = ------------------------ (Eq 1) a0 + a1*z^-1 + a2*z^-2 有6个系数,而不是5个。可以把a0归一化,则公式可以变为: (b0/a0) + (b1/a0)*z^-1 + (b2/a0)*z^-2 H(z) = --------------------------------------- (Eq 2) 1 + (a1/a0)*z^-1 + (a2/a0)*z^-2 or 1 + (b1/b0)*z^-1 + (b2/b0)*z^-2 H(z) = (b0/a0) * --------------------------------- (Eq 3) 1 + (a1/a0)*z^-1 + (a2/a0)*z^-2 这个滤波器的最直接实现方式叫 “Direct Form I” : y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2] - (a1/a0)*y[n-1] - (a2/a0)*y[n-2] (Eq 4) 用户先给出参数(期望的效果): Fs (the sampling frequency) f0 ("wherever it's happenin', man." Center Frequency or Corner Frequency, or shelf midpoint frequency, depending on which filter type. The "significant frequency".) dBgain (used only for peaking and shelving filters) Q (the EE kind of definition, except for peakingEQ in which A*Q is the classic EE Q. That adjustment in definition was made so that a boost of N dB followed by a cut of N dB for identical Q and f0/Fs results in a precisely flat unity gain filter or "wire".) _or_ BW, the bandwidth in octaves (between -3 dB frequencies for BPF and notch or between midpoint (dBgain/2) gain frequencies for peaking EQ) _or_ S, a "shelf slope" parameter (for shelving EQ only). When S = 1, the shelf slope is as steep as it can be and remain monotonically increasing or decreasing gain with frequency. The shelf slope, in dB/octave, remains proportional to S for all other values for a fixed f0/Fs and dBgain. 然后,计算几个中间变量: A = sqrt( 10^(dBgain/20) ) = 10^(dBgain/40) (for peaking and shelving EQ filters only) w0 = 2*pi*f0/Fs cos(w0) sin(w0) alpha = sin(w0)/(2*Q) (case: Q) = sin(w0)*sinh( ln(2)/2 * BW * w0/sin(w0) ) (case: BW) = sin(w0)/2 * sqrt( (A + 1/A)*(1/S - 1) + 2 ) (case: S) FYI: The relationship between bandwidth and Q is 1/Q = 2*sinh(ln(2)/2*BW*w0/sin(w0)) (digital filter w BLT) or 1/Q = 2*sinh(ln(2)/2*BW) (analog filter prototype) The relationship between shelf slope and Q is 1/Q = sqrt((A + 1/A)*(1/S - 1) + 2) 2*sqrt(A)*alpha = sin(w0) * sqrt( (A^2 + 1)*(1/S - 1) + 2*A ) is a handy intermediate variable for shelving EQ filters. 最后,计算每种滤波器的系数:
(对应的模拟滤波器原型, H(s), 也写了出来,按照归一化频率来写的公式.) 低通 Low Pass Filter
LPF: H(s) = 1 / (s^2 + s/Q + 1) b0 = (1 - cos(w0))/2 b1 = 1 - cos(w0) b2 = (1 - cos(w0))/2 a0 = 1 + alpha a1 = -2*cos(w0) a2 = 1 - alpha 高通 High Pass Filter
HPF: H(s) = s^2 / (s^2 + s/Q + 1) b0 = (1 + cos(w0))/2 b1 = -(1 + cos(w0)) b2 = (1 + cos(w0))/2 a0 = 1 + alpha a1 = -2*cos(w0) a2 = 1 - alpha 带通 Band Pass Filter(增益 = Q )
BPF: H(s) = s / (s^2 + s/Q + 1) (constant skirt gain, peak gain = Q) b0 = sin(w0)/2 = Q*alpha b1 = 0 b2 = -sin(w0)/2 = -Q*alpha a0 = 1 + alpha a1 = -2*cos(w0) a2 = 1 - alpha 带通 Band Pass Filter( 0 db增益)
BPF: H(s) = (s/Q) / (s^2 + s/Q + 1) (constant 0 dB peak gain) b0 = alpha b1 = 0 b2 = -alpha a0 = 1 + alpha a1 = -2*cos(w0) a2 = 1 - alpha Notch滤波器
notch: H(s) = (s^2 + 1) / (s^2 + s/Q + 1) b0 = 1 b1 = -2*cos(w0) b2 = 1 a0 = 1 + alpha a1 = -2*cos(w0) a2 = 1 - alpha 全通 All Pass Filter
APF: H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1) b0 = 1 - alpha b1 = -2*cos(w0) b2 = 1 + alpha a0 = 1 + alpha a1 = -2*cos(w0) a2 = 1 - alpha 尖峰EQ
peakingEQ: H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) b0 = 1 + alpha*A b1 = -2*cos(w0) b2 = 1 - alpha*A a0 = 1 + alpha/A a1 = -2*cos(w0) a2 = 1 - alpha/A lowShelf: H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) b0 = A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha ) b1 = 2*A*( (A-1) - (A+1)*cos(w0) ) b2 = A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha ) a0 = (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha a1 = -2*( (A-1) + (A+1)*cos(w0) ) a2 = (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha highShelf: H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A) b0 = A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha ) b1 = -2*A*( (A-1) + (A+1)*cos(w0) ) b2 = A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha ) a0 = (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha a1 = 2*( (A-1) - (A+1)*cos(w0) ) a2 = (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha 【待译】

附录:译者写的matlab 代码

clear; dBgain = 0.1; fs = 44100; %f0 = 0.3*fs; % should be [-0.5,0.5] f0 = 600; Q = 0.707; A = sqrt( 10^(dBgain/20) ); %(for peaking and shelving EQ filters only) w0 = 2*pi*f0/fs; alpha = sin(w0)/(2*Q); % (case: Q) numerator_B = zeros(9,3); denominator_A = zeros(9,3); %LPF: H(s) = 1 / (s^2 + s/Q + 1) b0 = (1 - cos(w0))/2; b1 = 1 - cos(w0); b2 = (1 - cos(w0))/2; a0 = 1 + alpha; a1 = -2*cos(w0); a2 = 1 - alpha; numerator_B(1,:) = [b0,b1,b2]/a0; denominator_A(1,:) = [a0,a1,a2]/a0; %HPF: H(s) = s^2 / (s^2 + s/Q + 1) b0 = (1 + cos(w0))/2; b1 = -(1 + cos(w0)); b2 = (1 + cos(w0))/2; a0 = 1 + alpha; a1 = -2*cos(w0); a2 = 1 - alpha; numerator_B(2,:) = [b0,b1,b2]/a0; denominator_A(2,:) = [a0,a1,a2]/a0; %BPF: H(s) = s / (s^2 + s/Q + 1) (constant skirt gain, peak gain = Q) b0 = sin(w0)/2; %= Q*alpha b1 = 0; b2 = -sin(w0)/2; % = -Q*alpha a0 = 1 + alpha; a1 = -2*cos(w0); a2 = 1 - alpha; numerator_B(3,:) = [b0,b1,b2]/a0; denominator_A(3,:) = [a0,a1,a2]/a0; %BPF: H(s) = (s/Q) / (s^2 + s/Q + 1) (constant 0 dB peak gain) b0 = alpha; b1 = 0; b2 = -alpha; a0 = 1 + alpha; a1 = -2*cos(w0); a2 = 1 - alpha; numerator_B(4,:) = [b0,b1,b2]/a0; denominator_A(4,:) = [a0,a1,a2]/a0; %notch: H(s) = (s^2 + 1) / (s^2 + s/Q + 1) b0 = 1; b1 = -2*cos(w0); b2 = 1; a0 = 1 + alpha; a1 = -2*cos(w0); a2 = 1 - alpha; numerator_B(5,:) = [b0,b1,b2]/a0; denominator_A(5,:) = [a0,a1,a2]/a0; %APF: H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1) b0 = 1 - alpha; b1 = -2*cos(w0); b2 = 1 + alpha; a0 = 1 + alpha; a1 = -2*cos(w0); a2 = 1 - alpha; numerator_B(6,:) = [b0,b1,b2]/a0; denominator_A(6,:) = [a0,a1,a2]/a0; %peakingEQ: H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) b0 = 1 + alpha*A; b1 = -2*cos(w0); b2 = 1 - alpha*A; a0 = 1 + alpha/A; a1 = -2*cos(w0); a2 = 1 - alpha/A; numerator_B(7,:) = [b0,b1,b2]/a0; denominator_A(7,:) = [a0,a1,a2]/a0; %lowShelf: H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) b0 = A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha ); b1 = 2*A*( (A-1) - (A+1)*cos(w0) ); b2 = A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha ); a0 = (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha; a1 = -2*( (A-1) + (A+1)*cos(w0) ); a2 = (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha; numerator_B(8,:) = [b0,b1,b2]/a0; denominator_A(8,:) = [a0,a1,a2]/a0; %highShelf: H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A) b0 = A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha ); b1 = -2*A*( (A-1) + (A+1)*cos(w0) ); b2 = A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha ); a0 = (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha; a1 = 2*( (A-1) - (A+1)*cos(w0) ); a2 = (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha; numerator_B(9,:) = [b0,b1,b2]/a0; denominator_A(9,:) = [a0,a1,a2]/a0; N = 512; H = zeros(9,N); [H(1,:),W] = freqz(numerator_B(1,:),denominator_A(1,:),N); [H(2,:),W] = freqz(numerator_B(2,:),denominator_A(2,:),N); [H(3,:),W] = freqz(numerator_B(3,:),denominator_A(3,:),N); [H(4,:),W] = freqz(numerator_B(4,:),denominator_A(4,:),N); [H(5,:),W] = freqz(numerator_B(5,:),denominator_A(5,:),N); [H(6,:),W] = freqz(numerator_B(6,:),denominator_A(6,:),N); [H(7,:),W] = freqz(numerator_B(7,:),denominator_A(7,:),N); [H(8,:),W] = freqz(numerator_B(8,:),denominator_A(8,:),N); [H(9,:),W] = freqz(numerator_B(9,:),denominator_A(9,:),N); PLOT_LINES = 3; PLOT_COLUMNS = 3; plot_index = 1; subplot(PLOT_LINES, PLOT_COLUMNS, plot_index); plot(W/(2*pi),20*log10(abs(H(1,:))),'.-'); title('LPF:H(s) = 1 / (s^2 + s/Q + 1)'); plot_index = plot_index + 1 ; subplot(PLOT_LINES, PLOT_COLUMNS, plot_index); plot(W/(2*pi),20*log10(abs(H(2,:))),'.-'); title('HPF:H(s) = s^2 / (s^2 + s/Q + 1)'); plot_index = plot_index + 1 ; subplot(PLOT_LINES, PLOT_COLUMNS, plot_index); plot(W/(2*pi),20*log10(abs(H(3,:))),'.-'); title('BPF:H(s) = s / (s^2 + s/Q + 1)(constant skirt gain, peak gain = Q)');plot_index = plot_index + 1 ; subplot(PLOT_LINES, PLOT_COLUMNS, plot_index); plot(W/(2*pi),20*log10(abs(H(4,:))),'.-'); title('BPF:H(s) = (s/Q) / (s^2 + s/Q + 1)(constant 0 dB peak gain)');plot_index = plot_index + 1 ; subplot(PLOT_LINES, PLOT_COLUMNS, plot_index); plot(W/(2*pi),20*log10(abs(H(5,:))),'.-'); title('notch:H(s) = (s^2 + 1) / (s^2 + s/Q + 1)');plot_index = plot_index + 1 ; subplot(PLOT_LINES, PLOT_COLUMNS, plot_index); plot(W/(2*pi),abs(H(6,:)),'.-'); title('APF:H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1)');plot_index = plot_index + 1 ; subplot(PLOT_LINES, PLOT_COLUMNS, plot_index); plot(W/(2*pi),20*log10(abs(H(7,:))),'.-'); title('peakingEQ:H(s)=(s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1)');plot_index = plot_index + 1 ; subplot(PLOT_LINES, PLOT_COLUMNS, plot_index); plot(W/(2*pi),20*log10(abs(H(8,:))),'.-'); title('lowShelf:H(s)=A*(s^2 + (sqrt(A)/Q)*s+A)/(A*s^2+(sqrt(A)/Q)*s+1)');plot_index = plot_index + 1 ; subplot(PLOT_LINES, PLOT_COLUMNS, plot_index); plot(W/(2*pi),20*log10(abs(H(9,:))),'.-'); title('highShelf:H(s)=A*(A*s^2 + (sqrt(A)/Q)*s+1)/(s^2+(sqrt(A)/Q)*s+A)');plot_index = plot_index + 1 ;

英文原文

Cookbook formulae for audio EQ biquad filter coefficients

by Robert Bristow-Johnson All filter transfer functions were derived from analog prototypes (that
are shown below for each EQ filter type) and had been digitized using the
Bilinear Transform. BLT frequency warping has been taken into account for
both significant frequency relocation (this is the normal “prewarping” that
is necessary when using the BLT) and for bandwidth readjustment (since the
bandwidth is compressed when mapped from analog to digital using the BLT). First, given a biquad transfer function defined as: b0 + b1*z^-1 + b2*z^-2 H(z) = ------------------------ (Eq 1) a0 + a1*z^-1 + a2*z^-2 This shows 6 coefficients instead of 5 so, depending on your architechture,
you will likely normalize a0 to be 1 and perhaps also b0 to 1 (and collect
that into an overall gain coefficient). Then your transfer function would
look like: (b0/a0) + (b1/a0)*z^-1 + (b2/a0)*z^-2 H(z) = --------------------------------------- (Eq 2) 1 + (a1/a0)*z^-1 + (a2/a0)*z^-2 or 1 + (b1/b0)*z^-1 + (b2/b0)*z^-2 H(z) = (b0/a0) * --------------------------------- (Eq 3) 1 + (a1/a0)*z^-1 + (a2/a0)*z^-2 The most straight forward implementation would be the “Direct Form 1”
(Eq 2): y[n] = (b0/a0)*x[n] + (b1/a0)*x[n-1] + (b2/a0)*x[n-2] - (a1/a0)*y[n-1] - (a2/a0)*y[n-2] (Eq 4) This is probably both the best and the easiest method to implement in the
56K and other fixed-point or floating-point architechtures with a double
wide accumulator. Begin with these user defined parameters: Fs (the sampling frequency) f0 ("wherever it's happenin', man." Center Frequency or Corner Frequency, or shelf midpoint frequency, depending on which filter type. The "significant frequency".) dBgain (used only for peaking and shelving filters) Q (the EE kind of definition, except for peakingEQ in which A*Q is the classic EE Q. That adjustment in definition was made so that a boost of N dB followed by a cut of N dB for identical Q and f0/Fs results in a precisely flat unity gain filter or "wire".) _or_ BW, the bandwidth in octaves (between -3 dB frequencies for BPF and notch or between midpoint (dBgain/2) gain frequencies for peaking EQ) _or_ S, a "shelf slope" parameter (for shelving EQ only). When S = 1, the shelf slope is as steep as it can be and remain monotonically increasing or decreasing gain with frequency. The shelf slope, in dB/octave, remains proportional to S for all other values for a fixed f0/Fs and dBgain. Then compute a few intermediate variables: A = sqrt( 10^(dBgain/20) ) = 10^(dBgain/40) (for peaking and shelving EQ filters only) w0 = 2*pi*f0/Fs cos(w0) sin(w0) alpha = sin(w0)/(2*Q) (case: Q) = sin(w0)*sinh( ln(2)/2 * BW * w0/sin(w0) ) (case: BW) = sin(w0)/2 * sqrt( (A + 1/A)*(1/S - 1) + 2 ) (case: S) FYI: The relationship between bandwidth and Q is 1/Q = 2*sinh(ln(2)/2*BW*w0/sin(w0)) (digital filter w BLT) or 1/Q = 2*sinh(ln(2)/2*BW) (analog filter prototype) The relationship between shelf slope and Q is 1/Q = sqrt((A + 1/A)*(1/S - 1) + 2) 2*sqrt(A)*alpha = sin(w0) * sqrt( (A^2 + 1)*(1/S - 1) + 2*A ) is a handy intermediate variable for shelving EQ filters. Finally, compute the coefficients for whichever filter type you want:
(The analog prototypes, H(s), are shown for each filter
type for normalized frequency.) LPF: H(s) = 1 / (s^2 + s/Q + 1) b0 = (1 - cos(w0))/2 b1 = 1 - cos(w0) b2 = (1 - cos(w0))/2 a0 = 1 + alpha a1 = -2*cos(w0) a2 = 1 - alpha HPF: H(s) = s^2 / (s^2 + s/Q + 1) b0 = (1 + cos(w0))/2 b1 = -(1 + cos(w0)) b2 = (1 + cos(w0))/2 a0 = 1 + alpha a1 = -2*cos(w0) a2 = 1 - alpha BPF: H(s) = s / (s^2 + s/Q + 1) (constant skirt gain, peak gain = Q) b0 = sin(w0)/2 = Q*alpha b1 = 0 b2 = -sin(w0)/2 = -Q*alpha a0 = 1 + alpha a1 = -2*cos(w0) a2 = 1 - alpha BPF: H(s) = (s/Q) / (s^2 + s/Q + 1) (constant 0 dB peak gain) b0 = alpha b1 = 0 b2 = -alpha a0 = 1 + alpha a1 = -2*cos(w0) a2 = 1 - alpha notch: H(s) = (s^2 + 1) / (s^2 + s/Q + 1) b0 = 1 b1 = -2*cos(w0) b2 = 1 a0 = 1 + alpha a1 = -2*cos(w0) a2 = 1 - alpha APF: H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1) b0 = 1 - alpha b1 = -2*cos(w0) b2 = 1 + alpha a0 = 1 + alpha a1 = -2*cos(w0) a2 = 1 - alpha peakingEQ: H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) b0 = 1 + alpha*A b1 = -2*cos(w0) b2 = 1 - alpha*A a0 = 1 + alpha/A a1 = -2*cos(w0) a2 = 1 - alpha/A lowShelf: H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) b0 = A*( (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha ) b1 = 2*A*( (A-1) - (A+1)*cos(w0) ) b2 = A*( (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha ) a0 = (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha a1 = -2*( (A-1) + (A+1)*cos(w0) ) a2 = (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha highShelf: H(s) = A * (A*s^2 + (sqrt(A)/Q)*s + 1)/(s^2 + (sqrt(A)/Q)*s + A) b0 = A*( (A+1) + (A-1)*cos(w0) + 2*sqrt(A)*alpha ) b1 = -2*A*( (A-1) + (A+1)*cos(w0) ) b2 = A*( (A+1) + (A-1)*cos(w0) - 2*sqrt(A)*alpha ) a0 = (A+1) - (A-1)*cos(w0) + 2*sqrt(A)*alpha a1 = 2*( (A-1) - (A+1)*cos(w0) ) a2 = (A+1) - (A-1)*cos(w0) - 2*sqrt(A)*alpha FYI: The bilinear transform (with compensation for frequency warping)
substitutes: 1 1 - z^-1 (normalized) s <-- ----------- * ---------- tan(w0/2) 1 + z^-1 and makes use of these trig identities: sin(w0) 1 - cos(w0) tan(w0/2) = ------------- (tan(w0/2))^2 = ------------- 1 + cos(w0) 1 + cos(w0) resulting in these substitutions: 1 + cos(w0) 1 + 2*z^-1 + z^-2 1 <-- ------------- * ------------------- 1 + cos(w0) 1 + 2*z^-1 + z^-2 1 + cos(w0) 1 - z^-1 s <-- ------------- * ---------- sin(w0) 1 + z^-1 1 + cos(w0) 1 - z^-2 = ------------- * ------------------- sin(w0) 1 + 2*z^-1 + z^-2 1 + cos(w0) 1 - 2*z^-1 + z^-2 s^2 <-- ------------- * ------------------- 1 - cos(w0) 1 + 2*z^-1 + z^-2 The factor: 1 + cos(w0) ------------------- 1 + 2*z^-1 + z^-2 is common to all terms in both numerator and denominator, can be factored
out, and thus be left out in the substitutions above resulting in: 1 + 2*z^-1 + z^-2 1 <-- ------------------- 1 + cos(w0) 1 - z^-2 s <-- ------------------- sin(w0) 1 - 2*z^-1 + z^-2 s^2 <-- ------------------- 1 - cos(w0) In addition, all terms, numerator and denominator, can be multiplied by a
common (sin(w0))^2 factor, finally resulting in these substitutions: 1 <-- (1 + 2*z^-1 + z^-2) * (1 - cos(w0)) s <-- (1 - z^-2) * sin(w0) s^2 <-- (1 - 2*z^-1 + z^-2) * (1 + cos(w0)) 1 + s^2 <-- 2 * (1 - 2*cos(w0)*z^-1 + z^-2) The biquad coefficient formulae above come out after a little
simplification.