LCOV - code coverage report
Current view: top level - dom/media/webaudio - StereoPannerNode.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 98 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "StereoPannerNode.h"
       8             : #include "mozilla/dom/StereoPannerNodeBinding.h"
       9             : #include "AudioNodeEngine.h"
      10             : #include "AudioNodeStream.h"
      11             : #include "AudioDestinationNode.h"
      12             : #include "AlignmentUtils.h"
      13             : #include "WebAudioUtils.h"
      14             : #include "PanningUtils.h"
      15             : #include "AudioParamTimeline.h"
      16             : #include "AudioParam.h"
      17             : 
      18             : namespace mozilla {
      19             : namespace dom {
      20             : 
      21             : using namespace std;
      22             : 
      23           0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(StereoPannerNode, AudioNode, mPan)
      24             : 
      25           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(StereoPannerNode)
      26           0 : NS_INTERFACE_MAP_END_INHERITING(AudioNode)
      27             : 
      28           0 : NS_IMPL_ADDREF_INHERITED(StereoPannerNode, AudioNode)
      29           0 : NS_IMPL_RELEASE_INHERITED(StereoPannerNode, AudioNode)
      30             : 
      31           0 : class StereoPannerNodeEngine final : public AudioNodeEngine
      32             : {
      33             : public:
      34           0 :   StereoPannerNodeEngine(AudioNode* aNode,
      35             :                          AudioDestinationNode* aDestination)
      36           0 :     : AudioNodeEngine(aNode)
      37           0 :     , mDestination(aDestination->Stream())
      38             :     // Keep the default value in sync with the default value in
      39             :     // StereoPannerNode::StereoPannerNode.
      40           0 :     , mPan(0.f)
      41             :   {
      42           0 :   }
      43             : 
      44             :   enum Parameters {
      45             :     PAN
      46             :   };
      47           0 :   void RecvTimelineEvent(uint32_t aIndex,
      48             :                          AudioTimelineEvent& aEvent) override
      49             :   {
      50           0 :     MOZ_ASSERT(mDestination);
      51           0 :     WebAudioUtils::ConvertAudioTimelineEventToTicks(aEvent,
      52           0 :                                                     mDestination);
      53             : 
      54           0 :     switch (aIndex) {
      55             :     case PAN:
      56           0 :       mPan.InsertEvent<int64_t>(aEvent);
      57           0 :       break;
      58             :     default:
      59           0 :       NS_ERROR("Bad StereoPannerNode TimelineParameter");
      60             :     }
      61           0 :   }
      62             : 
      63           0 :   void GetGainValuesForPanning(float aPanning,
      64             :                                bool aMonoToStereo,
      65             :                                float& aLeftGain,
      66             :                                float& aRightGain)
      67             :   {
      68             :     // Clamp and normalize the panning in [0; 1]
      69           0 :     aPanning = std::min(std::max(aPanning, -1.f), 1.f);
      70             : 
      71           0 :     if (aMonoToStereo) {
      72           0 :       aPanning += 1;
      73           0 :       aPanning /= 2;
      74           0 :     } else if (aPanning <= 0) {
      75           0 :       aPanning += 1;
      76             :     }
      77             : 
      78           0 :     aLeftGain  = cos(0.5 * M_PI * aPanning);
      79           0 :     aRightGain = sin(0.5 * M_PI * aPanning);
      80           0 :   }
      81             : 
      82           0 :   void SetToSilentStereoBlock(AudioBlock* aChunk)
      83             :   {
      84           0 :     for (uint32_t channel = 0; channel < 2; channel++) {
      85           0 :       float* samples = aChunk->ChannelFloatsForWrite(channel);
      86           0 :       for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; i++) {
      87           0 :         samples[i] = 0.f;
      88             :       }
      89             :     }
      90           0 :   }
      91             : 
      92           0 :   void UpmixToStereoIfNeeded(const AudioBlock& aInput, AudioBlock* aOutput)
      93             :   {
      94           0 :     if (aInput.ChannelCount() == 2) {
      95           0 :       const float* inputL = static_cast<const float*>(aInput.mChannelData[0]);
      96           0 :       const float* inputR = static_cast<const float*>(aInput.mChannelData[1]);
      97           0 :       float* outputL = aOutput->ChannelFloatsForWrite(0);
      98           0 :       float* outputR = aOutput->ChannelFloatsForWrite(1);
      99             : 
     100           0 :       AudioBlockCopyChannelWithScale(inputL, aInput.mVolume, outputL);
     101           0 :       AudioBlockCopyChannelWithScale(inputR, aInput.mVolume, outputR);
     102             :     } else {
     103           0 :       MOZ_ASSERT(aInput.ChannelCount() == 1);
     104           0 :       GainMonoToStereo(aInput, aOutput, aInput.mVolume, aInput.mVolume);
     105             :     }
     106           0 :   }
     107             : 
     108           0 :   virtual void ProcessBlock(AudioNodeStream* aStream,
     109             :                             GraphTime aFrom,
     110             :                             const AudioBlock& aInput,
     111             :                             AudioBlock* aOutput,
     112             :                             bool *aFinished) override
     113             :   {
     114             :     // The output of this node is always stereo, no matter what the inputs are.
     115           0 :     MOZ_ASSERT(aInput.ChannelCount() <= 2);
     116           0 :     aOutput->AllocateChannels(2);
     117           0 :     bool monoToStereo = aInput.ChannelCount() == 1;
     118             : 
     119           0 :     if (aInput.IsNull()) {
     120             :       // If input is silent, so is the output
     121           0 :       SetToSilentStereoBlock(aOutput);
     122           0 :     } else if (mPan.HasSimpleValue()) {
     123           0 :       float panning = mPan.GetValue();
     124             :       // If the panning is 0.0, we can simply copy the input to the
     125             :       // output with gain applied, up-mixing to stereo if needed.
     126           0 :       if (panning == 0.0f) {
     127           0 :         UpmixToStereoIfNeeded(aInput, aOutput);
     128             :       } else {
     129             :         // Optimize the case where the panning is constant for this processing
     130             :         // block: we can just apply a constant gain on the left and right
     131             :         // channel
     132             :         float gainL, gainR;
     133             : 
     134           0 :         GetGainValuesForPanning(panning, monoToStereo, gainL, gainR);
     135           0 :         ApplyStereoPanning(aInput, aOutput,
     136           0 :                            gainL * aInput.mVolume,
     137           0 :                            gainR * aInput.mVolume,
     138           0 :                            panning <= 0);
     139             :       }
     140             :     } else {
     141             :       float computedGain[2*WEBAUDIO_BLOCK_SIZE + 4];
     142             :       bool onLeft[WEBAUDIO_BLOCK_SIZE];
     143             : 
     144             :       float values[WEBAUDIO_BLOCK_SIZE];
     145           0 :       StreamTime tick = mDestination->GraphTimeToStreamTime(aFrom);
     146           0 :       mPan.GetValuesAtTime(tick, values, WEBAUDIO_BLOCK_SIZE);
     147             : 
     148           0 :       float* alignedComputedGain = ALIGNED16(computedGain);
     149           0 :       ASSERT_ALIGNED16(alignedComputedGain);
     150           0 :       for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
     151             :         float left, right;
     152           0 :         GetGainValuesForPanning(values[counter], monoToStereo, left, right);
     153             : 
     154           0 :         alignedComputedGain[counter] = left * aInput.mVolume;
     155           0 :         alignedComputedGain[WEBAUDIO_BLOCK_SIZE + counter] = right * aInput.mVolume;
     156           0 :         onLeft[counter] = values[counter] <= 0;
     157             :       }
     158             : 
     159             :       // Apply the gain to the output buffer
     160           0 :       ApplyStereoPanning(aInput, aOutput, alignedComputedGain, &alignedComputedGain[WEBAUDIO_BLOCK_SIZE], onLeft);
     161             :     }
     162           0 :   }
     163             : 
     164           0 :   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override
     165             :   {
     166           0 :     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
     167             :   }
     168             : 
     169             :   AudioNodeStream* mDestination;
     170             :   AudioParamTimeline mPan;
     171             : };
     172             : 
     173           0 : StereoPannerNode::StereoPannerNode(AudioContext* aContext)
     174             :   : AudioNode(aContext,
     175             :               2,
     176             :               ChannelCountMode::Clamped_max,
     177             :               ChannelInterpretation::Speakers)
     178           0 :   , mPan(new AudioParam(this, StereoPannerNodeEngine::PAN, "pan", 0.f, -1.f, 1.f))
     179             : {
     180           0 :   StereoPannerNodeEngine* engine = new StereoPannerNodeEngine(this, aContext->Destination());
     181           0 :   mStream = AudioNodeStream::Create(aContext, engine,
     182             :                                     AudioNodeStream::NO_STREAM_FLAGS,
     183           0 :                                     aContext->Graph());
     184           0 : }
     185             : 
     186             : /* static */ already_AddRefed<StereoPannerNode>
     187           0 : StereoPannerNode::Create(AudioContext& aAudioContext,
     188             :                          const StereoPannerOptions& aOptions,
     189             :                          ErrorResult& aRv)
     190             : {
     191           0 :   if (aAudioContext.CheckClosed(aRv)) {
     192           0 :     return nullptr;
     193             :   }
     194             : 
     195           0 :   RefPtr<StereoPannerNode> audioNode = new StereoPannerNode(&aAudioContext);
     196             : 
     197           0 :   audioNode->Initialize(aOptions, aRv);
     198           0 :   if (NS_WARN_IF(aRv.Failed())) {
     199           0 :     return nullptr;
     200             :   }
     201             : 
     202           0 :   audioNode->Pan()->SetValue(aOptions.mPan);
     203           0 :   return audioNode.forget();
     204             : }
     205             : 
     206             : size_t
     207           0 : StereoPannerNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
     208             : {
     209           0 :   size_t amount = AudioNode::SizeOfExcludingThis(aMallocSizeOf);
     210           0 :   amount += mPan->SizeOfIncludingThis(aMallocSizeOf);
     211           0 :   return amount;
     212             : }
     213             : 
     214             : size_t
     215           0 : StereoPannerNode::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
     216             : {
     217           0 :   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
     218             : }
     219             : 
     220             : JSObject*
     221           0 : StereoPannerNode::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     222             : {
     223           0 :   return StereoPannerNodeBinding::Wrap(aCx, this, aGivenProto);
     224             : }
     225             : 
     226             : } // namespace dom
     227             : } // namespace mozilla

Generated by: LCOV version 1.13