OLD | NEW |
| (Empty) |
1 <!DOCTYPE html> | |
2 | |
3 <html> | |
4 <head> | |
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 <script src="resources/audiobuffersource-testing.js"></script> | |
10 </head> | |
11 | |
12 <body> | |
13 <script> | |
14 description("Tests AudioBufferSourceNode looping with a variety of loop points."
); | |
15 | |
16 // The following test cases assume an AudioBuffer of length 8 whose PCM data is
a linear ramp, 0, 1, 2, 3,... | |
17 // |description| is optional and will be computed from the other parameters. |of
fsetFrame| is | |
18 // optional and defaults to 0. | |
19 | |
20 var tests = [ | |
21 | |
22 { description: "loop whole buffer by default with loopStart == loopEnd == 0", | |
23 loopStartFrame: 0, | |
24 loopEndFrame: 0, | |
25 renderFrames: 16, | |
26 playbackRate: 1, | |
27 expected: [0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7] }, | |
28 | |
29 { description: "loop whole buffer explicitly", | |
30 loopStartFrame: 0, | |
31 loopEndFrame: 8, | |
32 renderFrames: 16, | |
33 playbackRate: 1, | |
34 expected: [0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7] }, | |
35 | |
36 { description: "loop from middle to end of buffer", | |
37 loopStartFrame: 4, | |
38 loopEndFrame: 8, | |
39 renderFrames: 16, | |
40 playbackRate: 1, | |
41 expected: [0,1,2,3,4,5,6,7,4,5,6,7,4,5,6,7] }, | |
42 | |
43 { description: "loop from start to middle of buffer", | |
44 loopStartFrame: 0, | |
45 loopEndFrame: 4, | |
46 renderFrames: 16, | |
47 playbackRate: 1, | |
48 expected: [0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3] }, | |
49 | |
50 { loopStartFrame: 4, | |
51 loopEndFrame: 6, | |
52 renderFrames: 16, | |
53 playbackRate: 1, | |
54 expected: [0,1,2,3,4,5,4,5,4,5,4,5,4,5,4,5] }, | |
55 | |
56 { loopStartFrame: 3, | |
57 loopEndFrame: 7, | |
58 renderFrames: 16, | |
59 playbackRate: 1, | |
60 expected: [0,1,2,3,4,5,6,3,4,5,6,3,4,5,6,3] }, | |
61 | |
62 { loopStartFrame: 4, | |
63 loopEndFrame: 6, | |
64 renderFrames: 16, | |
65 playbackRate: 0.5, | |
66 expected: [0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 4, 4.5, 5, 5.5] }, | |
67 | |
68 { loopStartFrame: 4, | |
69 loopEndFrame: 6, | |
70 renderFrames: 16, | |
71 playbackRate: 1.5, | |
72 expected: [0, 1.5, 3, 4.5, 4, 5.5, 5, 4.5, 4, 5.5, 5, 4.5, 4, 5.5, 5, 4.5] }, | |
73 | |
74 // Offset past loop end, so playback starts at loop start | |
75 { loopStartFrame: 2, | |
76 loopEndFrame: 5, | |
77 renderFrames: 16, | |
78 playbackRate: 1, | |
79 offsetFrame: 6, | |
80 expected: [2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2] }, | |
81 | |
82 // Offset before loop start, so start at offset and continue | |
83 { loopStartFrame: 3, | |
84 loopEndFrame: 6, | |
85 renderFrames: 16, | |
86 playbackRate: 1, | |
87 offsetFrame: 1, | |
88 expected: [1, 2, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4] }, | |
89 | |
90 // Offset between loop start and loop end, so start at offset and continue | |
91 { loopStartFrame: 3, | |
92 loopEndFrame: 6, | |
93 renderFrames: 16, | |
94 playbackRate: 1, | |
95 offsetFrame: 4, | |
96 expected: [4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4] }, | |
97 | |
98 { description: "illegal playbackRate of 47 greater than loop length", | |
99 loopStartFrame: 4, | |
100 loopEndFrame: 6, | |
101 renderFrames: 16, | |
102 playbackRate: 47, | |
103 expected: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] }, | |
104 | |
105 // Try illegal loop-points - they should be ignored and we'll loop the whole buf
fer. | |
106 | |
107 { description: "illegal loop: loopStartFrame > loopEndFrame", | |
108 loopStartFrame: 7, | |
109 loopEndFrame: 3, | |
110 renderFrames: 16, | |
111 playbackRate: 1, | |
112 expected: [0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7] }, | |
113 | |
114 { description: "illegal loop: loopStartFrame == loopEndFrame", | |
115 loopStartFrame: 3, | |
116 loopEndFrame: 3, | |
117 renderFrames: 16, | |
118 playbackRate: 1, | |
119 expected: [0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7] }, | |
120 | |
121 { description: "illegal loop: loopStartFrame < 0", | |
122 loopStartFrame: -8, | |
123 loopEndFrame: 3, | |
124 renderFrames: 16, | |
125 playbackRate: 1, | |
126 expected: [0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7] }, | |
127 | |
128 { description: "illegal loop: loopEndFrame > bufferLength", | |
129 loopStartFrame: 0, | |
130 loopEndFrame: 30000, | |
131 renderFrames: 16, | |
132 playbackRate: 1, | |
133 expected: [0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7] }, | |
134 | |
135 // Start a loop with a duration longer than the buffer. The output should be th
e data from frame 1 | |
136 // to 6, and then looping from 3 to 5 until 20 frames have been played. | |
137 { description: "loop from 3 -> 6 with offset 1 for 20 frames", | |
138 loopStartFrame: 3, | |
139 loopEndFrame: 6, | |
140 playbackRate: 1, | |
141 offsetFrame: 1, | |
142 renderFrames: 30, | |
143 durationFrames: 20, | |
144 expected: [1, 2, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 3, 4, 5, 0, 0, 0
, 0, 0, 0, 0, 0, 0, 0] }, | |
145 | |
146 // Start a loop with a duration less than the length of the looping frames. The
output should be | |
147 // the data from frame 1 to 3, and then stopping because duration = 3 | |
148 { description: "loop from 3 -> 8 with offset 1 for 3 frames", | |
149 loopStartFrame: 3, | |
150 loopEndFrame: 8, | |
151 playbackRate: 1, | |
152 offsetFrame: 1, | |
153 durationFrames: 3, | |
154 renderFrames: 30, | |
155 expected: [1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
, 0, 0, 0, 0, 0, 0, 0] }, | |
156 | |
157 // Start a loop with a duration less than the length of the looping frames. The
output should be | |
158 // the data from frame 1 to 3, and then stopping because duration = 3 | |
159 { description: "loop from 3 -> 8 with offset 7 for 3 frames", | |
160 loopStartFrame: 3, | |
161 loopEndFrame: 8, | |
162 playbackRate: 1, | |
163 offsetFrame: 7, | |
164 durationFrames: 3, | |
165 renderFrames: 30, | |
166 expected: [7, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
, 0, 0, 0, 0, 0, 0, 0] } | |
167 | |
168 ]; | |
169 | |
170 var sampleRate = 44100; | |
171 var buffer; | |
172 var bufferFrameLength = 8; | |
173 var testSpacingFrames = 32; | |
174 var testSpacingSeconds = testSpacingFrames / sampleRate; | |
175 var totalRenderLengthFrames = tests.length * testSpacingFrames; | |
176 | |
177 function runLoopTest(context, testNumber, test) { | |
178 var source = context.createBufferSource(); | |
179 | |
180 source.buffer = buffer; | |
181 source.playbackRate.value = test.playbackRate; | |
182 source.loop = true; | |
183 source.loopStart = test.loopStartFrame / context.sampleRate; | |
184 source.loopEnd = test.loopEndFrame / context.sampleRate; | |
185 | |
186 var offset = test.offsetFrame ? test.offsetFrame / context.sampleRate : 0; | |
187 | |
188 source.connect(context.destination); | |
189 | |
190 // Render each test one after the other, spaced apart by testSpacingSeconds. | |
191 var startTime = testNumber * testSpacingSeconds; | |
192 | |
193 // If durationFrames is given, run the test for the specified duration. | |
194 if (test.durationFrames) { | |
195 if (!test.renderFrames) { | |
196 testFailed("renderFrames is required for test " + testNumber + ": "
+ test.description); | |
197 } else { | |
198 if (test.durationFrames > testSpacingFrames || test.durationFrames <
0) { | |
199 testFailed("Test " + testNumber | |
200 + ": durationFrames (" + test.durationFrames + ") outside th
e range [0, " | |
201 + testSpacingFrames + "]"); | |
202 } | |
203 source.start(startTime, offset, test.durationFrames / context.sample
Rate); | |
204 } | |
205 } else if (test.renderFrames) { | |
206 var duration = test.renderFrames / context.sampleRate; | |
207 if (test.renderFrames > testSpacingFrames || test.renderFrames < 0) { | |
208 testFailed("Test " + testNumber | |
209 + ": renderFrames (" + test.renderFrames + ") outside the range
[0, " | |
210 + testSpacingFrames + "]"); | |
211 } | |
212 source.start(startTime, offset); | |
213 source.stop(startTime + duration); | |
214 } else { | |
215 testFailed("Test " + testNumber + " must specify renderFrames and possib
ly durationFrames"); | |
216 } | |
217 } | |
218 | |
219 function runTest() { | |
220 window.jsTestIsAsync = true; | |
221 | |
222 // Create offline audio context. | |
223 var context = new OfflineAudioContext(1, totalRenderLengthFrames, sampleRate
); | |
224 buffer = createTestBuffer(context, bufferFrameLength); | |
225 | |
226 for (var i = 0; i < tests.length; ++i) | |
227 runLoopTest(context, i, tests[i]); | |
228 | |
229 context.oncomplete = checkAllTests; | |
230 context.startRendering(); | |
231 } | |
232 | |
233 runTest(); | |
234 successfullyParsed = true; | |
235 | |
236 </script> | |
237 | |
238 </body> | |
239 </html> | |
OLD | NEW |