Bug 815643 - Part 1: Implement the DOM bindings for ConvolverNode; r=roc
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 10 Jun 2013 16:07:55 -0400
changeset 134585 6058da103d45
parent 134584 5eb3a09775c9
child 134586 dc80f47a7123
push id29285
push usereakhgari@mozilla.com
push dateTue, 11 Jun 2013 00:10:14 +0000
treeherdermozilla-inbound@63386b71d1b5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs815643
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 815643 - Part 1: Implement the DOM bindings for ConvolverNode; r=roc
content/media/webaudio/AudioContext.cpp
content/media/webaudio/AudioContext.h
content/media/webaudio/ConvolverNode.cpp
content/media/webaudio/ConvolverNode.h
content/media/webaudio/moz.build
dom/bindings/Bindings.conf
dom/webidl/AudioContext.webidl
dom/webidl/ConvolverNode.webidl
dom/webidl/WebIDL.mk
--- a/content/media/webaudio/AudioContext.cpp
+++ b/content/media/webaudio/AudioContext.cpp
@@ -21,16 +21,17 @@
 #include "AudioListener.h"
 #include "DynamicsCompressorNode.h"
 #include "BiquadFilterNode.h"
 #include "ScriptProcessorNode.h"
 #include "ChannelMergerNode.h"
 #include "ChannelSplitterNode.h"
 #include "WaveShaperNode.h"
 #include "WaveTable.h"
+#include "ConvolverNode.h"
 #include "nsNetUtil.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED_2(AudioContext, nsDOMEventTargetHelper,
                                      mDestination, mListener)
 
@@ -259,16 +260,23 @@ AudioContext::CreateDelay(double aMaxDel
 already_AddRefed<PannerNode>
 AudioContext::CreatePanner()
 {
   nsRefPtr<PannerNode> pannerNode = new PannerNode(this);
   mPannerNodes.PutEntry(pannerNode);
   return pannerNode.forget();
 }
 
+already_AddRefed<ConvolverNode>
+AudioContext::CreateConvolver()
+{
+  nsRefPtr<ConvolverNode> convolverNode = new ConvolverNode(this);
+  return convolverNode.forget();
+}
+
 already_AddRefed<ChannelSplitterNode>
 AudioContext::CreateChannelSplitter(uint32_t aNumberOfOutputs, ErrorResult& aRv)
 {
   if (aNumberOfOutputs == 0 ||
       aNumberOfOutputs > WebAudioUtils::MaxChannelCount) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return nullptr;
   }
--- a/content/media/webaudio/AudioContext.h
+++ b/content/media/webaudio/AudioContext.h
@@ -41,16 +41,17 @@ namespace dom {
 class AnalyserNode;
 class AudioBuffer;
 class AudioBufferSourceNode;
 class AudioDestinationNode;
 class AudioListener;
 class BiquadFilterNode;
 class ChannelMergerNode;
 class ChannelSplitterNode;
+class ConvolverNode;
 class DelayNode;
 class DynamicsCompressorNode;
 class GainNode;
 class GlobalObject;
 class OfflineRenderSuccessCallback;
 class PannerNode;
 class ScriptProcessorNode;
 class WaveShaperNode;
@@ -162,16 +163,19 @@ public:
   CreateDelayNode(double aMaxDelayTime, ErrorResult& aRv)
   {
     return CreateDelay(aMaxDelayTime, aRv);
   }
 
   already_AddRefed<PannerNode>
   CreatePanner();
 
+  already_AddRefed<ConvolverNode>
+  CreateConvolver();
+
   already_AddRefed<ChannelSplitterNode>
   CreateChannelSplitter(uint32_t aNumberOfOutputs, ErrorResult& aRv);
 
   already_AddRefed<ChannelMergerNode>
   CreateChannelMerger(uint32_t aNumberOfInputs, ErrorResult& aRv);
 
   already_AddRefed<DynamicsCompressorNode>
   CreateDynamicsCompressor();
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/ConvolverNode.cpp
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ConvolverNode.h"
+#include "mozilla/dom/ConvolverNodeBinding.h"
+#include "AudioNodeEngine.h"
+#include "AudioNodeStream.h"
+
+#include <cmath>
+#include "nsMathUtils.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTION_INHERITED_1(ConvolverNode, AudioNode, mBuffer)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ConvolverNode)
+NS_INTERFACE_MAP_END_INHERITING(AudioNode)
+
+NS_IMPL_ADDREF_INHERITED(ConvolverNode, AudioNode)
+NS_IMPL_RELEASE_INHERITED(ConvolverNode, AudioNode)
+
+class ConvolverNodeEngine : public AudioNodeEngine
+{
+public:
+  ConvolverNodeEngine(AudioNode* aNode, bool aNormalize)
+    : AudioNodeEngine(aNode)
+    , mNormalize(aNormalize)
+  {
+  }
+
+  enum Parameters {
+    NORMALIZE
+  };
+  virtual void SetInt32Parameter(uint32_t aIndex, int32_t aParam) MOZ_OVERRIDE
+  {
+    switch (aIndex) {
+    case NORMALIZE:
+      mNormalize = !!aParam;
+      break;
+    default:
+      NS_ERROR("Bad ConvolverNodeEngine Int32Parameter");
+    }
+  }
+  virtual void SetBuffer(already_AddRefed<ThreadSharedFloatArrayBufferList> aBuffer)
+  {
+    mBuffer = aBuffer;
+  }
+
+  virtual void ProduceAudioBlock(AudioNodeStream* aStream,
+                                 const AudioChunk& aInput,
+                                 AudioChunk* aOutput,
+                                 bool* aFinished)
+  {
+    *aOutput = aInput;
+  }
+
+private:
+  nsRefPtr<ThreadSharedFloatArrayBufferList> mBuffer;
+  bool mNormalize;
+};
+
+ConvolverNode::ConvolverNode(AudioContext* aContext)
+  : AudioNode(aContext,
+              2,
+              ChannelCountMode::Clamped_max,
+              ChannelInterpretation::Speakers)
+  , mNormalize(true)
+{
+  ConvolverNodeEngine* engine = new ConvolverNodeEngine(this, mNormalize);
+  mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
+}
+
+JSObject*
+ConvolverNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
+{
+  return ConvolverNodeBinding::Wrap(aCx, aScope, this);
+}
+
+void
+ConvolverNode::SetBuffer(JSContext* aCx, AudioBuffer* aBuffer, ErrorResult& aRv)
+{
+  switch (aBuffer->NumberOfChannels()) {
+  case 1:
+  case 2:
+  case 4:
+    // Supported number of channels
+    break;
+  default:
+    aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+    return;
+  }
+
+  mBuffer = aBuffer;
+
+  // Send the buffer to the stream
+  AudioNodeStream* ns = static_cast<AudioNodeStream*>(mStream.get());
+  MOZ_ASSERT(ns, "Why don't we have a stream here?");
+  if (mBuffer) {
+    nsRefPtr<ThreadSharedFloatArrayBufferList> data =
+      mBuffer->GetThreadSharedChannelsForRate(aCx);
+    ns->SetBuffer(data.forget());
+  } else {
+    ns->SetBuffer(nullptr);
+  }
+}
+
+void
+ConvolverNode::SetNormalize(bool aNormalize)
+{
+  mNormalize = aNormalize;
+  SendInt32ParameterToStream(ConvolverNodeEngine::NORMALIZE, aNormalize);
+}
+
+}
+}
+
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/ConvolverNode.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef ConvolverNode_h_
+#define ConvolverNode_h_
+
+#include "AudioNode.h"
+#include "AudioBuffer.h"
+
+namespace mozilla {
+namespace dom {
+
+class ConvolverNode : public AudioNode
+{
+public:
+  explicit ConvolverNode(AudioContext* aContext);
+
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ConvolverNode, AudioNode);
+
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
+
+  AudioBuffer* GetBuffer(JSContext* aCx) const
+  {
+    return mBuffer;
+  }
+
+  void SetBuffer(JSContext* aCx, AudioBuffer* aBufferi, ErrorResult& aRv);
+
+  bool Normalize() const
+  {
+    return mNormalize;
+  }
+
+  void SetNormalize(bool aNormal);
+
+private:
+  nsRefPtr<AudioBuffer> mBuffer;
+  bool mNormalize;
+};
+
+
+} //end namespace dom
+} //end namespace mozilla
+
+#endif
+
--- a/content/media/webaudio/moz.build
+++ b/content/media/webaudio/moz.build
@@ -25,16 +25,17 @@ EXPORTS.mozilla.dom += [
     'AudioDestinationNode.h',
     'AudioListener.h',
     'AudioNode.h',
     'AudioParam.h',
     'AudioProcessingEvent.h',
     'BiquadFilterNode.h',
     'ChannelMergerNode.h',
     'ChannelSplitterNode.h',
+    'ConvolverNode.h',
     'DelayNode.h',
     'DynamicsCompressorNode.h',
     'EnableWebAudioCheck.h',
     'GainNode.h',
     'OfflineAudioCompletionEvent.h',
     'PannerNode.h',
     'ScriptProcessorNode.h',
     'WaveShaperNode.h',
@@ -49,16 +50,17 @@ CPP_SOURCES += [
     'AudioDestinationNode.cpp',
     'AudioListener.cpp',
     'AudioNode.cpp',
     'AudioParam.cpp',
     'AudioProcessingEvent.cpp',
     'BiquadFilterNode.cpp',
     'ChannelMergerNode.cpp',
     'ChannelSplitterNode.cpp',
+    'ConvolverNode.cpp',
     'DelayNode.cpp',
     'DynamicsCompressorNode.cpp',
     'EnableWebAudioCheck.cpp',
     'GainNode.cpp',
     'MediaBufferDecoder.cpp',
     'OfflineAudioCompletionEvent.cpp',
     'PannerNode.cpp',
     'ScriptProcessorNode.cpp',
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -201,16 +201,21 @@ DOMInterfaces = {
 'CommandEvent': {
     'nativeType': 'nsDOMCommandEvent',
 },
 
 'CompositionEvent': {
     'nativeType': 'nsDOMCompositionEvent',
 },
 
+'ConvolverNode': {
+    'implicitJSContext': [ 'buffer' ],
+    'resultNotAddRefed': [ 'buffer' ],
+},
+
 'Coordinates': {
     'headerFile': 'nsGeoPosition.h'
 },
 
 'CSS': {
     'concrete': False,
 },
 
--- a/dom/webidl/AudioContext.webidl
+++ b/dom/webidl/AudioContext.webidl
@@ -47,16 +47,18 @@ interface AudioContext : EventTarget {
     [Creator, Throws]
     DelayNode createDelay(optional double maxDelayTime = 1);
     [Creator]
     BiquadFilterNode createBiquadFilter();
     [Creator]
     WaveShaperNode createWaveShaper();
     [Creator]
     PannerNode createPanner();
+    [Creator]
+    ConvolverNode createConvolver();
 
     [Creator, Throws]
     ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
     [Creator, Throws]
     ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6);
 
     [Creator]
     DynamicsCompressorNode createDynamicsCompressor();
new file mode 100644
--- /dev/null
+++ b/dom/webidl/ConvolverNode.webidl
@@ -0,0 +1,21 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html
+ *
+ * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
+ * liability, trademark and document use rules apply.
+ */
+
+[PrefControlled]
+interface ConvolverNode : AudioNode {
+
+      [SetterThrows]
+      attribute AudioBuffer? buffer;
+      attribute boolean normalize;
+
+};
+
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -38,16 +38,17 @@ webidl_files = \
   CharacterData.webidl \
   ChildNode.webidl \
   ClientRect.webidl \
   ClientRectList.webidl \
   ClipboardEvent.webidl \
   CommandEvent.webidl \
   Comment.webidl \
   CompositionEvent.webidl \
+  ConvolverNode.webidl \
   Coordinates.webidl \
   CSS.webidl \
   CSSPrimitiveValue.webidl \
   CSSStyleDeclaration.webidl \
   CSSStyleSheet.webidl \
   CSSValue.webidl \
   CSSValueList.webidl \
   DataContainerEvent.webidl \