content/media/webaudio/GainNode.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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/. */
     7 #include "GainNode.h"
     8 #include "mozilla/dom/GainNodeBinding.h"
     9 #include "AudioNodeEngine.h"
    10 #include "AudioNodeStream.h"
    11 #include "AudioDestinationNode.h"
    12 #include "WebAudioUtils.h"
    14 namespace mozilla {
    15 namespace dom {
    17 NS_IMPL_CYCLE_COLLECTION_INHERITED(GainNode, AudioNode,
    18                                    mGain)
    20 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(GainNode)
    21 NS_INTERFACE_MAP_END_INHERITING(AudioNode)
    23 NS_IMPL_ADDREF_INHERITED(GainNode, AudioNode)
    24 NS_IMPL_RELEASE_INHERITED(GainNode, AudioNode)
    26 class GainNodeEngine : public AudioNodeEngine
    27 {
    28 public:
    29   GainNodeEngine(AudioNode* aNode, AudioDestinationNode* aDestination)
    30     : AudioNodeEngine(aNode)
    31     , mSource(nullptr)
    32     , mDestination(static_cast<AudioNodeStream*> (aDestination->Stream()))
    33     // Keep the default value in sync with the default value in GainNode::GainNode.
    34     , mGain(1.f)
    35   {
    36   }
    38   void SetSourceStream(AudioNodeStream* aSource)
    39   {
    40     mSource = aSource;
    41   }
    43   enum Parameters {
    44     GAIN
    45   };
    46   void SetTimelineParameter(uint32_t aIndex,
    47                             const AudioParamTimeline& aValue,
    48                             TrackRate aSampleRate) MOZ_OVERRIDE
    49   {
    50     switch (aIndex) {
    51     case GAIN:
    52       MOZ_ASSERT(mSource && mDestination);
    53       mGain = aValue;
    54       WebAudioUtils::ConvertAudioParamToTicks(mGain, mSource, mDestination);
    55       break;
    56     default:
    57       NS_ERROR("Bad GainNodeEngine TimelineParameter");
    58     }
    59   }
    61   virtual void ProcessBlock(AudioNodeStream* aStream,
    62                             const AudioChunk& aInput,
    63                             AudioChunk* aOutput,
    64                             bool* aFinished)
    65   {
    66     MOZ_ASSERT(mSource == aStream, "Invalid source stream");
    68     if (aInput.IsNull()) {
    69       // If input is silent, so is the output
    70       aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
    71     } else if (mGain.HasSimpleValue()) {
    72       // Optimize the case where we only have a single value set as the volume
    73       float gain = mGain.GetValue();
    74       if (gain == 0.0f) {
    75         aOutput->SetNull(WEBAUDIO_BLOCK_SIZE);
    76       } else {
    77         *aOutput = aInput;
    78         aOutput->mVolume *= gain;
    79       }
    80     } else {
    81       // First, compute a vector of gains for each track tick based on the
    82       // timeline at hand, and then for each channel, multiply the values
    83       // in the buffer with the gain vector.
    84       AllocateAudioBlock(aInput.mChannelData.Length(), aOutput);
    86       // Compute the gain values for the duration of the input AudioChunk
    87       // XXX we need to add a method to AudioEventTimeline to compute this buffer directly.
    88       float computedGain[WEBAUDIO_BLOCK_SIZE];
    89       for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
    90         TrackTicks tick = aStream->GetCurrentPosition();
    91         computedGain[counter] = mGain.GetValueAtTime(tick, counter) * aInput.mVolume;
    92       }
    94       // Apply the gain to the output buffer
    95       for (size_t channel = 0; channel < aOutput->mChannelData.Length(); ++channel) {
    96         const float* inputBuffer = static_cast<const float*> (aInput.mChannelData[channel]);
    97         float* buffer = static_cast<float*> (const_cast<void*>
    98                           (aOutput->mChannelData[channel]));
    99         AudioBlockCopyChannelWithScale(inputBuffer, computedGain, buffer);
   100       }
   101     }
   102   }
   104   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
   105   {
   106     // Not owned:
   107     // - mSource (probably)
   108     // - mDestination (probably)
   109     // - mGain - Internal ref owned by AudioNode
   110     return AudioNodeEngine::SizeOfExcludingThis(aMallocSizeOf);
   111   }
   113   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
   114   {
   115     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   116   }
   118   AudioNodeStream* mSource;
   119   AudioNodeStream* mDestination;
   120   AudioParamTimeline mGain;
   121 };
   123 GainNode::GainNode(AudioContext* aContext)
   124   : AudioNode(aContext,
   125               2,
   126               ChannelCountMode::Max,
   127               ChannelInterpretation::Speakers)
   128   , mGain(new AudioParam(MOZ_THIS_IN_INITIALIZER_LIST(),
   129                          SendGainToStream, 1.0f))
   130 {
   131   GainNodeEngine* engine = new GainNodeEngine(this, aContext->Destination());
   132   mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM);
   133   engine->SetSourceStream(static_cast<AudioNodeStream*> (mStream.get()));
   134 }
   136 size_t
   137 GainNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
   138 {
   139   size_t amount = AudioNode::SizeOfExcludingThis(aMallocSizeOf);
   140   amount += mGain->SizeOfIncludingThis(aMallocSizeOf);
   141   return amount;
   142 }
   144 size_t
   145 GainNode::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
   146 {
   147   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   148 }
   150 JSObject*
   151 GainNode::WrapObject(JSContext* aCx)
   152 {
   153   return GainNodeBinding::Wrap(aCx, this);
   154 }
   156 void
   157 GainNode::SendGainToStream(AudioNode* aNode)
   158 {
   159   GainNode* This = static_cast<GainNode*>(aNode);
   160   SendTimelineParameterToStream(This, GainNodeEngine::GAIN, *This->mGain);
   161 }
   163 }
   164 }

mercurial