| <!DOCTYPE html> |
| <html> |
| |
| <head> |
| <title>Test AudioBufferSourceNode looping without explicit duration</title> |
| <script src="../resources/js-test.js"></script> |
| <script src="resources/compatibility.js"></script> |
| <script src="resources/audio-testing.js"></script> |
| </head> |
| |
| <body> |
| <script> |
| description("Test AudioBufferSourceNode looping without explicit duration"); |
| window.jsTestIsAsync = true; |
| |
| // Reasonably low sample rate for the optimum test speed. |
| var sampleRate = 4096; |
| |
| var audit = Audit.createTaskRunner(); |
| |
| // Task: create a short linear ramp and enable looping. The test will |
| // verify that the ramp was looped the appropriate number of times. |
| audit.defineTask('loop-count', function (done) { |
| // How many loops of the source we want to render. Any whole number |
| // greater than 1 will work. |
| var loopCount = 4; |
| var sourceFrames = 8; |
| var renderFrames = sourceFrames * loopCount; |
| |
| var context = new OfflineAudioContext(1, renderFrames, sampleRate); |
| var source = context.createBufferSource(); |
| var linearRampBuffer = createLinearRampBuffer(context, sourceFrames); |
| |
| source.buffer = linearRampBuffer; |
| source.connect(context.destination); |
| |
| // Enable looping and start the source with an offset, but without a |
| // duration. In this case, the source should loop "forever". |
| // See crbug.com/457009. |
| source.loop = true; |
| source.start(0, 0); |
| |
| context.startRendering().then(function (renderedBuffer) { |
| var badIndex = -1; |
| var success = true; |
| |
| var actual = renderedBuffer.getChannelData(0); |
| var linearRamp = linearRampBuffer.getChannelData(0); |
| |
| // Manually create a |loopCount| copies of linear ramps. |
| var expected = new Float32Array(linearRamp.length * loopCount); |
| for (var i = 0; i < loopCount; i++) |
| expected.set(linearRamp, linearRamp.length * i); |
| |
| // The actual output should match the created loop. |
| Should('The output of actual and expected loops', actual) |
| .beEqualToArray(expected); |
| }).then(done); |
| }); |
| |
| // Task: Test that looping an AudioBufferSource works correctly if the |
| // source is started and the buffer is assigned later, but before the source |
| // would start. |
| audit.defineTask('delayed-start', function (done) { |
| var renderDuration = 2; |
| var context = new OfflineAudioContext(2, sampleRate * renderDuration, sampleRate); |
| var linearRampBuffer = createLinearRampBuffer(context, 128); |
| |
| var normal = context.createBufferSource(); |
| var delayed = context.createBufferSource(); |
| var merger = context.createChannelMerger(2); |
| |
| // Connect the normally started source to the left channel, and the |
| // delayed to the right channel. |
| normal.connect(merger, 0, 0); |
| delayed.connect(merger, 0, 1); |
| merger.connect(context.destination); |
| |
| normal.buffer = linearRampBuffer; |
| normal.loop = true; |
| delayed.loop = true; |
| |
| normal.start(1, 0); |
| delayed.start(1, 0); |
| |
| // Assign the buffer to the delayed source node at 0.5 second. |
| context.suspend(0.5).then(function () { |
| delayed.buffer = linearRampBuffer; |
| context.resume(); |
| }); |
| |
| context.startRendering().then(function (buffer) { |
| // The left and right channel must match regardless of the timing |
| // of buffer assignment. |
| Should('The content of the left and right channel', |
| buffer.getChannelData(0)).beEqualToArray(buffer.getChannelData(1)); |
| }).then(done); |
| }); |
| |
| audit.defineTask('finish', function (done) { |
| finishJSTest(); |
| done(); |
| }); |
| |
| audit.runTasks( |
| 'loop-count', |
| 'delayed-start', |
| 'finish' |
| ); |
| |
| successfullyParsed = true; |
| </script> |
| </body> |
| |
| </html> |