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