tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ChannelMergerNode.cpp (3467B)


      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 
      9 #include "AudioNodeEngine.h"
     10 #include "AudioNodeTrack.h"
     11 #include "Tracing.h"
     12 #include "mozilla/dom/ChannelMergerNodeBinding.h"
     13 #include "nsPrintfCString.h"
     14 
     15 namespace mozilla::dom {
     16 
     17 class ChannelMergerNodeEngine final : public AudioNodeEngine {
     18 public:
     19  explicit ChannelMergerNodeEngine(ChannelMergerNode* aNode)
     20      : AudioNodeEngine(aNode) {
     21    MOZ_ASSERT(NS_IsMainThread());
     22  }
     23 
     24  void ProcessBlocksOnPorts(AudioNodeTrack* aTrack, GraphTime aFrom,
     25                            Span<const AudioBlock> aInput,
     26                            Span<AudioBlock> aOutput,
     27                            bool* aFinished) override {
     28    MOZ_ASSERT(aInput.Length() == InputCount());
     29    MOZ_ASSERT(aOutput.Length() == 1, "Should have only one output port");
     30    TRACE("ChannelMergerNodeEngine::ProcessBlocksOnPorts");
     31 
     32    // Get the number of output channels, and allocate it
     33    size_t channelCount = InputCount();
     34    bool allNull = true;
     35    for (size_t i = 0; i < channelCount; ++i) {
     36      allNull &= aInput[i].IsNull();
     37    }
     38    if (allNull) {
     39      aOutput[0].SetNull(WEBAUDIO_BLOCK_SIZE);
     40      return;
     41    }
     42 
     43    aOutput[0].AllocateChannels(channelCount);
     44 
     45    for (size_t i = 0; i < channelCount; ++i) {
     46      float* output = aOutput[0].ChannelFloatsForWrite(i);
     47      if (aInput[i].IsNull()) {
     48        PodZero(output, WEBAUDIO_BLOCK_SIZE);
     49      } else {
     50        AudioBlockCopyChannelWithScale(
     51            static_cast<const float*>(aInput[i].mChannelData[0]),
     52            aInput[i].mVolume, output);
     53      }
     54    }
     55  }
     56 
     57  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override {
     58    return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
     59  }
     60 };
     61 
     62 ChannelMergerNode::ChannelMergerNode(AudioContext* aContext,
     63                                     uint16_t aInputCount)
     64    : AudioNode(aContext, 1, ChannelCountMode::Explicit,
     65                ChannelInterpretation::Speakers),
     66      mInputCount(aInputCount) {
     67  mTrack =
     68      AudioNodeTrack::Create(aContext, new ChannelMergerNodeEngine(this),
     69                             AudioNodeTrack::NO_TRACK_FLAGS, aContext->Graph());
     70 }
     71 
     72 /* static */
     73 already_AddRefed<ChannelMergerNode> ChannelMergerNode::Create(
     74    AudioContext& aAudioContext, const ChannelMergerOptions& aOptions,
     75    ErrorResult& aRv) {
     76  if (aOptions.mNumberOfInputs == 0 ||
     77      aOptions.mNumberOfInputs > WebAudioUtils::MaxChannelCount) {
     78    aRv.ThrowIndexSizeError(
     79        nsPrintfCString("Number of inputs (%u) must be in the range [1, number "
     80                        "of supported channels]",
     81                        aOptions.mNumberOfInputs));
     82    return nullptr;
     83  }
     84 
     85  RefPtr<ChannelMergerNode> audioNode =
     86      new ChannelMergerNode(&aAudioContext, aOptions.mNumberOfInputs);
     87 
     88  audioNode->Initialize(aOptions, aRv);
     89  if (NS_WARN_IF(aRv.Failed())) {
     90    return nullptr;
     91  }
     92 
     93  return audioNode.forget();
     94 }
     95 
     96 JSObject* ChannelMergerNode::WrapObject(JSContext* aCx,
     97                                        JS::Handle<JSObject*> aGivenProto) {
     98  return ChannelMergerNode_Binding::Wrap(aCx, this, aGivenProto);
     99 }
    100 
    101 }  // namespace mozilla::dom