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