summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/webaudio
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-06-02 12:07:03 +0100
committerBen Murdoch <benm@google.com>2011-06-10 10:47:21 +0100
commit2daae5fd11344eaa88a0d92b0f6d65f8d2255c00 (patch)
treee4964fbd1cb70599f7718ff03e50ea1dab33890b /Source/WebCore/webaudio
parent87bdf0060a247bfbe668342b87e0874182e0ffa9 (diff)
downloadexternal_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.zip
external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.gz
external_webkit-2daae5fd11344eaa88a0d92b0f6d65f8d2255c00.tar.bz2
Merge WebKit at r84325: Initial merge by git.
Change-Id: Ic1a909300ecc0a13ddc6b4e784371d2ac6e3d59b
Diffstat (limited to 'Source/WebCore/webaudio')
-rw-r--r--Source/WebCore/webaudio/AudioContext.cpp95
-rw-r--r--Source/WebCore/webaudio/AudioContext.h39
-rw-r--r--Source/WebCore/webaudio/AudioContext.idl11
-rw-r--r--Source/WebCore/webaudio/AudioDestinationNode.cpp35
-rw-r--r--Source/WebCore/webaudio/AudioDestinationNode.h23
-rw-r--r--Source/WebCore/webaudio/ConvolverNode.cpp4
-rw-r--r--Source/WebCore/webaudio/DefaultAudioDestinationNode.cpp82
-rw-r--r--Source/WebCore/webaudio/DefaultAudioDestinationNode.h61
-rw-r--r--Source/WebCore/webaudio/OfflineAudioCompletionEvent.cpp58
-rw-r--r--Source/WebCore/webaudio/OfflineAudioCompletionEvent.h55
-rw-r--r--Source/WebCore/webaudio/OfflineAudioCompletionEvent.idl32
-rw-r--r--Source/WebCore/webaudio/OfflineAudioDestinationNode.cpp166
-rw-r--r--Source/WebCore/webaudio/OfflineAudioDestinationNode.h78
13 files changed, 679 insertions, 60 deletions
diff --git a/Source/WebCore/webaudio/AudioContext.cpp b/Source/WebCore/webaudio/AudioContext.cpp
index f25b494..0d23cf5 100644
--- a/Source/WebCore/webaudio/AudioContext.cpp
+++ b/Source/WebCore/webaudio/AudioContext.cpp
@@ -39,6 +39,7 @@
#include "AudioNodeOutput.h"
#include "AudioPannerNode.h"
#include "ConvolverNode.h"
+#include "DefaultAudioDestinationNode.h"
#include "DelayNode.h"
#include "Document.h"
#include "FFTFrame.h"
@@ -47,9 +48,15 @@
#include "HighPass2FilterNode.h"
#include "JavaScriptAudioNode.h"
#include "LowPass2FilterNode.h"
+#include "OfflineAudioCompletionEvent.h"
+#include "OfflineAudioDestinationNode.h"
#include "PlatformString.h"
#include "RealtimeAnalyserNode.h"
+#if DEBUG_AUDIONODE_REFERENCES
+#include <stdio.h>
+#endif
+
#include <wtf/OwnPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/RefCounted.h>
@@ -66,6 +73,12 @@ PassRefPtr<AudioContext> AudioContext::create(Document* document)
return adoptRef(new AudioContext(document));
}
+PassRefPtr<AudioContext> AudioContext::createOfflineContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, double sampleRate)
+{
+ return adoptRef(new AudioContext(document, numberOfChannels, numberOfFrames, sampleRate));
+}
+
+// Constructor for rendering to the audio hardware.
AudioContext::AudioContext(Document* document)
: ActiveDOMObject(document, this)
, m_isInitialized(false)
@@ -75,6 +88,46 @@ AudioContext::AudioContext(Document* document)
, m_connectionCount(0)
, m_audioThread(0)
, m_graphOwnerThread(UndefinedThreadIdentifier)
+ , m_isOfflineContext(false)
+{
+ constructCommon();
+
+ m_destinationNode = DefaultAudioDestinationNode::create(this);
+
+ // This sets in motion an asynchronous loading mechanism on another thread.
+ // We can check m_hrtfDatabaseLoader->isLoaded() to find out whether or not it has been fully loaded.
+ // It's not that useful to have a callback function for this since the audio thread automatically starts rendering on the graph
+ // when this has finished (see AudioDestinationNode).
+ m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate());
+
+ // FIXME: for now default AudioContext does not need an explicit startRendering() call.
+ // We may want to consider requiring it for symmetry with OfflineAudioContext
+ m_destinationNode->startRendering();
+}
+
+// Constructor for offline (non-realtime) rendering.
+AudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, double sampleRate)
+ : ActiveDOMObject(document, this)
+ , m_isInitialized(false)
+ , m_isAudioThreadFinished(false)
+ , m_document(document)
+ , m_destinationNode(0)
+ , m_connectionCount(0)
+ , m_audioThread(0)
+ , m_graphOwnerThread(UndefinedThreadIdentifier)
+ , m_isOfflineContext(true)
+{
+ constructCommon();
+
+ // FIXME: the passed in sampleRate MUST match the hardware sample-rate since HRTFDatabaseLoader is a singleton.
+ m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate);
+
+ // Create a new destination for offline rendering.
+ m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate);
+ m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTarget.get());
+}
+
+void AudioContext::constructCommon()
{
// Note: because adoptRef() won't be called until we leave this constructor, but code in this constructor needs to reference this context,
// relax the check.
@@ -82,16 +135,9 @@ AudioContext::AudioContext(Document* document)
FFTFrame::initialize();
- m_destinationNode = AudioDestinationNode::create(this);
m_listener = AudioListener::create();
m_temporaryMonoBus = adoptPtr(new AudioBus(1, AudioNode::ProcessingSizeInFrames));
m_temporaryStereoBus = adoptPtr(new AudioBus(2, AudioNode::ProcessingSizeInFrames));
-
- // This sets in motion an asynchronous loading mechanism on another thread.
- // We can check m_hrtfDatabaseLoader->isLoaded() to find out whether or not it has been fully loaded.
- // It's not that useful to have a callback function for this since the audio thread automatically starts rendering on the graph
- // when this has finished (see AudioDestinationNode).
- m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate());
}
AudioContext::~AudioContext()
@@ -167,7 +213,7 @@ void AudioContext::stop()
uninitialize();
}
-Document* AudioContext::document()
+Document* AudioContext::document() const
{
ASSERT(m_document);
return m_document;
@@ -526,6 +572,39 @@ void AudioContext::handleDirtyAudioNodeOutputs()
m_dirtyAudioNodeOutputs.clear();
}
+ScriptExecutionContext* AudioContext::scriptExecutionContext() const
+{
+ return document();
+}
+
+AudioContext* AudioContext::toAudioContext()
+{
+ return this;
+}
+
+void AudioContext::startRendering()
+{
+ destination()->startRendering();
+}
+
+void AudioContext::fireCompletionEvent()
+{
+ ASSERT(isMainThread());
+ if (!isMainThread())
+ return;
+
+ AudioBuffer* renderedBuffer = m_renderTarget.get();
+
+ ASSERT(renderedBuffer);
+ if (!renderedBuffer)
+ return;
+
+ // Avoid firing the event if the document has already gone away.
+ if (hasDocument()) {
+ // Call the offline rendering completion event listener.
+ dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer));
+ }
+}
} // namespace WebCore
diff --git a/Source/WebCore/webaudio/AudioContext.h b/Source/WebCore/webaudio/AudioContext.h
index ddd474c..4f89091 100644
--- a/Source/WebCore/webaudio/AudioContext.h
+++ b/Source/WebCore/webaudio/AudioContext.h
@@ -28,6 +28,8 @@
#include "ActiveDOMObject.h"
#include "AudioBus.h"
#include "AudioDestinationNode.h"
+#include "EventListener.h"
+#include "EventTarget.h"
#include "HRTFDatabaseLoader.h"
#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
@@ -59,13 +61,19 @@ class JavaScriptAudioNode;
// AudioContext is the cornerstone of the web audio API and all AudioNodes are created from it.
// For thread safety between the audio thread and the main thread, it has a rendering graph locking mechanism.
-class AudioContext : public ActiveDOMObject, public RefCounted<AudioContext> {
+class AudioContext : public ActiveDOMObject, public RefCounted<AudioContext>, public EventTarget {
public:
+ // Create an AudioContext for rendering to the audio hardware.
static PassRefPtr<AudioContext> create(Document*);
+ // Create an AudioContext for offline (non-realtime) rendering.
+ static PassRefPtr<AudioContext> createOfflineContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, double sampleRate);
+
virtual ~AudioContext();
bool isInitialized() const;
+
+ bool isOfflineContext() { return m_isOfflineContext; }
// Returns true when initialize() was called AND all asynchronous initialization has completed.
bool isRunnable() const;
@@ -73,7 +81,7 @@ public:
// Document notification
virtual void stop();
- Document* document(); // ASSERTs if document no longer exists.
+ Document* document() const; // ASSERTs if document no longer exists.
bool hasDocument();
AudioDestinationNode* destination() { return m_destinationNode.get(); }
@@ -180,9 +188,27 @@ public:
// Only accessed when the graph lock is held.
void markAudioNodeInputDirty(AudioNodeInput*);
void markAudioNodeOutputDirty(AudioNodeOutput*);
+
+ // EventTarget
+ virtual ScriptExecutionContext* scriptExecutionContext() const;
+ virtual AudioContext* toAudioContext();
+ virtual EventTargetData* eventTargetData() { return &m_eventTargetData; }
+ virtual EventTargetData* ensureEventTargetData() { return &m_eventTargetData; }
+
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(complete);
+
+ // Reconcile ref/deref which are defined both in AudioNode and EventTarget.
+ using RefCounted<AudioContext>::ref;
+ using RefCounted<AudioContext>::deref;
+
+ void startRendering();
+ void fireCompletionEvent();
private:
AudioContext(Document*);
+ AudioContext(Document*, unsigned numberOfChannels, size_t numberOfFrames, double sampleRate);
+ void constructCommon();
+
void lazyInitialize();
void uninitialize();
@@ -252,6 +278,15 @@ private:
// HRTF Database loader
RefPtr<HRTFDatabaseLoader> m_hrtfDatabaseLoader;
+
+ // EventTarget
+ virtual void refEventTarget() { ref(); }
+ virtual void derefEventTarget() { deref(); }
+ EventTargetData m_eventTargetData;
+
+ RefPtr<AudioBuffer> m_renderTarget;
+
+ bool m_isOfflineContext;
};
} // WebCore
diff --git a/Source/WebCore/webaudio/AudioContext.idl b/Source/WebCore/webaudio/AudioContext.idl
index 531774e..39b36c1 100644
--- a/Source/WebCore/webaudio/AudioContext.idl
+++ b/Source/WebCore/webaudio/AudioContext.idl
@@ -27,7 +27,10 @@ module webaudio {
Conditional=WEB_AUDIO,
CanBeConstructed,
CustomConstructFunction,
- V8CustomConstructor
+ V8CustomConstructor,
+#if defined(V8_BINDING) && V8_BINDING
+ EventTarget
+#endif
] AudioContext {
// All rendered audio ultimately connects to destination, which represents the audio hardware.
readonly attribute AudioDestinationNode destination;
@@ -62,5 +65,11 @@ module webaudio {
// Channel splitting and merging
AudioChannelSplitter createChannelSplitter();
AudioChannelMerger createChannelMerger();
+
+ // Offline rendering
+ // void prepareOfflineBufferRendering(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate);
+ attribute EventListener oncomplete;
+ void startRendering();
+
};
}
diff --git a/Source/WebCore/webaudio/AudioDestinationNode.cpp b/Source/WebCore/webaudio/AudioDestinationNode.cpp
index d2f4928..8c46b44 100644
--- a/Source/WebCore/webaudio/AudioDestinationNode.cpp
+++ b/Source/WebCore/webaudio/AudioDestinationNode.cpp
@@ -32,19 +32,16 @@
#include "AudioContext.h"
#include "AudioNodeInput.h"
#include "AudioNodeOutput.h"
-#include <wtf/Threading.h>
namespace WebCore {
-
-AudioDestinationNode::AudioDestinationNode(AudioContext* context)
- : AudioNode(context, AudioDestination::hardwareSampleRate())
+
+AudioDestinationNode::AudioDestinationNode(AudioContext* context, double sampleRate)
+ : AudioNode(context, sampleRate)
, m_currentTime(0.0)
{
addInput(adoptPtr(new AudioNodeInput(this)));
setType(NodeTypeDestination);
-
- initialize();
}
AudioDestinationNode::~AudioDestinationNode()
@@ -52,32 +49,6 @@ AudioDestinationNode::~AudioDestinationNode()
uninitialize();
}
-void AudioDestinationNode::initialize()
-{
- if (isInitialized())
- return;
-
- double hardwareSampleRate = AudioDestination::hardwareSampleRate();
-#ifndef NDEBUG
- fprintf(stderr, ">>>> hardwareSampleRate = %f\n", hardwareSampleRate);
-#endif
-
- m_destination = AudioDestination::create(*this, hardwareSampleRate);
- m_destination->start();
-
- AudioNode::initialize();
-}
-
-void AudioDestinationNode::uninitialize()
-{
- if (!isInitialized())
- return;
-
- m_destination->stop();
-
- AudioNode::uninitialize();
-}
-
// The audio hardware calls us back here to gets its input stream.
void AudioDestinationNode::provideInput(AudioBus* destinationBus, size_t numberOfFrames)
{
diff --git a/Source/WebCore/webaudio/AudioDestinationNode.h b/Source/WebCore/webaudio/AudioDestinationNode.h
index 4c21bb8..5913205 100644
--- a/Source/WebCore/webaudio/AudioDestinationNode.h
+++ b/Source/WebCore/webaudio/AudioDestinationNode.h
@@ -25,11 +25,9 @@
#ifndef AudioDestinationNode_h
#define AudioDestinationNode_h
-#include "AudioDestination.h"
+#include "AudioBuffer.h"
#include "AudioNode.h"
#include "AudioSourceProvider.h"
-#include <wtf/OwnPtr.h>
-#include <wtf/PassRefPtr.h>
namespace WebCore {
@@ -38,32 +36,25 @@ class AudioContext;
class AudioDestinationNode : public AudioNode, public AudioSourceProvider {
public:
- static PassRefPtr<AudioDestinationNode> create(AudioContext* context)
- {
- return adoptRef(new AudioDestinationNode(context));
- }
-
+ AudioDestinationNode(AudioContext*, double sampleRate);
virtual ~AudioDestinationNode();
// AudioNode
virtual void process(size_t) { }; // we're pulled by hardware so this is never called
virtual void reset() { m_currentTime = 0.0; };
- virtual void initialize();
- virtual void uninitialize();
// The audio hardware calls here periodically to gets its input stream.
virtual void provideInput(AudioBus*, size_t numberOfFrames);
double currentTime() { return m_currentTime; }
- double sampleRate() const { return m_destination->sampleRate(); }
+ virtual double sampleRate() const = 0;
- unsigned numberOfChannels() const { return 2; } // FIXME: update when multi-channel (more than stereo) is supported
-
-private:
- AudioDestinationNode(AudioContext*);
+ virtual unsigned numberOfChannels() const { return 2; } // FIXME: update when multi-channel (more than stereo) is supported
- OwnPtr<AudioDestination> m_destination;
+ virtual void startRendering() = 0;
+
+protected:
double m_currentTime;
};
diff --git a/Source/WebCore/webaudio/ConvolverNode.cpp b/Source/WebCore/webaudio/ConvolverNode.cpp
index c778a41..91f6dc6 100644
--- a/Source/WebCore/webaudio/ConvolverNode.cpp
+++ b/Source/WebCore/webaudio/ConvolverNode.cpp
@@ -29,6 +29,7 @@
#include "ConvolverNode.h"
#include "AudioBuffer.h"
+#include "AudioContext.h"
#include "AudioNodeInput.h"
#include "AudioNodeOutput.h"
#include "Reverb.h"
@@ -131,7 +132,8 @@ void ConvolverNode::setBuffer(AudioBuffer* buffer)
bufferBus.setChannelMemory(i, buffer->getChannelData(i)->data(), bufferLength);
// Create the reverb with the given impulse response.
- OwnPtr<Reverb> reverb = adoptPtr(new Reverb(&bufferBus, AudioNode::ProcessingSizeInFrames, MaxFFTSize, 2, true));
+ bool useBackgroundThreads = !context()->isOfflineContext();
+ OwnPtr<Reverb> reverb = adoptPtr(new Reverb(&bufferBus, AudioNode::ProcessingSizeInFrames, MaxFFTSize, 2, useBackgroundThreads));
{
// Synchronize with process().
diff --git a/Source/WebCore/webaudio/DefaultAudioDestinationNode.cpp b/Source/WebCore/webaudio/DefaultAudioDestinationNode.cpp
new file mode 100644
index 0000000..f1a7263
--- /dev/null
+++ b/Source/WebCore/webaudio/DefaultAudioDestinationNode.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEB_AUDIO)
+
+#include "DefaultAudioDestinationNode.h"
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+namespace WebCore {
+
+DefaultAudioDestinationNode::DefaultAudioDestinationNode(AudioContext* context)
+ : AudioDestinationNode(context, AudioDestination::hardwareSampleRate())
+{
+ initialize();
+}
+
+DefaultAudioDestinationNode::~DefaultAudioDestinationNode()
+{
+ uninitialize();
+}
+
+void DefaultAudioDestinationNode::initialize()
+{
+ if (isInitialized())
+ return;
+
+ double hardwareSampleRate = AudioDestination::hardwareSampleRate();
+#ifndef NDEBUG
+ fprintf(stderr, ">>>> hardwareSampleRate = %f\n", hardwareSampleRate);
+#endif
+
+ m_destination = AudioDestination::create(*this, hardwareSampleRate);
+
+ AudioNode::initialize();
+}
+
+void DefaultAudioDestinationNode::uninitialize()
+{
+ if (!isInitialized())
+ return;
+
+ m_destination->stop();
+
+ AudioNode::uninitialize();
+}
+
+void DefaultAudioDestinationNode::startRendering()
+{
+ ASSERT(isInitialized());
+ if (isInitialized())
+ m_destination->start();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/webaudio/DefaultAudioDestinationNode.h b/Source/WebCore/webaudio/DefaultAudioDestinationNode.h
new file mode 100644
index 0000000..f1d689d
--- /dev/null
+++ b/Source/WebCore/webaudio/DefaultAudioDestinationNode.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DefaultAudioDestinationNode_h
+#define DefaultAudioDestinationNode_h
+
+#include "AudioDestination.h"
+#include "AudioDestinationNode.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class AudioContext;
+
+class DefaultAudioDestinationNode : public AudioDestinationNode {
+public:
+ static PassRefPtr<DefaultAudioDestinationNode> create(AudioContext* context)
+ {
+ return adoptRef(new DefaultAudioDestinationNode(context));
+ }
+
+ virtual ~DefaultAudioDestinationNode();
+
+ // AudioNode
+ virtual void initialize();
+ virtual void uninitialize();
+
+ double sampleRate() const { return m_destination->sampleRate(); }
+
+ virtual void startRendering();
+
+private:
+ DefaultAudioDestinationNode(AudioContext*);
+
+ OwnPtr<AudioDestination> m_destination;
+};
+
+} // namespace WebCore
+
+#endif // DefaultAudioDestinationNode_h
diff --git a/Source/WebCore/webaudio/OfflineAudioCompletionEvent.cpp b/Source/WebCore/webaudio/OfflineAudioCompletionEvent.cpp
new file mode 100644
index 0000000..6160c82
--- /dev/null
+++ b/Source/WebCore/webaudio/OfflineAudioCompletionEvent.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEB_AUDIO)
+
+#include "OfflineAudioCompletionEvent.h"
+
+#include "AudioBuffer.h"
+#include "EventNames.h"
+
+namespace WebCore {
+
+PassRefPtr<OfflineAudioCompletionEvent> OfflineAudioCompletionEvent::create(PassRefPtr<AudioBuffer> renderedBuffer)
+{
+ return adoptRef(new OfflineAudioCompletionEvent(renderedBuffer));
+}
+
+OfflineAudioCompletionEvent::OfflineAudioCompletionEvent(PassRefPtr<AudioBuffer> renderedBuffer)
+ : Event(eventNames().completeEvent, true, false)
+ , m_renderedBuffer(renderedBuffer)
+{
+}
+
+OfflineAudioCompletionEvent::~OfflineAudioCompletionEvent()
+{
+}
+
+bool OfflineAudioCompletionEvent::isOfflineAudioCompletionEvent() const
+{
+ return true;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/webaudio/OfflineAudioCompletionEvent.h b/Source/WebCore/webaudio/OfflineAudioCompletionEvent.h
new file mode 100644
index 0000000..bd700e8
--- /dev/null
+++ b/Source/WebCore/webaudio/OfflineAudioCompletionEvent.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef OfflineAudioCompletionEvent_h
+#define OfflineAudioCompletionEvent_h
+
+#include "AudioBuffer.h"
+#include "Event.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class AudioBuffer;
+
+class OfflineAudioCompletionEvent : public Event {
+public:
+ static PassRefPtr<OfflineAudioCompletionEvent> create(PassRefPtr<AudioBuffer> renderedBuffer);
+
+ virtual ~OfflineAudioCompletionEvent();
+
+ virtual bool isOfflineAudioCompletionEvent() const;
+
+ AudioBuffer* renderedBuffer() { return m_renderedBuffer.get(); }
+
+private:
+ OfflineAudioCompletionEvent(PassRefPtr<AudioBuffer> renderedBuffer);
+
+ RefPtr<AudioBuffer> m_renderedBuffer;
+};
+
+} // namespace WebCore
+
+#endif // OfflineAudioCompletionEvent_h
diff --git a/Source/WebCore/webaudio/OfflineAudioCompletionEvent.idl b/Source/WebCore/webaudio/OfflineAudioCompletionEvent.idl
new file mode 100644
index 0000000..cd5ccb0
--- /dev/null
+++ b/Source/WebCore/webaudio/OfflineAudioCompletionEvent.idl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module audio {
+ interface [
+ Conditional=WEB_AUDIO,
+ GenerateToJS
+ ] OfflineAudioCompletionEvent : Event {
+ readonly attribute AudioBuffer renderedBuffer;
+ };
+}
diff --git a/Source/WebCore/webaudio/OfflineAudioDestinationNode.cpp b/Source/WebCore/webaudio/OfflineAudioDestinationNode.cpp
new file mode 100644
index 0000000..e3a0758
--- /dev/null
+++ b/Source/WebCore/webaudio/OfflineAudioDestinationNode.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEB_AUDIO)
+
+#include "OfflineAudioDestinationNode.h"
+
+#include "AudioBus.h"
+#include "AudioContext.h"
+#include "HRTFDatabaseLoader.h"
+#include <algorithm>
+#include <wtf/Threading.h>
+
+using namespace std;
+
+namespace WebCore {
+
+const size_t renderQuantumSize = 128;
+
+OfflineAudioDestinationNode::OfflineAudioDestinationNode(AudioContext* context, AudioBuffer* renderTarget)
+ : AudioDestinationNode(context, renderTarget->sampleRate())
+ , m_renderTarget(renderTarget)
+ , m_startedRendering(false)
+{
+ m_renderBus = adoptPtr(new AudioBus(renderTarget->numberOfChannels(), renderQuantumSize));
+
+ initialize();
+}
+
+OfflineAudioDestinationNode::~OfflineAudioDestinationNode()
+{
+ uninitialize();
+}
+
+void OfflineAudioDestinationNode::initialize()
+{
+ if (isInitialized())
+ return;
+
+ AudioNode::initialize();
+}
+
+void OfflineAudioDestinationNode::uninitialize()
+{
+ if (!isInitialized())
+ return;
+
+ AudioNode::uninitialize();
+}
+
+void OfflineAudioDestinationNode::startRendering()
+{
+ ASSERT(isMainThread());
+ ASSERT(m_renderTarget.get());
+ if (!m_renderTarget.get())
+ return;
+
+ if (!m_startedRendering) {
+ m_startedRendering = true;
+ m_renderThread = createThread(OfflineAudioDestinationNode::renderEntry, this, "offline renderer");
+ }
+}
+
+// Do offline rendering in this thread.
+void* OfflineAudioDestinationNode::renderEntry(void* threadData)
+{
+ OfflineAudioDestinationNode* destinationNode = reinterpret_cast<OfflineAudioDestinationNode*>(threadData);
+ ASSERT(destinationNode);
+ destinationNode->render();
+
+ return 0;
+}
+
+void OfflineAudioDestinationNode::render()
+{
+ ASSERT(!isMainThread());
+ ASSERT(m_renderBus.get());
+ if (!m_renderBus.get())
+ return;
+
+ bool channelsMatch = m_renderBus->numberOfChannels() == m_renderTarget->numberOfChannels();
+ ASSERT(channelsMatch);
+ if (!channelsMatch)
+ return;
+
+ bool isRenderBusAllocated = m_renderBus->length() >= renderQuantumSize;
+ ASSERT(isRenderBusAllocated);
+ if (!isRenderBusAllocated)
+ return;
+
+ // Synchronize with HRTFDatabaseLoader.
+ // The database must be loaded before we can proceed.
+ HRTFDatabaseLoader* loader = HRTFDatabaseLoader::loader();
+ ASSERT(loader);
+ if (!loader)
+ return;
+
+ loader->waitForLoaderThreadCompletion();
+
+ // Break up the render target into smaller "render quantize" sized pieces.
+ // Render until we're finished.
+ size_t framesToProcess = m_renderTarget->length();
+ unsigned numberOfChannels = m_renderTarget->numberOfChannels();
+
+ unsigned n = 0;
+ while (framesToProcess > 0) {
+ // Render one render quantum.
+ provideInput(m_renderBus.get(), renderQuantumSize);
+
+ size_t framesAvailableToCopy = min(framesToProcess, renderQuantumSize);
+
+ for (unsigned channelIndex = 0; channelIndex < numberOfChannels; ++channelIndex) {
+ float* source = m_renderBus->channel(channelIndex)->data();
+ float* destination = m_renderTarget->getChannelData(channelIndex)->data();
+ memcpy(destination + n, source, sizeof(float) * framesAvailableToCopy);
+ }
+
+ n += framesAvailableToCopy;
+ framesToProcess -= framesAvailableToCopy;
+ }
+
+ // Our work is done. Let the AudioContext know.
+ callOnMainThread(notifyCompleteDispatch, this);
+}
+
+void OfflineAudioDestinationNode::notifyCompleteDispatch(void* userData)
+{
+ OfflineAudioDestinationNode* destinationNode = static_cast<OfflineAudioDestinationNode*>(userData);
+ ASSERT(destinationNode);
+ if (!destinationNode)
+ return;
+
+ destinationNode->notifyComplete();
+}
+
+void OfflineAudioDestinationNode::notifyComplete()
+{
+ context()->fireCompletionEvent();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/webaudio/OfflineAudioDestinationNode.h b/Source/WebCore/webaudio/OfflineAudioDestinationNode.h
new file mode 100644
index 0000000..714c120
--- /dev/null
+++ b/Source/WebCore/webaudio/OfflineAudioDestinationNode.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef OfflineAudioDestinationNode_h
+#define OfflineAudioDestinationNode_h
+
+#include "AudioBuffer.h"
+#include "AudioDestinationNode.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Threading.h>
+
+namespace WebCore {
+
+class AudioBus;
+class AudioContext;
+
+class OfflineAudioDestinationNode : public AudioDestinationNode {
+public:
+ static PassRefPtr<OfflineAudioDestinationNode> create(AudioContext* context, AudioBuffer* renderTarget)
+ {
+ return adoptRef(new OfflineAudioDestinationNode(context, renderTarget));
+ }
+
+ virtual ~OfflineAudioDestinationNode();
+
+ // AudioNode
+ virtual void initialize();
+ virtual void uninitialize();
+
+ double sampleRate() const { return m_renderTarget->sampleRate(); }
+
+ void startRendering();
+
+private:
+ OfflineAudioDestinationNode(AudioContext*, AudioBuffer* renderTarget);
+
+ // This AudioNode renders into this AudioBuffer.
+ RefPtr<AudioBuffer> m_renderTarget;
+
+ // Temporary AudioBus for each render quantum.
+ OwnPtr<AudioBus> m_renderBus;
+
+ // Rendering thread.
+ volatile ThreadIdentifier m_renderThread;
+ bool m_startedRendering;
+ static void* renderEntry(void* threadData);
+ void render();
+
+ // For completion callback on main thread.
+ static void notifyCompleteDispatch(void* userData);
+ void notifyComplete();
+};
+
+} // namespace WebCore
+
+#endif // OfflineAudioDestinationNode_h