Log Message
Implement optional arguments in AudioBufferSourceNode start() method https://bugs.webkit.org/show_bug.cgi?id=100894
Reviewed by Kenneth Russell. Source/WebCore: The start() method should be able to take 1, 2, or 3 arguments, optionally supporting offset and duration. Currently, only 1 and 3 arguments are supported. Test: webaudio/audiobuffersource-start.html * Modules/webaudio/AudioBufferSourceNode.cpp: (WebCore::AudioBufferSourceNode::renderFromBuffer): (WebCore::AudioBufferSourceNode::startGrain): (WebCore): * Modules/webaudio/AudioBufferSourceNode.h: (AudioBufferSourceNode): * Modules/webaudio/AudioBufferSourceNode.idl: LayoutTests: * webaudio/audiobuffersource-loop-comprehensive.html: * webaudio/audiobuffersource-start-expected.txt: Added. * webaudio/audiobuffersource-start.html: Added. * webaudio/resources/audiobuffersource-testing.js: Added. (createTestBuffer): (checkSingleTest): (checkAllTests):
Modified Paths
- trunk/LayoutTests/ChangeLog
- trunk/LayoutTests/webaudio/audiobuffersource-loop-comprehensive.html
- trunk/Source/WebCore/ChangeLog
- trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp
- trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.h
- trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.idl
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (133100 => 133101)
--- trunk/LayoutTests/ChangeLog 2012-11-01 00:31:14 UTC (rev 133100)
+++ trunk/LayoutTests/ChangeLog 2012-11-01 00:39:39 UTC (rev 133101)
@@ -1,3 +1,18 @@
+2012-10-31 Chris Rogers <[email protected]>
+
+ Implement optional arguments in AudioBufferSourceNode start() method
+ https://bugs.webkit.org/show_bug.cgi?id=100894
+
+ Reviewed by Kenneth Russell.
+
+ * webaudio/audiobuffersource-loop-comprehensive.html:
+ * webaudio/audiobuffersource-start-expected.txt: Added.
+ * webaudio/audiobuffersource-start.html: Added.
+ * webaudio/resources/audiobuffersource-testing.js: Added.
+ (createTestBuffer):
+ (checkSingleTest):
+ (checkAllTests):
+
2012-10-31 Stephen White <[email protected]>
[Chromium] Unreviewed gardening.
Modified: trunk/LayoutTests/webaudio/audiobuffersource-loop-comprehensive.html (133100 => 133101)
--- trunk/LayoutTests/webaudio/audiobuffersource-loop-comprehensive.html 2012-11-01 00:31:14 UTC (rev 133100)
+++ trunk/LayoutTests/webaudio/audiobuffersource-loop-comprehensive.html 2012-11-01 00:39:39 UTC (rev 133101)
@@ -4,6 +4,7 @@
<head>
<link rel="stylesheet" href=""
<script src=""
+<script src=""
<script src=""
</head>
@@ -69,17 +70,6 @@
var testSpacingSeconds = testSpacingFrames / sampleRate;
var totalRenderLengthFrames = tests.length * testSpacingFrames;
-function createTestBuffer(context, sampleFrameLength) {
- var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
- var channelData = audioBuffer.getChannelData(0);
-
- // Create a simple linear ramp starting at zero, with each value in the buffer equal to its index position.
- for (var i = 0; i < sampleFrameLength; ++i)
- channelData[i] = i;
-
- return audioBuffer;
-}
-
function runLoopTest(context, testNumber, test) {
var source = context.createBufferSource();
@@ -98,45 +88,6 @@
source.stop(startTime + duration);
}
-function checkSingleTest(renderedBuffer, i) {
- var renderedData = renderedBuffer.getChannelData(0);
- var offsetFrame = i * testSpacingFrames;
-
- var test = tests[i];
- var description = test.description;
- var expected = test.expected;
-
- var success = true;
-
- for (var j = 0; j < test.renderFrames; ++j) {
- if (expected[j] != renderedData[offsetFrame + j]) {
- // Copy from Float32Array to regular _javascript_ array for error message.
- var renderedArray = new Array();
- for (var j = 0; j < test.renderFrames; ++j)
- renderedArray[j] = renderedData[offsetFrame + j];
-
- var s = description + ": expected: " + expected + " actual: " + renderedArray;
- testFailed(s);
- success = false;
- break;
- }
- }
-
- if (success)
- testPassed(description);
-
- return success;
-}
-
-function checkLoopResults(event) {
- var renderedBuffer = event.renderedBuffer;
- for (var i = 0; i < tests.length; ++i)
- checkSingleTest(renderedBuffer, i);
-
- if (window.testRunner)
- testRunner.notifyDone()
-}
-
function runTest() {
if (window.testRunner) {
testRunner.dumpAsText();
@@ -152,7 +103,7 @@
for (var i = 0; i < tests.length; ++i)
runLoopTest(context, i, tests[i]);
- context._oncomplete_ = checkLoopResults;
+ context._oncomplete_ = checkAllTests;
context.startRendering();
}
Added: trunk/LayoutTests/webaudio/audiobuffersource-start-expected.txt (0 => 133101)
--- trunk/LayoutTests/webaudio/audiobuffersource-start-expected.txt (rev 0)
+++ trunk/LayoutTests/webaudio/audiobuffersource-start-expected.txt 2012-11-01 00:39:39 UTC (rev 133101)
@@ -0,0 +1,10 @@
+Tests AudioBufferSourceNode start() with a variety of offsets and durations.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS start(when): implicitly play whole buffer from beginning to end
+PASS start(when, 0): play whole buffer from beginning to end explicitly giving offset of 0
+PASS start(when, 0, 8_frames): play whole buffer from beginning to end explicitly giving offset of 0 and duration of 8 frames
+PASS start(when, 4_frames): play with explicit non-zero offset
+PASS start(when, 4_frames, 4_frames): play with explicit non-zero offset and duration
+
Added: trunk/LayoutTests/webaudio/audiobuffersource-start.html (0 => 133101)
--- trunk/LayoutTests/webaudio/audiobuffersource-start.html (rev 0)
+++ trunk/LayoutTests/webaudio/audiobuffersource-start.html 2012-11-01 00:39:39 UTC (rev 133101)
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+<link rel="stylesheet" href=""
+<script src=""
+<script src=""
+<script src=""
+</head>
+
+<body>
+
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+description("Tests AudioBufferSourceNode start() with a variety of offsets and durations.");
+
+// The following test cases assume an AudioBuffer of length 8 whose PCM data is a linear ramp, 0, 1, 2, 3,...
+
+var tests = [
+
+{ description: "start(when): implicitly play whole buffer from beginning to end",
+ offsetFrame: "none", durationFrames: "none", renderFrames: 16, playbackRate: 1, expected: [0,1,2,3,4,5,6,7,0,0,0,0,0,0,0,0] },
+
+{ description: "start(when, 0): play whole buffer from beginning to end explicitly giving offset of 0",
+ offsetFrame: 0, durationFrames: "none", renderFrames: 16, playbackRate: 1, expected: [0,1,2,3,4,5,6,7,0,0,0,0,0,0,0,0] },
+
+{ description: "start(when, 0, 8_frames): play whole buffer from beginning to end explicitly giving offset of 0 and duration of 8 frames",
+ offsetFrame: 0, durationFrames: 8, renderFrames: 16, playbackRate: 1, expected: [0,1,2,3,4,5,6,7,0,0,0,0,0,0,0,0] },
+
+{ description: "start(when, 4_frames): play with explicit non-zero offset",
+ offsetFrame: 4, durationFrames: "none", renderFrames: 16, playbackRate: 1, expected: [4,5,6,7,0,0,0,0,0,0,0,0,0,0,0,0] },
+
+{ description: "start(when, 4_frames, 4_frames): play with explicit non-zero offset and duration",
+ offsetFrame: 4, durationFrames: 4, renderFrames: 16, playbackRate: 1, expected: [4,5,6,7,0,0,0,0,0,0,0,0,0,0,0,0] },
+
+// Enable test when AudioBufferSourceNode hack is fixed: https://bugs.webkit.org/show_bug.cgi?id=77224
+// { description: "start(when, 3_frames, 3_frames): play a middle section with explicit offset and duration",
+// offsetFrame: 3, durationFrames: 3, renderFrames: 16, playbackRate: 1, expected: [4,5,6,7,0,0,0,0,0,0,0,0,0,0,0,0] },
+
+];
+
+var sampleRate = 44100;
+var buffer;
+var bufferFrameLength = 8;
+var testSpacingFrames = 32;
+var testSpacingSeconds = testSpacingFrames / sampleRate;
+var totalRenderLengthFrames = tests.length * testSpacingFrames;
+
+function runLoopTest(context, testNumber, test) {
+ var source = context.createBufferSource();
+
+ source.buffer = buffer;
+ source.playbackRate.value = test.playbackRate;
+
+ source.connect(context.destination);
+
+ // Render each test one after the other, spaced apart by testSpacingSeconds.
+ var startTime = testNumber * testSpacingSeconds;
+
+ if (test.offsetFrame == "none" && test.durationFrames == "none") {
+ source.start(startTime);
+ } else if (test.durationFrames == "none") {
+ var offset = test.offsetFrame / context.sampleRate;
+ source.start(startTime, offset);
+ } else {
+ var offset = test.offsetFrame / context.sampleRate;
+ var duration = test.durationFrames / context.sampleRate;
+ source.start(startTime, offset, duration);
+ }
+}
+
+function runTest() {
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ }
+
+ window.jsTestIsAsync = true;
+
+ // Create offline audio context.
+ var context = new webkitAudioContext(1, totalRenderLengthFrames, sampleRate);
+ buffer = createTestBuffer(context, bufferFrameLength);
+
+ for (var i = 0; i < tests.length; ++i)
+ runLoopTest(context, i, tests[i]);
+
+ context._oncomplete_ = checkAllTests;
+ context.startRendering();
+}
+
+runTest();
+successfullyParsed = true;
+
+</script>
+
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/webaudio/resources/audiobuffersource-testing.js (0 => 133101)
--- trunk/LayoutTests/webaudio/resources/audiobuffersource-testing.js (rev 0)
+++ trunk/LayoutTests/webaudio/resources/audiobuffersource-testing.js 2012-11-01 00:39:39 UTC (rev 133101)
@@ -0,0 +1,49 @@
+function createTestBuffer(context, sampleFrameLength) {
+ var audioBuffer = context.createBuffer(1, sampleFrameLength, context.sampleRate);
+ var channelData = audioBuffer.getChannelData(0);
+
+ // Create a simple linear ramp starting at zero, with each value in the buffer equal to its index position.
+ for (var i = 0; i < sampleFrameLength; ++i)
+ channelData[i] = i;
+
+ return audioBuffer;
+}
+
+function checkSingleTest(renderedBuffer, i) {
+ var renderedData = renderedBuffer.getChannelData(0);
+ var offsetFrame = i * testSpacingFrames;
+
+ var test = tests[i];
+ var description = test.description;
+ var expected = test.expected;
+
+ var success = true;
+
+ for (var j = 0; j < test.renderFrames; ++j) {
+ if (expected[j] != renderedData[offsetFrame + j]) {
+ // Copy from Float32Array to regular _javascript_ array for error message.
+ var renderedArray = new Array();
+ for (var j = 0; j < test.renderFrames; ++j)
+ renderedArray[j] = renderedData[offsetFrame + j];
+
+ var s = description + ": expected: " + expected + " actual: " + renderedArray;
+ testFailed(s);
+ success = false;
+ break;
+ }
+ }
+
+ if (success)
+ testPassed(description);
+
+ return success;
+}
+
+function checkAllTests(event) {
+ var renderedBuffer = event.renderedBuffer;
+ for (var i = 0; i < tests.length; ++i)
+ checkSingleTest(renderedBuffer, i);
+
+ if (window.testRunner)
+ testRunner.notifyDone()
+}
Modified: trunk/Source/WebCore/ChangeLog (133100 => 133101)
--- trunk/Source/WebCore/ChangeLog 2012-11-01 00:31:14 UTC (rev 133100)
+++ trunk/Source/WebCore/ChangeLog 2012-11-01 00:39:39 UTC (rev 133101)
@@ -1,3 +1,23 @@
+2012-10-31 Chris Rogers <[email protected]>
+
+ Implement optional arguments in AudioBufferSourceNode start() method
+ https://bugs.webkit.org/show_bug.cgi?id=100894
+
+ Reviewed by Kenneth Russell.
+
+ The start() method should be able to take 1, 2, or 3 arguments, optionally supporting
+ offset and duration. Currently, only 1 and 3 arguments are supported.
+
+ Test: webaudio/audiobuffersource-start.html
+
+ * Modules/webaudio/AudioBufferSourceNode.cpp:
+ (WebCore::AudioBufferSourceNode::renderFromBuffer):
+ (WebCore::AudioBufferSourceNode::startGrain):
+ (WebCore):
+ * Modules/webaudio/AudioBufferSourceNode.h:
+ (AudioBufferSourceNode):
+ * Modules/webaudio/AudioBufferSourceNode.idl:
+
2012-10-31 Mike West <[email protected]>
Implement the canonical "Content-Security-Policy" header.
Modified: trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp (133100 => 133101)
--- trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp 2012-11-01 00:31:14 UTC (rev 133100)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp 2012-11-01 00:39:39 UTC (rev 133101)
@@ -195,35 +195,26 @@
size_t bufferLength = buffer()->length();
double bufferSampleRate = buffer()->sampleRate();
- // Calculate the start and end frames in our buffer that we want to play.
- // If m_isGrain is true, then we will be playing a portion of the total buffer.
- unsigned startFrame = m_isGrain ? AudioUtilities::timeToSampleFrame(m_grainOffset, bufferSampleRate) : 0;
-
// Avoid converting from time to sample-frames twice by computing
// the grain end time first before computing the sample frame.
unsigned endFrame = m_isGrain ? AudioUtilities::timeToSampleFrame(m_grainOffset + m_grainDuration, bufferSampleRate) : bufferLength;
- ASSERT(endFrame >= startFrame);
- if (endFrame < startFrame)
- return false;
-
// This is a HACK to allow for HRTF tail-time - avoids glitch at end.
// FIXME: implement tailTime for each AudioNode for a more general solution to this problem.
+ // https://bugs.webkit.org/show_bug.cgi?id=77224
if (m_isGrain)
endFrame += 512;
// Do some sanity checking.
- if (startFrame >= bufferLength)
- startFrame = !bufferLength ? 0 : bufferLength - 1;
if (endFrame > bufferLength)
endFrame = bufferLength;
if (m_virtualReadIndex >= endFrame)
- m_virtualReadIndex = startFrame; // reset to start
+ m_virtualReadIndex = 0; // reset to start
// If the .loop attribute is true, then values of m_loopStart == 0 && m_loopEnd == 0 implies
// that we should use the entire buffer as the loop, otherwise use the loop values in m_loopStart and m_loopEnd.
double virtualEndFrame = endFrame;
- double virtualDeltaFrames = endFrame - startFrame;
+ double virtualDeltaFrames = endFrame;
if (loop() && (m_loopStart || m_loopEnd) && m_loopStart >= 0 && m_loopEnd > 0 && m_loopStart < m_loopEnd) {
// Convert from seconds to sample-frames.
@@ -234,6 +225,7 @@
virtualDeltaFrames = virtualEndFrame - loopStartFrame;
}
+
double pitchRate = totalPitchRate();
// Sanity check that our playback rate isn't larger than the loop size.
@@ -372,6 +364,12 @@
return output(0)->numberOfChannels();
}
+void AudioBufferSourceNode::startGrain(double when, double grainOffset)
+{
+ // Duration of 0 has special value, meaning calculate based on the entire buffer's duration.
+ startGrain(when, grainOffset, 0);
+}
+
void AudioBufferSourceNode::startGrain(double when, double grainOffset, double grainDuration)
{
ASSERT(isMainThread());
@@ -385,21 +383,22 @@
// Do sanity checking of grain parameters versus buffer size.
double bufferDuration = buffer()->duration();
- if (grainDuration > bufferDuration)
- return; // FIXME: maybe should throw exception - consider in specification.
-
- double maxGrainOffset = bufferDuration - grainDuration;
- maxGrainOffset = max(0.0, maxGrainOffset);
-
grainOffset = max(0.0, grainOffset);
- grainOffset = min(maxGrainOffset, grainOffset);
+ grainOffset = min(bufferDuration, grainOffset);
m_grainOffset = grainOffset;
+ // Handle default/unspecified duration.
+ double maxDuration = bufferDuration - grainOffset;
+ if (!grainDuration)
+ grainDuration = maxDuration;
+
+ grainDuration = max(0.0, grainDuration);
+ grainDuration = min(maxDuration, grainDuration);
m_grainDuration = grainDuration;
-
+
m_isGrain = true;
m_startTime = when;
-
+
// We call timeToSampleFrame here since at playbackRate == 1 we don't want to go through linear interpolation
// at a sub-sample position since it will degrade the quality.
// When aligned to the sample-frame the playback will be identical to the PCM data stored in the buffer.
Modified: trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.h (133100 => 133101)
--- trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.h 2012-11-01 00:31:14 UTC (rev 133100)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.h 2012-11-01 00:39:39 UTC (rev 133101)
@@ -62,6 +62,7 @@
unsigned numberOfChannels();
// Play-state
+ void startGrain(double when, double grainOffset);
void startGrain(double when, double grainOffset, double grainDuration);
#if ENABLE(LEGACY_WEB_AUDIO)
Modified: trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.idl (133100 => 133101)
--- trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.idl 2012-11-01 00:31:14 UTC (rev 133100)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.idl 2012-11-01 00:39:39 UTC (rev 133101)
@@ -46,6 +46,7 @@
attribute double loopEnd;
[V8MeasureAs=WebAudioStart] void start(in double when);
+ [V8MeasureAs=WebAudioStart, ImplementedAs=startGrain] void start(in double when, in double grainOffset);
[V8MeasureAs=WebAudioStart, ImplementedAs=startGrain] void start(in double when, in double grainOffset, in double grainDuration);
void stop(in double when);
_______________________________________________ webkit-changes mailing list [email protected] http://lists.webkit.org/mailman/listinfo/webkit-changes
