When create JavaScriptNode, do not ignore NumberOfOutputChannels parameter.
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Apr 2012 18:49:40 +0000 (18:49 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 9 Apr 2012 18:49:40 +0000 (18:49 +0000)
https://bugs.webkit.org/show_bug.cgi?id=83250

Patch by Raymond Liu <raymond.liu@intel.com> on 2012-04-09
Reviewed by Chris Rogers.

* Modules/webaudio/AudioContext.cpp:
(WebCore::AudioContext::createJavaScriptNode):
(WebCore):
* Modules/webaudio/AudioContext.h:
(AudioContext):
* Modules/webaudio/AudioContext.idl:
* Modules/webaudio/JavaScriptAudioNode.cpp:
(WebCore::JavaScriptAudioNode::create):
(WebCore):
(WebCore::JavaScriptAudioNode::JavaScriptAudioNode):
(WebCore::JavaScriptAudioNode::initialize):
(WebCore::JavaScriptAudioNode::process):
* Modules/webaudio/JavaScriptAudioNode.h:
(JavaScriptAudioNode):

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

Source/WebCore/ChangeLog
Source/WebCore/Modules/webaudio/AudioContext.cpp
Source/WebCore/Modules/webaudio/AudioContext.h
Source/WebCore/Modules/webaudio/AudioContext.idl
Source/WebCore/Modules/webaudio/JavaScriptAudioNode.cpp
Source/WebCore/Modules/webaudio/JavaScriptAudioNode.h

index dced877..5d33805 100644 (file)
@@ -1,3 +1,25 @@
+2012-04-09  Raymond Liu  <raymond.liu@intel.com>
+
+        When create JavaScriptNode, do not ignore NumberOfOutputChannels parameter.
+        https://bugs.webkit.org/show_bug.cgi?id=83250
+
+        Reviewed by Chris Rogers.
+
+        * Modules/webaudio/AudioContext.cpp:
+        (WebCore::AudioContext::createJavaScriptNode):
+        (WebCore):
+        * Modules/webaudio/AudioContext.h:
+        (AudioContext):
+        * Modules/webaudio/AudioContext.idl:
+        * Modules/webaudio/JavaScriptAudioNode.cpp:
+        (WebCore::JavaScriptAudioNode::create):
+        (WebCore):
+        (WebCore::JavaScriptAudioNode::JavaScriptAudioNode):
+        (WebCore::JavaScriptAudioNode::initialize):
+        (WebCore::JavaScriptAudioNode::process):
+        * Modules/webaudio/JavaScriptAudioNode.h:
+        (JavaScriptAudioNode):
+
 2012-04-09  Abhishek Arya  <inferno@chromium.org>
 
         Crash due to floats not cleared before starting SVG <text> layout.
index f123fd9..e898467 100644 (file)
@@ -369,11 +369,28 @@ PassRefPtr<MediaElementAudioSourceNode> AudioContext::createMediaElementSource(H
 }
 #endif
 
-PassRefPtr<JavaScriptAudioNode> AudioContext::createJavaScriptNode(size_t bufferSize)
+PassRefPtr<JavaScriptAudioNode> AudioContext::createJavaScriptNode(size_t bufferSize, ExceptionCode& ec)
+{
+    // Set number of input/output channels to stereo by default.
+    return createJavaScriptNode(bufferSize, 2, 2, ec);
+}
+
+PassRefPtr<JavaScriptAudioNode> AudioContext::createJavaScriptNode(size_t bufferSize, size_t numberOfInputChannels, ExceptionCode& ec)
+{
+    // Set number of output channels to stereo by default.
+    return createJavaScriptNode(bufferSize, numberOfInputChannels, 2, ec);
+}
+
+PassRefPtr<JavaScriptAudioNode> AudioContext::createJavaScriptNode(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionCode& ec)
 {
     ASSERT(isMainThread());
     lazyInitialize();
-    RefPtr<JavaScriptAudioNode> node = JavaScriptAudioNode::create(this, m_destinationNode->sampleRate(), bufferSize);
+    RefPtr<JavaScriptAudioNode> node = JavaScriptAudioNode::create(this, m_destinationNode->sampleRate(), bufferSize, numberOfInputChannels, numberOfOutputChannels);
+
+    if (!node.get()) {
+        ec = SYNTAX_ERR;
+        return 0;
+    }
 
     refNode(node.get()); // context keeps reference until we stop making javascript rendering callbacks
     return node;
index adc3982..2d79a2a 100644 (file)
@@ -123,7 +123,9 @@ public:
     PassRefPtr<ConvolverNode> createConvolver();
     PassRefPtr<DynamicsCompressorNode> createDynamicsCompressor();    
     PassRefPtr<RealtimeAnalyserNode> createAnalyser();
-    PassRefPtr<JavaScriptAudioNode> createJavaScriptNode(size_t bufferSize);
+    PassRefPtr<JavaScriptAudioNode> createJavaScriptNode(size_t bufferSize, ExceptionCode&);
+    PassRefPtr<JavaScriptAudioNode> createJavaScriptNode(size_t bufferSize, size_t numberOfInputChannels, ExceptionCode&);
+    PassRefPtr<JavaScriptAudioNode> createJavaScriptNode(size_t bufferSize, size_t numberOfInputChannels, size_t numberOfOutputChannels, ExceptionCode&);
     PassRefPtr<AudioChannelSplitter> createChannelSplitter();
     PassRefPtr<AudioChannelMerger> createChannelMerger();
     PassRefPtr<Oscillator> createOscillator();
index 1f81d66..ed05a94 100644 (file)
@@ -71,7 +71,8 @@ module webaudio {
         ConvolverNode createConvolver();
         DynamicsCompressorNode createDynamicsCompressor();
         RealtimeAnalyserNode createAnalyser();
-        JavaScriptAudioNode createJavaScriptNode(in unsigned long bufferSize);
+        JavaScriptAudioNode createJavaScriptNode(in unsigned long bufferSize, in [Optional] unsigned long numberOfInputChannels, in [Optional] unsigned long numberOfOutputChannels)
+            raises(DOMException);
         Oscillator createOscillator();
         WaveTable createWaveTable(in Float32Array real, in Float32Array imag)
             raises(DOMException);
index ea3d7aa..81c1dc7 100644 (file)
@@ -42,18 +42,7 @@ namespace WebCore {
 
 const size_t DefaultBufferSize = 4096;
 
-PassRefPtr<JavaScriptAudioNode> JavaScriptAudioNode::create(AudioContext* context, float sampleRate, size_t bufferSize, unsigned numberOfInputs, unsigned numberOfOutputs)
-{
-    return adoptRef(new JavaScriptAudioNode(context, sampleRate, bufferSize, numberOfInputs, numberOfOutputs));
-}
-
-JavaScriptAudioNode::JavaScriptAudioNode(AudioContext* context, float sampleRate, size_t bufferSize, unsigned numberOfInputs, unsigned numberOfOutputs)
-    : AudioNode(context, sampleRate)
-    , m_doubleBufferIndex(0)
-    , m_doubleBufferIndexForEvent(0)
-    , m_bufferSize(bufferSize)
-    , m_bufferReadWriteIndex(0)
-    , m_isRequestOutstanding(false)
+PassRefPtr<JavaScriptAudioNode> JavaScriptAudioNode::create(AudioContext* context, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels)
 {
     // Check for valid buffer size.
     switch (bufferSize) {
@@ -64,22 +53,37 @@ JavaScriptAudioNode::JavaScriptAudioNode(AudioContext* context, float sampleRate
     case 4096:
     case 8192:
     case 16384:
-        m_bufferSize = bufferSize;
         break;
     default:
-        m_bufferSize = DefaultBufferSize;
+        return 0;
     }
-        
-    // Regardless of the allowed buffer sizes above, we still need to process at the granularity of the AudioNode.
+
+    // FIXME: We still need to implement numberOfInputChannels.
+    ASSERT_UNUSED(numberOfInputChannels, numberOfInputChannels <= AudioContext::maxNumberOfChannels());
+
+    if (!numberOfOutputChannels || numberOfOutputChannels > AudioContext::maxNumberOfChannels())
+        return 0;
+
+    return adoptRef(new JavaScriptAudioNode(context, sampleRate, bufferSize, numberOfInputChannels, numberOfOutputChannels));
+}
+
+JavaScriptAudioNode::JavaScriptAudioNode(AudioContext* context, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels)
+    : AudioNode(context, sampleRate)
+    , m_doubleBufferIndex(0)
+    , m_doubleBufferIndexForEvent(0)
+    , m_bufferSize(bufferSize)
+    , m_bufferReadWriteIndex(0)
+    , m_isRequestOutstanding(false)
+{
+    // Regardless of the allowed buffer sizes, we still need to process at the granularity of the AudioNode.
     if (m_bufferSize < AudioNode::ProcessingSizeInFrames)
         m_bufferSize = AudioNode::ProcessingSizeInFrames;
 
-    // FIXME: Right now we're hardcoded to single input and single output.
-    // Although the specification says this is OK for a simple implementation, multiple inputs and outputs would be good.
-    ASSERT_UNUSED(numberOfInputs, numberOfInputs == 1);
-    ASSERT_UNUSED(numberOfOutputs, numberOfOutputs == 1);
+    // FIXME: We still need to implement numberOfInputChannels.
+    ASSERT_UNUSED(numberOfInputChannels, numberOfInputChannels > 0);
+
     addInput(adoptPtr(new AudioNodeInput(this)));
-    addOutput(adoptPtr(new AudioNodeOutput(this, 2)));
+    addOutput(adoptPtr(new AudioNodeOutput(this, numberOfOutputChannels)));
 
     setNodeType(NodeTypeJavaScript);
 
@@ -102,7 +106,7 @@ void JavaScriptAudioNode::initialize()
     // These AudioBuffers will be directly accessed in the main thread by JavaScript.
     for (unsigned i = 0; i < 2; ++i) {
         m_inputBuffers.append(AudioBuffer::create(2, bufferSize(), sampleRate));
-        m_outputBuffers.append(AudioBuffer::create(2, bufferSize(), sampleRate));
+        m_outputBuffers.append(AudioBuffer::create(this->output(0)->numberOfChannels(), bufferSize(), sampleRate));
     }
 
     AudioNode::initialize();
@@ -155,16 +159,15 @@ void JavaScriptAudioNode::process(size_t framesToProcess)
         return;
         
     unsigned numberOfInputChannels = inputBus->numberOfChannels();
+    unsigned numberOfOutputChannels = outputBus->numberOfChannels();
     
-    bool channelsAreGood = (numberOfInputChannels == 1 || numberOfInputChannels == 2) && outputBus->numberOfChannels() == 2;
+    bool channelsAreGood = (numberOfInputChannels == 1 || numberOfInputChannels == 2);
     ASSERT(channelsAreGood);
     if (!channelsAreGood)
         return;
 
     const float* sourceL = inputBus->channel(0)->data();
     const float* sourceR = numberOfInputChannels > 1 ? inputBus->channel(1)->data() : 0;
-    float* destinationL = outputBus->channel(0)->mutableData();
-    float* destinationR = outputBus->channel(1)->mutableData();
 
     // Copy from the input to the input buffer.  See "buffersAreGood" check above for safety.
     size_t bytesToCopy = sizeof(float) * framesToProcess;
@@ -178,9 +181,9 @@ void JavaScriptAudioNode::process(size_t framesToProcess)
         memcpy(inputBuffer->getChannelData(1)->data() + m_bufferReadWriteIndex, sourceL, bytesToCopy);
     }
     
-    // Copy from the output buffer to the output.  See "buffersAreGood" check above for safety.
-    memcpy(destinationL, outputBuffer->getChannelData(0)->data() + m_bufferReadWriteIndex, bytesToCopy);
-    memcpy(destinationR, outputBuffer->getChannelData(1)->data() + m_bufferReadWriteIndex, bytesToCopy);
+    // Copy from the output buffer to the output. 
+    for (unsigned i = 0; i < numberOfOutputChannels; ++i)
+        memcpy(outputBus->channel(i)->mutableData(), outputBuffer->getChannelData(i)->data() + m_bufferReadWriteIndex, bytesToCopy);
 
     // Update the buffering index.
     m_bufferReadWriteIndex = (m_bufferReadWriteIndex + framesToProcess) % bufferSize();
index 65049cb..b940e1a 100644 (file)
@@ -53,7 +53,7 @@ public:
     // This value controls how frequently the onaudioprocess event handler is called and how many sample-frames need to be processed each call.
     // Lower numbers for bufferSize will result in a lower (better) latency. Higher numbers will be necessary to avoid audio breakup and glitches.
     // The value chosen must carefully balance between latency and audio quality.
-    static PassRefPtr<JavaScriptAudioNode> create(AudioContext*, float sampleRate, size_t bufferSize, unsigned numberOfInputs = 1, unsigned numberOfOutputs = 1);
+    static PassRefPtr<JavaScriptAudioNode> create(AudioContext*, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels);
 
     virtual ~JavaScriptAudioNode();
 
@@ -81,7 +81,7 @@ private:
     virtual double tailTime() const OVERRIDE;
     virtual double latencyTime() const OVERRIDE;
 
-    JavaScriptAudioNode(AudioContext*, float sampleRate, size_t bufferSize, unsigned numberOfInputs, unsigned numberOfOutputs);
+    JavaScriptAudioNode(AudioContext*, float sampleRate, size_t bufferSize, unsigned numberOfInputChannels, unsigned numberOfOutputChannels);
 
     static void fireProcessEventDispatch(void* userData);
     void fireProcessEvent();