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.

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

mercurial