| OLD | NEW |
| 1 // A biquad filter has a z-transform of | 1 // A biquad filter has a z-transform of |
| 2 // H(z) = (b0 + b1 / z + b2 / z^2) / (1 + a1 / z + a2 / z^2) | 2 // H(z) = (b0 + b1 / z + b2 / z^2) / (1 + a1 / z + a2 / z^2) |
| 3 // | 3 // |
| 4 // The formulas for the various filters were taken from | 4 // The formulas for the various filters were taken from |
| 5 // http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt. | 5 // http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt. |
| 6 | 6 |
| 7 | 7 |
| 8 // Lowpass filter. | 8 // Lowpass filter. |
| 9 function createLowpassFilter(freq, q, gain) { | 9 function createLowpassFilter(freq, q, gain) { |
| 10 var b0; | 10 var b0; |
| 11 var b1; | 11 var b1; |
| 12 var b2; | 12 var b2; |
| 13 var a0; |
| 13 var a1; | 14 var a1; |
| 14 var a2; | 15 var a2; |
| 15 | 16 |
| 16 if (freq == 1) { | 17 if (freq == 1) { |
| 17 // The formula below works, except for roundoff. When freq = 1, | 18 // The formula below works, except for roundoff. When freq = 1, |
| 18 // the filter is just a wire, so hardwire the coefficients. | 19 // the filter is just a wire, so hardwire the coefficients. |
| 19 b0 = 1; | 20 b0 = 1; |
| 20 b1 = 0; | 21 b1 = 0; |
| 21 b2 = 0; | 22 b2 = 0; |
| 23 a0 = 1; |
| 22 a1 = 0; | 24 a1 = 0; |
| 23 a2 = 0; | 25 a2 = 0; |
| 24 } else { | 26 } else { |
| 25 var g = Math.pow(10, q / 20); | |
| 26 var d = Math.sqrt((4 - Math.sqrt(16 - 16 / (g * g))) / 2); | |
| 27 var theta = Math.PI * freq; | 27 var theta = Math.PI * freq; |
| 28 var sn = d * Math.sin(theta) / 2; | 28 var alpha = Math.sin(theta) / (2 * Math.pow(10, q / 20)); |
| 29 var beta = 0.5 * (1 - sn) / (1 + sn); | 29 var cosw = Math.cos(theta); |
| 30 var gamma = (0.5 + beta) * Math.cos(theta); | 30 var beta = (1 - cosw) / 2; |
| 31 var alpha = 0.25 * (0.5 + beta - gamma); | |
| 32 | 31 |
| 33 b0 = 2 * alpha; | 32 b0 = beta; |
| 34 b1 = 4 * alpha; | 33 b1 = 2 * beta; |
| 35 b2 = 2 * alpha; | 34 b2 = beta; |
| 36 a1 = 2 * (-gamma); | 35 a0 = 1 + alpha; |
| 37 a2 = 2 * beta; | 36 a1 = -2 * cosw; |
| 37 a2 = 1 - alpha; |
| 38 } | 38 } |
| 39 | 39 |
| 40 return {b0 : b0, b1 : b1, b2 : b2, a1 : a1, a2 : a2}; | 40 return normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
| 41 } | 41 } |
| 42 | 42 |
| 43 function createHighpassFilter(freq, q, gain) { | 43 function createHighpassFilter(freq, q, gain) { |
| 44 var b0; | 44 var b0; |
| 45 var b1; | 45 var b1; |
| 46 var b2; | 46 var b2; |
| 47 var a0; |
| 47 var a1; | 48 var a1; |
| 48 var a2; | 49 var a2; |
| 49 | 50 |
| 50 if (freq == 1) { | 51 if (freq == 1) { |
| 51 // The filter is 0 | 52 // The filter is 0 |
| 52 b0 = 0; | 53 b0 = 0; |
| 53 b1 = 0; | 54 b1 = 0; |
| 54 b2 = 0; | 55 b2 = 0; |
| 56 a0 = 1; |
| 55 a1 = 0; | 57 a1 = 0; |
| 56 a2 = 0; | 58 a2 = 0; |
| 57 } else if (freq == 0) { | 59 } else if (freq == 0) { |
| 58 // The filter is 1. Computation of coefficients below is ok, but | 60 // The filter is 1. Computation of coefficients below is ok, but |
| 59 // there's a pole at 1 and a zero at 1, so round-off could make | 61 // there's a pole at 1 and a zero at 1, so round-off could make |
| 60 // the filter unstable. | 62 // the filter unstable. |
| 61 b0 = 1; | 63 b0 = 1; |
| 62 b1 = 0; | 64 b1 = 0; |
| 63 b2 = 0; | 65 b2 = 0; |
| 66 a0 = 1; |
| 64 a1 = 0; | 67 a1 = 0; |
| 65 a2 = 0; | 68 a2 = 0; |
| 66 } else { | 69 } else { |
| 67 var g = Math.pow(10, q / 20); | |
| 68 var d = Math.sqrt((4 - Math.sqrt(16 - 16 / (g * g))) / 2); | |
| 69 var theta = Math.PI * freq; | 70 var theta = Math.PI * freq; |
| 70 var sn = d * Math.sin(theta) / 2; | 71 var alpha = Math.sin(theta) / (2 * Math.pow(10, q / 20)); |
| 71 var beta = 0.5 * (1 - sn) / (1 + sn); | 72 var cosw = Math.cos(theta); |
| 72 var gamma = (0.5 + beta) * Math.cos(theta); | 73 var beta = (1 + cosw) / 2; |
| 73 var alpha = 0.25 * (0.5 + beta + gamma); | |
| 74 | 74 |
| 75 b0 = 2 * alpha; | 75 b0 = beta; |
| 76 b1 = -4 * alpha; | 76 b1 = -2 * beta; |
| 77 b2 = 2 * alpha; | 77 b2 = beta; |
| 78 a1 = 2 * (-gamma); | 78 a0 = 1 + alpha; |
| 79 a2 = 2 * beta; | 79 a1 = -2 * cosw; |
| 80 a2 = 1 - alpha; |
| 80 } | 81 } |
| 81 | 82 |
| 82 return {b0 : b0, b1 : b1, b2 : b2, a1 : a1, a2 : a2}; | 83 return normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2); |
| 83 } | 84 } |
| 84 | 85 |
| 85 function normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2) { | 86 function normalizeFilterCoefficients(b0, b1, b2, a0, a1, a2) { |
| 86 var scale = 1 / a0; | 87 var scale = 1 / a0; |
| 87 | 88 |
| 88 return {b0 : b0 * scale, | 89 return {b0 : b0 * scale, |
| 89 b1 : b1 * scale, | 90 b1 : b1 * scale, |
| 90 b2 : b2 * scale, | 91 b2 : b2 * scale, |
| 91 a1 : a1 * scale, | 92 a1 : a1 * scale, |
| 92 a2 : a2 * scale}; | 93 a2 : a2 * scale}; |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 "bandpass": "Bandpass filter", | 360 "bandpass": "Bandpass filter", |
| 360 "lowshelf": "Lowshelf filter", | 361 "lowshelf": "Lowshelf filter", |
| 361 "highshelf": "Highshelf filter", | 362 "highshelf": "Highshelf filter", |
| 362 "peaking": "Peaking filter", | 363 "peaking": "Peaking filter", |
| 363 "notch": "Notch filter", | 364 "notch": "Notch filter", |
| 364 "allpass": "Allpass filter"}; | 365 "allpass": "Allpass filter"}; |
| 365 | 366 |
| 366 function createFilter(filterType, freq, q, gain) { | 367 function createFilter(filterType, freq, q, gain) { |
| 367 return filterCreatorFunction[filterType](freq, q, gain); | 368 return filterCreatorFunction[filterType](freq, q, gain); |
| 368 } | 369 } |
| OLD | NEW |