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