/src/mozilla-central/dom/media/webaudio/DelayBuffer.h
Line | Count | Source (jump to first uncovered line) |
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 "AudioBlock.h" |
12 | | #include "AudioSegment.h" |
13 | | #include "mozilla/dom/AudioNodeBinding.h" // for ChannelInterpretation |
14 | | |
15 | | namespace mozilla { |
16 | | |
17 | | class DelayBuffer final |
18 | | { |
19 | | typedef dom::ChannelInterpretation ChannelInterpretation; |
20 | | |
21 | | public: |
22 | | explicit DelayBuffer(float aMaxDelayTicks) |
23 | | // Round the maximum delay up to the next tick. |
24 | | : mMaxDelayTicks(std::ceil(aMaxDelayTicks)) |
25 | | , mCurrentChunk(0) |
26 | | // mLastReadChunk is initialized in EnsureBuffer |
27 | | #ifdef DEBUG |
28 | | , mHaveWrittenBlock(false) |
29 | | #endif |
30 | 0 | { |
31 | 0 | // The 180 second limit in AudioContext::CreateDelay() and the |
32 | 0 | // 1 << MEDIA_TIME_FRAC_BITS limit on sample rate provide a limit on the |
33 | 0 | // maximum delay. |
34 | 0 | MOZ_ASSERT(aMaxDelayTicks <= |
35 | 0 | std::numeric_limits<decltype(mMaxDelayTicks)>::max()); |
36 | 0 | } |
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 | 0 | { |
62 | 0 | mCurrentChunk = (mCurrentChunk + 1) % mChunks.Length(); |
63 | | #ifdef DEBUG |
64 | | MOZ_ASSERT(mHaveWrittenBlock); |
65 | | mHaveWrittenBlock = false; |
66 | | #endif |
67 | | } |
68 | | |
69 | 0 | void Reset() { |
70 | 0 | mChunks.Clear(); |
71 | 0 | }; |
72 | | |
73 | 0 | int MaxDelayTicks() const { return mMaxDelayTicks; } |
74 | | |
75 | | size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; |
76 | | |
77 | | private: |
78 | | void ReadChannels(const float aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], |
79 | | AudioBlock* aOutputChunk, |
80 | | uint32_t aFirstChannel, uint32_t aNumChannelsToRead, |
81 | | ChannelInterpretation aChannelInterpretation); |
82 | | bool EnsureBuffer(); |
83 | | int PositionForDelay(int aDelay); |
84 | | int ChunkForPosition(int aPosition); |
85 | | int OffsetForPosition(int aPosition); |
86 | | int ChunkForDelay(int aDelay); |
87 | | void UpdateUpmixChannels(int aNewReadChunk, uint32_t channelCount, |
88 | | ChannelInterpretation aChannelInterpretation); |
89 | | |
90 | | // Circular buffer for capturing delayed samples. |
91 | | FallibleTArray<AudioChunk> mChunks; |
92 | | // Cache upmixed channel arrays. |
93 | | AutoTArray<const float*,GUESS_AUDIO_CHANNELS> mUpmixChannels; |
94 | | // Maximum delay, in ticks |
95 | | int mMaxDelayTicks; |
96 | | // The current position in the circular buffer. The next write will be to |
97 | | // this chunk, and the next read may begin before this chunk. |
98 | | int mCurrentChunk; |
99 | | // The chunk owning the pointers in mUpmixChannels |
100 | | int mLastReadChunk; |
101 | | #ifdef DEBUG |
102 | | bool mHaveWrittenBlock; |
103 | | #endif |
104 | | }; |
105 | | |
106 | | } // namespace mozilla |
107 | | |
108 | | #endif // DelayBuffer_h_ |