1a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch/* 2a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2010, Google Inc. All rights reserved. 3a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 4a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Redistribution and use in source and binary forms, with or without 5a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * modification, are permitted provided that the following conditions 6a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * are met: 7a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 1. Redistributions of source code must retain the above copyright 8a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * notice, this list of conditions and the following disclaimer. 9a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 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. 12a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 13a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 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 17a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * (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. 23a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch */ 24a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 25a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "config.h" 26a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 27a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#if ENABLE(WEB_AUDIO) 28a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 29a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "AudioBasicProcessorNode.h" 30a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 31a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "AudioBus.h" 3228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu#include "AudioContext.h" 33a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "AudioNodeInput.h" 34a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "AudioNodeOutput.h" 35a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "AudioProcessor.h" 36a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 37a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochnamespace WebCore { 38a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 39a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochAudioBasicProcessorNode::AudioBasicProcessorNode(AudioContext* context, double sampleRate) 40a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch : AudioNode(context, sampleRate) 41a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 42a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch addInput(adoptPtr(new AudioNodeInput(this))); 43a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch addOutput(adoptPtr(new AudioNodeOutput(this, 0))); 44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 45a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // The subclass must create m_processor. 46a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 47a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid AudioBasicProcessorNode::initialize() 49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 50a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (isInitialized()) 51a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return; 52a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 53a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(processor()); 54a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch processor()->initialize(); 55a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 56a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AudioNode::initialize(); 57a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 58a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 59a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid AudioBasicProcessorNode::uninitialize() 60a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 61a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!isInitialized()) 62a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return; 63a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 64a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(processor()); 65a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch processor()->uninitialize(); 66a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AudioNode::uninitialize(); 68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid AudioBasicProcessorNode::process(size_t framesToProcess) 71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AudioBus* destinationBus = output(0)->bus(); 73a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 74a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // The realtime thread can't block on this lock, so we call tryLock() instead. 75a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_processLock.tryLock()) { 76a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!isInitialized() || !processor()) 77a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch destinationBus->zero(); 78a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch else { 79a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AudioBus* sourceBus = input(0)->bus(); 80a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 81a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // FIXME: if we take "tail time" into account, then we can avoid calling processor()->process() once the tail dies down. 82a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!input(0)->isConnected()) 83a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch sourceBus->zero(); 84a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 85a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch processor()->process(sourceBus, destinationBus, framesToProcess); 86a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 87a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 88a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_processLock.unlock(); 89a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } else { 90a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Too bad - the tryLock() failed. We must be in the middle of re-connecting and were already outputting silence anyway... 91a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch destinationBus->zero(); 92a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 93a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 94a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 95a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// Nice optimization in the very common case allowing for "in-place" processing 96a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid AudioBasicProcessorNode::pullInputs(size_t framesToProcess) 97a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 98a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Render input stream - suggest to the input to render directly into output bus for in-place processing in process() if possible. 99a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch input(0)->pull(output(0)->bus(), framesToProcess); 100a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 101a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 102a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid AudioBasicProcessorNode::reset() 103a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 104a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (processor()) 105a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch processor()->reset(); 106a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 107a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 108a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// As soon as we know the channel count of our input, we can lazily initialize. 109a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// Sometimes this may be called more than once with different channel counts, in which case we must safely 110a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// uninitialize and then re-initialize with the new channel count. 111a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid AudioBasicProcessorNode::checkNumberOfChannelsForInput(AudioNodeInput* input) 112a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 11328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu ASSERT(context()->isAudioThread() && context()->isGraphOwner()); 114a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 115a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(input == this->input(0)); 116a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (input != this->input(0)) 117a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return; 118a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 119a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(processor()); 120a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!processor()) 121a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return; 122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 123a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch unsigned numberOfChannels = input->numberOfChannels(); 124a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 125a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (isInitialized() && numberOfChannels != output(0)->numberOfChannels()) { 126a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // We're already initialized but the channel count has changed. 127a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // We need to be careful since we may be actively processing right now, so synchronize with process(). 128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch MutexLocker locker(m_processLock); 129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch uninitialize(); 130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 13228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if (!isInitialized()) { 13328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu // This will propagate the channel count to any nodes connected further down the chain... 13428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu output(0)->setNumberOfChannels(numberOfChannels); 135a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 13628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu // Re-initialize the processor with the new channel count. 13728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu processor()->setNumberOfChannels(numberOfChannels); 13828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu initialize(); 13928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu } 140a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 141a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 142a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochunsigned AudioBasicProcessorNode::numberOfChannels() 143a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 144a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return output(0)->numberOfChannels(); 145a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 146a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 147a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} // namespace WebCore 148a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 149a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif // ENABLE(WEB_AUDIO) 150