| Index: third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html
|
| diff --git a/third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html b/third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html
|
| index 8e3a8232c2d17cebf0d98d359f6d6ed7b8a51353..2c23649aeda6210c720906726e38e9e59b8eac09 100644
|
| --- a/third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html
|
| +++ b/third_party/WebKit/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-points.html
|
| @@ -1,156 +1,160 @@
|
| <!DOCTYPE html>
|
| -
|
| <!--
|
| Tests that AudioBufferSourceNode supports loop-points with .loopStart and .loopEnd.
|
| -->
|
| -
|
| <html>
|
| -<head>
|
| -<script src="../../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>
|
| -let audit = Audit.createTaskRunner();
|
| -
|
| -let sampleRate = 44100.0;
|
| -let numberOfNotes = 60; // play over a 5 octave range
|
| -let noteDuration = 0.025;
|
| -let noteSpacing =
|
| - noteDuration + 0.005; // leave 5ms of silence between each "note"
|
| -let lengthInSeconds = numberOfNotes * noteSpacing;
|
| -
|
| -let context = 0;
|
| -let expectedAudio;
|
| -
|
| -function createTestBuffer(frequency, sampleRate) {
|
| - // Create a buffer containing two periods at this frequency.
|
| - // The 1st half is a pure sine wave period scaled by a linear ramp from 0 ->
|
| - // 1. The 2nd half of the buffer corresponds exactly to one pure sine wave
|
| - // period.
|
| - let onePeriodDuration = 1 / frequency;
|
| - let sampleFrameLength = 2 * onePeriodDuration * sampleRate;
|
| -
|
| - let audioBuffer = context.createBuffer(1, sampleFrameLength, sampleRate);
|
| -
|
| - let n = audioBuffer.length;
|
| - let channelData = audioBuffer.getChannelData(0);
|
| -
|
| - for (let i = 0; i < n; ++i) {
|
| - let sample = Math.sin(frequency * 2.0 * Math.PI * i / sampleRate);
|
| -
|
| - // Linear ramp from 0 -> 1 for the first period.
|
| - // Stay at 1 for the 2nd period.
|
| - let scale = i < n / 2 ? i / (n / 2) : 1;
|
| - sample *= scale;
|
| -
|
| - channelData[i] = sample;
|
| - }
|
| -
|
| - return audioBuffer;
|
| -}
|
| -
|
| -function playNote(buffer, time, duration, playbackRate) {
|
| - let source = context.createBufferSource();
|
| - source.buffer = buffer;
|
| - source.playbackRate.value = playbackRate;
|
| -
|
| - let gainNode = context.createGain();
|
| - source.connect(gainNode);
|
| - gainNode.connect(context.destination);
|
| -
|
| - // Loop the 2nd half of the buffer.
|
| - // We should be able to hear any problems as glitches if the looping
|
| - // incorrectly indexes to anywhere outside of the desired loop-points, since
|
| - // only the 2nd half is a perfect sine-wave cycle, while the 1st half of the
|
| - // buffer contains a linear ramp of a sine-wave cycle.
|
| - source.loop = true;
|
| - source.loopStart = 0.5 * buffer.duration;
|
| - source.loopEnd = buffer.duration;
|
| -
|
| - // Play for the given duration.
|
| - source.start(time);
|
| - source.stop(time + duration);
|
| -
|
| - // Apply a quick linear fade-out to avoid a click at the end of the note.
|
| - gainNode.gain.value = 1;
|
| - gainNode.gain.setValueAtTime(1, time + duration - 0.005);
|
| - gainNode.gain.linearRampToValueAtTime(0, time + duration);
|
| -}
|
| -
|
| -audit.define(
|
| - {label: 'initialize', description: 'Set up context and expected results'},
|
| - (task, should) => {
|
| - // Create offline audio context.
|
| - should(
|
| - () => {context = new OfflineAudioContext(
|
| - 2, sampleRate * lengthInSeconds, sampleRate)},
|
| - 'Creating context for testing')
|
| - .notThrow();
|
| -
|
| - should(
|
| - Audit.loadFileFromUrl('audiobuffersource-loop-points-expected.wav')
|
| - .then(arrayBuffer => {
|
| - context.decodeAudioData(arrayBuffer).then(audioBuffer => {
|
| - expectedAudio = audioBuffer;
|
| - });
|
| - }),
|
| - 'Fetching expected audio')
|
| - .beResolved()
|
| - .then(() => task.done());
|
| - });
|
| -
|
| -audit.define(
|
| - {
|
| - label: 'test',
|
| - description: 'Test loop points and compare with expected results'
|
| - },
|
| - (task, should) => {
|
| - // Create the test buffer.
|
| - // We'll loop this with the loop-points set for the 2nd half of this
|
| - // buffer.
|
| - let buffer = createTestBuffer(440.0, sampleRate);
|
| -
|
| - // Play all the notes as a chromatic scale.
|
| - for (let i = 0; i < numberOfNotes; ++i) {
|
| - let time = i * noteSpacing;
|
| - // start three octaves down
|
| - let semitone = i - numberOfNotes / 2;
|
| -
|
| - // Convert from semitone to rate.
|
| - let playbackRate = Math.pow(2, semitone / 12);
|
| -
|
| - playNote(buffer, time, noteDuration, playbackRate);
|
| + <head>
|
| + <title>
|
| + audiobuffersource-loop-points.html
|
| + </title>
|
| + <script src="../../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">
|
| + let audit = Audit.createTaskRunner();
|
| +
|
| + let sampleRate = 44100.0;
|
| + let numberOfNotes = 60; // play over a 5 octave range
|
| + let noteDuration = 0.025;
|
| + let noteSpacing =
|
| + noteDuration + 0.005; // leave 5ms of silence between each "note"
|
| + let lengthInSeconds = numberOfNotes * noteSpacing;
|
| +
|
| + let context = 0;
|
| + let expectedAudio;
|
| +
|
| + function createTestBuffer(frequency, sampleRate) {
|
| + // Create a buffer containing two periods at this frequency.
|
| + // The 1st half is a pure sine wave period scaled by a linear ramp from
|
| + // 0 -> 1. The 2nd half of the buffer corresponds exactly to one pure
|
| + // sine wave period.
|
| + let onePeriodDuration = 1 / frequency;
|
| + let sampleFrameLength = 2 * onePeriodDuration * sampleRate;
|
| +
|
| + let audioBuffer =
|
| + context.createBuffer(1, sampleFrameLength, sampleRate);
|
| +
|
| + let n = audioBuffer.length;
|
| + let channelData = audioBuffer.getChannelData(0);
|
| +
|
| + for (let i = 0; i < n; ++i) {
|
| + let sample = Math.sin(frequency * 2.0 * Math.PI * i / sampleRate);
|
| +
|
| + // Linear ramp from 0 -> 1 for the first period.
|
| + // Stay at 1 for the 2nd period.
|
| + let scale = i < n / 2 ? i / (n / 2) : 1;
|
| + sample *= scale;
|
| +
|
| + channelData[i] = sample;
|
| + }
|
| +
|
| + return audioBuffer;
|
| }
|
|
|
| - context.startRendering()
|
| - .then(renderedAudio => {
|
| - // Compute a threshold based on the maximum error, |maxUlp|, in ULP.
|
| - // This is experimentally determined. Assuming that the reference
|
| - // file is a 16-bit wav file, the max values in the wave file
|
| - // are +/- 32768.
|
| - let maxUlp = 0.9999;
|
| - let threshold = maxUlp / 32768;
|
| -
|
| - for (let k = 0; k < renderedAudio.numberOfChannels; ++k) {
|
| - should(
|
| - renderedAudio.getChannelData(k),
|
| - 'Rendered audio for channel ' + k)
|
| - .beCloseToArray(
|
| - expectedAudio.getChannelData(k),
|
| - {absoluteThreshold: threshold});
|
| - }
|
| - })
|
| - .then(() => task.done());
|
| - });
|
| -
|
| -audit.run();
|
| + function playNote(buffer, time, duration, playbackRate) {
|
| + let source = context.createBufferSource();
|
| + source.buffer = buffer;
|
| + source.playbackRate.value = playbackRate;
|
| +
|
| + let gainNode = context.createGain();
|
| + source.connect(gainNode);
|
| + gainNode.connect(context.destination);
|
| +
|
| + // Loop the 2nd half of the buffer.
|
| + // We should be able to hear any problems as glitches if the looping
|
| + // incorrectly indexes to anywhere outside of the desired loop-points,
|
| + // since only the 2nd half is a perfect sine-wave cycle, while the 1st
|
| + // half of the buffer contains a linear ramp of a sine-wave cycle.
|
| + source.loop = true;
|
| + source.loopStart = 0.5 * buffer.duration;
|
| + source.loopEnd = buffer.duration;
|
| +
|
| + // Play for the given duration.
|
| + source.start(time);
|
| + source.stop(time + duration);
|
| +
|
| + // Apply a quick linear fade-out to avoid a click at the end of the
|
| + // note.
|
| + gainNode.gain.value = 1;
|
| + gainNode.gain.setValueAtTime(1, time + duration - 0.005);
|
| + gainNode.gain.linearRampToValueAtTime(0, time + duration);
|
| + }
|
|
|
| -</script>
|
| + audit.define(
|
| + {
|
| + label: 'initialize',
|
| + description: 'Set up context and expected results'
|
| + },
|
| + (task, should) => {
|
| + // Create offline audio context.
|
| + should(
|
| + () => {context = new OfflineAudioContext(
|
| + 2, sampleRate * lengthInSeconds, sampleRate)},
|
| + 'Creating context for testing')
|
| + .notThrow();
|
| +
|
| + should(
|
| + Audit
|
| + .loadFileFromUrl(
|
| + 'audiobuffersource-loop-points-expected.wav')
|
| + .then(arrayBuffer => {
|
| + context.decodeAudioData(arrayBuffer).then(audioBuffer => {
|
| + expectedAudio = audioBuffer;
|
| + });
|
| + }),
|
| + 'Fetching expected audio')
|
| + .beResolved()
|
| + .then(() => task.done());
|
| + });
|
| +
|
| + audit.define(
|
| + {
|
| + label: 'test',
|
| + description: 'Test loop points and compare with expected results'
|
| + },
|
| + (task, should) => {
|
| + // Create the test buffer.
|
| + // We'll loop this with the loop-points set for the 2nd half of this
|
| + // buffer.
|
| + let buffer = createTestBuffer(440.0, sampleRate);
|
| +
|
| + // Play all the notes as a chromatic scale.
|
| + for (let i = 0; i < numberOfNotes; ++i) {
|
| + let time = i * noteSpacing;
|
| + // start three octaves down
|
| + let semitone = i - numberOfNotes / 2;
|
| +
|
| + // Convert from semitone to rate.
|
| + let playbackRate = Math.pow(2, semitone / 12);
|
| +
|
| + playNote(buffer, time, noteDuration, playbackRate);
|
| + }
|
|
|
| -</body>
|
| + context.startRendering()
|
| + .then(renderedAudio => {
|
| + // Compute a threshold based on the maximum error, |maxUlp|,
|
| + // in ULP. This is experimentally determined. Assuming that
|
| + // the reference file is a 16-bit wav file, the max values in
|
| + // the wave file are +/- 32768.
|
| + let maxUlp = 0.9999;
|
| + let threshold = maxUlp / 32768;
|
| +
|
| + for (let k = 0; k < renderedAudio.numberOfChannels; ++k) {
|
| + should(
|
| + renderedAudio.getChannelData(k),
|
| + 'Rendered audio for channel ' + k)
|
| + .beCloseToArray(
|
| + expectedAudio.getChannelData(k),
|
| + {absoluteThreshold: threshold});
|
| + }
|
| + })
|
| + .then(() => task.done());
|
| + });
|
| +
|
| + audit.run();
|
| + </script>
|
| + </body>
|
| </html>
|
|
|