diff options
Diffstat (limited to 'dom/media/webaudio/DelayBuffer.h')
-rw-r--r-- | dom/media/webaudio/DelayBuffer.h | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/dom/media/webaudio/DelayBuffer.h b/dom/media/webaudio/DelayBuffer.h new file mode 100644 index 0000000000..5f238fde03 --- /dev/null +++ b/dom/media/webaudio/DelayBuffer.h @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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 DelayBuffer_h_ +#define DelayBuffer_h_ + +#include "nsTArray.h" +#include "AudioBlock.h" +#include "AudioSegment.h" +#include "mozilla/dom/AudioNodeBinding.h" // for ChannelInterpretation + +namespace mozilla { + +class DelayBuffer final { + typedef dom::ChannelInterpretation ChannelInterpretation; + + public: + explicit DelayBuffer(float aMaxDelayTicks) + // Round the maximum delay up to the next tick. + : mMaxDelayTicks(std::ceil(aMaxDelayTicks)), + mCurrentChunk(0) + // mLastReadChunk is initialized in EnsureBuffer +#ifdef DEBUG + , + mHaveWrittenBlock(false) +#endif + { + // The 180 second limit in AudioContext::CreateDelay() and the + // 1 << MEDIA_TIME_FRAC_BITS limit on sample rate provide a limit on the + // maximum delay. + MOZ_ASSERT(aMaxDelayTicks <= + float(std::numeric_limits<decltype(mMaxDelayTicks)>::max())); + } + + // Write a WEBAUDIO_BLOCK_SIZE block for aChannelCount channels. + void Write(const AudioBlock& aInputChunk); + + // Read a block with an array of delays, in ticks, for each sample frame. + // Each delay should be >= 0 and <= MaxDelayTicks(). + void Read(const float aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + AudioBlock* aOutputChunk, + ChannelInterpretation aChannelInterpretation); + // Read a block with a constant delay. The delay should be >= 0 and + // <= MaxDelayTicks(). + void Read(float aDelayTicks, AudioBlock* aOutputChunk, + ChannelInterpretation aChannelInterpretation); + + // Read into one of the channels of aOutputChunk, given an array of + // delays in ticks. This is useful when delays are different on different + // channels. aOutputChunk must have already been allocated with at least as + // many channels as were in any of the blocks passed to Write(). + void ReadChannel(const float aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + AudioBlock* aOutputChunk, uint32_t aChannel, + ChannelInterpretation aChannelInterpretation); + + // Advance the buffer pointer + void NextBlock() { + mCurrentChunk = (mCurrentChunk + 1) % mChunks.Length(); +#ifdef DEBUG + MOZ_ASSERT(mHaveWrittenBlock); + mHaveWrittenBlock = false; +#endif + } + + void Reset() { mChunks.Clear(); }; + + int MaxDelayTicks() const { return mMaxDelayTicks; } + + size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; + + private: + void ReadChannels(const float aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], + AudioBlock* aOutputChunk, uint32_t aFirstChannel, + uint32_t aNumChannelsToRead, + ChannelInterpretation aChannelInterpretation); + bool EnsureBuffer(); + int PositionForDelay(int aDelay); + int ChunkForPosition(int aPosition); + int OffsetForPosition(int aPosition); + int ChunkForDelay(int aDelay); + void UpdateUpmixChannels(int aNewReadChunk, uint32_t channelCount, + ChannelInterpretation aChannelInterpretation); + + // Circular buffer for capturing delayed samples. + FallibleTArray<AudioChunk> mChunks; + // Cache upmixed channel arrays. + AutoTArray<const float*, GUESS_AUDIO_CHANNELS> mUpmixChannels; + // Maximum delay, in ticks + int mMaxDelayTicks; + // The current position in the circular buffer. The next write will be to + // this chunk, and the next read may begin before this chunk. + int mCurrentChunk; + // The chunk owning the pointers in mUpmixChannels + int mLastReadChunk; +#ifdef DEBUG + bool mHaveWrittenBlock; +#endif +}; + +} // namespace mozilla + +#endif // DelayBuffer_h_ |