| OLD | NEW |
| 1 <!doctype html> | 1 <!doctype html> |
| 2 <html> | 2 <html> |
| 3 <head> | 3 <head> |
| 4 <title>Biquad Automation Test</title> | 4 <title>Biquad Automation Test</title> |
| 5 <script src="../resources/js-test.js"></script> | 5 <script src="../resources/js-test.js"></script> |
| 6 <script src="resources/compatibility.js"></script> | 6 <script src="resources/compatibility.js"></script> |
| 7 <script src="resources/audio-testing.js"></script> | 7 <script src="resources/audio-testing.js"></script> |
| 8 <script src="resources/biquad-filters.js"></script> | 8 <script src="resources/biquad-filters.js"></script> |
| 9 <script src="resources/audioparam-testing.js"></script> | 9 <script src="resources/audioparam-testing.js"></script> |
| 10 </head> | 10 </head> |
| 11 <body> | 11 <body> |
| 12 <script> | 12 <script> |
| 13 description("Test Automation of Biquad Filters"); | 13 description("Test Automation of Biquad Filters"); |
| 14 | 14 |
| 15 window.jsTestIsAsync = true; | 15 window.jsTestIsAsync = true; |
| 16 | 16 |
| 17 // Don't need to run these tests at high sampling rate, so just use a low
one to reduce memory | 17 // Don't need to run these tests at high sampling rate, so just use a low
one to reduce memory |
| 18 // usage and complexity. | 18 // usage and complexity. |
| 19 var sampleRate = 16000; | 19 var sampleRate = 16000; |
| 20 | 20 |
| 21 // How long to render for each test. | 21 // How long to render for each test. |
| 22 var renderDuration = 1; | 22 var renderDuration = 1; |
| 23 // Where to end the automations. Fairly arbitrary, but must end before |
| 24 // the renderDuration. |
| 25 var automationEndTime = renderDuration / 2; |
| 23 | 26 |
| 24 var audit = Audit.createTaskRunner(); | 27 var audit = Audit.createTaskRunner(); |
| 25 | 28 |
| 26 // The definition of the linear ramp automation function. | 29 // The definition of the linear ramp automation function. |
| 27 function linearRamp(t, v0, v1, t0, t1) { | 30 function linearRamp(t, v0, v1, t0, t1) { |
| 28 return v0 + (v1 - v0) * (t - t0) / (t1 - t0); | 31 return v0 + (v1 - v0) * (t - t0) / (t1 - t0); |
| 29 } | 32 } |
| 30 | 33 |
| 31 // Generate the filter coefficients for the specified filter using the giv
en parameters for | 34 // Generate the filter coefficients for the specified filter using the giv
en parameters for |
| 32 // the given duration. |filterTypeFunction| is a function that returns th
e filter | 35 // the given duration. |filterTypeFunction| is a function that returns th
e filter |
| 33 // coefficients for one set of parameters. |parameters| is a property bag
that contains the | 36 // coefficients for one set of parameters. |parameters| is a property bag
that contains the |
| 34 // start and end values (as an array) for each of the biquad attributes.
The properties are | 37 // start and end values (as an array) for each of the biquad attributes.
The properties are |
| 35 // |freq|, |Q|, |gain|, and |detune|. |duration| is the number of seconds
for which the | 38 // |freq|, |Q|, |gain|, and |detune|. |duration| is the number of seconds
for which the |
| 36 // coefficients are generated. | 39 // coefficients are generated. |
| 37 // | 40 // |
| 38 // A property bag with properties |b0|, |b1|, |b2|, |a1|, |a2|. Each prop
ery is an array | 41 // A property bag with properties |b0|, |b1|, |b2|, |a1|, |a2|. Each prop
ery is an array |
| 39 // consisting of the coefficients for the time-varying biquad filter. | 42 // consisting of the coefficients for the time-varying biquad filter. |
| 40 function generateFilterCoefficients(filterTypeFunction, parameters, durati
on) { | 43 function generateFilterCoefficients(filterTypeFunction, parameters, durati
on) { |
| 44 var renderEndFrame = Math.ceil(renderDuration * sampleRate); |
| 41 var endFrame = Math.ceil(duration * sampleRate); | 45 var endFrame = Math.ceil(duration * sampleRate); |
| 42 var nCoef = endFrame; | 46 var nCoef = renderEndFrame; |
| 43 var b0 = new Float64Array(nCoef); | 47 var b0 = new Float64Array(nCoef); |
| 44 var b1 = new Float64Array(nCoef); | 48 var b1 = new Float64Array(nCoef); |
| 45 var b2 = new Float64Array(nCoef); | 49 var b2 = new Float64Array(nCoef); |
| 46 var a1 = new Float64Array(nCoef); | 50 var a1 = new Float64Array(nCoef); |
| 47 var a2 = new Float64Array(nCoef); | 51 var a2 = new Float64Array(nCoef); |
| 48 | 52 |
| 49 var k = 0; | 53 var k = 0; |
| 50 // If the property is not given, use the defaults. | 54 // If the property is not given, use the defaults. |
| 51 var freqs = parameters.freq || [350, 350]; | 55 var freqs = parameters.freq || [350, 350]; |
| 52 var qs = parameters.Q || [1, 1]; | 56 var qs = parameters.Q || [1, 1]; |
| 53 var gains = parameters.gain || [0, 0]; | 57 var gains = parameters.gain || [0, 0]; |
| 54 var detunes = parameters.detune || [0, 0]; | 58 var detunes = parameters.detune || [0, 0]; |
| 55 | 59 |
| 56 for (var frame = 0; frame < endFrame; ++frame) { | 60 for (var frame = 0; frame <= endFrame; ++frame) { |
| 57 // Apply linear ramp at frame |frame|. | 61 // Apply linear ramp at frame |frame|. |
| 58 var f = linearRamp(frame / sampleRate, freqs[0], freqs[1], 0, durati
on); | 62 var f = linearRamp(frame / sampleRate, freqs[0], freqs[1], 0, durati
on); |
| 59 var q = linearRamp(frame / sampleRate, qs[0], qs[1], 0, duration); | 63 var q = linearRamp(frame / sampleRate, qs[0], qs[1], 0, duration); |
| 60 var g = linearRamp(frame / sampleRate, gains[0], gains[1], 0, durati
on); | 64 var g = linearRamp(frame / sampleRate, gains[0], gains[1], 0, durati
on); |
| 61 var d = linearRamp(frame / sampleRate, detunes[0], detunes[1], 0, du
ration); | 65 var d = linearRamp(frame / sampleRate, detunes[0], detunes[1], 0, du
ration); |
| 62 | 66 |
| 63 // Compute actual frequency parameter | 67 // Compute actual frequency parameter |
| 64 f = f * Math.pow(2, d / 1200); | 68 f = f * Math.pow(2, d / 1200); |
| 65 | 69 |
| 66 // Compute filter coefficients | 70 // Compute filter coefficients |
| 67 var coef = filterTypeFunction(f / (sampleRate / 2), q, g); | 71 var coef = filterTypeFunction(f / (sampleRate / 2), q, g); |
| 68 b0[k] = coef.b0; | 72 b0[k] = coef.b0; |
| 69 b1[k] = coef.b1; | 73 b1[k] = coef.b1; |
| 70 b2[k] = coef.b2; | 74 b2[k] = coef.b2; |
| 71 a1[k] = coef.a1; | 75 a1[k] = coef.a1; |
| 72 a2[k] = coef.a2; | 76 a2[k] = coef.a2; |
| 73 ++k; | 77 ++k; |
| 74 } | 78 } |
| 75 | 79 |
| 80 // Fill the rest of the arrays with the constant value to the end of |
| 81 // the rendering duration. |
| 82 b0.fill(b0[endFrame], endFrame + 1); |
| 83 b1.fill(b1[endFrame], endFrame + 1); |
| 84 b2.fill(b2[endFrame], endFrame + 1); |
| 85 a1.fill(a1[endFrame], endFrame + 1); |
| 86 a2.fill(a2[endFrame], endFrame + 1); |
| 87 |
| 76 return {b0: b0, b1: b1, b2: b2, a1: a1, a2: a2}; | 88 return {b0: b0, b1: b1, b2: b2, a1: a1, a2: a2}; |
| 77 } | 89 } |
| 78 | 90 |
| 79 // Apply the given time-varying biquad filter to the given signal, |signal
|. |coef| should be | 91 // Apply the given time-varying biquad filter to the given signal, |signal
|. |coef| should be |
| 80 // the time-varying coefficients of the filter, as returned by |generateFi
lterCoefficients|. | 92 // the time-varying coefficients of the filter, as returned by |generateFi
lterCoefficients|. |
| 81 function timeVaryingFilter(signal, coef) { | 93 function timeVaryingFilter(signal, coef) { |
| 82 var length = signal.length; | 94 var length = signal.length; |
| 83 // Use double precision for the internal computations. | 95 // Use double precision for the internal computations. |
| 84 var y = new Float64Array(length); | 96 var y = new Float64Array(length); |
| 85 | 97 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 113 f.connect(context.destination); | 125 f.connect(context.destination); |
| 114 | 126 |
| 115 src.start(); | 127 src.start(); |
| 116 | 128 |
| 117 return {filter: f, source: b}; | 129 return {filter: f, source: b}; |
| 118 } | 130 } |
| 119 | 131 |
| 120 function createFilterVerifier(filterCreator, threshold, parameters, input,
message) { | 132 function createFilterVerifier(filterCreator, threshold, parameters, input,
message) { |
| 121 return function (resultBuffer) { | 133 return function (resultBuffer) { |
| 122 var actual = resultBuffer.getChannelData(0); | 134 var actual = resultBuffer.getChannelData(0); |
| 123 var coefs = generateFilterCoefficients(filterCreator, parameters, rend
erDuration); | 135 var coefs = generateFilterCoefficients(filterCreator, parameters, auto
mationEndTime); |
| 124 | 136 |
| 125 reference = timeVaryingFilter(input, coefs); | 137 reference = timeVaryingFilter(input, coefs); |
| 126 | 138 |
| 127 Should(message, actual).beCloseToArray(reference, threshold); | 139 Should(message, actual, { |
| 140 verbose: true |
| 141 }).beCloseToArray(reference, threshold); |
| 128 }; | 142 }; |
| 129 } | 143 } |
| 130 | 144 |
| 131 // Automate just the frequency parameter. A bandpass filter is used where
the center | 145 // Automate just the frequency parameter. A bandpass filter is used where
the center |
| 132 // frequency is swept across the source (which is a simple tone). | 146 // frequency is swept across the source (which is a simple tone). |
| 133 audit.defineTask("automate-freq", function (done) { | 147 audit.defineTask("automate-freq", function (done) { |
| 134 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa
mpleRate); | 148 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa
mpleRate); |
| 135 | 149 |
| 136 // Center frequency of bandpass filter and also the frequency of the tes
t tone. | 150 // Center frequency of bandpass filter and also the frequency of the tes
t tone. |
| 137 var centerFreq = 10*440; | 151 var centerFreq = 10*440; |
| 138 | 152 |
| 139 // Sweep the frequency +/- 9*440 Hz from the center. This should cause
the output to low at | 153 // Sweep the frequency +/- 5*440 Hz from the center. This should cause |
| 140 // the beginning and end of the test where the done is outside the pass
band of the filter, | 154 // the output to be low at the beginning and end of the test where the |
| 141 // but high in the center where the tone is near the center of the pass
band. | 155 // tone is outside the pass band of the filter, but high in the middle |
| 156 // of the automation time where the tone is near the center of the pass |
| 157 // band. Make sure the frequency sweep stays inside the Nyquist |
| 158 // frequency. |
| 142 var parameters = { | 159 var parameters = { |
| 143 freq: [centerFreq - 9*440, centerFreq + 9*440] | 160 freq: [centerFreq - 5*440, centerFreq + 5*440] |
| 144 } | 161 } |
| 145 var graph = configureGraph(context, centerFreq); | 162 var graph = configureGraph(context, centerFreq); |
| 146 var f = graph.filter; | 163 var f = graph.filter; |
| 147 var b = graph.source; | 164 var b = graph.source; |
| 148 | 165 |
| 149 f.type = "bandpass"; | 166 f.type = "bandpass"; |
| 150 f.frequency.setValueAtTime(parameters.freq[0], 0); | 167 f.frequency.setValueAtTime(parameters.freq[0], 0); |
| 151 f.frequency.linearRampToValueAtTime(parameters.freq[1], renderDuration); | 168 f.frequency.linearRampToValueAtTime(parameters.freq[1], automationEndTim
e); |
| 152 | 169 |
| 153 context.startRendering() | 170 context.startRendering() |
| 154 .then(createFilterVerifier(createBandpassFilter, 5e-5, parameters, b.g
etChannelData(0), | 171 .then(createFilterVerifier(createBandpassFilter, 4.8429e-6, parameters
, b.getChannelData(0), |
| 155 "Output of bandpass filter with frequency automation")) | 172 "Output of bandpass filter with frequency automation")) |
| 156 .then(done); | 173 .then(done); |
| 157 }); | 174 }); |
| 158 | 175 |
| 159 // Automate just the Q parameter. A bandpass filter is used where the Q o
f the filter is | 176 // Automate just the Q parameter. A bandpass filter is used where the Q o
f the filter is |
| 160 // swept. | 177 // swept. |
| 161 audit.defineTask("automate-q", function (done) { | 178 audit.defineTask("automate-q", function (done) { |
| 162 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa
mpleRate); | 179 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa
mpleRate); |
| 163 | 180 |
| 164 // The frequency of the test tone. | 181 // The frequency of the test tone. |
| 165 var centerFreq = 440; | 182 var centerFreq = 440; |
| 166 | 183 |
| 167 // Sweep the Q paramter between 1 and 200. This will cause the output o
f the filter to pass | 184 // Sweep the Q paramter between 1 and 200. This will cause the output o
f the filter to pass |
| 168 // most of the tone at the beginning to passing less of the tone at the
end. This is | 185 // most of the tone at the beginning to passing less of the tone at the
end. This is |
| 169 // because we set center frequency of the bandpass filter to be slightly
off from the actual | 186 // because we set center frequency of the bandpass filter to be slightly
off from the actual |
| 170 // tone. | 187 // tone. |
| 171 var parameters = { | 188 var parameters = { |
| 172 Q: [1, 200], | 189 Q: [1, 200], |
| 173 // Center frequency of the bandpass filter is just 25 Hz above the ton
e frequency. | 190 // Center frequency of the bandpass filter is just 25 Hz above the ton
e frequency. |
| 174 freq: [centerFreq + 25, centerFreq + 25] | 191 freq: [centerFreq + 25, centerFreq + 25] |
| 175 }; | 192 }; |
| 176 var graph = configureGraph(context, centerFreq); | 193 var graph = configureGraph(context, centerFreq); |
| 177 var f = graph.filter; | 194 var f = graph.filter; |
| 178 var b = graph.source; | 195 var b = graph.source; |
| 179 | 196 |
| 180 f.type = "bandpass"; | 197 f.type = "bandpass"; |
| 181 f.frequency.value = parameters.freq[0]; | 198 f.frequency.value = parameters.freq[0]; |
| 182 f.Q.setValueAtTime(parameters.Q[0], 0); | 199 f.Q.setValueAtTime(parameters.Q[0], 0); |
| 183 f.Q.linearRampToValueAtTime(parameters.Q[1], renderDuration); | 200 f.Q.linearRampToValueAtTime(parameters.Q[1], automationEndTime); |
| 184 | 201 |
| 185 context.startRendering() | 202 context.startRendering() |
| 186 .then(createFilterVerifier(createBandpassFilter, 1.4e-6, parameters, b
.getChannelData(0), | 203 .then(createFilterVerifier(createBandpassFilter, 1.1062e-6, parameters
, b.getChannelData(0), |
| 187 "Output of bandpass filter with Q automation")) | 204 "Output of bandpass filter with Q automation")) |
| 188 .then(done); | 205 .then(done); |
| 189 }); | 206 }); |
| 190 | 207 |
| 191 // Automate just the gain of the lowshelf filter. A test tone will be in
the lowshelf part of | 208 // Automate just the gain of the lowshelf filter. A test tone will be in
the lowshelf part of |
| 192 // the filter. The output will vary as the gain of the lowshelf is change
d. | 209 // the filter. The output will vary as the gain of the lowshelf is change
d. |
| 193 audit.defineTask("automate-gain", function (done) { | 210 audit.defineTask("automate-gain", function (done) { |
| 194 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa
mpleRate); | 211 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa
mpleRate); |
| 195 | 212 |
| 196 // Frequency of the test tone. | 213 // Frequency of the test tone. |
| 197 var centerFreq = 440; | 214 var centerFreq = 440; |
| 198 | 215 |
| 199 // Set the cutoff frequency of the lowshelf to be significantly higher t
han the test tone. | 216 // Set the cutoff frequency of the lowshelf to be significantly higher t
han the test tone. |
| 200 // Sweep the gain from 20 dB to -20 dB. (We go from 20 to -20 to easily
verify that the | 217 // Sweep the gain from 20 dB to -20 dB. (We go from 20 to -20 to easily
verify that the |
| 201 // filter didn't go unstable.) | 218 // filter didn't go unstable.) |
| 202 var parameters = { | 219 var parameters = { |
| 203 freq: [3500, 3500], | 220 freq: [3500, 3500], |
| 204 gain: [20, -20] | 221 gain: [20, -20] |
| 205 } | 222 } |
| 206 var graph = configureGraph(context, centerFreq); | 223 var graph = configureGraph(context, centerFreq); |
| 207 var f = graph.filter; | 224 var f = graph.filter; |
| 208 var b = graph.source; | 225 var b = graph.source; |
| 209 | 226 |
| 210 f.type = "lowshelf"; | 227 f.type = "lowshelf"; |
| 211 f.frequency.value = parameters.freq[0]; | 228 f.frequency.value = parameters.freq[0]; |
| 212 f.gain.setValueAtTime(parameters.gain[0], 0); | 229 f.gain.setValueAtTime(parameters.gain[0], 0); |
| 213 f.gain.linearRampToValueAtTime(parameters.gain[1], renderDuration); | 230 f.gain.linearRampToValueAtTime(parameters.gain[1], automationEndTime); |
| 214 | 231 |
| 215 context.startRendering() | 232 context.startRendering() |
| 216 .then(createFilterVerifier(createLowShelfFilter, 8e-6, parameters, b.g
etChannelData(0), | 233 .then(createFilterVerifier(createLowShelfFilter, 1.4306e-5, parameters
, b.getChannelData(0), |
| 217 "Output of lowshelf filter with gain automation")) | 234 "Output of lowshelf filter with gain automation")) |
| 218 .then(done); | 235 .then(done); |
| 219 }); | 236 }); |
| 220 | 237 |
| 221 // Automate just the detune parameter. Basically the same test as for the
frequncy parameter | 238 // Automate just the detune parameter. Basically the same test as for the
frequncy parameter |
| 222 // but we just use the detune parameter to modulate the frequency paramete
r. | 239 // but we just use the detune parameter to modulate the frequency paramete
r. |
| 223 audit.defineTask("automate-detune", function (done) { | 240 audit.defineTask("automate-detune", function (done) { |
| 224 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa
mpleRate); | 241 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa
mpleRate); |
| 225 var centerFreq = 10*440; | 242 var centerFreq = 10*440; |
| 226 var parameters = { | 243 var parameters = { |
| 227 freq: [centerFreq, centerFreq], | 244 freq: [centerFreq, centerFreq], |
| 228 detune: [-10*1200, 10*1200] | 245 detune: [-10*1200, 10*1200] |
| 229 }; | 246 }; |
| 230 var graph = configureGraph(context, centerFreq); | 247 var graph = configureGraph(context, centerFreq); |
| 231 var f = graph.filter; | 248 var f = graph.filter; |
| 232 var b = graph.source; | 249 var b = graph.source; |
| 233 | 250 |
| 234 f.type = "bandpass"; | 251 f.type = "bandpass"; |
| 235 f.frequency.value = parameters.freq[0]; | 252 f.frequency.value = parameters.freq[0]; |
| 236 f.detune.setValueAtTime(parameters.detune[0], 0); | 253 f.detune.setValueAtTime(parameters.detune[0], 0); |
| 237 f.detune.linearRampToValueAtTime(parameters.detune[1], renderDuration); | 254 f.detune.linearRampToValueAtTime(parameters.detune[1], automationEndTime
); |
| 238 | 255 |
| 239 context.startRendering() | 256 context.startRendering() |
| 240 .then(createFilterVerifier(createBandpassFilter, 5e-6, parameters, b.g
etChannelData(0), | 257 .then(createFilterVerifier(createBandpassFilter, 2.9535e-5, parameters
, b.getChannelData(0), |
| 241 "Output of bandpass filter with detune automation")) | 258 "Output of bandpass filter with detune automation")) |
| 242 .then(done); | 259 .then(done); |
| 243 }); | 260 }); |
| 244 | 261 |
| 245 // Automate all of the filter parameters at once. This is a basic check t
hat everything is | 262 // Automate all of the filter parameters at once. This is a basic check t
hat everything is |
| 246 // working. A peaking filter is used because it uses all of the parameter
s. | 263 // working. A peaking filter is used because it uses all of the parameter
s. |
| 247 audit.defineTask("automate-all", function (done) { | 264 audit.defineTask("automate-all", function (done) { |
| 248 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa
mpleRate); | 265 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa
mpleRate); |
| 249 var graph = configureGraph(context, 10*440); | 266 var graph = configureGraph(context, 10*440); |
| 250 var f = graph.filter; | 267 var f = graph.filter; |
| 251 var b = graph.source; | 268 var b = graph.source; |
| 252 | 269 |
| 253 // Sweep all of the filter parameters. These are pretty much arbitrary. | 270 // Sweep all of the filter parameters. These are pretty much arbitrary. |
| 254 var parameters = { | 271 var parameters = { |
| 255 freq: [10000, 100], | 272 freq: [8000, 100], |
| 256 Q: [f.Q.value, .0001], | 273 Q: [f.Q.value, .0001], |
| 257 gain: [f.gain.value, 20], | 274 gain: [f.gain.value, 20], |
| 258 detune: [2400, -2400] | 275 detune: [2400, -2400] |
| 259 }; | 276 }; |
| 260 | 277 |
| 261 f.type = "peaking"; | 278 f.type = "peaking"; |
| 262 // Set starting points for all parameters of the filter. Start at 10 kH
z for the center | 279 // Set starting points for all parameters of the filter. Start at 10 kH
z for the center |
| 263 // frequency, and the defaults for Q and gain. | 280 // frequency, and the defaults for Q and gain. |
| 264 f.frequency.setValueAtTime(parameters.freq[0], 0); | 281 f.frequency.setValueAtTime(parameters.freq[0], 0); |
| 265 f.Q.setValueAtTime(parameters.Q[0], 0); | 282 f.Q.setValueAtTime(parameters.Q[0], 0); |
| 266 f.gain.setValueAtTime(parameters.gain[0], 0); | 283 f.gain.setValueAtTime(parameters.gain[0], 0); |
| 267 f.detune.setValueAtTime(parameters.detune[0], 0); | 284 f.detune.setValueAtTime(parameters.detune[0], 0); |
| 268 | 285 |
| 269 // Linear ramp each parameter | 286 // Linear ramp each parameter |
| 270 f.frequency.linearRampToValueAtTime(parameters.freq[1], renderDuration); | 287 f.frequency.linearRampToValueAtTime(parameters.freq[1], automationEndTim
e); |
| 271 f.Q.linearRampToValueAtTime(parameters.Q[1], renderDuration); | 288 f.Q.linearRampToValueAtTime(parameters.Q[1], automationEndTime); |
| 272 f.gain.linearRampToValueAtTime(parameters.gain[1], renderDuration); | 289 f.gain.linearRampToValueAtTime(parameters.gain[1], automationEndTime); |
| 273 f.detune.linearRampToValueAtTime(parameters.detune[1], renderDuration); | 290 f.detune.linearRampToValueAtTime(parameters.detune[1], automationEndTime
); |
| 274 | 291 |
| 275 context.startRendering() | 292 context.startRendering() |
| 276 .then(createFilterVerifier(createPeakingFilter, 3.3e-4, parameters, b.
getChannelData(0), | 293 .then(createFilterVerifier(createPeakingFilter, 3.1233e-4, parameters,
b.getChannelData(0), |
| 277 "Output of peaking filter with automation of all parameters")) | 294 "Output of peaking filter with automation of all parameters")) |
| 278 .then(done); | 295 .then(done); |
| 279 }); | 296 }); |
| 280 | 297 |
| 281 // Test that modulation of the frequency parameter of the filter works. A
sinusoid of 440 Hz | 298 // Test that modulation of the frequency parameter of the filter works. A
sinusoid of 440 Hz |
| 282 // is the test signal that is applied to a bandpass biquad filter. The fr
equency parameter of | 299 // is the test signal that is applied to a bandpass biquad filter. The fr
equency parameter of |
| 283 // the filter is modulated by a sinusoid at 103 Hz, and the frequency modu
lation varies from | 300 // the filter is modulated by a sinusoid at 103 Hz, and the frequency modu
lation varies from |
| 284 // 116 to 412 Hz. (This test was taken from the description in | 301 // 116 to 412 Hz. (This test was taken from the description in |
| 285 // https://github.com/WebAudio/web-audio-api/issues/509#issuecomment-94731
355) | 302 // https://github.com/WebAudio/web-audio-api/issues/509#issuecomment-94731
355) |
| 286 audit.defineTask("modulation", function (done) { | 303 audit.defineTask("modulation", function (done) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 b1[k] = c.b1; | 349 b1[k] = c.b1; |
| 333 b2[k] = c.b2; | 350 b2[k] = c.b2; |
| 334 a1[k] = c.a1; | 351 a1[k] = c.a1; |
| 335 a2[k] = c.a2; | 352 a2[k] = c.a2; |
| 336 } | 353 } |
| 337 reference = timeVaryingFilter(b.getChannelData(0), | 354 reference = timeVaryingFilter(b.getChannelData(0), |
| 338 {b0: b0, b1: b1, b2: b2, a1: a1, a2: a2}); | 355 {b0: b0, b1: b1, b2: b2, a1: a1, a2: a2}); |
| 339 | 356 |
| 340 Should("Output of bandpass filter with sinusoidal modulation of ban
dpass center frequency", | 357 Should("Output of bandpass filter with sinusoidal modulation of ban
dpass center frequency", |
| 341 actual) | 358 actual) |
| 342 .beCloseToArray(reference, 4e-6); | 359 .beCloseToArray(reference, 3.9787e-5); |
| 343 }) | 360 }) |
| 344 .then(done); | 361 .then(done); |
| 345 }); | 362 }); |
| 346 | 363 |
| 347 // All done! | 364 // All done! |
| 348 audit.defineTask("finish", function (done) { | 365 audit.defineTask("finish", function (done) { |
| 349 finishJSTest(); | 366 finishJSTest(); |
| 350 done(); | 367 done(); |
| 351 }); | 368 }); |
| 352 | 369 |
| 353 audit.runTasks(); | 370 audit.runTasks(); |
| 354 </script> | 371 </script> |
| 355 </body> | 372 </body> |
| 356 </html> | 373 </html> |
| OLD | NEW |