1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/webaudio/DelayBuffer.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,114 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef DelayBuffer_h_ 1.11 +#define DelayBuffer_h_ 1.12 + 1.13 +#include "nsTArray.h" 1.14 +#include "AudioSegment.h" 1.15 +#include "mozilla/dom/AudioNodeBinding.h" // for ChannelInterpretation 1.16 + 1.17 +namespace mozilla { 1.18 + 1.19 +class DelayBuffer { 1.20 + typedef dom::ChannelInterpretation ChannelInterpretation; 1.21 + 1.22 +public: 1.23 + // See WebAudioUtils::ComputeSmoothingRate() for frame to frame exponential 1.24 + // |smoothingRate| multiplier. 1.25 + DelayBuffer(double aMaxDelayTicks, double aSmoothingRate) 1.26 + : mSmoothingRate(aSmoothingRate) 1.27 + , mCurrentDelay(-1.0) 1.28 + // Round the maximum delay up to the next tick. 1.29 + , mMaxDelayTicks(ceil(aMaxDelayTicks)) 1.30 + , mCurrentChunk(0) 1.31 + // mLastReadChunk is initialized in EnsureBuffer 1.32 +#ifdef DEBUG 1.33 + , mHaveWrittenBlock(false) 1.34 +#endif 1.35 + { 1.36 + // The 180 second limit in AudioContext::CreateDelay() and the 1.37 + // 1 << MEDIA_TIME_FRAC_BITS limit on sample rate provide a limit on the 1.38 + // maximum delay. 1.39 + MOZ_ASSERT(aMaxDelayTicks <= 1.40 + std::numeric_limits<decltype(mMaxDelayTicks)>::max()); 1.41 + } 1.42 + 1.43 + // Write a WEBAUDIO_BLOCK_SIZE block for aChannelCount channels. 1.44 + void Write(const AudioChunk& aInputChunk); 1.45 + 1.46 + // Read a block with an array of delays, in ticks, for each sample frame. 1.47 + // Each delay should be >= 0 and <= MaxDelayTicks(). 1.48 + void Read(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], 1.49 + AudioChunk* aOutputChunk, 1.50 + ChannelInterpretation aChannelInterpretation); 1.51 + // Read a block with a constant delay, which will be smoothed with the 1.52 + // previous delay. The delay should be >= 0 and <= MaxDelayTicks(). 1.53 + void Read(double aDelayTicks, AudioChunk* aOutputChunk, 1.54 + ChannelInterpretation aChannelInterpretation); 1.55 + 1.56 + // Read into one of the channels of aOutputChunk, given an array of 1.57 + // delays in ticks. This is useful when delays are different on different 1.58 + // channels. aOutputChunk must have already been allocated with at least as 1.59 + // many channels as were in any of the blocks passed to Write(). 1.60 + void ReadChannel(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], 1.61 + const AudioChunk* aOutputChunk, uint32_t aChannel, 1.62 + ChannelInterpretation aChannelInterpretation); 1.63 + 1.64 + // Advance the buffer pointer 1.65 + void NextBlock() 1.66 + { 1.67 + mCurrentChunk = (mCurrentChunk + 1) % mChunks.Length(); 1.68 +#ifdef DEBUG 1.69 + MOZ_ASSERT(mHaveWrittenBlock); 1.70 + mHaveWrittenBlock = false; 1.71 +#endif 1.72 + } 1.73 + 1.74 + void Reset() { 1.75 + mChunks.Clear(); 1.76 + mCurrentDelay = -1.0; 1.77 + }; 1.78 + 1.79 + int MaxDelayTicks() const { return mMaxDelayTicks; } 1.80 + 1.81 + size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; 1.82 + 1.83 +private: 1.84 + void ReadChannels(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE], 1.85 + const AudioChunk* aOutputChunk, 1.86 + uint32_t aFirstChannel, uint32_t aNumChannelsToRead, 1.87 + ChannelInterpretation aChannelInterpretation); 1.88 + bool EnsureBuffer(); 1.89 + int PositionForDelay(int aDelay); 1.90 + int ChunkForPosition(int aPosition); 1.91 + int OffsetForPosition(int aPosition); 1.92 + int ChunkForDelay(int aDelay); 1.93 + void UpdateUpmixChannels(int aNewReadChunk, uint32_t channelCount, 1.94 + ChannelInterpretation aChannelInterpretation); 1.95 + 1.96 + // Circular buffer for capturing delayed samples. 1.97 + FallibleTArray<AudioChunk> mChunks; 1.98 + // Cache upmixed channel arrays. 1.99 + nsAutoTArray<const void*,GUESS_AUDIO_CHANNELS> mUpmixChannels; 1.100 + double mSmoothingRate; 1.101 + // Current delay, in fractional ticks 1.102 + double mCurrentDelay; 1.103 + // Maximum delay, in ticks 1.104 + int mMaxDelayTicks; 1.105 + // The current position in the circular buffer. The next write will be to 1.106 + // this chunk, and the next read may begin before this chunk. 1.107 + int mCurrentChunk; 1.108 + // The chunk owning the pointers in mUpmixChannels 1.109 + int mLastReadChunk; 1.110 +#ifdef DEBUG 1.111 + bool mHaveWrittenBlock; 1.112 +#endif 1.113 +}; 1.114 + 1.115 +} // mozilla 1.116 + 1.117 +#endif // DelayBuffer_h_