gecko/content/media/webaudio/DelayBuffer.h
Karl Tomlinson 0935b39ced b=857610 handle DelayNode channel count changes and separate buffer read and write r=padenot
The basic idea is to write out the signal that came in with the same number of
channels as it had when it came in.  Things get a bit more complicated when
one output block may be derived from more than one input block, each having
different numbers of channels.  When this happens, the input blocks with fewer
channels are upmixed, so as not to lose (or distort) any signal in the block
with more channels.

HRTFPanner no longer uses exponential decay (with time constant 20ms) for
delay changes, but a smoother linear transition during cross-fade time (~45ms).

--HG--
rename : content/media/webaudio/DelayProcessor.cpp => content/media/webaudio/DelayBuffer.cpp
rename : content/media/webaudio/DelayProcessor.h => content/media/webaudio/DelayBuffer.h
extra : rebase_source : 18453d631779cd7d0672b5325e110b107ab4237d
2014-03-05 10:06:57 +13:00

97 lines
3.5 KiB
C++

/* -*- 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 "AudioSegment.h"
#include "mozilla/dom/AudioNodeBinding.h" // for ChannelInterpretation
namespace mozilla {
class DelayBuffer {
typedef dom::ChannelInterpretation ChannelInterpretation;
public:
// See WebAudioUtils::ComputeSmoothingRate() for frame to frame exponential
// |smoothingRate| multiplier.
DelayBuffer(int aMaxDelayTicks, double aSmoothingRate)
: mSmoothingRate(aSmoothingRate)
, mCurrentDelay(-1.0)
, mMaxDelayTicks(aMaxDelayTicks)
, mCurrentChunk(0)
// mLastReadChunk is initialized in EnsureBuffer
{
}
// Write a WEBAUDIO_BLOCK_SIZE block for aChannelCount channels.
void Write(const AudioChunk& aInputChunk);
// Read a block with an array of delays, in ticks, for each sample frame.
// Each delay must be > 0 and < MaxDelayTicks().
void Read(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE],
AudioChunk* aOutputChunk,
ChannelInterpretation aChannelInterpretation);
// Read a block with a constant delay, which will be smoothed with the
// previous delay. The delay must be > 0 and < MaxDelayTicks().
void Read(double aDelayTicks, AudioChunk* 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 double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE],
const AudioChunk* aOutputChunk, uint32_t aChannel,
ChannelInterpretation aChannelInterpretation);
// Advance the buffer pointer
void NextBlock()
{
mCurrentChunk = (mCurrentChunk + 1) % mChunks.Length();
}
void Reset() {
mChunks.Clear();
mCurrentDelay = -1.0;
};
int MaxDelayTicks() const { return mMaxDelayTicks; }
private:
void ReadChannels(const double aPerFrameDelays[WEBAUDIO_BLOCK_SIZE],
const AudioChunk* 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.
nsAutoTArray<const void*,GUESS_AUDIO_CHANNELS> mUpmixChannels;
double mSmoothingRate;
// Current delay, in fractional ticks
double mCurrentDelay;
// 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;
};
} // mozilla
#endif // DelayBuffer_h_