DelayNode delay buffer is not correctly wrapping around
authorcrogers@google.com <crogers@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Sep 2011 18:55:07 +0000 (18:55 +0000)
committercrogers@google.com <crogers@google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 12 Sep 2011 18:55:07 +0000 (18:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=67872

Reviewed by Kenneth Russell.

Source/WebCore:

Test: webaudio/delaynode.html

* webaudio/DelayDSPKernel.cpp:
(WebCore::DelayDSPKernel::process):

LayoutTests:

* webaudio/delaynode-expected.txt: Added.
* webaudio/delaynode.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@94969 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/webaudio/delaynode-expected.txt [new file with mode: 0644]
LayoutTests/webaudio/delaynode.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/webaudio/DelayDSPKernel.cpp

index bda4457..d37fdf5 100644 (file)
@@ -1,3 +1,13 @@
+2011-09-12  Chris Rogers  <crogers@google.com>
+
+        DelayNode delay buffer is not correctly wrapping around
+        https://bugs.webkit.org/show_bug.cgi?id=67872
+
+        Reviewed by Kenneth Russell.
+
+        * webaudio/delaynode-expected.txt: Added.
+        * webaudio/delaynode.html: Added.
+
 2011-09-12  Arko Saha  <arko@motorola.com>
 
         Selectstart is not fired when selection was created by arrow keys.
diff --git a/LayoutTests/webaudio/delaynode-expected.txt b/LayoutTests/webaudio/delaynode-expected.txt
new file mode 100644 (file)
index 0000000..63a52d8
--- /dev/null
@@ -0,0 +1,9 @@
+Tests basic functionality of DelayNode.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS Test signal was correctly delayed.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/webaudio/delaynode.html b/LayoutTests/webaudio/delaynode.html
new file mode 100644 (file)
index 0000000..ab65997
--- /dev/null
@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+<link rel="stylesheet" href="../fast/js/resources/js-test-style.css"/>
+<script src="../fast/js/resources/js-test-pre.js"></script>
+</head>
+
+<body>
+
+<div id="description"></div>
+<div id="console"></div>
+
+<script>
+description("Tests basic functionality of DelayNode.");
+
+var sampleRate = 44100.0;
+
+var context;
+var toneBuffer;
+
+var renderLengthSeconds = 4;
+var delayTimeSeconds = 0.5;
+var toneLengthSeconds = 2;
+
+function createToneBuffer(frequency, numberOfCycles, sampleRate) {
+    var duration = numberOfCycles / frequency;
+    var sampleFrameLength = duration * sampleRate;
+    
+    var audioBuffer = context.createBuffer(1, sampleFrameLength, sampleRate);
+
+    var n = audioBuffer.length;
+    var data = audioBuffer.getChannelData(0);
+
+    for (var i = 0; i < n; ++i)
+        data[i] = Math.sin(frequency * 2.0*Math.PI * i / sampleRate);
+
+    return audioBuffer;
+}
+
+function checkDelayedResult(event) {
+    var renderedBuffer = event.renderedBuffer;
+
+    var sourceData = toneBuffer.getChannelData(0);
+    var renderedData = renderedBuffer.getChannelData(0);
+    
+    var delayTimeFrames = delayTimeSeconds * sampleRate;
+    var toneLengthFrames = toneLengthSeconds * sampleRate;
+
+    var success = true;
+    
+    var n = renderedBuffer.length;
+    
+    for (var i = 0; i < n; ++i) {
+        if (i < delayTimeFrames) {
+            // Check that initial portion is 0 (since signal is delayed).
+            if (renderedData[i] != 0) {
+                success = false;
+                break;
+            }
+        } else if (i >= delayTimeFrames && i < delayTimeFrames + toneLengthFrames) {
+            // Make sure that the tone data is delayed by exactly the expected number of frames.
+            var j = i - delayTimeFrames;
+            if (renderedData[i] != sourceData[j]) {
+                success = false;
+                break;
+            }
+        } else {
+            // Make sure we have silence after the delayed tone.
+            if (renderedData[i] != 0) {
+                success = false;
+                break;
+            }
+        }    
+    }
+
+    if (success) {
+        testPassed("Test signal was correctly delayed.");
+    } else {
+        testFailed("Test signal was not correctly delayed.");
+    }
+
+    finishJSTest();
+}
+
+function runTest() {
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+    
+    window.jsTestIsAsync = true;
+        
+    // Create offline audio context.
+    context = new webkitAudioContext(1, sampleRate * renderLengthSeconds, sampleRate);
+    toneBuffer = createToneBuffer(20, 20 * toneLengthSeconds, sampleRate); // 20Hz tone
+    
+    var bufferSource = context.createBufferSource();
+    bufferSource.buffer = toneBuffer;
+
+    var delay = context.createDelayNode();
+    delay.delayTime.value = delayTimeSeconds;
+
+    bufferSource.connect(delay);
+    delay.connect(context.destination);
+    bufferSource.noteOn(0);
+    
+    context.oncomplete = checkDelayedResult;
+    context.startRendering();
+}
+
+runTest();
+successfullyParsed = true;
+
+</script>
+
+<script src="../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
index d4e9852..1e6c7e0 100644 (file)
@@ -1,3 +1,15 @@
+2011-09-12  Chris Rogers  <crogers@google.com>
+
+        DelayNode delay buffer is not correctly wrapping around
+        https://bugs.webkit.org/show_bug.cgi?id=67872
+
+        Reviewed by Kenneth Russell.
+
+        Test: webaudio/delaynode.html
+
+        * webaudio/DelayDSPKernel.cpp:
+        (WebCore::DelayDSPKernel::process):
+
 2011-09-12  Arko Saha  <arko@motorola.com>
 
         Selectstart is not fired when selection was created by arrow keys.
index 45a9b32..8e0b40e 100644 (file)
@@ -108,7 +108,7 @@ void DelayDSPKernel::process(const float* source, float* destination, size_t fra
         double desiredDelayFrames = m_currentDelayTime * sampleRate;
 
         double readPosition = m_writeIndex + bufferLength - desiredDelayFrames;
-        if (readPosition > bufferLength)
+        if (readPosition >= bufferLength)
             readPosition -= bufferLength;
 
         // Linearly interpolate in-between delay times.