DelayBuffer.h (3882B)
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 #ifndef DelayBuffer_h_ 8 #define DelayBuffer_h_ 9 10 #include "AudioBlock.h" 11 #include "AudioSegment.h" 12 #include "mozilla/dom/AudioNodeBinding.h" // for ChannelInterpretation 13 #include "nsTArray.h" 14 15 namespace mozilla { 16 17 class DelayBuffer final { 18 typedef dom::ChannelInterpretation ChannelInterpretation; 19 20 public: 21 explicit DelayBuffer(float aMaxDelayTicks) 22 // Round the maximum delay up to the next tick. 23 : mMaxDelayTicks(std::ceil(aMaxDelayTicks)), 24 mCurrentChunk(0) 25 // mLastReadChunk is initialized in EnsureBuffer 26 #ifdef DEBUG 27 , 28 mHaveWrittenBlock(false) 29 #endif 30 { 31 // The 180 second limit in AudioContext::CreateDelay() and the 32 // 1 << MEDIA_TIME_FRAC_BITS limit on sample rate provide a limit on the 33 // maximum delay. 34 MOZ_ASSERT(aMaxDelayTicks <= 35 float(std::numeric_limits<decltype(mMaxDelayTicks)>::max())); 36 } 37 38 // Write a WEBAUDIO_BLOCK_SIZE block for aChannelCount channels. 39 void Write(const AudioBlock& aInputChunk); 40 41 // Read a block with an array of delays, in ticks, for each sample frame. 42 // Each delay should be >= 0 and <= MaxDelayTicks(). 43 void Read(const float aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], 44 AudioBlock* aOutputChunk, 45 ChannelInterpretation aChannelInterpretation); 46 // Read a block with a constant delay. The delay should be >= 0 and 47 // <= MaxDelayTicks(). 48 void Read(float aDelayTicks, AudioBlock* aOutputChunk, 49 ChannelInterpretation aChannelInterpretation); 50 51 // Read into one of the channels of aOutputChunk, given an array of 52 // delays in ticks. This is useful when delays are different on different 53 // channels. aOutputChunk must have already been allocated with at least as 54 // many channels as were in any of the blocks passed to Write(). 55 void ReadChannel(const float aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], 56 AudioBlock* aOutputChunk, uint32_t aChannel, 57 ChannelInterpretation aChannelInterpretation); 58 59 // Advance the buffer pointer 60 void NextBlock() { 61 mCurrentChunk = (mCurrentChunk + 1) % mChunks.Length(); 62 #ifdef DEBUG 63 MOZ_ASSERT(mHaveWrittenBlock); 64 mHaveWrittenBlock = false; 65 #endif 66 } 67 68 void Reset() { mChunks.Clear(); }; 69 70 int MaxDelayTicks() const { return mMaxDelayTicks; } 71 72 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; 73 74 private: 75 void ReadChannels(const float aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], 76 AudioBlock* aOutputChunk, uint32_t aFirstChannel, 77 uint32_t aNumChannelsToRead, 78 ChannelInterpretation aChannelInterpretation); 79 bool EnsureBuffer(); 80 int PositionForDelay(int aDelay); 81 int ChunkForPosition(int aPosition); 82 int OffsetForPosition(int aPosition); 83 int ChunkForDelay(int aDelay); 84 void UpdateUpmixChannels(int aNewReadChunk, uint32_t channelCount, 85 ChannelInterpretation aChannelInterpretation); 86 87 // Circular buffer for capturing delayed samples. 88 FallibleTArray<AudioChunk> mChunks; 89 // Cached upmixed channel arrays, to avoid repeated allocations. 90 CopyableAutoTArray<const float*, GUESS_AUDIO_CHANNELS> mUpmixChannels; 91 // Maximum delay, in ticks 92 int mMaxDelayTicks; 93 // The current position in the circular buffer. The next write will be to 94 // this chunk, and the next read may begin before this chunk. 95 int mCurrentChunk; 96 // The chunk owning the pointers in mUpmixChannels 97 int mLastReadChunk; 98 #ifdef DEBUG 99 bool mHaveWrittenBlock; 100 #endif 101 }; 102 103 } // namespace mozilla 104 105 #endif // DelayBuffer_h_