tor-browser

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

AudioParam.cpp (5159B)


      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 "AudioParam.h"
      8 
      9 #include "AudioContext.h"
     10 #include "AudioNodeEngine.h"
     11 #include "AudioNodeTrack.h"
     12 #include "mozilla/dom/AudioParamBinding.h"
     13 
     14 namespace mozilla::dom {
     15 
     16 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(AudioParam)
     17 
     18 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioParam)
     19  tmp->DisconnectFromGraphAndDestroyTrack();
     20  NS_IMPL_CYCLE_COLLECTION_UNLINK(mNode)
     21  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
     22 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     23 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioParam)
     24  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNode)
     25 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     26 
     27 NS_IMPL_CYCLE_COLLECTING_NATIVE_ADDREF(AudioParam)
     28 NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(AudioParam)
     29 
     30 AudioParam::AudioParam(AudioNode* aNode, uint32_t aIndex,
     31                       const nsAString& aName, float aDefaultValue,
     32                       float aMinValue, float aMaxValue)
     33    : AudioParamTimeline(aDefaultValue),
     34      mNode(aNode),
     35      mName(aName),
     36      mIndex(aIndex),
     37      mDefaultValue(aDefaultValue),
     38      mMinValue(aMinValue),
     39      mMaxValue(aMaxValue) {}
     40 
     41 AudioParam::~AudioParam() { DisconnectFromGraphAndDestroyTrack(); }
     42 
     43 JSObject* AudioParam::WrapObject(JSContext* aCx,
     44                                 JS::Handle<JSObject*> aGivenProto) {
     45  return AudioParam_Binding::Wrap(aCx, this, aGivenProto);
     46 }
     47 
     48 void AudioParam::DisconnectFromGraphAndDestroyTrack() {
     49  MOZ_ASSERT(mRefCnt.get() > mInputNodes.Length(),
     50             "Caller should be holding a reference or have called "
     51             "mRefCnt.stabilizeForDeletion()");
     52 
     53  while (!mInputNodes.IsEmpty()) {
     54    RefPtr<AudioNode> input = mInputNodes.PopLastElement().mInputNode;
     55    input->RemoveOutputParam(this);
     56  }
     57 
     58  if (mNodeTrackPort) {
     59    mNodeTrackPort->Destroy();
     60    mNodeTrackPort = nullptr;
     61  }
     62 
     63  if (mTrack) {
     64    mTrack->Destroy();
     65    mTrack = nullptr;
     66  }
     67 }
     68 
     69 mozilla::MediaTrack* AudioParam::GetTrack() const { return mTrack; }
     70 
     71 mozilla::MediaTrack* AudioParam::Track() {
     72  if (mTrack) {
     73    return mTrack;
     74  }
     75 
     76  AudioNodeEngine* engine = new AudioNodeEngine(nullptr);
     77  mTrack = AudioNodeTrack::Create(mNode->Context(), engine,
     78                                  AudioNodeTrack::NO_TRACK_FLAGS,
     79                                  mNode->Context()->Graph());
     80 
     81  // Force the input to have only one channel, and make it down-mix using
     82  // the speaker rules if needed.
     83  mTrack->SetChannelMixingParametersImpl(1, ChannelCountMode::Explicit,
     84                                         ChannelInterpretation::Speakers);
     85  // Mark as an AudioParam helper track
     86  mTrack->SetAudioParamHelperTrack();
     87 
     88  // Setup the AudioParam's track as an input to the owner AudioNode's track
     89  AudioNodeTrack* nodeTrack = mNode->GetTrack();
     90  if (nodeTrack) {
     91    mNodeTrackPort = nodeTrack->AllocateInputPort(mTrack);
     92  }
     93 
     94  // Send the track to the timeline on the MTG side.
     95  AudioParamEvent event(mTrack);
     96  SendEventToEngine(event);
     97 
     98  return mTrack;
     99 }
    100 
    101 void AudioParam::SendEventToEngine(const AudioParamEvent& aEvent) {
    102  if (WEB_AUDIO_API_LOG_TEST()) {
    103    nsAutoCString params;
    104    if (aEvent.mType == AudioTimelineEvent::SetValueCurve) {
    105      params.AppendFmt("length={} time={:f} duration={:f}",
    106                       aEvent.CurveLength(), aEvent.Time<double>(),
    107                       aEvent.Duration());
    108    } else {
    109      params.AppendFmt("value={} time={:f}", aEvent.NominalValue(),
    110                       aEvent.Time<double>());
    111      if (aEvent.mType == AudioTimelineEvent::SetTarget) {
    112        params.AppendFmt(" constant={}", aEvent.TimeConstant());
    113      }
    114    }
    115    WEB_AUDIO_API_LOG("{:f}: {} for {} {} {}", GetParentObject()->CurrentTime(),
    116                      NS_ConvertUTF16toUTF8(mName).get(), ParentNodeId(),
    117                      AudioTimelineEvent::EnumValueToString(aEvent.mType),
    118                      params.get());
    119  }
    120  AudioNodeTrack* track = mNode->GetTrack();
    121  if (track) {
    122    track->SendTimelineEvent(mIndex, aEvent);
    123  }
    124 }
    125 
    126 void AudioParam::CleanupOldEvents() {
    127  MOZ_ASSERT(NS_IsMainThread());
    128  double currentTime = mNode->Context()->CurrentTime();
    129 
    130  CleanupEventsOlderThan(currentTime);
    131 }
    132 
    133 float AudioParamTimeline::AudioNodeInputValue(size_t aCounter) const {
    134  MOZ_ASSERT(mTrack);
    135 
    136  // If we have a chunk produced by the AudioNode inputs to the AudioParam,
    137  // get its value now.  We use aCounter to tell us which frame of the last
    138  // AudioChunk to look at.
    139  float audioNodeInputValue = 0.0f;
    140  const AudioBlock& lastAudioNodeChunk = mTrack->LastChunks()[0];
    141  if (!lastAudioNodeChunk.IsNull()) {
    142    MOZ_ASSERT(lastAudioNodeChunk.GetDuration() == WEBAUDIO_BLOCK_SIZE);
    143    audioNodeInputValue =
    144        static_cast<const float*>(lastAudioNodeChunk.mChannelData[0])[aCounter];
    145    audioNodeInputValue *= lastAudioNodeChunk.mVolume;
    146  }
    147 
    148  return audioNodeInputValue;
    149 }
    150 
    151 }  // namespace mozilla::dom