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