Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / modules / webaudio / ChannelMergerNode.cpp
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 blink {
42
43 ChannelMergerNode* ChannelMergerNode::create(AudioContext* context, float sampleRate, unsigned numberOfInputs)
44 {
45     if (!numberOfInputs || numberOfInputs > AudioContext::maxNumberOfChannels())
46         return 0;
47
48     return adoptRefCountedGarbageCollectedWillBeNoop(new ChannelMergerNode(context, sampleRate, numberOfInputs));
49 }
50
51 ChannelMergerNode::ChannelMergerNode(AudioContext* context, float sampleRate, unsigned numberOfInputs)
52     : AudioNode(context, sampleRate)
53     , m_desiredNumberOfOutputChannels(DefaultNumberOfOutputChannels)
54 {
55     // Create the requested number of inputs.
56     for (unsigned i = 0; i < numberOfInputs; ++i)
57         addInput();
58
59     addOutput(AudioNodeOutput::create(this, 1));
60     setNodeType(NodeTypeChannelMerger);
61     initialize();
62 }
63
64 void ChannelMergerNode::process(size_t framesToProcess)
65 {
66     AudioNodeOutput* output = this->output(0);
67     ASSERT(output);
68     ASSERT_UNUSED(framesToProcess, framesToProcess == output->bus()->length());
69
70     // Output bus not updated yet, so just output silence.
71     if (m_desiredNumberOfOutputChannels != output->numberOfChannels()) {
72         output->bus()->zero();
73         return;
74     }
75
76     // Merge all the channels from all the inputs into one output.
77     unsigned outputChannelIndex = 0;
78     unsigned maxAllowedOutputChannels = output->numberOfChannels();
79
80     for (unsigned i = 0; i < numberOfInputs(); ++i) {
81         AudioNodeInput* input = this->input(i);
82         if (input->isConnected()) {
83             unsigned numberOfInputChannels = input->bus()->numberOfChannels();
84
85             // Merge channels from this particular input, but be careful not to exceed the number of
86             // output channels.  (This can happen if there are many inputs with each input
87             // containing many channels.)
88             for (unsigned j = 0; j < numberOfInputChannels; ++j) {
89                 if (outputChannelIndex < maxAllowedOutputChannels) {
90                     AudioChannel* inputChannel = input->bus()->channel(j);
91                     AudioChannel* outputChannel = output->bus()->channel(outputChannelIndex);
92                     outputChannel->copyFrom(inputChannel);
93
94                     ++outputChannelIndex;
95                 }
96             }
97         }
98         if (outputChannelIndex >= maxAllowedOutputChannels)
99             break;
100     }
101
102     ASSERT(outputChannelIndex == output->numberOfChannels());
103 }
104
105 // Any time a connection or disconnection happens on any of our inputs, we potentially need to change the
106 // number of channels of our output.
107 void ChannelMergerNode::checkNumberOfChannelsForInput(AudioNodeInput* input)
108 {
109     ASSERT(context()->isAudioThread() && context()->isGraphOwner());
110
111     // Count how many channels we have all together from all of the inputs.
112     unsigned numberOfOutputChannels = 0;
113     for (unsigned i = 0; i < numberOfInputs(); ++i) {
114         AudioNodeInput* input = this->input(i);
115         if (input->isConnected())
116             numberOfOutputChannels += input->numberOfChannels();
117     }
118
119     // If the actual number of channels exceeds the max allowed, just drop the excess.
120     numberOfOutputChannels = std::min(numberOfOutputChannels, AudioContext::maxNumberOfChannels());
121
122     // Set the correct number of channels on the output
123     AudioNodeOutput* output = this->output(0);
124     ASSERT(output);
125     output->setNumberOfChannels(numberOfOutputChannels);
126     // There can in rare cases be a slight delay before the output bus is updated to the new number of
127     // channels because of tryLocks() in the context's updating system. So record the new number of
128     // output channels here.
129     m_desiredNumberOfOutputChannels = numberOfOutputChannels;
130
131     AudioNode::checkNumberOfChannelsForInput(input);
132 }
133
134 } // namespace blink
135
136 #endif // ENABLE(WEB_AUDIO)