15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010, Google Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if ENABLE(WEB_AUDIO) 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webaudio/GainNode.h" 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 311e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/audio/AudioBus.h" 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webaudio/AudioNodeInput.h" 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webaudio/AudioNodeOutput.h" 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)GainNode::GainNode(AudioContext* context, float sampleRate) 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : AudioNode(context, sampleRate) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_lastGain(1.0) 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_sampleAccurateGainValues(AudioNode::ProcessingSizeInFrames) // FIXME: can probably share temp buffer in context 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) ScriptWrappable::init(this); 43926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) m_gain = AudioParam::create(context, "gain", 1.0, 0.0, 1.0); 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) addInput(adoptPtr(new AudioNodeInput(this))); 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) addOutput(adoptPtr(new AudioNodeOutput(this, 1))); 47926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setNodeType(NodeTypeGain); 49926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) initialize(); 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void GainNode::process(size_t framesToProcess) 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: for some cases there is a nice optimization to avoid processing here, and let the gain change 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // happen in the summing junction input of the AudioNode we're connected to. 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Then we can avoid all of the following: 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AudioBus* outputBus = output(0)->bus(); 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(outputBus); 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isInitialized() || !input(0)->isConnected()) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outputBus->zero(); 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else { 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AudioBus* inputBus = input(0)->bus(); 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (gain()->hasSampleAccurateValues()) { 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Apply sample-accurate gain scaling for precise envelopes, grain windows, etc. 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(framesToProcess <= m_sampleAccurateGainValues.size()); 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (framesToProcess <= m_sampleAccurateGainValues.size()) { 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float* gainValues = m_sampleAccurateGainValues.data(); 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gain()->calculateSampleAccurateValues(gainValues, framesToProcess); 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outputBus->copyWithSampleAccurateGainValuesFrom(*inputBus, gainValues, framesToProcess); 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Apply the gain with de-zippering into the output bus. 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) outputBus->copyWithGainFrom(*inputBus, &m_lastGain, gain()->value()); 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void GainNode::reset() 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Snap directly to desired gain. 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_lastGain = gain()->value(); 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: this can go away when we do mixing with gain directly in summing junction of AudioNodeInput 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// As soon as we know the channel count of our input, we can lazily initialize. 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Sometimes this may be called more than once with different channel counts, in which case we must safely 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// uninitialize and then re-initialize with the new channel count. 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void GainNode::checkNumberOfChannelsForInput(AudioNodeInput* input) 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(context()->isAudioThread() && context()->isGraphOwner()); 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(input && input == this->input(0)); 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (input != this->input(0)) 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 10002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch 10102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch unsigned numberOfChannels = input->numberOfChannels(); 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (isInitialized() && numberOfChannels != output(0)->numberOfChannels()) { 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We're already initialized but the channel count has changed. 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) uninitialize(); 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!isInitialized()) { 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This will propagate the channel count to any nodes connected further downstream in the graph. 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) output(0)->setNumberOfChannels(numberOfChannels); 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) initialize(); 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AudioNode::checkNumberOfChannelsForInput(input); 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // ENABLE(WEB_AUDIO) 120