ChannelSplitterNode.cpp (3860B)
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/ChannelSplitterNode.h" 8 9 #include "AudioNodeEngine.h" 10 #include "AudioNodeTrack.h" 11 #include "Tracing.h" 12 #include "mozilla/dom/ChannelSplitterNodeBinding.h" 13 14 namespace mozilla::dom { 15 16 class ChannelSplitterNodeEngine final : public AudioNodeEngine { 17 public: 18 explicit ChannelSplitterNodeEngine(ChannelSplitterNode* aNode) 19 : AudioNodeEngine(aNode) { 20 MOZ_ASSERT(NS_IsMainThread()); 21 } 22 23 void ProcessBlocksOnPorts(AudioNodeTrack* aTrack, GraphTime aFrom, 24 Span<const AudioBlock> aInput, 25 Span<AudioBlock> aOutput, 26 bool* aFinished) override { 27 MOZ_ASSERT(aInput.Length() == 1, "Should only have one input port"); 28 MOZ_ASSERT(aOutput.Length() == OutputCount()); 29 TRACE("ChannelSplitterNodeEngine::ProcessBlocksOnPorts"); 30 31 for (uint16_t i = 0; i < OutputCount(); ++i) { 32 if (i < aInput[0].ChannelCount()) { 33 // Split out existing channels 34 aOutput[i].AllocateChannels(1); 35 AudioBlockCopyChannelWithScale( 36 static_cast<const float*>(aInput[0].mChannelData[i]), 37 aInput[0].mVolume, aOutput[i].ChannelFloatsForWrite(0)); 38 } else { 39 // Pad with silent channels if needed 40 aOutput[i].SetNull(WEBAUDIO_BLOCK_SIZE); 41 } 42 } 43 } 44 45 size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override { 46 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); 47 } 48 }; 49 50 ChannelSplitterNode::ChannelSplitterNode(AudioContext* aContext, 51 uint16_t aOutputCount) 52 : AudioNode(aContext, aOutputCount, ChannelCountMode::Explicit, 53 ChannelInterpretation::Discrete), 54 mOutputCount(aOutputCount) { 55 mTrack = 56 AudioNodeTrack::Create(aContext, new ChannelSplitterNodeEngine(this), 57 AudioNodeTrack::NO_TRACK_FLAGS, aContext->Graph()); 58 } 59 60 /* static */ 61 already_AddRefed<ChannelSplitterNode> ChannelSplitterNode::Create( 62 AudioContext& aAudioContext, const ChannelSplitterOptions& aOptions, 63 ErrorResult& aRv) { 64 if (aOptions.mNumberOfOutputs == 0 || 65 aOptions.mNumberOfOutputs > WebAudioUtils::MaxChannelCount) { 66 aRv.ThrowIndexSizeError(nsPrintfCString( 67 "%u is not a valid number of outputs", aOptions.mNumberOfOutputs)); 68 return nullptr; 69 } 70 71 RefPtr<ChannelSplitterNode> audioNode = 72 new ChannelSplitterNode(&aAudioContext, aOptions.mNumberOfOutputs); 73 74 // Manually check that the other options are valid, this node has 75 // channelCount, channelCountMode and channelInterpretation constraints: they 76 // cannot be changed from the default. 77 if (aOptions.mChannelCount.WasPassed()) { 78 audioNode->SetChannelCount(aOptions.mChannelCount.Value(), aRv); 79 if (aRv.Failed()) { 80 return nullptr; 81 } 82 } 83 if (aOptions.mChannelInterpretation.WasPassed()) { 84 audioNode->SetChannelInterpretationValue( 85 aOptions.mChannelInterpretation.Value(), aRv); 86 if (aRv.Failed()) { 87 return nullptr; 88 } 89 } 90 if (aOptions.mChannelCountMode.WasPassed()) { 91 audioNode->SetChannelCountModeValue(aOptions.mChannelCountMode.Value(), 92 aRv); 93 if (aRv.Failed()) { 94 return nullptr; 95 } 96 } 97 98 return audioNode.forget(); 99 } 100 101 JSObject* ChannelSplitterNode::WrapObject(JSContext* aCx, 102 JS::Handle<JSObject*> aGivenProto) { 103 return ChannelSplitterNode_Binding::Wrap(aCx, this, aGivenProto); 104 } 105 106 } // namespace mozilla::dom