WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-77225-20120131155526.patch (text/plain), 23.10 KB, created by
Raymond Toy
on 2012-01-31 15:55:27 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Raymond Toy
Created:
2012-01-31 15:55:27 PST
Size:
23.10 KB
patch
obsolete
>Subversion Revision: 106215 >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 15b8a80e4c02d41fd67dc2743a5a6c4ca86c6f20..2fca1e888b9b5ec7eb1a5b57e95b5b76b26e1117 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,26 @@ >+2012-01-30 Raymond Toy <rtoy@google.com> >+ >+ noteGrainOn needs more tests >+ https://bugs.webkit.org/show_bug.cgi?id=77225 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * webaudio/note-grain-on-play.html: Added. >+ * webaudio/note-grain-on-play-expected.txt: Added. >+ * webaudio/note-grain-on-timing.html: Refactored to use new >+ functions in note-grain-on-testing.js. >+ * webaudio/note-grain-on-timing-expected.txt: Updated. >+ * webaudio/resources/audio-testing.js: >+ (grainLengthInSampleFrames): Utility to compute length of a grain >+ in samples. >+ * webaudio/resources/note-grain-on-testing.js: Added. >+ (createSignalBuffer): >+ (findStartAndEndSamples): >+ (playNote): >+ (playAllNotes): >+ (verifyStartEndTimes): Common functions for note-grain-on-play and >+ note-grain-on-timing tests to use. >+ > 2012-01-29 Yuzo Fujishima <yuzo@google.com> > > [Chromium] Unreviewed test expectation change. >diff --git a/LayoutTests/webaudio/note-grain-on-play-expected.txt b/LayoutTests/webaudio/note-grain-on-play-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..49f5930c8a965e020f2e8bb787743c44699ba8a8 >--- /dev/null >+++ b/LayoutTests/webaudio/note-grain-on-play-expected.txt >@@ -0,0 +1,13 @@ >+Test noteGrainOn offset rendering. >+ >+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". >+ >+PASS Found all 100 pulses. >+PASS All 100 pulses started at the correct time. >+PASS All 100 pulses ended at the correct time. >+PASS All 100 grains contained the correct data. >+PASS noteGrainOn data tests passed. >+PASS successfullyParsed is true >+ >+TEST COMPLETE >+ >diff --git a/LayoutTests/webaudio/note-grain-on-play.html b/LayoutTests/webaudio/note-grain-on-play.html >new file mode 100644 >index 0000000000000000000000000000000000000000..220fba8bc0d6eda6ddc9448ca977dc89a42283f9 >--- /dev/null >+++ b/LayoutTests/webaudio/note-grain-on-play.html >@@ -0,0 +1,135 @@ >+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> >+<html> >+ <head> >+ <script src="resources/audio-testing.js"></script> >+ <script src="resources/note-grain-on-testing.js"></script> >+ <script src="../fast/js/resources/js-test-pre.js"></script> >+ </head> >+ >+ <body> >+ <div id="description"></div> >+ <div id="console"></div> >+ >+ <script> >+ description("Test noteGrainOn offset rendering."); >+ >+ // To test noteGrainOn, a single ramp signal is created. >+ // Various sections of the ramp are rendered by noteGrainOn() >+ // out at different times, and we verify that the actual output >+ // matches our expectations. >+ >+ >+ var linearRampBuffer; >+ >+ // Array of the grain offset used for each ramp played. >+ var grainOffsetTime = []; >+ >+ // Verify the received signal is a ramp from the correct section >+ // of our ramp signal. >+ function verifyGrain(renderedData, startFrame, endFrame, rampNumber) { >+ var rampOffsetFrame = timeToSampleFrame(grainOffsetTime[rampNumber], sampleRate); >+ var rampFrameLength = endFrame - startFrame; >+ var ramp = linearRampBuffer.getChannelData(0); >+ var isCorrect = true; >+ >+ var expected; >+ var actual; >+ var frame; >+ >+ for (var k = 0; k < rampFrameLength; ++k) { >+ if (renderedData[startFrame + k] != ramp[rampOffsetFrame + k]) { >+ expected = ramp[rampOffsetFrame + k]; >+ actual = renderedData[startFrame + k]; >+ frame = startFrame + k; >+ isCorrect = false; >+ break; >+ } >+ } >+ return { verified: isCorrect, >+ expected : expected , >+ actual : actual, >+ frame : frame }; >+ } >+ >+ function checkResult(event) { >+ var buffer = event.renderedBuffer; >+ renderedData = buffer.getChannelData(0); >+ var nSamples = renderedData.length; >+ >+ var success = true; >+ >+ // Number of grains that we found that have incorrect data. >+ var invalidGrainDataCount = 0; >+ >+ var startEndFrames = findStartAndEndSamples(renderedData); >+ >+ // Verify the start and stop times. Not strictly needed for >+ // this test, but it's useful to know that if the ramp data >+ // appears to be incorrect. >+ success = success && verifyStartEndFrames(startEndFrames); >+ >+ // Loop through each of the rendered grains and check that >+ // each grain contains our expected ramp. >+ for (var k = 0; k < startEndFrames.start.length; ++k) { >+ // Verify that the rendered data matches the expected >+ // section of our ramp signal. >+ var result = verifyGrain(renderedData, startEndFrames.start[k], startEndFrames.end[k], k); >+ >+ if (!result.verified) { >+ testFailed("Grain " + k + " incorrect. Expected " + result.expected + " but received " + result.actual + " at sample frame " + result.frame); >+ ++invalidGrainDataCount; >+ success = false; >+ } >+ } >+ >+ if (!invalidGrainDataCount) { >+ testPassed("All " + numberOfTests + " grains contained the correct data."); >+ } else { >+ testFailed(invalidGrainDataCount + " grains out of " + numberOfTests + " did not contain the expected data."); >+ success = false; >+ } >+ >+ if (success) { >+ testPassed("noteGrainOn data tests passed."); >+ } else { >+ testFailed("noteGrainOn data tests failed."); >+ } >+ >+ finishJSTest(); >+ } >+ >+ function runTest() { >+ if (window.layoutTestController) { >+ layoutTestController.dumpAsText(); >+ layoutTestController.waitUntilDone(); >+ } >+ >+ window.jsTestIsAsync = true; >+ >+ // Create offline audio context. >+ context = new webkitAudioContext(2, sampleRate * renderTime, sampleRate); >+ >+ // Create a linear ramp for testing noteGrainOn. >+ linearRampBuffer = createSignalBuffer(context, >+ function(k) { >+ // Want the ramp to start >+ // with 1, not 0. >+ return k + 1; >+ }); >+ >+ var noteInfo = playAllGrains(context, linearRampBuffer, numberOfTests); >+ >+ grainOffsetTime = noteInfo.grainOffsetTimes; >+ >+ context.oncomplete = checkResult; >+ context.startRendering(); >+ } >+ >+ runTest(); >+ successfullyParsed = true; >+ >+ </script> >+ >+ <script src="../fast/js/resources/js-test-post.js"></script> >+ </body> >+</html> >diff --git a/LayoutTests/webaudio/note-grain-on-timing-expected.txt b/LayoutTests/webaudio/note-grain-on-timing-expected.txt >index c524f8296bd732826bca79c6dc2ce04455d7137e..c8e990b3675717f635f22ae652ad5579f84df217 100644 >--- a/LayoutTests/webaudio/note-grain-on-timing-expected.txt >+++ b/LayoutTests/webaudio/note-grain-on-timing-expected.txt >@@ -3,8 +3,8 @@ Test timing of noteGrainOn. > On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". > > PASS Found all 100 pulses. >-PASS All 100 square pulses started at the correct time. >-PASS All 100 square pulses ended at the correct time. >+PASS All 100 pulses started at the correct time. >+PASS All 100 pulses ended at the correct time. > PASS noteGrainOn timing tests passed. > PASS successfullyParsed is true > >diff --git a/LayoutTests/webaudio/note-grain-on-timing.html b/LayoutTests/webaudio/note-grain-on-timing.html >index f33af09b5b0d3a51985b617281c5ff3b6cce556e..66d84bca074c1d4b4593f62bac0f0b84f1309f17 100644 >--- a/LayoutTests/webaudio/note-grain-on-timing.html >+++ b/LayoutTests/webaudio/note-grain-on-timing.html >@@ -2,6 +2,7 @@ > <html> > <head> > <script src="resources/audio-testing.js"></script> >+ <script src="resources/note-grain-on-testing.js"></script> > <script src="../fast/js/resources/js-test-pre.js"></script> > </head> > >@@ -12,148 +13,19 @@ > <script> > description("Test timing of noteGrainOn."); > >- var sampleRate = 44100.0; >- >- // HRTF extra frames. This is a magic constant currently in >- // AudioBufferSourceNode::process that always extends the >- // duration by this number of samples. See bug 77224 >- // (https://bugs.webkit.org/show_bug.cgi?id=77224). >- var extraFramesHRTF = 512; >- >- // How many square pulses to play. >- var numberOfTests = 100; >- >- // Duration of the square pulse to be played >- var duration = 0.01; >- >- // Time step between the start of each square pulse. We need to >- // add a little bit of silence so we can detect pulse boundaries >- // and also account for the extra frames for HRTF. >- var timeStep = duration + .005 + extraFramesHRTF / sampleRate; >- >- // Time step between the grain start for each square pulse. >- var grainOffsetStep = 0.005; >- >- // How long to render to cover all of the pulses. >- var renderTime = (numberOfTests + 1) * timeStep; >- >- var context; > var squarePulseBuffer; >- var renderedData; >- >- function createSquarePulse(context) { >- // Create a square pulse that is long enough so that all the >- // possible grain offsets still results in a square pulse of >- // of the requested duration. (The extra 1 is for any >- // round-off.) >- >- var pulseLength = Math.floor(1 + extraFramesHRTF + sampleRate * (numberOfTests * grainOffsetStep + duration)); > >- squarePulseBuffer = context.createBuffer(2, pulseLength, sampleRate); >- var data = squarePulseBuffer.getChannelData(0); >- for (var k = 0; k < pulseLength; ++k) { >- data[k] = 1; >- } >- } >- >- function trueGrainLength(grainOffset, duration) { >- var startFrame = timeToSampleFrame(grainOffset, sampleRate); >- var endFrame = timeToSampleFrame(grainOffset + duration, sampleRate); >- >- return endFrame - startFrame; >- } >- > function checkResult(event) { > var buffer = event.renderedBuffer; > renderedData = buffer.getChannelData(0); > var nSamples = renderedData.length; > > var success = true; >- var errorCountStart = 0; >- var errorCountEnd = 0; > >- var startTime = []; >- var endTime = []; >- var lookForStart = true; >- >- // Look through the rendered data to find the start and stop >- // times of each pulse. >- for (var k = 0; k < nSamples; ++k) { >- if (lookForStart) { >- // Find a non-zero point and record it. We're not >- // concerned with the value in this test, only that >- // the pulse started here. Other tests should cover >- // this case. >- if (renderedData[k] > 0) { >- startTime.push(k); >- lookForStart = false; >- } >- } else { >- // Find a zero and record it. >- if (renderedData[k] == 0) { >- endTime.push(k); >- lookForStart = true; >- } >- } >- } >+ var startEndFrames = findStartAndEndSamples(renderedData); > >- if (startTime.length != endTime.length) { >- testFailed("Could not find the beginning or end of a square pulse."); >- success = false; >- } >- >- if (startTime.length == numberOfTests && endTime.length == numberOfTests) { >- testPassed("Found all " + numberOfTests + " pulses."); >- } else { >- testFailed("Did not find all " + numberOfTests + " pulses."); >- } >- >- // Examine the start and stop times to see if they match our >- // expectations. >- for (var k = 0; k < startTime.length; ++k) { >- var expectedStart = timeToSampleFrame(k * timeStep, sampleRate); >- // The end point is the duration, plus the extra frames >- // for HRTF. >- var expectedEnd = extraFramesHRTF + expectedStart + trueGrainLength(k * grainOffsetStep, duration); >- >- if (startTime[k] != expectedStart) { >- testFailed("Pulse " + k + " started at " + startTime[k] + " but expected at " + expectedStart); >- ++errorCountStart; >- success = false; >- } >- >- if (endTime[k] != expectedEnd) { >- testFailed("Pulse " + k + " ended at " + endTime[k] + " but expected at " + expectedEnd); >- ++errorCountEnd; >- success = false; >- } >- } >- >- if (!errorCountStart) { >- if (startTime.length == numberOfTests) { >- testPassed("All " + numberOfTests + " square pulses started at the correct time."); >- } else { >- testFailed("All pulses started at the correct time, but only " + startTime.length + " pulses found."); >- success = false; >- } >- } else { >- testFailed(errorCountStart + " out of " + numberOfTests + " square pulses started at the wrong time."); >- success = false; >- } >+ success = success && verifyStartEndFrames(startEndFrames); > >- if (!errorCountEnd) { >- if (endTime.length == numberOfTests) { >- testPassed("All " + numberOfTests + " square pulses ended at the correct time."); >- } else { >- testFailed("All pulses ended at the correct time, but only " + endTime.length + " pulses found."); >- success = false; >- } >- } else { >- testFailed(errorCountEnd + " out of " + numberOfTests + " square pulses ended at the wrong time."); >- success = false; >- } >- >- > if (success) { > testPassed("noteGrainOn timing tests passed."); > } else { >@@ -163,16 +35,6 @@ > finishJSTest(); > } > >- function playNote(time, grainOffset, duration) { >- var bufferSource = context.createBufferSource(); >- bufferSource.buffer = squarePulseBuffer; >- bufferSource.connect(context.destination); >- // We're only testing that the source starts and ends at a >- // particular time. See bug 77225 >- // (https://bugs.webkit.org/show_bug.cgi?id=77225). >- bufferSource.noteGrainOn(time, grainOffset, duration); >- } >- > function runTest() { > if (window.layoutTestController) { > layoutTestController.dumpAsText(); >@@ -183,12 +45,10 @@ > > // Create offline audio context. > context = new webkitAudioContext(2, sampleRate * renderTime, sampleRate); >- createSquarePulse(context); > >- for (var i = 0; i < numberOfTests; ++i) { >- var timeOffset = timeStep * i; >- playNote(timeOffset, i * grainOffsetStep, duration); >- } >+ squarePulseBuffer = createSignalBuffer(context, function (k) { return 1 }); >+ >+ playAllGrains(context, squarePulseBuffer, numberOfTests); > > context.oncomplete = checkResult; > context.startRendering(); >diff --git a/LayoutTests/webaudio/resources/audio-testing.js b/LayoutTests/webaudio/resources/audio-testing.js >index c428ae014e0a0a27e1668cfb2db09e3ea7879753..7c7666c1ad1dc3782ab0f7e2a0abe95699dbb26b 100644 >--- a/LayoutTests/webaudio/resources/audio-testing.js >+++ b/LayoutTests/webaudio/resources/audio-testing.js >@@ -125,3 +125,11 @@ function timeToSampleFrame(time, sampleRate) { > return Math.floor(0.5 + time * sampleRate); > } > >+// Compute the number of sample frames consumed by noteGrainOn with >+// the specified |grainOffset|, |duration|, and |sampleRate|. >+function grainLengthInSampleFrames(grainOffset, duration, sampleRate) { >+ var startFrame = timeToSampleFrame(grainOffset, sampleRate); >+ var endFrame = timeToSampleFrame(grainOffset + duration, sampleRate); >+ >+ return endFrame - startFrame; >+} >diff --git a/LayoutTests/webaudio/resources/note-grain-on-testing.js b/LayoutTests/webaudio/resources/note-grain-on-testing.js >new file mode 100644 >index 0000000000000000000000000000000000000000..091d52aea384d0529d417b4af8926a1626b3769d >--- /dev/null >+++ b/LayoutTests/webaudio/resources/note-grain-on-testing.js >@@ -0,0 +1,179 @@ >+var sampleRate = 44100.0; >+ >+// HRTF extra frames. This is a magic constant currently in >+// AudioBufferSourceNode::process that always extends the >+// duration by this number of samples. See bug 77224 >+// (https://bugs.webkit.org/show_bug.cgi?id=77224). >+var extraFramesHRTF = 512; >+ >+// How many pulses to play. >+var numberOfTests = 100; >+ >+// Duration of each pulse to be played >+var duration = 0.01; >+ >+// Time step between the start of each pulse. We need to add a little >+// bit of silence so we can detect pulse boundaries and also account >+// for the extra frames for HRTF. >+var timeStep = duration + .005 + extraFramesHRTF / sampleRate; >+ >+// Time step between the grain start for each pulse. >+var grainOffsetStep = 0.001; >+ >+// How long to render to cover all of the pulses. >+var renderTime = (numberOfTests + 1) * timeStep; >+ >+var context; >+var renderedData; >+ >+// Create a buffer containing the data that we want. The function f >+// returns the desired value at sample frame k. >+function createSignalBuffer(context, f) { >+ >+ // Make sure the buffer has enough data for all of the possible >+ // grain offsets and durations. Need to include the extra frames >+ // for HRTF. The additional 1 is for any round-off errors. >+ var signalLength = Math.floor(1 + extraFramesHRTF + sampleRate * (numberOfTests * grainOffsetStep + duration)); >+ >+ var buffer = context.createBuffer(2, signalLength, sampleRate); >+ var data = buffer.getChannelData(0); >+ >+ for (var k = 0; k < signalLength; ++k) { >+ data[k] = f(k); >+ } >+ >+ return buffer; >+} >+ >+// From the data array, find the start and end sample frame for each >+// pulse. This depends on the data having 0's between pulses, and >+// that the pulse is always strictly non-zero. >+function findStartAndEndSamples(data) { >+ var nSamples = data.length; >+ >+ var startTime = []; >+ var endTime = []; >+ var lookForStart = true; >+ >+ // Look through the rendered data to find the start and stop >+ // times of each pulse. >+ for (var k = 0; k < nSamples; ++k) { >+ if (lookForStart) { >+ // Find a non-zero point and record the start. We're not >+ // concerned with the value in this test, only that the >+ // pulse started here. >+ if (renderedData[k]) { >+ startTime.push(k); >+ lookForStart = false; >+ } >+ } else { >+ // Find a zero and record the end of the pulse. >+ if (!renderedData[k]) { >+ endTime.push(k); >+ lookForStart = true; >+ } >+ } >+ } >+ >+ return {start : startTime, end : endTime}; >+} >+ >+function playGrain(context, source, time, offset, duration) { >+ var bufferSource = context.createBufferSource(); >+ >+ bufferSource.buffer = source; >+ bufferSource.connect(context.destination); >+ bufferSource.noteGrainOn(time, offset, duration); >+} >+ >+// Play out all grains. Returns a object containing two arrays, one >+// for the start time and one for the grain offset time. >+function playAllGrains(context, source, numberOfNotes) { >+ var startTimes = new Array(numberOfNotes); >+ var offsets = new Array(numberOfNotes); >+ >+ for (var k = 0; k < numberOfNotes; ++k) { >+ var timeOffset = k * timeStep; >+ var grainOffset = k * grainOffsetStep; >+ >+ playGrain(context, source, timeOffset, grainOffset, duration); >+ startTimes[k] = timeOffset; >+ offsets[k] = grainOffset; >+ } >+ >+ return { startTimes : startTimes, grainOffsetTimes : offsets }; >+} >+ >+// Verify that the start and end frames for each pulse match our >+// expected start and end frames. >+function verifyStartEndFrames(startEndFrames) { >+ var startFrames = startEndFrames.start; >+ var endFrames = startEndFrames.end; >+ >+ var success = true; >+ >+ // Count of how many pulses started at the incorrect time. >+ var errorCountStart = 0; >+ >+ // Count of how many pulses ended at the incorrect time. >+ var errorCountEnd = 0; >+ >+ if (startFrames.length != endFrames.length) { >+ testFailed("Could not find the beginning or end of a pulse."); >+ success = false; >+ } >+ >+ if (startFrames.length == numberOfTests && endFrames.length == numberOfTests) { >+ testPassed("Found all " + numberOfTests + " pulses."); >+ } else { >+ testFailed("Did not find all " + numberOfTests + " pulses."); >+ } >+ >+ // Examine the start and stop times to see if they match our >+ // expectations. >+ for (var k = 0; k < startFrames.length; ++k) { >+ var expectedStart = timeToSampleFrame(k * timeStep, sampleRate); >+ // The end point is the duration, plus the extra frames >+ // for HRTF. >+ var expectedEnd = extraFramesHRTF + expectedStart + grainLengthInSampleFrames(k * grainOffsetStep, duration, sampleRate); >+ >+ if (startFrames[k] != expectedStart) { >+ testFailed("Pulse " + k + " started at " + startFrames[k] + " but expected at " + expectedStart); >+ ++errorCountStart; >+ success = false; >+ } >+ >+ if (endFrames[k] != expectedEnd) { >+ testFailed("Pulse " + k + " ended at " + endFrames[k] + " but expected at " + expectedEnd); >+ ++errorCountEnd; >+ success = false; >+ } >+ } >+ >+ // Check that all the pulses started or ended at the correct time. >+ if (!errorCountStart) { >+ if (startFrames.length == numberOfTests) { >+ testPassed("All " + numberOfTests + " pulses started at the correct time."); >+ } else { >+ testFailed("All pulses started at the correct time, but only " + startFrames.length + " pulses found."); >+ success = false; >+ } >+ } else { >+ testFailed(errorCountStart + " out of " + numberOfTests + " pulses started at the wrong time."); >+ success = false; >+ } >+ >+ if (!errorCountEnd) { >+ if (endFrames.length == numberOfTests) { >+ testPassed("All " + numberOfTests + " pulses ended at the correct time."); >+ } else { >+ testFailed("All pulses ended at the correct time, but only " + endFrames.length + " pulses found."); >+ success = false; >+ } >+ } else { >+ testFailed(errorCountEnd + " out of " + numberOfTests + " pulses ended at the wrong time."); >+ success = false; >+ } >+ >+ return success; >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 77225
:
124590
|
124597
|
124838
|
124963