|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include "mozilla/dom/ChannelMergerNode.h" |
|
8 #include "mozilla/dom/ChannelMergerNodeBinding.h" |
|
9 #include "AudioNodeEngine.h" |
|
10 #include "AudioNodeStream.h" |
|
11 |
|
12 namespace mozilla { |
|
13 namespace dom { |
|
14 |
|
15 NS_IMPL_ISUPPORTS_INHERITED0(ChannelMergerNode, AudioNode) |
|
16 |
|
17 class ChannelMergerNodeEngine : public AudioNodeEngine |
|
18 { |
|
19 public: |
|
20 ChannelMergerNodeEngine(ChannelMergerNode* aNode) |
|
21 : AudioNodeEngine(aNode) |
|
22 { |
|
23 MOZ_ASSERT(NS_IsMainThread()); |
|
24 } |
|
25 |
|
26 virtual void ProcessBlocksOnPorts(AudioNodeStream* aStream, |
|
27 const OutputChunks& aInput, |
|
28 OutputChunks& aOutput, |
|
29 bool* aFinished) MOZ_OVERRIDE |
|
30 { |
|
31 MOZ_ASSERT(aInput.Length() >= 1, "Should have one or more input ports"); |
|
32 |
|
33 // Get the number of output channels, and allocate it |
|
34 uint32_t channelCount = 0; |
|
35 for (uint16_t i = 0; i < InputCount(); ++i) { |
|
36 channelCount += aInput[i].mChannelData.Length(); |
|
37 } |
|
38 if (channelCount == 0) { |
|
39 aOutput[0].SetNull(WEBAUDIO_BLOCK_SIZE); |
|
40 return; |
|
41 } |
|
42 channelCount = std::min(channelCount, WebAudioUtils::MaxChannelCount); |
|
43 AllocateAudioBlock(channelCount, &aOutput[0]); |
|
44 |
|
45 // Append each channel in each input to the output |
|
46 uint32_t channelIndex = 0; |
|
47 for (uint16_t i = 0; true; ++i) { |
|
48 MOZ_ASSERT(i < InputCount()); |
|
49 for (uint32_t j = 0; j < aInput[i].mChannelData.Length(); ++j) { |
|
50 AudioBlockCopyChannelWithScale( |
|
51 static_cast<const float*>(aInput[i].mChannelData[j]), |
|
52 aInput[i].mVolume, |
|
53 static_cast<float*>(const_cast<void*>(aOutput[0].mChannelData[channelIndex]))); |
|
54 ++channelIndex; |
|
55 if (channelIndex >= channelCount) { |
|
56 return; |
|
57 } |
|
58 } |
|
59 } |
|
60 } |
|
61 |
|
62 virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE |
|
63 { |
|
64 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); |
|
65 } |
|
66 }; |
|
67 |
|
68 ChannelMergerNode::ChannelMergerNode(AudioContext* aContext, |
|
69 uint16_t aInputCount) |
|
70 : AudioNode(aContext, |
|
71 2, |
|
72 ChannelCountMode::Max, |
|
73 ChannelInterpretation::Speakers) |
|
74 , mInputCount(aInputCount) |
|
75 { |
|
76 mStream = aContext->Graph()->CreateAudioNodeStream(new ChannelMergerNodeEngine(this), |
|
77 MediaStreamGraph::INTERNAL_STREAM); |
|
78 } |
|
79 |
|
80 JSObject* |
|
81 ChannelMergerNode::WrapObject(JSContext* aCx) |
|
82 { |
|
83 return ChannelMergerNodeBinding::Wrap(aCx, this); |
|
84 } |
|
85 |
|
86 } |
|
87 } |
|
88 |