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