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