1 /* 2 * Copyright (C) 2010, Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include "config.h" 26 27 #if ENABLE(WEB_AUDIO) 28 29 #include "modules/webaudio/GainNode.h" 30 31 #include "core/platform/audio/AudioBus.h" 32 #include "modules/webaudio/AudioNodeInput.h" 33 #include "modules/webaudio/AudioNodeOutput.h" 34 35 namespace WebCore { 36 37 GainNode::GainNode(AudioContext* context, float sampleRate) 38 : AudioNode(context, sampleRate) 39 , m_lastGain(1.0) 40 , m_sampleAccurateGainValues(AudioNode::ProcessingSizeInFrames) // FIXME: can probably share temp buffer in context 41 { 42 ScriptWrappable::init(this); 43 m_gain = AudioParam::create(context, "gain", 1.0, 0.0, 1.0); 44 45 addInput(adoptPtr(new AudioNodeInput(this))); 46 addOutput(adoptPtr(new AudioNodeOutput(this, 1))); 47 48 setNodeType(NodeTypeGain); 49 50 initialize(); 51 } 52 53 void GainNode::process(size_t framesToProcess) 54 { 55 // FIXME: for some cases there is a nice optimization to avoid processing here, and let the gain change 56 // happen in the summing junction input of the AudioNode we're connected to. 57 // Then we can avoid all of the following: 58 59 AudioBus* outputBus = output(0)->bus(); 60 ASSERT(outputBus); 61 62 if (!isInitialized() || !input(0)->isConnected()) 63 outputBus->zero(); 64 else { 65 AudioBus* inputBus = input(0)->bus(); 66 67 if (gain()->hasSampleAccurateValues()) { 68 // Apply sample-accurate gain scaling for precise envelopes, grain windows, etc. 69 ASSERT(framesToProcess <= m_sampleAccurateGainValues.size()); 70 if (framesToProcess <= m_sampleAccurateGainValues.size()) { 71 float* gainValues = m_sampleAccurateGainValues.data(); 72 gain()->calculateSampleAccurateValues(gainValues, framesToProcess); 73 outputBus->copyWithSampleAccurateGainValuesFrom(*inputBus, gainValues, framesToProcess); 74 } 75 } else { 76 // Apply the gain with de-zippering into the output bus. 77 outputBus->copyWithGainFrom(*inputBus, &m_lastGain, gain()->value()); 78 } 79 } 80 } 81 82 void GainNode::reset() 83 { 84 // Snap directly to desired gain. 85 m_lastGain = gain()->value(); 86 } 87 88 // FIXME: this can go away when we do mixing with gain directly in summing junction of AudioNodeInput 89 // 90 // As soon as we know the channel count of our input, we can lazily initialize. 91 // Sometimes this may be called more than once with different channel counts, in which case we must safely 92 // uninitialize and then re-initialize with the new channel count. 93 void GainNode::checkNumberOfChannelsForInput(AudioNodeInput* input) 94 { 95 ASSERT(context()->isAudioThread() && context()->isGraphOwner()); 96 97 ASSERT(input && input == this->input(0)); 98 if (input != this->input(0)) 99 return; 100 101 unsigned numberOfChannels = input->numberOfChannels(); 102 103 if (isInitialized() && numberOfChannels != output(0)->numberOfChannels()) { 104 // We're already initialized but the channel count has changed. 105 uninitialize(); 106 } 107 108 if (!isInitialized()) { 109 // This will propagate the channel count to any nodes connected further downstream in the graph. 110 output(0)->setNumberOfChannels(numberOfChannels); 111 initialize(); 112 } 113 114 AudioNode::checkNumberOfChannelsForInput(input); 115 } 116 117 } // namespace WebCore 118 119 #endif // ENABLE(WEB_AUDIO) 120