OLD | NEW |
| (Empty) |
1 <!doctype html> | |
2 <html> | |
3 <head> | |
4 <title>Test Different PeriodicWave Lengths at Different Sample Rates</title> | |
5 <script src="../resources/js-test.js"></script> | |
6 <script src="resources/compatibility.js"></script> | |
7 <script src="resources/audit-util.js"></script> | |
8 <script src="resources/audio-testing.js"></script> | |
9 </head> | |
10 | |
11 <body> | |
12 <script> | |
13 description("Test Different PeriodicWave Lengths at Different Sample Rates
"); | |
14 window.jsTestIsAsync = true; | |
15 | |
16 // Test PeriodicWave objects with varying number of coefficients at differ
ent sample rates. | |
17 // Basically, verify that the coefficients are used at the appropriate sam
ple rates. This is | |
18 // done by comparing the outputs of two periodic waves used in oscillators
. The output should | |
19 // either be exactly zero or not depending on whether the coefficients wer
e used. | |
20 | |
21 var renderLength = 1; | |
22 var context; | |
23 | |
24 var audit = Audit.createTaskRunner(); | |
25 | |
26 // The set of Audit tests to be run to verify that PeriodicWave is using t
he correct number of | |
27 // coefficients. The name does not have to be unique; the index of the en
try is appended to | |
28 // the test. Every entry (except the last) needs sampleRate, bigWave, sma
llWave, and | |
29 // verifier values. | |
30 | |
31 var testSet = [ | |
32 // Tests for contexts at 192 kHz. | |
33 | |
34 // Test that we use more than 2048 Fourier coefficients at 192 kHz sampl
e rate. Basically | |
35 // verifies that 8192 is acceptable. | |
36 { | |
37 name: "192khz-test-1", | |
38 sampleRate: 192000, | |
39 bigWave: 8192, | |
40 smallWave: 2048, | |
41 verifier: resultShouldBeNonZero | |
42 }, | |
43 | |
44 // Test that we use at least 2049 Fourier coefficients at 192 kHz sample
rate. | |
45 { | |
46 name: "192khz-test-2", | |
47 sampleRate: 192000, | |
48 bigWave: 2049, | |
49 smallWave: 2048, | |
50 verifier: resultShouldBeNonZero | |
51 }, | |
52 | |
53 // Test that we use all 8192 Fourier coefficients at 192 kHz sample rate
. Ideally, we'd | |
54 // like to compare 8191 coefficients vs 8192 coefficients. However, due
to single-precision | |
55 // arithmetic, the wave forms are identical in this case. Thus, use a s
omewhat smaller | |
56 // value where the wave forms are actually different. | |
57 { | |
58 name: "192khz-test-3", | |
59 sampleRate: 192000, | |
60 bigWave: 8192, | |
61 smallWave: (8 - 1 / 256) * 1024, | |
62 verifier: resultShouldBeNonZero | |
63 }, | |
64 | |
65 // Tests for contexts at 48 kHz. | |
66 | |
67 // Test that we do not use more than 2048 Fourier coefficients at 48 kHz
. This depends on | |
68 // the internal implementation where, for backward compatibility and spe
ed, we only use 2048 | |
69 // coefficients at 48 kHz. (This is also true for rates below 88.2 kHz.
) Also tests that | |
70 // 8192 coefficients are allowed (but not all coefficients are used, of
course). | |
71 { | |
72 name: "48khz-test-1", | |
73 sampleRate: 48000, | |
74 bigWave: 8192, | |
75 smallWave: 2048, | |
76 verifier: resultShouldBeZero | |
77 }, | |
78 | |
79 // Test that we do not use more than 2048 Fourier coefficients. | |
80 { | |
81 name: "48khz-test-2", | |
82 sampleRate: 48000, | |
83 bigWave: 2049, | |
84 smallWave: 2048, | |
85 verifier: resultShouldBeZero | |
86 }, | |
87 | |
88 // It's not immediately clear with single-preicison arithmetic that we c
an distinguish | |
89 // between 2049 and 2048 coefficients, so do one more test with slightly
more coefficients. | |
90 { | |
91 name: "48khz-test-3", | |
92 sampleRate: 48000, | |
93 bigWave: (2 + 1 / 64) * 1024, | |
94 smallWave: 2048, | |
95 verifier: resultShouldBeZero | |
96 }, | |
97 | |
98 // Test that we use at least 2048 Fourier coefficients at 48 kHz. Ideal
ly we want to | |
99 // compare 2047 and 2048 coefficients, but single-precision arithmetic m
akes the resulting | |
100 // waveforms the same. Hence use a smaller value that produces differen
t waveforms. | |
101 { | |
102 name: "48khz-test-4", | |
103 sampleRate: 48000, | |
104 bigWave: 2048, | |
105 smallWave: 2046, | |
106 verifier: resultShouldBeNonZero | |
107 }, | |
108 | |
109 // Tests for contexts at 24 kHz. | |
110 | |
111 // Test that we do not use more than 1024 Fourier coefficients at 24 kHz
. | |
112 { | |
113 name: "24khz-test-1", | |
114 sampleRate: 24000, | |
115 bigWave: 8192, | |
116 smallWave: 1024, | |
117 verifier: resultShouldBeZero | |
118 }, | |
119 | |
120 // Test that we do not use more than 1024 Fourier coefficients at 24 kHz
. | |
121 { | |
122 name: "24khz-test-2", | |
123 sampleRate: 24000, | |
124 bigWave: 1025, | |
125 smallWave: 1024, | |
126 verifier: resultShouldBeZero | |
127 }, | |
128 | |
129 // Test that we use at least 1024 Fourier coefficients at 24 kHz. Again
, 1023 and 1024 | |
130 // produce the same waveforms in single-precisiion so use a smaller wave
table size. | |
131 { | |
132 name: "24khz-test-3", | |
133 sampleRate: 24000, | |
134 bigWave: 1024, | |
135 smallWave: 1022, | |
136 verifier: resultShouldBeNonZero | |
137 }, | |
138 ]; | |
139 | |
140 function generatePrefix (sampleRate, bigLength, smallLength) { | |
141 return "At " + (sampleRate / 1000) + " kHz, PeriodicWave with " | |
142 + bigLength + " coefficients vs " | |
143 + smallLength + ": "; | |
144 } | |
145 | |
146 // Returns a function the verifies that the result is zero. The parameter
s control what is | |
147 // printed in the messages. | |
148 function resultShouldBeZero(sampleRate, bigLength, smallLength) { | |
149 return function (buffer) { | |
150 var prefix = generatePrefix(sampleRate, bigLength, smallLength); | |
151 if (isBufferZero(buffer)) | |
152 testPassed(prefix + "identical as expected."); | |
153 else | |
154 testFailed(prefix + "unexpectedly differ."); | |
155 } | |
156 } | |
157 | |
158 // Returns a function the verifies that the result is non-zero. The param
eters control what is | |
159 // printed in the messages. | |
160 function resultShouldBeNonZero(sampleRate, bigLength, smallLength) { | |
161 return function (buffer) { | |
162 var prefix = generatePrefix(sampleRate, bigLength, smallLength); | |
163 if (!isBufferZero(buffer)) | |
164 testPassed(prefix + "differ as expected."); | |
165 else | |
166 testFailed(prefix + "unexpectedly are identical."); | |
167 } | |
168 } | |
169 | |
170 // Creates a function that is used to run an Audit test for a given sample
rate, periodic wave | |
171 // sizes, and verifier. | |
172 function createAuditTestFunction(sampleRate, bigLength, smallLength, verif
ier) { | |
173 return function (done) { | |
174 // Create the audio graph, render it, and then verify that the output
is the expected | |
175 // result. | |
176 createAudioGraph(sampleRate, bigLength, smallLength); | |
177 | |
178 context.startRendering() | |
179 .then(verifier(sampleRate, bigLength, smallLength)) | |
180 .then(done); | |
181 } | |
182 } | |
183 | |
184 // Create the audio graph for the test. | |
185 function createAudioGraph(sampleRate, bigPeriodicWaveLength, smallPeriodic
WaveLength) { | |
186 context = new OfflineAudioContext(1, renderLength * sampleRate, sampleR
ate); | |
187 | |
188 // Two PeriodicWave objects are created with different sizes (small and
big). The contents | |
189 // are the same except that the samll sized PeriodicWave has fewer coef
ficients. | |
190 var smallWaveRealCoef = new Float32Array(smallPeriodicWaveLength); | |
191 var smallWaveImagCoef = new Float32Array(smallPeriodicWaveLength); | |
192 var bigWaveRealCoef = new Float32Array(bigPeriodicWaveLength); | |
193 var bigWaveImagCoef = new Float32Array(bigPeriodicWaveLength); | |
194 | |
195 // Set up the Fourier coefficients for a square wave. | |
196 for (var k = 0; k < bigPeriodicWaveLength; k += 2) { | |
197 bigWaveImagCoef[k] = 4 / Math.PI / k; | |
198 if (k < smallPeriodicWaveLength) | |
199 smallWaveImagCoef[k] = bigWaveImagCoef[k]; | |
200 } | |
201 | |
202 var smallPeriodicWave = context.createPeriodicWave(smallWaveRealCoef, s
mallWaveImagCoef); | |
203 var bigPeriodicWave = context.createPeriodicWave(bigWaveRealCoef, bigWa
veImagCoef); | |
204 | |
205 // Create oscillators using these PeriodicWave's. | |
206 var smallOscillator = context.createOscillator(); | |
207 var bigOscillator = context.createOscillator(); | |
208 | |
209 smallOscillator.setPeriodicWave(smallPeriodicWave); | |
210 bigOscillator.setPeriodicWave(bigPeriodicWave); | |
211 | |
212 // Use a frequency of 1 Hz to make the distinction easier. Can't tell
from this test, but | |
213 // if you plot the signals from these oscillators, it's very clear that
they are different. | |
214 smallOscillator.frequency.value = 1; | |
215 bigOscillator.frequency.value = 1; | |
216 | |
217 // The desired output is the difference between these oscillators. | |
218 var gain = context.createGain(); | |
219 gain.gain.value = -1; | |
220 smallOscillator.connect(gain); | |
221 | |
222 gain.connect(context.destination); | |
223 bigOscillator.connect(context.destination); | |
224 | |
225 // Start the oscillators. | |
226 smallOscillator.start(); | |
227 bigOscillator.start(); | |
228 } | |
229 | |
230 // Return true if the buffer is exactly zero. | |
231 function isBufferZero(buffer) { | |
232 if (buffer.getChannelData(0).find(function (x) { return x != 0; })) | |
233 return false; | |
234 return true; | |
235 } | |
236 | |
237 // Ensure the actual Audit test name is unique by prepending an index to t
he provided test | |
238 // name. | |
239 function actualTestName(name, index) { | |
240 return index + ":" + name; | |
241 } | |
242 | |
243 // Define the tasks based on the entries in testSet. | |
244 function defineAuditTests () { | |
245 for (var k = 0; k < testSet.length; ++k) { | |
246 var test = testSet[k]; | |
247 var actualName = actualTestName(test.name, k); | |
248 audit.defineTask(actualName, | |
249 createAuditTestFunction(test.sampleRate, test.bigWave, test.smallWav
e, test.verifier)); | |
250 } | |
251 // Define the finish test last. | |
252 audit.defineTask(actualTestName("finish-tests", testSet.length), functio
n (done) { | |
253 finishJSTest(); | |
254 done(); | |
255 }); | |
256 } | |
257 | |
258 defineAuditTests(); | |
259 audit.runTasks(); | |
260 | |
261 successfullyParsed = true; | |
262 </script> | |
263 </body> | |
264 </html> | |
OLD | NEW |