Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Side by Side Diff: third_party/WebKit/LayoutTests/webaudio/BiquadFilter/biquad-automation.html

Issue 2895963003: Apply layout-test-tidy to LayoutTests/webaudio (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 <!doctype html> 1 <!DOCTYPE html>
2 <html> 2 <html>
3 <head> 3 <head>
4 <title>Biquad Automation Test</title> 4 <title>
5 Biquad Automation Test
6 </title>
5 <script src="../../resources/testharness.js"></script> 7 <script src="../../resources/testharness.js"></script>
6 <script src="../../resources/testharnessreport.js"></script> 8 <script src="../../resources/testharnessreport.js"></script>
7 <script src="../resources/audit-util.js"></script> 9 <script src="../resources/audit-util.js"></script>
8 <script src="../resources/audit.js"></script> 10 <script src="../resources/audit.js"></script>
9 <script src="../resources/biquad-filters.js"></script> 11 <script src="../resources/biquad-filters.js"></script>
10 <script src="../resources/audioparam-testing.js"></script> 12 <script src="../resources/audioparam-testing.js"></script>
11 </head> 13 </head>
12 <body> 14 <body>
13 <script> 15 <script id="layout-test-code">
14 16 // Don't need to run these tests at high sampling rate, so just use a low
15 17 // one to reduce memory usage and complexity.
16 // Don't need to run these tests at high sampling rate, so just use a low one to reduce memory 18 let sampleRate = 16000;
17 // usage and complexity.
18 var sampleRate = 16000;
19 19
20 // How long to render for each test. 20 // How long to render for each test.
21 var renderDuration = 0.25; 21 let renderDuration = 0.25;
22 // Where to end the automations. Fairly arbitrary, but must end before 22 // Where to end the automations. Fairly arbitrary, but must end before
23 // the renderDuration. 23 // the renderDuration.
24 var automationEndTime = renderDuration / 2; 24 let automationEndTime = renderDuration / 2;
25 25
26 var audit = Audit.createTaskRunner(); 26 let audit = Audit.createTaskRunner();
27 27
28 // The definition of the linear ramp automation function. 28 // The definition of the linear ramp automation function.
29 function linearRamp(t, v0, v1, t0, t1) { 29 function linearRamp(t, v0, v1, t0, t1) {
30 return v0 + (v1 - v0) * (t - t0) / (t1 - t0); 30 return v0 + (v1 - v0) * (t - t0) / (t1 - t0);
31 } 31 }
32 32
33 // Generate the filter coefficients for the specified filter using the giv en parameters for 33 // Generate the filter coefficients for the specified filter using the
34 // the given duration. |filterTypeFunction| is a function that returns th e filter 34 // given parameters for the given duration. |filterTypeFunction| is a
35 // coefficients for one set of parameters. |parameters| is a property bag that contains the 35 // function that returns the filter coefficients for one set of
36 // start and end values (as an array) for each of the biquad attributes. The properties are 36 // parameters. |parameters| is a property bag that contains the start and
37 // |freq|, |Q|, |gain|, and |detune|. |duration| is the number of seconds for which the 37 // end values (as an array) for each of the biquad attributes. The
38 // coefficients are generated. 38 // properties are |freq|, |Q|, |gain|, and |detune|. |duration| is the
39 // number of seconds for which the coefficients are generated.
39 // 40 //
40 // 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
41 // consisting of the coefficients for the time-varying biquad filter. 42 // propery is an array consisting of the coefficients for the time-varying
42 function generateFilterCoefficients(filterTypeFunction, parameters, durati on) { 43 // biquad filter.
43 var renderEndFrame = Math.ceil(renderDuration * sampleRate); 44 function generateFilterCoefficients(
44 var endFrame = Math.ceil(duration * sampleRate); 45 filterTypeFunction, parameters, duration) {
45 var nCoef = renderEndFrame; 46 let renderEndFrame = Math.ceil(renderDuration * sampleRate);
46 var b0 = new Float64Array(nCoef); 47 let endFrame = Math.ceil(duration * sampleRate);
47 var b1 = new Float64Array(nCoef); 48 let nCoef = renderEndFrame;
48 var b2 = new Float64Array(nCoef); 49 let b0 = new Float64Array(nCoef);
49 var a1 = new Float64Array(nCoef); 50 let b1 = new Float64Array(nCoef);
50 var a2 = new Float64Array(nCoef); 51 let b2 = new Float64Array(nCoef);
52 let a1 = new Float64Array(nCoef);
53 let a2 = new Float64Array(nCoef);
51 54
52 var k = 0; 55 let k = 0;
53 // If the property is not given, use the defaults. 56 // If the property is not given, use the defaults.
54 var freqs = parameters.freq || [350, 350]; 57 let freqs = parameters.freq || [350, 350];
55 var qs = parameters.Q || [1, 1]; 58 let qs = parameters.Q || [1, 1];
56 var gains = parameters.gain || [0, 0]; 59 let gains = parameters.gain || [0, 0];
57 var detunes = parameters.detune || [0, 0]; 60 let detunes = parameters.detune || [0, 0];
58 61
59 for (var frame = 0; frame <= endFrame; ++frame) { 62 for (let frame = 0; frame <= endFrame; ++frame) {
60 // Apply linear ramp at frame |frame|. 63 // Apply linear ramp at frame |frame|.
61 var f = linearRamp(frame / sampleRate, freqs[0], freqs[1], 0, durati on); 64 let f =
62 var q = linearRamp(frame / sampleRate, qs[0], qs[1], 0, duration); 65 linearRamp(frame / sampleRate, freqs[0], freqs[1], 0, duration);
63 var g = linearRamp(frame / sampleRate, gains[0], gains[1], 0, durati on); 66 let q = linearRamp(frame / sampleRate, qs[0], qs[1], 0, duration);
64 var d = linearRamp(frame / sampleRate, detunes[0], detunes[1], 0, du ration); 67 let g =
68 linearRamp(frame / sampleRate, gains[0], gains[1], 0, duration);
69 let d = linearRamp(
70 frame / sampleRate, detunes[0], detunes[1], 0, duration);
65 71
66 // Compute actual frequency parameter 72 // Compute actual frequency parameter
67 f = f * Math.pow(2, d / 1200); 73 f = f * Math.pow(2, d / 1200);
68 74
69 // Compute filter coefficients 75 // Compute filter coefficients
70 var coef = filterTypeFunction(f / (sampleRate / 2), q, g); 76 let coef = filterTypeFunction(f / (sampleRate / 2), q, g);
71 b0[k] = coef.b0; 77 b0[k] = coef.b0;
72 b1[k] = coef.b1; 78 b1[k] = coef.b1;
73 b2[k] = coef.b2; 79 b2[k] = coef.b2;
74 a1[k] = coef.a1; 80 a1[k] = coef.a1;
75 a2[k] = coef.a2; 81 a2[k] = coef.a2;
76 ++k; 82 ++k;
77 } 83 }
78 84
79 // Fill the rest of the arrays with the constant value to the end of 85 // Fill the rest of the arrays with the constant value to the end of
80 // the rendering duration. 86 // the rendering duration.
81 b0.fill(b0[endFrame], endFrame + 1); 87 b0.fill(b0[endFrame], endFrame + 1);
82 b1.fill(b1[endFrame], endFrame + 1); 88 b1.fill(b1[endFrame], endFrame + 1);
83 b2.fill(b2[endFrame], endFrame + 1); 89 b2.fill(b2[endFrame], endFrame + 1);
84 a1.fill(a1[endFrame], endFrame + 1); 90 a1.fill(a1[endFrame], endFrame + 1);
85 a2.fill(a2[endFrame], endFrame + 1); 91 a2.fill(a2[endFrame], endFrame + 1);
86 92
87 return {b0: b0, b1: b1, b2: b2, a1: a1, a2: a2}; 93 return {b0: b0, b1: b1, b2: b2, a1: a1, a2: a2};
88 } 94 }
89 95
90 // Apply the given time-varying biquad filter to the given signal, |signal |. |coef| should be 96 // Apply the given time-varying biquad filter to the given signal,
91 // the time-varying coefficients of the filter, as returned by |generateFi lterCoefficients|. 97 // |signal|. |coef| should be the time-varying coefficients of the
98 // filter, as returned by |generateFilterCoefficients|.
92 function timeVaryingFilter(signal, coef) { 99 function timeVaryingFilter(signal, coef) {
93 var length = signal.length; 100 let length = signal.length;
94 // Use double precision for the internal computations. 101 // Use double precision for the internal computations.
95 var y = new Float64Array(length); 102 let y = new Float64Array(length);
96 103
97 // Prime the pump. (Assumes the signal has length >= 2!) 104 // Prime the pump. (Assumes the signal has length >= 2!)
98 y[0] = coef.b0[0] * signal[0]; 105 y[0] = coef.b0[0] * signal[0];
99 y[1] = coef.b0[1] * signal[1] + coef.b1[1] * signal[0] - coef.a1[1] * y[ 0]; 106 y[1] =
107 coef.b0[1] * signal[1] + coef.b1[1] * signal[0] - coef.a1[1] * y[0];
100 108
101 for (var n = 2; n < length; ++n) { 109 for (let n = 2; n < length; ++n) {
102 y[n] = coef.b0[n] * signal[n] + coef.b1[n] * signal[n-1] + coef.b2[n] * signal[n-2]; 110 y[n] = coef.b0[n] * signal[n] + coef.b1[n] * signal[n - 1] +
103 y[n] -= coef.a1[n] * y[n-1] + coef.a2[n] * y[n-2]; 111 coef.b2[n] * signal[n - 2];
112 y[n] -= coef.a1[n] * y[n - 1] + coef.a2[n] * y[n - 2];
104 } 113 }
105 114
106 // But convert the result to single precision for comparison. 115 // But convert the result to single precision for comparison.
107 return y.map(Math.fround); 116 return y.map(Math.fround);
108 } 117 }
109 118
110 // Configure the audio graph using |context|. Returns the biquad filter n ode and the 119 // Configure the audio graph using |context|. Returns the biquad filter
111 // AudioBuffer used for the source. 120 // node and the AudioBuffer used for the source.
112 function configureGraph(context, toneFrequency) { 121 function configureGraph(context, toneFrequency) {
113 // The source is just a simple sine wave. 122 // The source is just a simple sine wave.
114 var src = context.createBufferSource(); 123 let src = context.createBufferSource();
115 var b = context.createBuffer(1, renderDuration * sampleRate, sampleRate) ; 124 let b =
116 var data = b.getChannelData(0); 125 context.createBuffer(1, renderDuration * sampleRate, sampleRate);
117 var omega = 2 * Math.PI * toneFrequency / sampleRate; 126 let data = b.getChannelData(0);
118 for (var k = 0; k < data.length; ++k) { 127 let omega = 2 * Math.PI * toneFrequency / sampleRate;
128 for (let k = 0; k < data.length; ++k) {
119 data[k] = Math.sin(omega * k); 129 data[k] = Math.sin(omega * k);
120 } 130 }
121 src.buffer = b; 131 src.buffer = b;
122 var f = context.createBiquadFilter(); 132 let f = context.createBiquadFilter();
123 src.connect(f); 133 src.connect(f);
124 f.connect(context.destination); 134 f.connect(context.destination);
125 135
126 src.start(); 136 src.start();
127 137
128 return {filter: f, source: b}; 138 return {filter: f, source: b};
129 } 139 }
130 140
131 function createFilterVerifier(should, filterCreator, threshold, parameters , input, message) { 141 function createFilterVerifier(
132 return function (resultBuffer) { 142 should, filterCreator, threshold, parameters, input, message) {
133 var actual = resultBuffer.getChannelData(0); 143 return function(resultBuffer) {
134 var coefs = generateFilterCoefficients(filterCreator, parameters, auto mationEndTime); 144 let actual = resultBuffer.getChannelData(0);
145 let coefs = generateFilterCoefficients(
146 filterCreator, parameters, automationEndTime);
135 147
136 reference = timeVaryingFilter(input, coefs); 148 reference = timeVaryingFilter(input, coefs);
137 149
138 should(actual, message).beCloseToArray(reference, { 150 should(actual, message).beCloseToArray(reference, {
139 absoluteThreshold: threshold 151 absoluteThreshold: threshold
140 }); 152 });
141 }; 153 };
142 } 154 }
143 155
144 // Automate just the frequency parameter. A bandpass filter is used where the center 156 // Automate just the frequency parameter. A bandpass filter is used where
145 // frequency is swept across the source (which is a simple tone). 157 // the center frequency is swept across the source (which is a simple
146 audit.define("automate-freq", (task, should) => { 158 // tone).
147 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate); 159 audit.define('automate-freq', (task, should) => {
160 let context =
161 new OfflineAudioContext(1, renderDuration * sampleRate, sampleRate);
148 162
149 // Center frequency of bandpass filter and also the frequency of the tes t tone. 163 // Center frequency of bandpass filter and also the frequency of the
150 var centerFreq = 10*440; 164 // test tone.
165 let centerFreq = 10 * 440;
151 166
152 // Sweep the frequency +/- 5*440 Hz from the center. This should cause 167 // Sweep the frequency +/- 5*440 Hz from the center. This should cause
153 // the output to be low at the beginning and end of the test where the 168 // the output to be low at the beginning and end of the test where the
154 // tone is outside the pass band of the filter, but high in the middle 169 // tone is outside the pass band of the filter, but high in the middle
155 // of the automation time where the tone is near the center of the pass 170 // of the automation time where the tone is near the center of the pass
156 // band. Make sure the frequency sweep stays inside the Nyquist 171 // band. Make sure the frequency sweep stays inside the Nyquist
157 // frequency. 172 // frequency.
158 var parameters = { 173 let parameters = {freq: [centerFreq - 5 * 440, centerFreq + 5 * 440]};
159 freq: [centerFreq - 5*440, centerFreq + 5*440] 174 let graph = configureGraph(context, centerFreq);
160 }; 175 let f = graph.filter;
161 var graph = configureGraph(context, centerFreq); 176 let b = graph.source;
162 var f = graph.filter; 177
163 var b = graph.source; 178 f.type = 'bandpass';
164
165 f.type = "bandpass";
166 f.frequency.setValueAtTime(parameters.freq[0], 0); 179 f.frequency.setValueAtTime(parameters.freq[0], 0);
167 f.frequency.linearRampToValueAtTime(parameters.freq[1], automationEndTim e); 180 f.frequency.linearRampToValueAtTime(
168 181 parameters.freq[1], automationEndTime);
169 context.startRendering() 182
170 .then(createFilterVerifier(should, createBandpassFilter, 4.6455e-6, 183 context.startRendering()
171 parameters, b.getChannelData(0), 184 .then(createFilterVerifier(
172 "Output of bandpass filter with frequency automation")) 185 should, createBandpassFilter, 4.6455e-6, parameters,
173 .then(() => task.done()); 186 b.getChannelData(0),
174 }); 187 'Output of bandpass filter with frequency automation'))
175 188 .then(() => task.done());
176 // Automate just the Q parameter. A bandpass filter is used where the Q o f the filter is 189 });
177 // swept. 190
178 audit.define("automate-q", (task, should) => { 191 // Automate just the Q parameter. A bandpass filter is used where the Q
179 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate); 192 // of the filter is swept.
193 audit.define('automate-q', (task, should) => {
194 let context =
195 new OfflineAudioContext(1, renderDuration * sampleRate, sampleRate);
180 196
181 // The frequency of the test tone. 197 // The frequency of the test tone.
182 var centerFreq = 440; 198 let centerFreq = 440;
183 199
184 // Sweep the Q paramter between 1 and 200. This will cause the output o f the filter to pass 200 // Sweep the Q paramter between 1 and 200. This will cause the output
185 // most of the tone at the beginning to passing less of the tone at the end. This is 201 // of the filter to pass most of the tone at the beginning to passing
186 // because we set center frequency of the bandpass filter to be slightly off from the actual 202 // less of the tone at the end. This is because we set center frequency
187 // tone. 203 // of the bandpass filter to be slightly off from the actual tone.
188 var parameters = { 204 let parameters = {
189 Q: [1, 200], 205 Q: [1, 200],
190 // Center frequency of the bandpass filter is just 25 Hz above the ton e frequency. 206 // Center frequency of the bandpass filter is just 25 Hz above the
207 // tone frequency.
191 freq: [centerFreq + 25, centerFreq + 25] 208 freq: [centerFreq + 25, centerFreq + 25]
192 }; 209 };
193 var graph = configureGraph(context, centerFreq); 210 let graph = configureGraph(context, centerFreq);
194 var f = graph.filter; 211 let f = graph.filter;
195 var b = graph.source; 212 let b = graph.source;
196 213
197 f.type = "bandpass"; 214 f.type = 'bandpass';
198 f.frequency.value = parameters.freq[0]; 215 f.frequency.value = parameters.freq[0];
199 f.Q.setValueAtTime(parameters.Q[0], 0); 216 f.Q.setValueAtTime(parameters.Q[0], 0);
200 f.Q.linearRampToValueAtTime(parameters.Q[1], automationEndTime); 217 f.Q.linearRampToValueAtTime(parameters.Q[1], automationEndTime);
201 218
202 context.startRendering() 219 context.startRendering()
203 .then(createFilterVerifier(should, createBandpassFilter, 9.8348e-7, 220 .then(createFilterVerifier(
204 parameters, b.getChannelData(0), 221 should, createBandpassFilter, 9.8348e-7, parameters,
205 "Output of bandpass filter with Q automation")) 222 b.getChannelData(0),
206 .then(() => task.done()); 223 'Output of bandpass filter with Q automation'))
207 }); 224 .then(() => task.done());
208 225 });
209 // Automate just the gain of the lowshelf filter. A test tone will be in the lowshelf part of 226
210 // the filter. The output will vary as the gain of the lowshelf is change d. 227 // Automate just the gain of the lowshelf filter. A test tone will be in
211 audit.define("automate-gain", (task, should) => { 228 // the lowshelf part of the filter. The output will vary as the gain of
212 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate); 229 // the lowshelf is changed.
230 audit.define('automate-gain', (task, should) => {
231 let context =
232 new OfflineAudioContext(1, renderDuration * sampleRate, sampleRate);
213 233
214 // Frequency of the test tone. 234 // Frequency of the test tone.
215 var centerFreq = 440; 235 let centerFreq = 440;
216 236
217 // Set the cutoff frequency of the lowshelf to be significantly higher t han the test tone. 237 // Set the cutoff frequency of the lowshelf to be significantly higher
218 // Sweep the gain from 20 dB to -20 dB. (We go from 20 to -20 to easily verify that the 238 // than the test tone. Sweep the gain from 20 dB to -20 dB. (We go from
219 // filter didn't go unstable.) 239 // 20 to -20 to easily verify that the filter didn't go unstable.)
220 var parameters = { 240 let parameters = {freq: [3500, 3500], gain: [20, -20]};
221 freq: [3500, 3500], 241 let graph = configureGraph(context, centerFreq);
222 gain: [20, -20] 242 let f = graph.filter;
223 }; 243 let b = graph.source;
224 var graph = configureGraph(context, centerFreq); 244
225 var f = graph.filter; 245 f.type = 'lowshelf';
226 var b = graph.source;
227
228 f.type = "lowshelf";
229 f.frequency.value = parameters.freq[0]; 246 f.frequency.value = parameters.freq[0];
230 f.gain.setValueAtTime(parameters.gain[0], 0); 247 f.gain.setValueAtTime(parameters.gain[0], 0);
231 f.gain.linearRampToValueAtTime(parameters.gain[1], automationEndTime); 248 f.gain.linearRampToValueAtTime(parameters.gain[1], automationEndTime);
232 249
233 context.startRendering() 250 context.startRendering()
234 .then(createFilterVerifier(should, createLowShelfFilter, 2.7657e-5, 251 .then(createFilterVerifier(
235 parameters, b.getChannelData(0), 252 should, createLowShelfFilter, 2.7657e-5, parameters,
236 "Output of lowshelf filter with gain automation")) 253 b.getChannelData(0),
237 .then(() => task.done()); 254 'Output of lowshelf filter with gain automation'))
238 }); 255 .then(() => task.done());
239 256 });
240 // Automate just the detune parameter. Basically the same test as for the frequncy parameter 257
241 // but we just use the detune parameter to modulate the frequency paramete r. 258 // Automate just the detune parameter. Basically the same test as for the
242 audit.define("automate-detune", (task, should) => { 259 // frequncy parameter but we just use the detune parameter to modulate the
243 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate); 260 // frequency parameter.
244 var centerFreq = 10*440; 261 audit.define('automate-detune', (task, should) => {
245 var parameters = { 262 let context =
263 new OfflineAudioContext(1, renderDuration * sampleRate, sampleRate);
264 let centerFreq = 10 * 440;
265 let parameters = {
246 freq: [centerFreq, centerFreq], 266 freq: [centerFreq, centerFreq],
247 detune: [-10*1200, 10*1200] 267 detune: [-10 * 1200, 10 * 1200]
248 }; 268 };
249 var graph = configureGraph(context, centerFreq); 269 let graph = configureGraph(context, centerFreq);
250 var f = graph.filter; 270 let f = graph.filter;
251 var b = graph.source; 271 let b = graph.source;
252 272
253 f.type = "bandpass"; 273 f.type = 'bandpass';
254 f.frequency.value = parameters.freq[0]; 274 f.frequency.value = parameters.freq[0];
255 f.detune.setValueAtTime(parameters.detune[0], 0); 275 f.detune.setValueAtTime(parameters.detune[0], 0);
256 f.detune.linearRampToValueAtTime(parameters.detune[1], automationEndTime ); 276 f.detune.linearRampToValueAtTime(
257 277 parameters.detune[1], automationEndTime);
258 context.startRendering() 278
259 .then(createFilterVerifier(should, createBandpassFilter, 3.1471e-5, 279 context.startRendering()
260 parameters, b.getChannelData(0), 280 .then(createFilterVerifier(
261 "Output of bandpass filter with detune automation")) 281 should, createBandpassFilter, 3.1471e-5, parameters,
262 .then(() => task.done()); 282 b.getChannelData(0),
263 }); 283 'Output of bandpass filter with detune automation'))
264 284 .then(() => task.done());
265 // Automate all of the filter parameters at once. This is a basic check t hat everything is 285 });
266 // working. A peaking filter is used because it uses all of the parameter s. 286
267 audit.define("automate-all", (task, should) => { 287 // Automate all of the filter parameters at once. This is a basic check
268 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate); 288 // that everything is working. A peaking filter is used because it uses
269 var graph = configureGraph(context, 10*440); 289 // all of the parameters.
270 var f = graph.filter; 290 audit.define('automate-all', (task, should) => {
271 var b = graph.source; 291 let context =
292 new OfflineAudioContext(1, renderDuration * sampleRate, sampleRate);
293 let graph = configureGraph(context, 10 * 440);
294 let f = graph.filter;
295 let b = graph.source;
272 296
273 // Sweep all of the filter parameters. These are pretty much arbitrary. 297 // Sweep all of the filter parameters. These are pretty much arbitrary.
274 var parameters = { 298 let parameters = {
275 freq: [8000, 100], 299 freq: [8000, 100],
276 Q: [f.Q.value, .0001], 300 Q: [f.Q.value, .0001],
277 gain: [f.gain.value, 20], 301 gain: [f.gain.value, 20],
278 detune: [2400, -2400] 302 detune: [2400, -2400]
279 }; 303 };
280 304
281 f.type = "peaking"; 305 f.type = 'peaking';
282 // Set starting points for all parameters of the filter. Start at 10 kH z for the center 306 // Set starting points for all parameters of the filter. Start at 10
283 // frequency, and the defaults for Q and gain. 307 // kHz for the center frequency, and the defaults for Q and gain.
284 f.frequency.setValueAtTime(parameters.freq[0], 0); 308 f.frequency.setValueAtTime(parameters.freq[0], 0);
285 f.Q.setValueAtTime(parameters.Q[0], 0); 309 f.Q.setValueAtTime(parameters.Q[0], 0);
286 f.gain.setValueAtTime(parameters.gain[0], 0); 310 f.gain.setValueAtTime(parameters.gain[0], 0);
287 f.detune.setValueAtTime(parameters.detune[0], 0); 311 f.detune.setValueAtTime(parameters.detune[0], 0);
288 312
289 // Linear ramp each parameter 313 // Linear ramp each parameter
290 f.frequency.linearRampToValueAtTime(parameters.freq[1], automationEndTim e); 314 f.frequency.linearRampToValueAtTime(
315 parameters.freq[1], automationEndTime);
291 f.Q.linearRampToValueAtTime(parameters.Q[1], automationEndTime); 316 f.Q.linearRampToValueAtTime(parameters.Q[1], automationEndTime);
292 f.gain.linearRampToValueAtTime(parameters.gain[1], automationEndTime); 317 f.gain.linearRampToValueAtTime(parameters.gain[1], automationEndTime);
293 f.detune.linearRampToValueAtTime(parameters.detune[1], automationEndTime ); 318 f.detune.linearRampToValueAtTime(
294 319 parameters.detune[1], automationEndTime);
295 context.startRendering() 320
296 .then(createFilterVerifier(should, createPeakingFilter, 6.2907e-4, 321 context.startRendering()
297 parameters, b.getChannelData(0), 322 .then(createFilterVerifier(
298 "Output of peaking filter with automation of all parameters")) 323 should, createPeakingFilter, 6.2907e-4, parameters,
299 .then(() => task.done()); 324 b.getChannelData(0),
300 }); 325 'Output of peaking filter with automation of all parameters'))
301 326 .then(() => task.done());
302 // Test that modulation of the frequency parameter of the filter works. A sinusoid of 440 Hz 327 });
303 // is the test signal that is applied to a bandpass biquad filter. The fr equency parameter of 328
304 // the filter is modulated by a sinusoid at 103 Hz, and the frequency modu lation varies from 329 // Test that modulation of the frequency parameter of the filter works. A
305 // 116 to 412 Hz. (This test was taken from the description in 330 // sinusoid of 440 Hz is the test signal that is applied to a bandpass
331 // biquad filter. The frequency parameter of the filter is modulated by a
332 // sinusoid at 103 Hz, and the frequency modulation varies from 116 to 412
333 // Hz. (This test was taken from the description in
306 // https://github.com/WebAudio/web-audio-api/issues/509#issuecomment-94731 355) 334 // https://github.com/WebAudio/web-audio-api/issues/509#issuecomment-94731 355)
307 audit.define("modulation", (task, should) => { 335 audit.define('modulation', (task, should) => {
308 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate); 336 let context =
309 337 new OfflineAudioContext(1, renderDuration * sampleRate, sampleRate);
310 // Create a graph with the sinusoidal source at 440 Hz as the input to a biquad filter. 338
311 var graph = configureGraph(context, 440); 339 // Create a graph with the sinusoidal source at 440 Hz as the input to a
312 var f = graph.filter; 340 // biquad filter.
313 var b = graph.source; 341 let graph = configureGraph(context, 440);
314 342 let f = graph.filter;
315 f.type = "bandpass"; 343 let b = graph.source;
344
345 f.type = 'bandpass';
316 f.Q.value = 5; 346 f.Q.value = 5;
317 f.frequency.value = 264; 347 f.frequency.value = 264;
318 348
319 // Create the modulation source, a sinusoid with frequency 103 Hz and am plitude 148. (The 349 // Create the modulation source, a sinusoid with frequency 103 Hz and
320 // amplitude of 148 is added to the filter's frequency value of 264 to p roduce a sinusoidal 350 // amplitude 148. (The amplitude of 148 is added to the filter's
321 // modulation of the frequency parameter from 116 to 412 Hz.) 351 // frequency value of 264 to produce a sinusoidal modulation of the
322 var mod = context.createBufferSource(); 352 // frequency parameter from 116 to 412 Hz.)
323 var mbuffer = context.createBuffer(1, renderDuration * sampleRate, sampl eRate); 353 let mod = context.createBufferSource();
324 var d = mbuffer.getChannelData(0); 354 let mbuffer =
325 var omega = 2 * Math.PI * 103 / sampleRate; 355 context.createBuffer(1, renderDuration * sampleRate, sampleRate);
326 for (var k = 0; k < d.length; ++k) { 356 let d = mbuffer.getChannelData(0);
357 let omega = 2 * Math.PI * 103 / sampleRate;
358 for (let k = 0; k < d.length; ++k) {
327 d[k] = 148 * Math.sin(omega * k); 359 d[k] = 148 * Math.sin(omega * k);
328 } 360 }
329 mod.buffer = mbuffer; 361 mod.buffer = mbuffer;
330 362
331 mod.connect(f.frequency); 363 mod.connect(f.frequency);
332 364
333 mod.start(); 365 mod.start();
334 context.startRendering() 366 context.startRendering()
335 .then(function (resultBuffer) { 367 .then(function(resultBuffer) {
336 var actual = resultBuffer.getChannelData(0); 368 let actual = resultBuffer.getChannelData(0);
337 // Compute the filter coefficients using the mod sine wave 369 // Compute the filter coefficients using the mod sine wave
338 370
339 var endFrame = Math.ceil(renderDuration * sampleRate); 371 let endFrame = Math.ceil(renderDuration * sampleRate);
340 var nCoef = endFrame; 372 let nCoef = endFrame;
341 var b0 = new Float64Array(nCoef); 373 let b0 = new Float64Array(nCoef);
342 var b1 = new Float64Array(nCoef); 374 let b1 = new Float64Array(nCoef);
343 var b2 = new Float64Array(nCoef); 375 let b2 = new Float64Array(nCoef);
344 var a1 = new Float64Array(nCoef); 376 let a1 = new Float64Array(nCoef);
345 var a2 = new Float64Array(nCoef); 377 let a2 = new Float64Array(nCoef);
346 378
347 // Generate the filter coefficients when the frequency varies from 116 to 248 Hz using 379 // Generate the filter coefficients when the frequency varies from
348 // the 103 Hz sinusoid. 380 // 116 to 248 Hz using the 103 Hz sinusoid.
349 for (var k = 0; k < nCoef; ++k) { 381 for (let k = 0; k < nCoef; ++k) {
350 var freq = f.frequency.value + d[k]; 382 let freq = f.frequency.value + d[k];
351 var c = createBandpassFilter(freq / (sampleRate / 2), f.Q.value, f.gain.value); 383 let c = createBandpassFilter(
352 b0[k] = c.b0; 384 freq / (sampleRate / 2), f.Q.value, f.gain.value);
353 b1[k] = c.b1; 385 b0[k] = c.b0;
354 b2[k] = c.b2; 386 b1[k] = c.b1;
355 a1[k] = c.a1; 387 b2[k] = c.b2;
356 a2[k] = c.a2; 388 a1[k] = c.a1;
357 } 389 a2[k] = c.a2;
358 reference = timeVaryingFilter(b.getChannelData(0), 390 }
359 {b0: b0, b1: b1, b2: b2, a1: a1, a2: a2}); 391 reference = timeVaryingFilter(
360 392 b.getChannelData(0),
361 should(actual, 393 {b0: b0, b1: b1, b2: b2, a1: a1, a2: a2});
362 "Output of bandpass filter with sinusoidal modulation of bandpa ss center frequency" 394
363 ) 395 should(
364 .beCloseToArray(reference, { 396 actual,
365 absoluteThreshold: 3.9787e-5 397 'Output of bandpass filter with sinusoidal modulation of bandp ass center frequency')
366 }); 398 .beCloseToArray(reference, {absoluteThreshold: 3.9787e-5});
367 }) 399 })
368 .then(() => task.done()); 400 .then(() => task.done());
369 }); 401 });
370 402
371 audit.run(); 403 audit.run();
372 </script> 404 </script>
373 </body> 405 </body>
374 </html> 406 </html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698