diff --git a/content/media/webaudio/AudioBuffer.cpp b/content/media/webaudio/AudioBuffer.cpp new file mode 100644 index 00000000000..35cc4b40092 --- /dev/null +++ b/content/media/webaudio/AudioBuffer.cpp @@ -0,0 +1,101 @@ +/* -*- 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 "AudioBuffer.h" +#include "mozilla/dom/AudioBufferBinding.h" +#include "nsContentUtils.h" +#include "AudioContext.h" +#include "jsfriendapi.h" +#include "mozilla/ErrorResult.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_CLASS(AudioBuffer) + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioBuffer) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext) + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mChannels) + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER + NS_DROP_JS_OBJECTS(tmp, AudioBuffer); +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioBuffer) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(AudioBuffer) + NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER + for (uint32_t i = 0; i < tmp->mChannels.Length(); ++i) { + NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mChannels[i]) + } +NS_IMPL_CYCLE_COLLECTION_TRACE_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(AudioBuffer) +NS_IMPL_CYCLE_COLLECTING_RELEASE(AudioBuffer) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioBuffer) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +AudioBuffer::AudioBuffer(AudioContext* aContext, uint32_t aLength, + uint32_t aSampleRate) + : mContext(aContext), + mLength(aLength), + mSampleRate(aSampleRate) +{ + SetIsDOMBinding(); +} + +AudioBuffer::~AudioBuffer() +{ + // Drop the JS object reference if we're still holding to the channels + if (mChannels.Length()) { + NS_DROP_JS_OBJECTS(this, AudioBuffer); + } +} + +bool +AudioBuffer::InitializeBuffers(uint32_t aNumberOfChannels, JSContext* aJSContext) +{ + if (!mChannels.SetCapacity(aNumberOfChannels)) { + return false; + } + for (uint32_t i = 0; i < aNumberOfChannels; ++i) { + JSObject* array = JS_NewFloat32Array(aJSContext, mLength); + if (!array) { + return false; + } + mChannels.AppendElement(array); + } + + NS_HOLD_JS_OBJECTS(this, AudioBuffer); + + return true; +} + +JSObject* +AudioBuffer::WrapObject(JSContext* aCx, JSObject* aScope, + bool* aTriedToWrap) +{ + return AudioBufferBinding::Wrap(aCx, aScope, this, aTriedToWrap); +} + +JSObject* +AudioBuffer::GetChannelData(JSContext* aJSContext, uint32_t aChannel, + ErrorResult& aRv) const +{ + if (aChannel >= mChannels.Length()) { + aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); + return nullptr; + } + return mChannels[aChannel]; +} + +} +} + diff --git a/content/media/webaudio/AudioBuffer.h b/content/media/webaudio/AudioBuffer.h new file mode 100644 index 00000000000..a5c2f3d027e --- /dev/null +++ b/content/media/webaudio/AudioBuffer.h @@ -0,0 +1,83 @@ +/* -*- 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/. */ + +#pragma once + +#include "nsWrapperCache.h" +#include "nsCycleCollectionParticipant.h" +#include "mozilla/Attributes.h" +#include "EnableWebAudioCheck.h" +#include "nsAutoPtr.h" +#include "nsTArray.h" +#include "AudioContext.h" + +struct JSContext; +struct JSObject; + +namespace mozilla { + +class ErrorResult; + +namespace dom { + +class AudioBuffer MOZ_FINAL : public nsISupports, + public nsWrapperCache, + public EnableWebAudioCheck +{ +public: + AudioBuffer(AudioContext* aContext, uint32_t aLength, + uint32_t aSampleRate); + ~AudioBuffer(); + + // This function needs to be called in order to allocate + // all of the channels. It is fallible! + bool InitializeBuffers(uint32_t aNumberOfChannels, + JSContext* aJSContext); + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AudioBuffer) + + AudioContext* GetParentObject() const + { + return mContext; + } + + virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope, + bool* aTriedToWrap); + + float SampleRate() const + { + return mSampleRate; + } + + uint32_t Length() const + { + return mLength; + } + + float Duration() const + { + return mLength / mSampleRate; + } + + uint32_t NumberOfChannels() const + { + return mChannels.Length(); + } + + JSObject* GetChannelData(JSContext* aJSContext, uint32_t aChannel, + ErrorResult& aRv) const; + +private: + nsRefPtr mContext; + FallibleTArray mChannels; + uint32_t mLength; + float mSampleRate; +}; + +} +} + diff --git a/content/media/webaudio/AudioContext.cpp b/content/media/webaudio/AudioContext.cpp index e806ee528bf..bbce362705e 100644 --- a/content/media/webaudio/AudioContext.cpp +++ b/content/media/webaudio/AudioContext.cpp @@ -11,6 +11,7 @@ #include "mozilla/dom/AudioContextBinding.h" #include "AudioDestinationNode.h" #include "AudioBufferSourceNode.h" +#include "AudioBuffer.h" namespace mozilla { namespace dom { @@ -63,6 +64,19 @@ AudioContext::CreateBufferSource() return bufferNode.forget(); } +already_AddRefed +AudioContext::CreateBuffer(JSContext* aJSContext, uint32_t aNumberOfChannels, + uint32_t aLength, float aSampleRate, + ErrorResult& aRv) +{ + nsRefPtr buffer = new AudioBuffer(this, aLength, aSampleRate); + if (!buffer->InitializeBuffers(aNumberOfChannels, aJSContext)) { + aRv.Throw(NS_ERROR_OUT_OF_MEMORY); + return nullptr; + } + return buffer.forget(); +} + } } diff --git a/content/media/webaudio/AudioContext.h b/content/media/webaudio/AudioContext.h index 8a2cf804589..45fcaa2038c 100644 --- a/content/media/webaudio/AudioContext.h +++ b/content/media/webaudio/AudioContext.h @@ -24,6 +24,7 @@ namespace dom { class AudioDestinationNode; class AudioBufferSourceNode; +class AudioBuffer; class AudioContext MOZ_FINAL : public nsISupports, public nsWrapperCache, @@ -55,6 +56,11 @@ public: already_AddRefed CreateBufferSource(); + already_AddRefed + CreateBuffer(JSContext* aJSContext, uint32_t aNumberOfChannels, + uint32_t aLength, float aSampleRate, + ErrorResult& aRv); + private: nsCOMPtr mWindow; nsRefPtr mDestination; diff --git a/content/media/webaudio/Makefile.in b/content/media/webaudio/Makefile.in index f63158c58db..56003ea9a9e 100644 --- a/content/media/webaudio/Makefile.in +++ b/content/media/webaudio/Makefile.in @@ -15,6 +15,7 @@ LIBRARY_NAME := gkconwebaudio_s LIBXUL_LIBRARY := 1 CPPSRCS := \ + AudioBuffer.cpp \ AudioBufferSourceNode.cpp \ AudioContext.cpp \ AudioDestinationNode.cpp \ @@ -25,6 +26,7 @@ CPPSRCS := \ EXPORTS_NAMESPACES := mozilla/dom EXPORTS_mozilla/dom := \ + AudioBuffer.h \ AudioBufferSourceNode.h \ AudioDestinationNode.h \ AudioNode.h \ diff --git a/content/media/webaudio/test/Makefile.in b/content/media/webaudio/test/Makefile.in index 8aaeb9d18ac..9060261682a 100644 --- a/content/media/webaudio/test/Makefile.in +++ b/content/media/webaudio/test/Makefile.in @@ -11,6 +11,7 @@ relativesrcdir := @relativesrcdir@ include $(DEPTH)/config/autoconf.mk MOCHITEST_FILES := \ + test_AudioBuffer.html \ test_AudioContext.html \ $(NULL) diff --git a/content/media/webaudio/test/test_AudioBuffer.html b/content/media/webaudio/test/test_AudioBuffer.html new file mode 100644 index 00000000000..1745ac959de --- /dev/null +++ b/content/media/webaudio/test/test_AudioBuffer.html @@ -0,0 +1,44 @@ + + + + Test whether we can create an AudioContext interface + + + + +
+
+
+ + diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index e59816f020f..7444f234c7c 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -66,8 +66,12 @@ DOMInterfaces = { +'AudioBuffer' : { +}, + 'mozAudioContext': { 'nativeType': 'AudioContext', + 'implicitJSContext': [ 'createBuffer' ], }, 'AudioNode' : { diff --git a/dom/bindings/stubgenerator/Skeleton.cpp b/dom/bindings/stubgenerator/Skeleton.cpp index 3606b7b3825..dfa17d23400 100644 --- a/dom/bindings/stubgenerator/Skeleton.cpp +++ b/dom/bindings/stubgenerator/Skeleton.cpp @@ -6,6 +6,7 @@ #include "Skeleton.h" #include "mozilla/dom/SkeletonBinding.h" +#include "nsContentUtils.h" namespace mozilla { namespace dom { diff --git a/dom/webidl/AudioBuffer.webidl b/dom/webidl/AudioBuffer.webidl new file mode 100644 index 00000000000..056beefee94 --- /dev/null +++ b/dom/webidl/AudioBuffer.webidl @@ -0,0 +1,28 @@ +/* -*- 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 AudioBuffer { + + readonly attribute float sampleRate; + readonly attribute long length; + + // in seconds + readonly attribute float duration; + + readonly attribute long numberOfChannels; + + [Throws] + Float32Array getChannelData(unsigned long channel); + +}; + diff --git a/dom/webidl/AudioContext.webidl b/dom/webidl/AudioContext.webidl index 5b6fc77fad9..523123198be 100644 --- a/dom/webidl/AudioContext.webidl +++ b/dom/webidl/AudioContext.webidl @@ -15,6 +15,12 @@ interface mozAudioContext { readonly attribute AudioDestinationNode destination; + [Creator, Throws] + AudioBuffer createBuffer(unsigned long numberOfChannels, unsigned long length, float sampleRate); + + // [Creator, Throws] + // AudioBuffer createBuffer(ArrayBuffer buffer, boolean mixToMono); + // AudioNode creation AudioBufferSourceNode createBufferSource(); diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 35c814d2bb6..2e9171b4d4f 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -9,6 +9,7 @@ generated_webidl_files = \ $(NULL) webidl_files = \ + AudioBuffer.webidl \ AudioBufferSourceNode.webidl \ AudioContext.webidl \ AudioDestinationNode.webidl \ diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h index aebab3f58ca..8780648560e 100644 --- a/js/src/jsfriendapi.h +++ b/js/src/jsfriendapi.h @@ -1024,6 +1024,8 @@ typedef uint32_t JSArrayBufferViewType; /* * Create a new typed array with nelements elements. + * + * These functions (except the WithBuffer variants) fill in the array with zeros. */ extern JS_FRIEND_API(JSObject *)