• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "config.h"
30 
31 #if ENABLE(WEB_AUDIO)
32 
33 #include "modules/webaudio/ChannelMergerNode.h"
34 
35 #include "modules/webaudio/AudioContext.h"
36 #include "modules/webaudio/AudioNodeInput.h"
37 #include "modules/webaudio/AudioNodeOutput.h"
38 
39 const unsigned DefaultNumberOfOutputChannels = 1;
40 
41 namespace WebCore {
42 
create(AudioContext * context,float sampleRate,unsigned numberOfInputs)43 PassRefPtr<ChannelMergerNode> ChannelMergerNode::create(AudioContext* context, float sampleRate, unsigned numberOfInputs)
44 {
45     if (!numberOfInputs || numberOfInputs > AudioContext::maxNumberOfChannels())
46         return 0;
47 
48     return adoptRef(new ChannelMergerNode(context, sampleRate, numberOfInputs));
49 }
50 
ChannelMergerNode(AudioContext * context,float sampleRate,unsigned numberOfInputs)51 ChannelMergerNode::ChannelMergerNode(AudioContext* context, float sampleRate, unsigned numberOfInputs)
52     : AudioNode(context, sampleRate)
53     , m_desiredNumberOfOutputChannels(DefaultNumberOfOutputChannels)
54 {
55     ScriptWrappable::init(this);
56     // Create the requested number of inputs.
57     for (unsigned i = 0; i < numberOfInputs; ++i)
58         addInput(adoptPtr(new AudioNodeInput(this)));
59 
60     addOutput(adoptPtr(new AudioNodeOutput(this, 1)));
61     setNodeType(NodeTypeChannelMerger);
62     initialize();
63 }
64 
process(size_t framesToProcess)65 void ChannelMergerNode::process(size_t framesToProcess)
66 {
67     AudioNodeOutput* output = this->output(0);
68     ASSERT(output);
69     ASSERT_UNUSED(framesToProcess, framesToProcess == output->bus()->length());
70 
71     // Output bus not updated yet, so just output silence.
72     if (m_desiredNumberOfOutputChannels != output->numberOfChannels()) {
73         output->bus()->zero();
74         return;
75     }
76 
77     // Merge all the channels from all the inputs into one output.
78     unsigned outputChannelIndex = 0;
79     for (unsigned i = 0; i < numberOfInputs(); ++i) {
80         AudioNodeInput* input = this->input(i);
81         if (input->isConnected()) {
82             unsigned numberOfInputChannels = input->bus()->numberOfChannels();
83 
84             // Merge channels from this particular input.
85             for (unsigned j = 0; j < numberOfInputChannels; ++j) {
86                 AudioChannel* inputChannel = input->bus()->channel(j);
87                 AudioChannel* outputChannel = output->bus()->channel(outputChannelIndex);
88                 outputChannel->copyFrom(inputChannel);
89 
90                 ++outputChannelIndex;
91             }
92         }
93     }
94 
95     ASSERT(outputChannelIndex == output->numberOfChannels());
96 }
97 
reset()98 void ChannelMergerNode::reset()
99 {
100 }
101 
102 // Any time a connection or disconnection happens on any of our inputs, we potentially need to change the
103 // number of channels of our output.
checkNumberOfChannelsForInput(AudioNodeInput * input)104 void ChannelMergerNode::checkNumberOfChannelsForInput(AudioNodeInput* input)
105 {
106     ASSERT(context()->isAudioThread() && context()->isGraphOwner());
107 
108     // Count how many channels we have all together from all of the inputs.
109     unsigned numberOfOutputChannels = 0;
110     for (unsigned i = 0; i < numberOfInputs(); ++i) {
111         AudioNodeInput* input = this->input(i);
112         if (input->isConnected())
113             numberOfOutputChannels += input->numberOfChannels();
114     }
115 
116     // Set the correct number of channels on the output
117     AudioNodeOutput* output = this->output(0);
118     ASSERT(output);
119     output->setNumberOfChannels(numberOfOutputChannels);
120     // There can in rare cases be a slight delay before the output bus is updated to the new number of
121     // channels because of tryLocks() in the context's updating system. So record the new number of
122     // output channels here.
123     m_desiredNumberOfOutputChannels = numberOfOutputChannels;
124 
125     AudioNode::checkNumberOfChannelsForInput(input);
126 }
127 
128 } // namespace WebCore
129 
130 #endif // ENABLE(WEB_AUDIO)
131