diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/media/webaudio/AudioNodeTrack.h | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/media/webaudio/AudioNodeTrack.h')
-rw-r--r-- | dom/media/webaudio/AudioNodeTrack.h | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/dom/media/webaudio/AudioNodeTrack.h b/dom/media/webaudio/AudioNodeTrack.h new file mode 100644 index 0000000000..29c5218d0a --- /dev/null +++ b/dom/media/webaudio/AudioNodeTrack.h @@ -0,0 +1,237 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MOZILLA_AUDIONODETRACK_H_ +#define MOZILLA_AUDIONODETRACK_H_ + +#include "MediaTrackGraph.h" +#include "mozilla/dom/AudioNodeBinding.h" +#include "AlignedTArray.h" +#include "AudioBlock.h" +#include "AudioSegment.h" + +namespace WebCore { +class Reverb; +} // namespace WebCore + +namespace mozilla { + +namespace dom { +struct ThreeDPoint; +struct AudioTimelineEvent; +class AudioContext; +} // namespace dom + +class AbstractThread; +class ThreadSharedFloatArrayBufferList; +class AudioNodeEngine; + +typedef AlignedAutoTArray<float, GUESS_AUDIO_CHANNELS * WEBAUDIO_BLOCK_SIZE, 16> + DownmixBufferType; + +/** + * An AudioNodeTrack produces one audio track with ID AUDIO_TRACK. + * The start time of the AudioTrack is aligned to the start time of the + * AudioContext's destination node track, plus some multiple of BLOCK_SIZE + * samples. + * + * An AudioNodeTrack has an AudioNodeEngine plugged into it that does the + * actual audio processing. AudioNodeTrack contains the glue code that + * integrates audio processing with the MediaTrackGraph. + */ +class AudioNodeTrack : public ProcessedMediaTrack { + typedef dom::ChannelCountMode ChannelCountMode; + typedef dom::ChannelInterpretation ChannelInterpretation; + + public: + typedef mozilla::dom::AudioContext AudioContext; + + enum { AUDIO_TRACK = 1 }; + + typedef AutoTArray<AudioBlock, 1> OutputChunks; + + // Flags re main thread updates and track output. + typedef unsigned Flags; + enum : Flags { + NO_TRACK_FLAGS = 0U, + NEED_MAIN_THREAD_ENDED = 1U << 0, + NEED_MAIN_THREAD_CURRENT_TIME = 1U << 1, + // Internal AudioNodeTracks can only pass their output to another + // AudioNode, whereas external AudioNodeTracks can pass their output + // to other ProcessedMediaTracks or hardware audio output. + EXTERNAL_OUTPUT = 1U << 2, + }; + /** + * Create a track that will process audio for an AudioNode. + * Takes ownership of aEngine. + * aGraph is required and equals the graph of aCtx in most cases. An exception + * is AudioDestinationNode where the context's graph hasn't been set up yet. + */ + static already_AddRefed<AudioNodeTrack> Create(AudioContext* aCtx, + AudioNodeEngine* aEngine, + Flags aKind, + MediaTrackGraph* aGraph); + + protected: + /** + * Transfers ownership of aEngine to the new AudioNodeTrack. + */ + AudioNodeTrack(AudioNodeEngine* aEngine, Flags aFlags, TrackRate aSampleRate); + + ~AudioNodeTrack(); + + public: + // Control API + /** + * Sets a parameter that's a time relative to some track's played time. + * This time is converted to a time relative to this track when it's set. + */ + void SetTrackTimeParameter(uint32_t aIndex, AudioContext* aContext, + double aTrackTime); + void SetDoubleParameter(uint32_t aIndex, double aValue); + void SetInt32Parameter(uint32_t aIndex, int32_t aValue); + void SetThreeDPointParameter(uint32_t aIndex, const dom::ThreeDPoint& aValue); + void SetBuffer(AudioChunk&& aBuffer); + void SetReverb(WebCore::Reverb* aReverb, uint32_t aImpulseChannelCount); + // This sends a single event to the timeline on the MTG thread side. + void SendTimelineEvent(uint32_t aIndex, + const dom::AudioTimelineEvent& aEvent); + // This consumes the contents of aData. aData will be emptied after this + // returns. + void SetRawArrayData(nsTArray<float>&& aData); + void SetChannelMixingParameters(uint32_t aNumberOfChannels, + ChannelCountMode aChannelCountMoe, + ChannelInterpretation aChannelInterpretation); + void SetPassThrough(bool aPassThrough); + void SendRunnable(already_AddRefed<nsIRunnable> aRunnable); + ChannelInterpretation GetChannelInterpretation() { + return mChannelInterpretation; + } + + void SetAudioParamHelperTrack() { + MOZ_ASSERT(!mAudioParamTrack, "Can only do this once"); + mAudioParamTrack = true; + } + // The value for channelCount on an AudioNode, but on the audio thread side. + uint32_t NumberOfChannels() const override; + + /* + * Resume track after updating its concept of current time by aAdvance. + * Main thread. Used only from AudioDestinationNode when resuming a track + * suspended to save running the MediaTrackGraph when there are no other + * nodes in the AudioContext. + */ + void AdvanceAndResume(TrackTime aAdvance); + + AudioNodeTrack* AsAudioNodeTrack() override { return this; } + void AddInput(MediaInputPort* aPort) override; + void RemoveInput(MediaInputPort* aPort) override; + + // Graph thread only + void SetTrackTimeParameterImpl(uint32_t aIndex, MediaTrack* aRelativeToTrack, + double aTrackTime); + void SetChannelMixingParametersImpl( + uint32_t aNumberOfChannels, ChannelCountMode aChannelCountMoe, + ChannelInterpretation aChannelInterpretation); + void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) override; + /** + * Produce the next block of output, before input is provided. + * ProcessInput() will be called later, and it then should not change + * the output. This is used only for DelayNodeEngine in a feedback loop. + */ + void ProduceOutputBeforeInput(GraphTime aFrom); + bool IsAudioParamTrack() const { return mAudioParamTrack; } + + const OutputChunks& LastChunks() const { return mLastChunks; } + bool MainThreadNeedsUpdates() const override { + return ((mFlags & NEED_MAIN_THREAD_ENDED) && mEnded) || + (mFlags & NEED_MAIN_THREAD_CURRENT_TIME); + } + + // Any thread + AudioNodeEngine* Engine() { return mEngine.get(); } + + size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override; + size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override; + + void SizeOfAudioNodesIncludingThis(MallocSizeOf aMallocSizeOf, + AudioNodeSizes& aUsage) const; + + /* + * SetActive() is called when either an active input is added or the engine + * for a source node transitions from inactive to active. This is not + * called from engines for processing nodes because they only become active + * when there are active input tracks, in which case this track is already + * active. + */ + void SetActive(); + /* + * ScheduleCheckForInactive() is called during track processing when the + * engine transitions from active to inactive, or the track finishes. It + * schedules a call to CheckForInactive() after track processing. + */ + void ScheduleCheckForInactive(); + + protected: + class AdvanceAndResumeMessage; + class CheckForInactiveMessage; + + void OnGraphThreadDone() override; + void DestroyImpl() override; + + /* + * CheckForInactive() is called when the engine transitions from active to + * inactive, or an active input is removed, or the track finishes. If the + * track is now inactive, then mInputChunks will be cleared and mLastChunks + * will be set to null. ProcessBlock() will not be called on the engine + * again until SetActive() is called. + */ + void CheckForInactive(); + + void AdvanceOutputSegment(); + void FinishOutput(); + void AccumulateInputChunk(uint32_t aInputIndex, const AudioBlock& aChunk, + AudioBlock* aBlock, + DownmixBufferType* aDownmixBuffer); + void UpMixDownMixChunk(const AudioBlock* aChunk, uint32_t aOutputChannelCount, + nsTArray<const float*>& aOutputChannels, + DownmixBufferType& aDownmixBuffer); + + uint32_t ComputedNumberOfChannels(uint32_t aInputChannelCount); + void ObtainInputBlock(AudioBlock& aTmpChunk, uint32_t aPortIndex); + void IncrementActiveInputCount(); + void DecrementActiveInputCount(); + + // The engine that will generate output for this node. + const UniquePtr<AudioNodeEngine> mEngine; + // The mixed input blocks are kept from iteration to iteration to avoid + // reallocating channel data arrays and any buffers for mixing. + OutputChunks mInputChunks; + // The last block produced by this node. + OutputChunks mLastChunks; + // Whether this is an internal or external track + const Flags mFlags; + // The number of input tracks that may provide non-silent input. + uint32_t mActiveInputCount = 0; + // The number of input channels that this track requires. 0 means don't care. + uint32_t mNumberOfInputChannels; + // The mixing modes + ChannelCountMode mChannelCountMode; + ChannelInterpretation mChannelInterpretation; + // Tracks are considered active if the track has not finished and either + // the engine is active or there are active input tracks. + bool mIsActive; + // Whether the track should be marked as ended as soon + // as the current time range has been computed block by block. + bool mMarkAsEndedAfterThisBlock; + // Whether the track is an AudioParamHelper track. + bool mAudioParamTrack; + // Whether the track just passes its input through. + bool mPassThrough; +}; + +} // namespace mozilla + +#endif /* MOZILLA_AUDIONODETRACK_H_ */ |