1a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch/* 228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * 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 828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * notice, this list of conditions and the following disclaimer. 9a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright 1028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * notice, this list of conditions and the following disclaimer in the 1128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * documentation and/or other materials provided with the distribution. 12a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 1328040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * 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 1628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * 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; 1928040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 2028040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2128040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 2228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu * 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 "AudioGainNode.h" 30a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 31a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "AudioBus.h" 32a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "AudioNodeInput.h" 33a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "AudioNodeOutput.h" 34a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 35a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochnamespace WebCore { 36a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 37a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochAudioGainNode::AudioGainNode(AudioContext* context, double sampleRate) 38a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch : AudioNode(context, sampleRate) 39a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch , m_lastGain(1.0) 40a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 41a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_gain = AudioGain::create("gain", 1.0, 0.0, 1.0); 42a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 43a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch addInput(adoptPtr(new AudioNodeInput(this))); 44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch addOutput(adoptPtr(new AudioNodeOutput(this, 1))); 45a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 46a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch setType(NodeTypeGain); 47a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch initialize(); 49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 50a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 51a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid AudioGainNode::process(size_t /*framesToProcess*/) 52a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 53a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // FIXME: there is a nice optimization to avoid processing here, and let the gain change 54a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // happen in the summing junction input of the AudioNode we're connected to. 55a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Then we can avoid all of the following: 56a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 57a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AudioBus* outputBus = output(0)->bus(); 58a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(outputBus); 59a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 60a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // The realtime thread can't block on this lock, so we call tryLock() instead. 61a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (m_processLock.tryLock()) { 62a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!isInitialized() || !input(0)->isConnected()) 63a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch outputBus->zero(); 64a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch else { 65a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch AudioBus* inputBus = input(0)->bus(); 66a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Apply the gain with de-zippering into the output bus. 68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch outputBus->copyWithGainFrom(*inputBus, &m_lastGain, gain()->value()); 69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_processLock.unlock(); 72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } else { 73a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Too bad - the tryLock() failed. We must be in the middle of re-connecting and were already outputting silence anyway... 74a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch outputBus->zero(); 75a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 76a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 77a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 78a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid AudioGainNode::reset() 79a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 80a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Snap directly to desired gain. 81a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch m_lastGain = gain()->value(); 82a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 83a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 84a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// FIXME: this can go away when we do mixing with gain directly in summing junction of AudioNodeInput 85a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// 86a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// As soon as we know the channel count of our input, we can lazily initialize. 87a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// Sometimes this may be called more than once with different channel counts, in which case we must safely 88a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch// uninitialize and then re-initialize with the new channel count. 89a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid AudioGainNode::checkNumberOfChannelsForInput(AudioNodeInput* input) 90a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 91a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(input && input == this->input(0)); 92a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (input != this->input(0)) 93a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return; 94a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 95a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch unsigned numberOfChannels = input->numberOfChannels(); 96a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 97a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (isInitialized() && numberOfChannels != output(0)->numberOfChannels()) { 98a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // We're already initialized but the channel count has changed. 99a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // We need to be careful since we may be actively processing right now, so synchronize with process(). 100a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch MutexLocker locker(m_processLock); 101a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch uninitialize(); 102a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 103a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 10428040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu if (!isInitialized()) { 10528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu // This will propagate the channel count to any nodes connected further downstream in the graph. 10628040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu output(0)->setNumberOfChannels(numberOfChannels); 10728040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu initialize(); 10828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu } 109a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 110a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 111a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} // namespace WebCore 112a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 113a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif // ENABLE(WEB_AUDIO) 114