forked from shepazu/Audio-EQ-Cookbook
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathaudio-eq-cookbook.html
644 lines (639 loc) · 19.6 KB
/
audio-eq-cookbook.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1">
<meta name="Description"
content="Cookbook formulae for audio EQ
biquad filter coefficients. Describes the most common analog biquad
filter types and how to convert them to the digital filter
equivalents. ">
<title>Cookbook formulae for audio EQ biquad filter coefficients</title>
<script>
MathJax = {
tex: {
// Allows automatic numbering
tags: 'ams'
},
options: {
// Tell MathJax to look for math in code and pre tags.
skipHtmlTags: {'[-]': ['code', 'pre']}
}
};
</script>
<script src=
"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,500;0,700;1,500&display=swap');
</style>
<style media="screen">
body {
width: 45em;
margin-left: auto;
margin-right: auto;
font-size: 16px;
line-height: 1.5;
font-family: 'Lora', serif;
}
.label {
font-style: italic;
color: gray;
}
dl {
margin: 2em 0;
padding: 0;
}
dt {
position: relative;
left: 0;
top: 1.1em;
width: 10em;
font-weight: bold;
}
dd {
border-left: 1px solid gray;
margin: 0 0 0 11em;
padding: 0 0 .5em .5em;
}
</style>
</head>
<body>
<h1>Cookbook formulae for audio equalizer biquad filter coefficients</h1>
<dl>
<dt>Author</dt>
<dd>
<a href="mailto:[email protected]">Robert Bristow-Johnson</a>
</dd>
<dt>Editors</dt>
<dd>
<a href="mailto:[email protected]">Raymond Toy</a>
</dd>
<dd>
<a href="mailto:[email protected]">Doug Schepers (previously W3C)</a>
</dd>
</dl>
<p>Adapted from <a href=
"https://webaudio.github.io/Audio-EQ-Cookbook/Audio-EQ-Cookbook.txt">Audio-EQ-Cookbook.txt</a>,
by Robert Bristow-Johnson, with permission.</p>
<section>
<h2>Biquad Filter Formulae</h2>
<p>All filter transfer functions were derived from analog prototypes (that
are shown below for each equalizer (EQ) filter type) and had been digitized
using the Bilinear Transform (BLT). 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).</p>
<p>First, given a biquad transfer function defined as:</p>
<pre>
$$
\begin{equation}
H(z) = \frac{b_0 + b_1z^{-1}+b_2z^{-2}}{a_0 + a_1z^{-1}+a_2z^{-2}}
\end{equation}
$$
</pre>
<p>This shows 6 coefficients instead of 5 so, depending on your
architecture, you will likely normalize \( a_0 \) to be 1 and perhaps also
\(b_0\) to 1 (and collect that into an overall gain coefficient). Then your
transfer function would look like:</p>
<pre>
$$
\begin{equation}
H(z) = \frac{\left(\displaystyle\frac{b_0}{a_0}\right) + \left(\displaystyle\frac{b_1}{a_0}\right)z^{-1}+\left(\displaystyle\frac{b_2}{a_0}\right)z^{-2}}{1 + \left(\displaystyle\frac{a_1}{a_0}\right)z^{-1}+\left(\displaystyle\frac{a_2}{a_0}\right)z^{-2}}
\label{direct-form-1}
\end{equation}
$$
</pre>
<p>or:</p>
<pre>
$$
\begin{equation}
H(z) = \left(\frac{b_0}{a_0}\right) \frac{1 + \left(\displaystyle\frac{b_1}{b_0}\right)z^{-1}+\left(\displaystyle\frac{b_2}{b_0}\right)z^{-2}}{1 + \left(\displaystyle\frac{a_1}{a_0}\right)z^{-1}+\left(\displaystyle\frac{a_2}{a_0}\right)z^{-2}}
\end{equation}
$$
</pre>
<p>The most straight forward implementation would be the "Direct Form 1"
(\(eq. \ref{direct-form-1}\)):</p>
<pre>
$$
\begin{align}
y[n] = \left(\frac{b_0}{a_0}\right)x[n] & +
\left(\frac{b_1}{a_0}\right)x[n-1] + \left(\frac{b_2}{a_0}\right)x[n-2]
\nonumber \\
&-\left(\frac{a_1}{a_0}\right)y[n-1] - \left(\frac{a_2}{a_0}\right)y[n-2]
\end{align}
$$
</pre>
<p>This is probably both the best and the easiest method to implement in
the 56K and other fixed-point or floating-point architectures with a double
wide accumulator.</p>
<p>Begin with these user defined parameters:</p>
<dl>
<dt>\(F_s\)</dt>
<dd>the sampling frequency</dd>
<dt>\(f_0\)</dt>
<dd>Center Frequency or Corner Frequency, or shelf midpoint frequency,
depending on which filter type. The "significant frequency". "wherever
it's happenin', man."</dd>
<dt>\(\mathrm{dBgain}\)</dt>
<dd>used only for peaking and shelving filters</dd>
<dt>\(Q\) or \(\mathrm{BW}\) or \(S\)</dt>
<dd>
<dl>
<dt>\(Q\)</dt>
<dd>the EE kind of definition, except for peakingEQ in which \(A\cdot
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 \(f_0/F_s\) results in a precisely flat unity
gain filter or "wire".</dd>
<dt>\(\mathrm{BW}\)</dt>
<dd>the bandwidth in octaves (between -3 dB frequencies for BPF and
notch or between midpoint (\(\mathrm{dBgain}/2\)) gain frequencies
for peaking EQ)</dd>
<dt>\(S\)</dt>
<dd>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 \(f_0/F_s\) and \(\mathrm{dBgain}\).</dd>
</dl>
</dd>
</dl>
<p>Then compute a few intermediate variables:</p>
<ol>
<li>
Only for peaking and shelving EQ filters:
<pre>
$$
\begin{align}
A &= \sqrt{10^{\mathrm{dBgain}/20}} & \\
& = 10^{\mathrm{dBgain}/40} &
\end{align}
$$
</pre>
</li>
<li>
<pre>
$$
\omega_0 = 2 \pi \frac{f_0}{F_s}
$$
</pre>
</li>
<li>
<pre>
$$
\begin{align*}
& \cos \omega_0 \\
& \sin \omega_0
\end{align*}
$$
</pre>
</li>
<li>
<pre>
$$
\begin{align}
\alpha &= \frac{\sin \omega_0}{2 Q} & \textrm{(case: Q)} \\
&= \sin \omega_0 \, \sinh\left(\frac{\log 2}{2} \cdot
\mathrm{BW} \cdot
\frac{\omega_0}{\sin \omega_0}\right) & \textrm{(case: BW)} \\
&= \frac{\sin \omega_0}{2} \sqrt{\left(A +
\frac{1}{A}\right) \left(\frac{1}{S} - 1\right) + 2} & \textrm{(case: S)}
\end{align}
$$
</pre>
</li>
</ol>
<p>FYI: The relationship between bandwidth and \(Q\) is</p>
<p class="label">digital filter with BLT</p>
<pre>
$$
\begin{equation}
\frac{1}{Q} = 2\sinh\left(\frac{\log 2}{2} \cdot \mathrm{BW} \cdot
\frac{\omega_0}{\sin \omega_0}\right)
\end{equation}
$$
</pre>
<p>or</p>
<p class="label">analog filter prototype</p>
<pre>
$$
\begin{equation}
\frac{1}{Q} = 2 \sinh\left(\frac{\log 2}{2} \cdot \mathrm{BW}\right)
\end{equation}
$$
</pre>
<p>The relationship between shelf slope, \(S\), and \(Q\) is</p>
<pre>
$$
\begin{equation}
\frac{1}{Q} = \sqrt{\left(A + \frac{1}{A}\right) \left(\frac{1}{S} -
1\right) + 2}
\end{equation}
$$
</pre>
<pre>
$$
\begin{equation}
2\sqrt{A}\,\alpha = (\sin \omega_0)\, \sqrt{\left(A^2 +
1\right)\left(\frac{1}{S}-1\right) + 2A}
\end{equation}
$$
</pre>
<p>is a handy intermediate variable for shelving EQ filters.</p>
<p>Finally, compute the coefficients for whichever filter type you
want:</p>
<p>(The analog prototypes, H(s), are shown for each filter type for
normalized frequency.)</p>
<dl>
<dt id="LPF-eqn">LPF</dt>
<dd>
<pre>
$$
\begin{equation}
H(s) = \frac{1}{s^2 + \displaystyle\frac{s}{Q} + 1}
\end{equation}
$$
</pre>
<pre id="LPF-coef">
$$
\begin{align}
\begin{split}
b_0 &= \frac{1-\cos\omega_0}{2} \\
b_1 &= 1-\cos\omega_0 \\
b_2 &= \frac{1-\cos\omega_0}{2} \\
a_0 &= 1 + \alpha \\
a_1 &= -2\cos\omega_0 \\
a_2 &= 1 - \alpha
\end{split}
\end{align}
$$
</pre>
</dd>
<dt id="HPF-eqn">HPF</dt>
<dd>
<pre>
$$
\begin{equation}
H(s) = \frac{s^2}{s^2 + \displaystyle\frac{s}{Q} + 1}
\end{equation}
$$
</pre>
<pre id="HPF-coef">
$$
\begin{align}
\begin{split}
b_0 &= \frac{1 + \cos \omega_0}{2} \\
b_1 &= -(1 + \cos \omega_0) \\
b_2 &= \frac{1 + \cos \omega_0}{2} \\
a_0 &= 1 + \alpha \\
a_1 &= -2\cos \omega_0 \\
a_2 &= 1 - \alpha
\end{split}
\end{align}
$$
</pre>
</dd>
<dt id="BPF-eqn-constant-skirt-gain">BPF<br>
(constant skirt gain,<br>
peak gain = \(Q\))</dt>
<dd>
<pre>
$$
\begin{equation}
H(s) = \frac{s}{s^2 + \displaystyle\frac{s}{Q} + 1}
\end{equation}
$$
</pre>
<pre id="BPF-coef-constant-skirt-gain">
$$
\begin{align}
\begin{split}
b_0 &= \frac{\sin\omega_0}{2} = Q \alpha \\
b_1 &= 0 \\
b_2 &= -\frac{\sin\omega_0}{2} = -Q \alpha \\
a_0 &= 1 + \alpha \\
a_1 &= -2\cos\omega_0 \\
a_2 &= 1 - \alpha
\end{split}
\end{align}
$$
</pre>
</dd>
<dt id="BPF-eqn-0dB-peak">BPF<br>
(constant 0 dB peak gain)</dt>
<dd>
<pre>
$$
\begin{equation}
H(s) = \frac{\displaystyle\frac{s}{Q}}{s^2 + \displaystyle\frac{s}{Q} + 1}
\end{equation}
$$
</pre>
<pre id="BPF-coef-0dB-peak">
$$
\begin{align}
\begin{split}
b_0 &= \alpha \\
b_1 &= 0 \\
b_2 &= -\alpha \\
a_0 &= 1 + \alpha \\
a_1 &= -2\cos \omega_0 \\
a_2 &= 1 - \alpha
\end{split}
\end{align}
$$
</pre>
</dd>
<dt id="notch-eqn">notch</dt>
<dd>
<pre>
$$
\begin{equation}
H(s) = \frac{s^2 + 1}{s^2 + \displaystyle\frac{s}{Q} + 1}
\end{equation}
$$
</pre>
<pre id="notch-coef">
$$
\begin{align}
\begin{split}
b_0 &= 1 \\
b_1 &= -2\cos \omega_0 \\
b_2 &= 1 \\
a_0 &= 1 + \alpha \\
a_1 &= -2\cos \omega_0 \\
a_2 &= 1 - \alpha
\end{split}
\end{align}
$$
</pre>
</dd>
<dt id="APF-eqn">APF</dt>
<dd>
<pre>
$$
\begin{equation}
H(s) = \frac{s^2 - \displaystyle\frac{s}{Q} + 1}{s^2 + \displaystyle\frac{s}{Q} + 1}
\end{equation}
$$
</pre>
<pre id="APF-coef">
$$
\begin{align}
\begin{split}
b_0 &= 1 - \alpha \\
b_1 &= -2\cos\omega_0 \\
b_2 &= 1 + \alpha \\
a_0 &= 1 + \alpha \\
a_1 &= -2\cos\omega_0 \\
a_2 &= 1 - \alpha
\end{split}
\end{align}
$$
</pre>
</dd>
<dt id="peaking-eqn">peakingEQ</dt>
<dd>
<pre>
$$
\begin{equation}
H(s) = \frac{s^2 + s\displaystyle\frac{A}{Q} + 1}{s^2 + \displaystyle\frac{s}{AQ} + 1}
\end{equation}
$$
</pre>
<pre id="peaking-coef">
$$
\begin{align}
\begin{split}
b_0 &= 1 + \alpha A \\
b_1 &= -2\cos\omega_0 \\
b_2 &= 1 - \alpha A \\
a_0 &= 1 + \frac{\alpha}{A} \\
a_1 &= -2\cos\omega_0 \\
a_2 &= 1 - \frac{\alpha}{A}
\end{split}
\end{align}
$$
</pre>
</dd>
<dt id="lowshelf-eqn">lowShelf</dt>
<dd>
<pre>
$$
\begin{equation}
H(s) = A \frac{s^2 + \displaystyle\frac{\sqrt{A}}{Q} s + A}
{As^2 + \displaystyle\frac{\sqrt{A}}{Q} s + 1}
\end{equation}
$$
</pre>
<pre id="lowshelf-coef">
$$
\begin{align}
\begin{split}
b_0 &= A\left( (A+1) - (A-1)\cos\omega_0 + 2\sqrt{A}\, \alpha \right) \\
b_1 &= 2A\Big( (A-1) - (A+1)\cos\omega_0 \Big) \\
b_2 &= A\left( (A+1) - (A-1)\cos\omega_0 - 2\sqrt{A}\, \alpha \right) \\
a_0 &= (A+1) + (A-1)\cos\omega_0 + 2\sqrt{A}\, \alpha \\
a_1 &= -2\Big( (A-1) + (A+1)\cos\omega_0 \Big) \\
a_2 &= (A+1) + (A-1)\cos\omega_0 - 2\sqrt{A}\, \alpha
\end{split}
\end{align}
$$
</pre>
</dd>
<dt id="highshelf-eqn">highShelf</dt>
<dd>
<pre>
$$
\begin{equation}
H(s) = A \frac{As^2 + \displaystyle\frac{\sqrt{A}}{Q}s + 1}
{s^2 + \displaystyle\frac{\sqrt{A}}{Q} s + A}
\end{equation}
$$
</pre>
<pre id="highshelf-coef">
$$
\begin{align}
\begin{split}
b_0 &= A\left( (A+1) + (A-1)\cos\omega_0 + 2\sqrt{A}\alpha \right) \\
b_1 &= -2A\Big( (A-1) + (A+1)\cos\omega_0 \Big) \\
b_2 &= A\left( (A+1) + (A-1)\cos\omega_0 - 2\sqrt{A}\alpha \right) \\
a_0 &= (A+1) - (A-1)\cos\omega_0 + 2\sqrt{A}\alpha \\
a_1 &= 2\Big( (A-1) - (A+1)\cos\omega_0 \Big) \\
a_2 &= (A+1) - (A-1)\cos\omega_0 - 2\sqrt{A}\alpha
\end{split}
\end{align}
$$
</pre>
</dd>
</dl>
<p>FYI: The bilinear transform (with compensation for frequency warping)
substitutes:</p>
<p class="label">(normalized)</p>
<pre>
$$
\begin{equation}
s \leftarrow \frac{1}{\tan\displaystyle\frac{\omega_0}{2}}
\times \frac{1-z^{-1}}{1+z^{-1}}
\end{equation}
$$
</pre>
<p>and makes use of these trig identities:</p>
<ol>
<li>
<pre>
$$
\begin{equation}
\tan\frac{\omega_0}{2} = \frac{\sin\omega_0}{1+\cos\omega_0}
\end{equation}
$$
</pre>
</li>
<li>
<pre>
$$
\begin{equation}
\left(\tan\frac{\omega_0}{2}\right)^2 = \frac{1-\cos\omega_0}{1+\cos\omega_0}
\end{equation}
$$
</pre>
</li>
</ol>
<p>resulting in these substitutions:</p>
<ol>
<li>
<pre>
$$
\begin{equation}
1 \leftarrow \frac{1+\cos\omega_0}{1+\cos\omega_0}
\times \frac{1+2z^{-1}+z^{-2}}{1+2z^{-1}+z^{-2}}
\end{equation}
$$
</pre>
</li>
<li>
<pre>
$$
\begin{align}
s \leftarrow & \, \frac{1+\cos\omega_0}{\sin\omega_0} \times
\frac{1-z^{-1}}{1+z^{-1}} \\
& = \frac{1+\cos\omega_0}{\sin\omega_0} \times \frac{1-z^{-2}}{1+2z^{-1}+z^{-2}}
\end{align}
$$
</pre>
</li>
<li>
<pre>
$$
\begin{equation}
s^2 \leftarrow \frac{1+\cos\omega_0}{1-\cos\omega_0}
\times \frac{1-2z^{-1}+z^{-2}}{1+2z^{-1}+z^{-2}}
\end{equation}
$$
</pre>
</li>
</ol>
<p>The factor:</p>
<pre>
$$
\begin{equation}
\frac{1+\cos\omega_0}{1+2z^{-1}+z^{-2}}
\end{equation}
$$
</pre>
<p>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:</p>
<ol>
<li>
<pre>
$$
\begin{equation}
1 \leftarrow \frac{1+2z^{-1}+z^{-2}}{1+\cos\omega_0}
\end{equation}
$$
</pre>
</li>
<li>
<pre>
$$
\begin{equation}
s \leftarrow \frac{1-z^{-2}}{\sin\omega_0}
\end{equation}
$$
</pre>
</li>
<li>
<pre>
$$
\begin{equation}
s^2 \leftarrow \frac{1-2z^{-1}+z^{-2}}{1-\cos\omega_0}
\end{equation}
$$
</pre>
</li>
</ol>
<p>In addition, all terms, numerator and denominator, can be multiplied by
a common \(\sin^2\omega_0\) factor, finally resulting in these
substitutions:</p>
<ol>
<li>
<pre>
$$
\begin{equation}
1 \leftarrow (1 + 2z^{-1} + z^{-2}) (1 - \cos\omega_0)
\end{equation}
$$
</pre>
</li>
<li>
<pre>
$$
\begin{equation}
s \leftarrow (1-z^{-2})\sin\omega_0
\end{equation}
$$
</pre>
</li>
<li>
<pre>
$$
\begin{equation}
s^2 \leftarrow (1 - 2z^{-1} + z^{-2}) (1 + \cos\omega_0)
\end{equation}
$$
</pre>
</li>
<li>
<pre>
$$
\begin{equation}
1 + s^2 \leftarrow 2\, (1 - 2\cos\omega_0\,z^{-1} + z^{-2})
\end{equation}
$$
</pre>
</li>
</ol>
<p>The biquad coefficient formulae above come out after a little
simplification.</p>
</section>
<section id="acknowledgements">
<h2>Acknowledgements</h2>
<p>Special thanks to <a href="mailto:[email protected]">Robert
Bristow-Johnson</a> for creating the Audio EQ Cookbook and permitting its
adaption and use for the Web Audio API.</p>
<p>Thanks to <a href="mailto:[email protected]">Peter
Krautzberger</a> for help in adapting these mathematical formulae to
MathML, and to the whole <a href="https://www.mathjax.org/">MathJax</a>
team for making the JavaScript extension that makes the use of math on the
web possible.</p>
<p>Thanks to Peter Jipsen, creator of <a href=
"http://www1.chapman.edu/~jipsen/mathml/asciimath.html">ASCIIMathML</a>,
for making it easier to convert ASCII math notation to MathML.</p>
<p>Converted to using TeX formulas instead of MathML by <a href=
"mailto:[email protected]">Raymond Toy</a>.</p>
</section>
</body>
</html>