| <!DOCTYPE html> |
| <html> |
| <head> |
| <title> |
| Test AudioBufferSourceNode looping without explicit duration |
| </title> |
| <script src="../../imported/w3c/web-platform-tests/resources/testharness.js"></script> |
| <script src="../../resources/testharnessreport.js"></script> |
| <script src="../resources/audit-util.js"></script> |
| <script src="../resources/audit.js"></script> |
| </head> |
| <body> |
| <script id="layout-test-code"> |
| // Reasonably low sample rate for the optimum test speed. |
| let sampleRate = 8192; |
| |
| let 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.define('loop-count', (task, should) => { |
| // How many loops of the source we want to render. Any whole number |
| // greater than 1 will work. |
| let loopCount = 4; |
| let sourceFrames = 8; |
| let renderFrames = sourceFrames * loopCount; |
| |
| let context = new OfflineAudioContext(1, renderFrames, sampleRate); |
| let source = context.createBufferSource(); |
| let 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) { |
| let badIndex = -1; |
| let success = true; |
| |
| let actual = renderedBuffer.getChannelData(0); |
| let linearRamp = linearRampBuffer.getChannelData(0); |
| |
| // Manually create a |loopCount| copies of linear ramps. |
| let expected = new Float32Array(linearRamp.length * loopCount); |
| for (let i = 0; i < loopCount; i++) |
| expected.set(linearRamp, linearRamp.length * i); |
| |
| // The actual output should match the created loop. |
| should(actual, 'The output of actual and expected loops') |
| .beEqualToArray(expected); |
| }) |
| .then(() => task.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.define('delayed-start', (task, should) => { |
| let renderDuration = 2; |
| let context = |
| new OfflineAudioContext(2, sampleRate * renderDuration, sampleRate); |
| let linearRampBuffer = createLinearRampBuffer(context, 128); |
| |
| let normal = context.createBufferSource(); |
| let delayed = context.createBufferSource(); |
| let 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( |
| buffer.getChannelData(0), |
| 'The content of the left and right channel') |
| .beEqualToArray(buffer.getChannelData(1)); |
| }) |
| .then(() => task.done()); |
| }); |
| |
| audit.run(); |
| </script> |
| </body> |
| </html> |