1bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen/*
2a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2010, Google Inc. All rights reserved.
3bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen *
4bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * Redistribution and use in source and binary forms, with or without
5bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * modification, are permitted provided that the following conditions
6bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * are met:
7bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * 1.  Redistributions of source code must retain the above copyright
8a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *    notice, this list of conditions and the following disclaimer.
9bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * 2.  Redistributions in binary form must reproduce the above copyright
10a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *    notice, this list of conditions and the following disclaimer in the
11a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *    documentation and/or other materials provided with the distribution.
12bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen *
13a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen */
24bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
25bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "config.h"
26bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
27bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if ENABLE(WEB_AUDIO)
28bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
29bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioContext.h"
30bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
31f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "ArrayBuffer.h"
32bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioBuffer.h"
33bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioBufferSourceNode.h"
34bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioChannelMerger.h"
35bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioChannelSplitter.h"
36bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioGainNode.h"
37bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioListener.h"
38e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "AudioNodeInput.h"
39e14391e94c850b8bd03680c23b38978db68687a8John Reck#include "AudioNodeOutput.h"
40bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "AudioPannerNode.h"
41bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "ConvolverNode.h"
422daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "DefaultAudioDestinationNode.h"
43bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "DelayNode.h"
44bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "Document.h"
452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "FFTFrame.h"
46bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "HRTFDatabaseLoader.h"
47bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "HRTFPanner.h"
48bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "HighPass2FilterNode.h"
49bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "JavaScriptAudioNode.h"
50bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "LowPass2FilterNode.h"
512daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "OfflineAudioCompletionEvent.h"
522daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include "OfflineAudioDestinationNode.h"
53bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "PlatformString.h"
54bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include "RealtimeAnalyserNode.h"
55bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#if DEBUG_AUDIONODE_REFERENCES
572daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#include <stdio.h>
582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch#endif
592daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
60bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/OwnPtr.h>
61bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/PassOwnPtr.h>
62bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#include <wtf/RefCounted.h>
63bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
64bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen// FIXME: check the proper way to reference an undefined thread ID
65bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenconst int UndefinedThreadIdentifier = 0xffffffff;
66a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochconst unsigned MaxNodesToDeletePerQuantum = 10;
68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
69bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsennamespace WebCore {
70bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
71bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<AudioContext> AudioContext::create(Document* document)
72bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
73bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return adoptRef(new AudioContext(document));
74bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
75bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochPassRefPtr<AudioContext> AudioContext::createOfflineContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, double sampleRate)
772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return adoptRef(new AudioContext(document, numberOfChannels, numberOfFrames, sampleRate));
792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Constructor for rendering to the audio hardware.
82bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenAudioContext::AudioContext(Document* document)
83bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    : ActiveDOMObject(document, this)
84bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    , m_isInitialized(false)
85bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    , m_isAudioThreadFinished(false)
86bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    , m_document(document)
87bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    , m_destinationNode(0)
88bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    , m_connectionCount(0)
89bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    , m_audioThread(0)
90bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    , m_graphOwnerThread(UndefinedThreadIdentifier)
912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_isOfflineContext(false)
922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    constructCommon();
942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_destinationNode = DefaultAudioDestinationNode::create(this);
962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // This sets in motion an asynchronous loading mechanism on another thread.
982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // We can check m_hrtfDatabaseLoader->isLoaded() to find out whether or not it has been fully loaded.
992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // It's not that useful to have a callback function for this since the audio thread automatically starts rendering on the graph
1002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // when this has finished (see AudioDestinationNode).
1012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate());
1022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: for now default AudioContext does not need an explicit startRendering() call.
1042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // We may want to consider requiring it for symmetry with OfflineAudioContext
1052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_destinationNode->startRendering();
1062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1082daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch// Constructor for offline (non-realtime) rendering.
1092daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochAudioContext::AudioContext(Document* document, unsigned numberOfChannels, size_t numberOfFrames, double sampleRate)
1102daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    : ActiveDOMObject(document, this)
1112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_isInitialized(false)
1122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_isAudioThreadFinished(false)
1132daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_document(document)
1142daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_destinationNode(0)
1152daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_connectionCount(0)
1162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_audioThread(0)
1172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_graphOwnerThread(UndefinedThreadIdentifier)
1182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    , m_isOfflineContext(true)
1192daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
1202daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    constructCommon();
1212daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1222daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // FIXME: the passed in sampleRate MUST match the hardware sample-rate since HRTFDatabaseLoader is a singleton.
1232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_hrtfDatabaseLoader = HRTFDatabaseLoader::createAndLoadAsynchronouslyIfNecessary(sampleRate);
1242daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1252daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Create a new destination for offline rendering.
1262daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_renderTarget = AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate);
1272daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    m_destinationNode = OfflineAudioDestinationNode::create(this, m_renderTarget.get());
1282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
1292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid AudioContext::constructCommon()
131bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
132bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Note: because adoptRef() won't be called until we leave this constructor, but code in this constructor needs to reference this context,
133bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // relax the check.
134bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    relaxAdoptionRequirement();
135bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
1362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    FFTFrame::initialize();
1372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
138bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_listener = AudioListener::create();
139bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_temporaryMonoBus = adoptPtr(new AudioBus(1, AudioNode::ProcessingSizeInFrames));
140bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_temporaryStereoBus = adoptPtr(new AudioBus(2, AudioNode::ProcessingSizeInFrames));
141bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
142bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
143bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenAudioContext::~AudioContext()
144bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
145bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#if DEBUG_AUDIONODE_REFERENCES
146bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    printf("%p: AudioContext::~AudioContext()\n", this);
147bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif
148bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // AudioNodes keep a reference to their context, so there should be no way to be in the destructor if there are still AudioNodes around.
149bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(!m_nodesToDelete.size());
150bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(!m_referencedNodes.size());
151bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(!m_finishedNodes.size());
152bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
153bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
154bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::lazyInitialize()
155bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
156bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    if (!m_isInitialized) {
157bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // Don't allow the context to initialize a second time after it's already been explicitly uninitialized.
158bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        ASSERT(!m_isAudioThreadFinished);
159bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        if (!m_isAudioThreadFinished) {
160bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen            if (m_destinationNode.get()) {
161bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                // This starts the audio thread.  The destination node's provideInput() method will now be called repeatedly to render audio.
162bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                // Each time provideInput() is called, a portion of the audio stream is rendered.  Let's call this time period a "render quantum".
163bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen                m_destinationNode->initialize();
164bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen            }
165bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen            m_isInitialized = true;
166bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        }
167bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    }
168bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
169bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
170bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::uninitialize()
171bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
172bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    if (m_isInitialized) {
173bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // This stops the audio thread and all audio rendering.
174bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        m_destinationNode->uninitialize();
175bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
176bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // Don't allow the context to initialize a second time after it's already been explicitly uninitialized.
177bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        m_isAudioThreadFinished = true;
178bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
179bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // We have to release our reference to the destination node before the context will ever be deleted since the destination node holds a reference to the context.
180bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        m_destinationNode.clear();
181bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
182bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // Get rid of the sources which may still be playing.
183bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        derefUnfinishedSourceNodes();
184bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
185bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // Because the AudioBuffers are garbage collected, we can't delete them here.
186bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // Instead, at least release the potentially large amount of allocated memory for the audio data.
187bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // Note that we do this *after* the context is uninitialized and stops processing audio.
188bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        for (unsigned i = 0; i < m_allocatedBuffers.size(); ++i)
189bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen            m_allocatedBuffers[i]->releaseMemory();
190bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        m_allocatedBuffers.clear();
191bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
192bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        m_isInitialized = false;
193bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    }
194bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
195bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
196bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenbool AudioContext::isInitialized() const
197bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
198bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return m_isInitialized;
199bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
200bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
201bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenbool AudioContext::isRunnable() const
202bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
203bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    if (!isInitialized())
204bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        return false;
205bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
206bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Check with the HRTF spatialization system to see if it's finished loading.
207a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return m_hrtfDatabaseLoader->isLoaded();
208bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
209bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
210bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::stop()
211bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
212bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_document = 0; // document is going away
213bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    uninitialize();
214bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
215bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
2162daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochDocument* AudioContext::document() const
217bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
218bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(m_document);
219bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return m_document;
220bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
221bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
222bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenbool AudioContext::hasDocument()
223bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
224bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return m_document;
225bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
226bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
227bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::refBuffer(PassRefPtr<AudioBuffer> buffer)
228bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
229bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_allocatedBuffers.append(buffer);
230bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
231bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
232bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<AudioBuffer> AudioContext::createBuffer(unsigned numberOfChannels, size_t numberOfFrames, double sampleRate)
233bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
234bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return AudioBuffer::create(numberOfChannels, numberOfFrames, sampleRate);
235bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
236bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
237f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochPassRefPtr<AudioBuffer> AudioContext::createBuffer(ArrayBuffer* arrayBuffer, bool mixToMono)
238f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
239f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ASSERT(arrayBuffer);
240f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!arrayBuffer)
241f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return 0;
242f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
243f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return AudioBuffer::createFromAudioFileData(arrayBuffer->data(), arrayBuffer->byteLength(), mixToMono, sampleRate());
244f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
245f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
246bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<AudioBufferSourceNode> AudioContext::createBufferSource()
247bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
248bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
249bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    lazyInitialize();
250bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    RefPtr<AudioBufferSourceNode> node = AudioBufferSourceNode::create(this, m_destinationNode->sampleRate());
251bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
252bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    refNode(node.get()); // context keeps reference until source has finished playing
253bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return node;
254bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
255bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
256bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<JavaScriptAudioNode> AudioContext::createJavaScriptNode(size_t bufferSize)
257bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
258bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
259bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    lazyInitialize();
260bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    RefPtr<JavaScriptAudioNode> node = JavaScriptAudioNode::create(this, m_destinationNode->sampleRate(), bufferSize);
261bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
262bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    refNode(node.get()); // context keeps reference until we stop making javascript rendering callbacks
263bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return node;
264bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
265bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
266bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<LowPass2FilterNode> AudioContext::createLowPass2Filter()
267bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
268bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
269bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    lazyInitialize();
270bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return LowPass2FilterNode::create(this, m_destinationNode->sampleRate());
271bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
272bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
273bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<HighPass2FilterNode> AudioContext::createHighPass2Filter()
274bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
275bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
276bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    lazyInitialize();
277bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return HighPass2FilterNode::create(this, m_destinationNode->sampleRate());
278bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
279bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
280bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<AudioPannerNode> AudioContext::createPanner()
281bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
282bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
283bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    lazyInitialize();
284bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return AudioPannerNode::create(this, m_destinationNode->sampleRate());
285bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
286bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
287bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<ConvolverNode> AudioContext::createConvolver()
288bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
289bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
290bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    lazyInitialize();
291bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return ConvolverNode::create(this, m_destinationNode->sampleRate());
292bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
293bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
294bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<RealtimeAnalyserNode> AudioContext::createAnalyser()
295bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
296bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
297bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    lazyInitialize();
298bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return RealtimeAnalyserNode::create(this, m_destinationNode->sampleRate());
299bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
300bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
301bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<AudioGainNode> AudioContext::createGainNode()
302bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
303bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
304bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    lazyInitialize();
305bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return AudioGainNode::create(this, m_destinationNode->sampleRate());
306bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
307bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
308bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<DelayNode> AudioContext::createDelayNode()
309bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
310bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
311bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    lazyInitialize();
312bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return DelayNode::create(this, m_destinationNode->sampleRate());
313bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
314bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
315bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<AudioChannelSplitter> AudioContext::createChannelSplitter()
316bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
317bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
318bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    lazyInitialize();
319bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return AudioChannelSplitter::create(this, m_destinationNode->sampleRate());
320bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
321bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
322bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian MonsenPassRefPtr<AudioChannelMerger> AudioContext::createChannelMerger()
323bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
324bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
325bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    lazyInitialize();
326bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return AudioChannelMerger::create(this, m_destinationNode->sampleRate());
327bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
328bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
329bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::notifyNodeFinishedProcessing(AudioNode* node)
330bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
331bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isAudioThread());
332bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_finishedNodes.append(node);
333bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
334bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
335bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::derefFinishedSourceNodes()
336bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
337bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isGraphOwner());
338bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isAudioThread() || isAudioThreadFinished());
339bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    for (unsigned i = 0; i < m_finishedNodes.size(); i++)
340bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        derefNode(m_finishedNodes[i]);
341bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
342bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_finishedNodes.clear();
343bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
344bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
345bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::refNode(AudioNode* node)
346bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
347bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
348bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    AutoLocker locker(this);
349bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
350bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    node->ref(AudioNode::RefTypeConnection);
351bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_referencedNodes.append(node);
352bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
353bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
354bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::derefNode(AudioNode* node)
355bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
356bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isGraphOwner());
357bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
358bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    node->deref(AudioNode::RefTypeConnection);
359bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
360bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    for (unsigned i = 0; i < m_referencedNodes.size(); ++i) {
361bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        if (node == m_referencedNodes[i]) {
362bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen            m_referencedNodes.remove(i);
363bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen            break;
364bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        }
365bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    }
366bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
367bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
368bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::derefUnfinishedSourceNodes()
369bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
370bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread() && isAudioThreadFinished());
371bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    for (unsigned i = 0; i < m_referencedNodes.size(); ++i)
372bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        m_referencedNodes[i]->deref(AudioNode::RefTypeConnection);
373bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
374bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_referencedNodes.clear();
375bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
376bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
377bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::lock(bool& mustReleaseLock)
378bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
379bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Don't allow regular lock in real-time audio thread.
380bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isMainThread());
381bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
382bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ThreadIdentifier thisThread = currentThread();
383bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
384bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    if (thisThread == m_graphOwnerThread) {
385bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // We already have the lock.
386bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        mustReleaseLock = false;
387bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    } else {
388bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // Acquire the lock.
389bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        m_contextGraphMutex.lock();
390a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        m_graphOwnerThread = thisThread;
391bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        mustReleaseLock = true;
392bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    }
393bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
394bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
395bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenbool AudioContext::tryLock(bool& mustReleaseLock)
396bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
397bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ThreadIdentifier thisThread = currentThread();
398bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    bool isAudioThread = thisThread == audioThread();
399bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
400bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Try to catch cases of using try lock on main thread - it should use regular lock.
401bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isAudioThread || isAudioThreadFinished());
402bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
403bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    if (!isAudioThread) {
404bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // In release build treat tryLock() as lock() (since above ASSERT(isAudioThread) never fires) - this is the best we can do.
405bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        lock(mustReleaseLock);
406bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        return true;
407bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    }
408bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
409bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    bool hasLock;
410bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
411bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    if (thisThread == m_graphOwnerThread) {
412bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // Thread already has the lock.
413bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        hasLock = true;
414bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        mustReleaseLock = false;
415bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    } else {
416bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // Don't already have the lock - try to acquire it.
417bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        hasLock = m_contextGraphMutex.tryLock();
418bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
419bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        if (hasLock)
420bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen            m_graphOwnerThread = thisThread;
421bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
422bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        mustReleaseLock = hasLock;
423bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    }
424bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
425bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return hasLock;
426bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
427bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
428bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::unlock()
429bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
430bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(currentThread() == m_graphOwnerThread);
431bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
432bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_graphOwnerThread = UndefinedThreadIdentifier;
433bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_contextGraphMutex.unlock();
434bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
435bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
436e14391e94c850b8bd03680c23b38978db68687a8John Reckbool AudioContext::isAudioThread() const
437bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
438bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return currentThread() == m_audioThread;
439bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
440bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
441e14391e94c850b8bd03680c23b38978db68687a8John Reckbool AudioContext::isGraphOwner() const
442bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
443bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    return currentThread() == m_graphOwnerThread;
444bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
445bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
446bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::addDeferredFinishDeref(AudioNode* node, AudioNode::RefType refType)
447bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
448bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isAudioThread());
449bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_deferredFinishDerefList.append(AudioContext::RefInfo(node, refType));
450bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
451bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
452e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid AudioContext::handlePreRenderTasks()
453e14391e94c850b8bd03680c23b38978db68687a8John Reck{
454e14391e94c850b8bd03680c23b38978db68687a8John Reck    ASSERT(isAudioThread());
455e14391e94c850b8bd03680c23b38978db68687a8John Reck
456e14391e94c850b8bd03680c23b38978db68687a8John Reck    // At the beginning of every render quantum, try to update the internal rendering graph state (from main thread changes).
457e14391e94c850b8bd03680c23b38978db68687a8John Reck    // It's OK if the tryLock() fails, we'll just take slightly longer to pick up the changes.
458e14391e94c850b8bd03680c23b38978db68687a8John Reck    bool mustReleaseLock;
459e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (tryLock(mustReleaseLock)) {
460e14391e94c850b8bd03680c23b38978db68687a8John Reck        // Fixup the state of any dirty AudioNodeInputs and AudioNodeOutputs.
461e14391e94c850b8bd03680c23b38978db68687a8John Reck        handleDirtyAudioNodeInputs();
462e14391e94c850b8bd03680c23b38978db68687a8John Reck        handleDirtyAudioNodeOutputs();
463e14391e94c850b8bd03680c23b38978db68687a8John Reck
464e14391e94c850b8bd03680c23b38978db68687a8John Reck        if (mustReleaseLock)
465e14391e94c850b8bd03680c23b38978db68687a8John Reck            unlock();
466e14391e94c850b8bd03680c23b38978db68687a8John Reck    }
467e14391e94c850b8bd03680c23b38978db68687a8John Reck}
468e14391e94c850b8bd03680c23b38978db68687a8John Reck
469bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::handlePostRenderTasks()
470bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
471bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isAudioThread());
472a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
473bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Must use a tryLock() here too.  Don't worry, the lock will very rarely be contended and this method is called frequently.
474bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // The worst that can happen is that there will be some nodes which will take slightly longer than usual to be deleted or removed
475bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // from the render graph (in which case they'll render silence).
476bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    bool mustReleaseLock;
477bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    if (tryLock(mustReleaseLock)) {
478bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // Take care of finishing any derefs where the tryLock() failed previously.
479bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        handleDeferredFinishDerefs();
480bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
481bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // Dynamically clean up nodes which are no longer needed.
482bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        derefFinishedSourceNodes();
483bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
484bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        // Finally actually delete.
485bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        deleteMarkedNodes();
486bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
487e14391e94c850b8bd03680c23b38978db68687a8John Reck        // Fixup the state of any dirty AudioNodeInputs and AudioNodeOutputs.
488e14391e94c850b8bd03680c23b38978db68687a8John Reck        handleDirtyAudioNodeInputs();
489e14391e94c850b8bd03680c23b38978db68687a8John Reck        handleDirtyAudioNodeOutputs();
490e14391e94c850b8bd03680c23b38978db68687a8John Reck
491bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        if (mustReleaseLock)
492bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen            unlock();
493bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    }
494bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
495bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
496bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::handleDeferredFinishDerefs()
497bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
498a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(isAudioThread() && isGraphOwner());
499bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    for (unsigned i = 0; i < m_deferredFinishDerefList.size(); ++i) {
500bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        AudioNode* node = m_deferredFinishDerefList[i].m_node;
501bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        AudioNode::RefType refType = m_deferredFinishDerefList[i].m_refType;
502bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        node->finishDeref(refType);
503bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    }
504bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
505bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_deferredFinishDerefList.clear();
506bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
507bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
508bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::markForDeletion(AudioNode* node)
509bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
510bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isGraphOwner());
511bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    m_nodesToDelete.append(node);
512bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
513bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
514bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsenvoid AudioContext::deleteMarkedNodes()
515bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen{
516bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    ASSERT(isGraphOwner() || isAudioThreadFinished());
517bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
518bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    // Note: deleting an AudioNode can cause m_nodesToDelete to grow.
519a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    size_t nodesDeleted = 0;
520bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    while (size_t n = m_nodesToDelete.size()) {
521bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        AudioNode* node = m_nodesToDelete[n - 1];
522bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        m_nodesToDelete.removeLast();
523e14391e94c850b8bd03680c23b38978db68687a8John Reck
524e14391e94c850b8bd03680c23b38978db68687a8John Reck        // Before deleting the node, clear out any AudioNodeInputs from m_dirtyAudioNodeInputs.
525e14391e94c850b8bd03680c23b38978db68687a8John Reck        unsigned numberOfInputs = node->numberOfInputs();
526e14391e94c850b8bd03680c23b38978db68687a8John Reck        for (unsigned i = 0; i < numberOfInputs; ++i)
527e14391e94c850b8bd03680c23b38978db68687a8John Reck            m_dirtyAudioNodeInputs.remove(node->input(i));
528e14391e94c850b8bd03680c23b38978db68687a8John Reck
529e14391e94c850b8bd03680c23b38978db68687a8John Reck        // Before deleting the node, clear out any AudioNodeOutputs from m_dirtyAudioNodeOutputs.
530e14391e94c850b8bd03680c23b38978db68687a8John Reck        unsigned numberOfOutputs = node->numberOfOutputs();
531e14391e94c850b8bd03680c23b38978db68687a8John Reck        for (unsigned i = 0; i < numberOfOutputs; ++i)
532e14391e94c850b8bd03680c23b38978db68687a8John Reck            m_dirtyAudioNodeOutputs.remove(node->output(i));
533e14391e94c850b8bd03680c23b38978db68687a8John Reck
534e14391e94c850b8bd03680c23b38978db68687a8John Reck        // Finally, delete it.
535bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen        delete node;
536a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
537a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // Don't delete too many nodes per render quantum since we don't want to do too much work in the realtime audio thread.
538a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (++nodesDeleted > MaxNodesToDeletePerQuantum)
539a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
540bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen    }
541bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen}
542bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
543e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid AudioContext::markAudioNodeInputDirty(AudioNodeInput* input)
544e14391e94c850b8bd03680c23b38978db68687a8John Reck{
545e14391e94c850b8bd03680c23b38978db68687a8John Reck    ASSERT(isGraphOwner());
546e14391e94c850b8bd03680c23b38978db68687a8John Reck    m_dirtyAudioNodeInputs.add(input);
547e14391e94c850b8bd03680c23b38978db68687a8John Reck}
548e14391e94c850b8bd03680c23b38978db68687a8John Reck
549e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid AudioContext::markAudioNodeOutputDirty(AudioNodeOutput* output)
550e14391e94c850b8bd03680c23b38978db68687a8John Reck{
551e14391e94c850b8bd03680c23b38978db68687a8John Reck    ASSERT(isGraphOwner());
552e14391e94c850b8bd03680c23b38978db68687a8John Reck    m_dirtyAudioNodeOutputs.add(output);
553e14391e94c850b8bd03680c23b38978db68687a8John Reck}
554e14391e94c850b8bd03680c23b38978db68687a8John Reck
555e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid AudioContext::handleDirtyAudioNodeInputs()
556e14391e94c850b8bd03680c23b38978db68687a8John Reck{
557e14391e94c850b8bd03680c23b38978db68687a8John Reck    ASSERT(isGraphOwner());
558e14391e94c850b8bd03680c23b38978db68687a8John Reck
559e14391e94c850b8bd03680c23b38978db68687a8John Reck    for (HashSet<AudioNodeInput*>::iterator i = m_dirtyAudioNodeInputs.begin(); i != m_dirtyAudioNodeInputs.end(); ++i)
560e14391e94c850b8bd03680c23b38978db68687a8John Reck        (*i)->updateRenderingState();
561e14391e94c850b8bd03680c23b38978db68687a8John Reck
562e14391e94c850b8bd03680c23b38978db68687a8John Reck    m_dirtyAudioNodeInputs.clear();
563e14391e94c850b8bd03680c23b38978db68687a8John Reck}
564e14391e94c850b8bd03680c23b38978db68687a8John Reck
565e14391e94c850b8bd03680c23b38978db68687a8John Reckvoid AudioContext::handleDirtyAudioNodeOutputs()
566e14391e94c850b8bd03680c23b38978db68687a8John Reck{
567e14391e94c850b8bd03680c23b38978db68687a8John Reck    ASSERT(isGraphOwner());
568e14391e94c850b8bd03680c23b38978db68687a8John Reck
569e14391e94c850b8bd03680c23b38978db68687a8John Reck    for (HashSet<AudioNodeOutput*>::iterator i = m_dirtyAudioNodeOutputs.begin(); i != m_dirtyAudioNodeOutputs.end(); ++i)
570e14391e94c850b8bd03680c23b38978db68687a8John Reck        (*i)->updateRenderingState();
571e14391e94c850b8bd03680c23b38978db68687a8John Reck
572e14391e94c850b8bd03680c23b38978db68687a8John Reck    m_dirtyAudioNodeOutputs.clear();
573e14391e94c850b8bd03680c23b38978db68687a8John Reck}
574e14391e94c850b8bd03680c23b38978db68687a8John Reck
5752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochScriptExecutionContext* AudioContext::scriptExecutionContext() const
5762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
5772daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return document();
5782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
5792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben MurdochAudioContext* AudioContext::toAudioContext()
5812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
5822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    return this;
5832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
5842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid AudioContext::startRendering()
5862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
5872daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    destination()->startRendering();
5882daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
5892daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid AudioContext::fireCompletionEvent()
5912daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch{
5922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(isMainThread());
5932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!isMainThread())
5942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
5952daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5962daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    AudioBuffer* renderedBuffer = m_renderTarget.get();
5972daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
5982daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    ASSERT(renderedBuffer);
5992daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!renderedBuffer)
6002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
6012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
6022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Avoid firing the event if the document has already gone away.
6032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (hasDocument()) {
6042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        // Call the offline rendering completion event listener.
6052daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        dispatchEvent(OfflineAudioCompletionEvent::create(renderedBuffer));
6062daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    }
6072daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch}
608e14391e94c850b8bd03680c23b38978db68687a8John Reck
609bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen} // namespace WebCore
610bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen
611bec39347bb3bb5bf1187ccaf471d26247f28b585Kristian Monsen#endif // ENABLE(WEB_AUDIO)
612