templatize AudioRingBuffer

This commit is contained in:
Zach Pomerantz 2017-01-19 15:46:24 -05:00
parent 4f7f3c2a60
commit 95a7b38ea4
2 changed files with 121 additions and 114 deletions

View file

@ -26,15 +26,15 @@
static const QString RING_BUFFER_OVERFLOW_DEBUG { "AudioRingBuffer::writeData has overflown the buffer. Overwriting old data." }; static const QString RING_BUFFER_OVERFLOW_DEBUG { "AudioRingBuffer::writeData has overflown the buffer. Overwriting old data." };
static const QString DROPPED_SILENT_DEBUG { "AudioRingBuffer::addSilentSamples dropping silent samples to prevent overflow." }; static const QString DROPPED_SILENT_DEBUG { "AudioRingBuffer::addSilentSamples dropping silent samples to prevent overflow." };
AudioRingBuffer::AudioRingBuffer(int numFrameSamples, int numFramesCapacity) : AudioRingBufferTemplate<int16_t>::AudioRingBufferTemplate(int numFrameSamples, int numFramesCapacity) :
_numFrameSamples(numFrameSamples), _numFrameSamples(numFrameSamples),
_frameCapacity(numFramesCapacity), _frameCapacity(numFramesCapacity),
_sampleCapacity(numFrameSamples * numFramesCapacity), _sampleCapacity(numFrameSamples * numFramesCapacity),
_bufferLength(numFrameSamples * (numFramesCapacity + 1)) _bufferLength(numFrameSamples * (numFramesCapacity + 1))
{ {
if (numFrameSamples) { if (numFrameSamples) {
_buffer = new int16_t[_bufferLength]; _buffer = new Sample[_bufferLength];
memset(_buffer, 0, _bufferLength * sizeof(int16_t)); memset(_buffer, 0, _bufferLength * SampleSize);
_nextOutput = _buffer; _nextOutput = _buffer;
_endOfLastWrite = _buffer; _endOfLastWrite = _buffer;
} }
@ -43,29 +43,29 @@ AudioRingBuffer::AudioRingBuffer(int numFrameSamples, int numFramesCapacity) :
static QString repeatedDroppedMessage = LogHandler::getInstance().addRepeatedMessageRegex(DROPPED_SILENT_DEBUG); static QString repeatedDroppedMessage = LogHandler::getInstance().addRepeatedMessageRegex(DROPPED_SILENT_DEBUG);
}; };
AudioRingBuffer::~AudioRingBuffer() { AudioRingBufferTemplate<int16_t>::~AudioRingBufferTemplate() {
delete[] _buffer; delete[] _buffer;
} }
void AudioRingBuffer::clear() { void AudioRingBufferTemplate<int16_t>::clear() {
_endOfLastWrite = _buffer; _endOfLastWrite = _buffer;
_nextOutput = _buffer; _nextOutput = _buffer;
} }
void AudioRingBuffer::reset() { void AudioRingBufferTemplate<int16_t>::reset() {
clear(); clear();
_overflowCount = 0; _overflowCount = 0;
} }
void AudioRingBuffer::resizeForFrameSize(int numFrameSamples) { void AudioRingBufferTemplate<int16_t>::resizeForFrameSize(int numFrameSamples) {
delete[] _buffer; delete[] _buffer;
_numFrameSamples = numFrameSamples; _numFrameSamples = numFrameSamples;
_sampleCapacity = numFrameSamples * _frameCapacity; _sampleCapacity = numFrameSamples * _frameCapacity;
_bufferLength = numFrameSamples * (_frameCapacity + 1); _bufferLength = numFrameSamples * (_frameCapacity + 1);
if (numFrameSamples) { if (numFrameSamples) {
_buffer = new int16_t[_bufferLength]; _buffer = new Sample[_bufferLength];
memset(_buffer, 0, _bufferLength * sizeof(int16_t)); memset(_buffer, 0, _bufferLength * SampleSize);
} else { } else {
_buffer = nullptr; _buffer = nullptr;
} }
@ -73,17 +73,17 @@ void AudioRingBuffer::resizeForFrameSize(int numFrameSamples) {
reset(); reset();
} }
int AudioRingBuffer::readSamples(int16_t* destination, int maxSamples) { int AudioRingBufferTemplate<int16_t>::readSamples(Sample* destination, int maxSamples) {
return readData((char*)destination, maxSamples * sizeof(int16_t)) / sizeof(int16_t); return readData((char*)destination, maxSamples * SampleSize) / SampleSize;
} }
int AudioRingBuffer::writeSamples(const int16_t* source, int maxSamples) { int AudioRingBufferTemplate<int16_t>::writeSamples(const Sample* source, int maxSamples) {
return writeData((char*)source, maxSamples * sizeof(int16_t)) / sizeof(int16_t); return writeData((char*)source, maxSamples * SampleSize) / SampleSize;
} }
int AudioRingBuffer::readData(char *data, int maxSize) { int AudioRingBufferTemplate<int16_t>::readData(char *data, int maxSize) {
// only copy up to the number of samples we have available // only copy up to the number of samples we have available
int maxSamples = maxSize / sizeof(int16_t); int maxSamples = maxSize / SampleSize;
int numReadSamples = std::min(maxSamples, samplesAvailable()); int numReadSamples = std::min(maxSamples, samplesAvailable());
if (_nextOutput + numReadSamples > _buffer + _bufferLength) { if (_nextOutput + numReadSamples > _buffer + _bufferLength) {
@ -91,22 +91,22 @@ int AudioRingBuffer::readData(char *data, int maxSize) {
int numSamplesToEnd = (_buffer + _bufferLength) - _nextOutput; int numSamplesToEnd = (_buffer + _bufferLength) - _nextOutput;
// read to the end of the buffer // read to the end of the buffer
memcpy(data, _nextOutput, numSamplesToEnd * sizeof(int16_t)); memcpy(data, _nextOutput, numSamplesToEnd * SampleSize);
// read the rest from the beginning of the buffer // read the rest from the beginning of the buffer
memcpy(data + (numSamplesToEnd * sizeof(int16_t)), _buffer, (numReadSamples - numSamplesToEnd) * sizeof(int16_t)); memcpy(data + (numSamplesToEnd * SampleSize), _buffer, (numReadSamples - numSamplesToEnd) * SampleSize);
} else { } else {
memcpy(data, _nextOutput, numReadSamples * sizeof(int16_t)); memcpy(data, _nextOutput, numReadSamples * SampleSize);
} }
shiftReadPosition(numReadSamples); shiftReadPosition(numReadSamples);
return numReadSamples * sizeof(int16_t); return numReadSamples * SampleSize;
} }
int AudioRingBuffer::writeData(const char* data, int maxSize) { int AudioRingBufferTemplate<int16_t>::writeData(const char* data, int maxSize) {
// only copy up to the number of samples we have capacity for // only copy up to the number of samples we have capacity for
int maxSamples = maxSize / sizeof(int16_t); int maxSamples = maxSize / SampleSize;
int numWriteSamples = std::min(maxSamples, _sampleCapacity); int numWriteSamples = std::min(maxSamples, _sampleCapacity);
int samplesRoomFor = _sampleCapacity - samplesAvailable(); int samplesRoomFor = _sampleCapacity - samplesAvailable();
@ -124,20 +124,20 @@ int AudioRingBuffer::writeData(const char* data, int maxSize) {
int numSamplesToEnd = (_buffer + _bufferLength) - _endOfLastWrite; int numSamplesToEnd = (_buffer + _bufferLength) - _endOfLastWrite;
// write to the end of the buffer // write to the end of the buffer
memcpy(_endOfLastWrite, data, numSamplesToEnd * sizeof(int16_t)); memcpy(_endOfLastWrite, data, numSamplesToEnd * SampleSize);
// write the rest to the beginning of the buffer // write the rest to the beginning of the buffer
memcpy(_buffer, data + (numSamplesToEnd * sizeof(int16_t)), (numWriteSamples - numSamplesToEnd) * sizeof(int16_t)); memcpy(_buffer, data + (numSamplesToEnd * SampleSize), (numWriteSamples - numSamplesToEnd) * SampleSize);
} else { } else {
memcpy(_endOfLastWrite, data, numWriteSamples * sizeof(int16_t)); memcpy(_endOfLastWrite, data, numWriteSamples * SampleSize);
} }
_endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, numWriteSamples); _endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, numWriteSamples);
return numWriteSamples * sizeof(int16_t); return numWriteSamples * SampleSize;
} }
int AudioRingBuffer::samplesAvailable() const { int AudioRingBufferTemplate<int16_t>::samplesAvailable() const {
if (!_endOfLastWrite) { if (!_endOfLastWrite) {
return 0; return 0;
} }
@ -149,31 +149,7 @@ int AudioRingBuffer::samplesAvailable() const {
return sampleDifference; return sampleDifference;
} }
int AudioRingBuffer::addSilentSamples(int silentSamples) { int16_t* AudioRingBufferTemplate<int16_t>::shiftedPositionAccomodatingWrap(Sample* position, int numSamplesShift) const {
// NOTE: This implementation is nearly identical to writeData save for s/memcpy/memset, refer to comments there
int numWriteSamples = std::min(silentSamples, _sampleCapacity);
int samplesRoomFor = _sampleCapacity - samplesAvailable();
if (numWriteSamples > samplesRoomFor) {
numWriteSamples = samplesRoomFor;
qCDebug(audio) << qPrintable(DROPPED_SILENT_DEBUG);
}
if (_endOfLastWrite + numWriteSamples > _buffer + _bufferLength) {
int numSamplesToEnd = (_buffer + _bufferLength) - _endOfLastWrite;
memset(_endOfLastWrite, 0, numSamplesToEnd * sizeof(int16_t));
memset(_buffer, 0, (numWriteSamples - numSamplesToEnd) * sizeof(int16_t));
} else {
memset(_endOfLastWrite, 0, numWriteSamples * sizeof(int16_t));
}
_endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, numWriteSamples);
return numWriteSamples;
}
int16_t* AudioRingBuffer::shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const {
// NOTE: It is possible to shift out-of-bounds if (|numSamplesShift| > 2 * _bufferLength), but this should not occur // NOTE: It is possible to shift out-of-bounds if (|numSamplesShift| > 2 * _bufferLength), but this should not occur
if (numSamplesShift > 0 && position + numSamplesShift >= _buffer + _bufferLength) { if (numSamplesShift > 0 && position + numSamplesShift >= _buffer + _bufferLength) {
// this shift will wrap the position around to the beginning of the ring // this shift will wrap the position around to the beginning of the ring
@ -186,11 +162,35 @@ int16_t* AudioRingBuffer::shiftedPositionAccomodatingWrap(int16_t* position, int
} }
} }
float AudioRingBuffer::getFrameLoudness(const int16_t* frameStart) const { int AudioRingBufferTemplate<int16_t>::addSilentSamples(int silentSamples) {
// NOTE: This implementation is nearly identical to writeData save for s/memcpy/memset, refer to comments there
int numWriteSamples = std::min(silentSamples, _sampleCapacity);
int samplesRoomFor = _sampleCapacity - samplesAvailable();
if (numWriteSamples > samplesRoomFor) {
numWriteSamples = samplesRoomFor;
qCDebug(audio) << qPrintable(DROPPED_SILENT_DEBUG);
}
if (_endOfLastWrite + numWriteSamples > _buffer + _bufferLength) {
int numSamplesToEnd = (_buffer + _bufferLength) - _endOfLastWrite;
memset(_endOfLastWrite, 0, numSamplesToEnd * SampleSize);
memset(_buffer, 0, (numWriteSamples - numSamplesToEnd) * SampleSize);
} else {
memset(_endOfLastWrite, 0, numWriteSamples * SampleSize);
}
_endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, numWriteSamples);
return numWriteSamples;
}
float AudioRingBufferTemplate<int16_t>::getFrameLoudness(const Sample* frameStart) const {
// FIXME: This is a bad measure of loudness - normal estimation uses sqrt(sum(x*x)) // FIXME: This is a bad measure of loudness - normal estimation uses sqrt(sum(x*x))
float loudness = 0.0f; float loudness = 0.0f;
const int16_t* sampleAt = frameStart; const Sample* sampleAt = frameStart;
const int16_t* bufferLastAt = _buffer + _bufferLength - 1; const Sample* bufferLastAt = _buffer + _bufferLength - 1;
for (int i = 0; i < _numFrameSamples; ++i) { for (int i = 0; i < _numFrameSamples; ++i) {
loudness += (float) std::abs(*sampleAt); loudness += (float) std::abs(*sampleAt);
@ -203,14 +203,14 @@ float AudioRingBuffer::getFrameLoudness(const int16_t* frameStart) const {
return loudness; return loudness;
} }
float AudioRingBuffer::getFrameLoudness(ConstIterator frameStart) const { float AudioRingBufferTemplate<int16_t>::getFrameLoudness(ConstIterator frameStart) const {
if (frameStart.isNull()) { if (frameStart.isNull()) {
return 0.0f; return 0.0f;
} }
return getFrameLoudness(&(*frameStart)); return getFrameLoudness(&(*frameStart));
} }
int AudioRingBuffer::writeSamples(ConstIterator source, int maxSamples) { int AudioRingBufferTemplate<int16_t>::writeSamples(ConstIterator source, int maxSamples) {
int samplesToCopy = std::min(maxSamples, _sampleCapacity); int samplesToCopy = std::min(maxSamples, _sampleCapacity);
int samplesRoomFor = _sampleCapacity - samplesAvailable(); int samplesRoomFor = _sampleCapacity - samplesAvailable();
if (samplesToCopy > samplesRoomFor) { if (samplesToCopy > samplesRoomFor) {
@ -221,7 +221,7 @@ int AudioRingBuffer::writeSamples(ConstIterator source, int maxSamples) {
qCDebug(audio) << qPrintable(RING_BUFFER_OVERFLOW_DEBUG); qCDebug(audio) << qPrintable(RING_BUFFER_OVERFLOW_DEBUG);
} }
int16_t* bufferLast = _buffer + _bufferLength - 1; Sample* bufferLast = _buffer + _bufferLength - 1;
for (int i = 0; i < samplesToCopy; i++) { for (int i = 0; i < samplesToCopy; i++) {
*_endOfLastWrite = *source; *_endOfLastWrite = *source;
_endOfLastWrite = (_endOfLastWrite == bufferLast) ? _buffer : _endOfLastWrite + 1; _endOfLastWrite = (_endOfLastWrite == bufferLast) ? _buffer : _endOfLastWrite + 1;
@ -231,7 +231,7 @@ int AudioRingBuffer::writeSamples(ConstIterator source, int maxSamples) {
return samplesToCopy; return samplesToCopy;
} }
int AudioRingBuffer::writeSamplesWithFade(ConstIterator source, int maxSamples, float fade) { int AudioRingBufferTemplate<int16_t>::writeSamplesWithFade(ConstIterator source, int maxSamples, float fade) {
int samplesToCopy = std::min(maxSamples, _sampleCapacity); int samplesToCopy = std::min(maxSamples, _sampleCapacity);
int samplesRoomFor = _sampleCapacity - samplesAvailable(); int samplesRoomFor = _sampleCapacity - samplesAvailable();
if (samplesToCopy > samplesRoomFor) { if (samplesToCopy > samplesRoomFor) {
@ -242,9 +242,9 @@ int AudioRingBuffer::writeSamplesWithFade(ConstIterator source, int maxSamples,
qCDebug(audio) << qPrintable(RING_BUFFER_OVERFLOW_DEBUG); qCDebug(audio) << qPrintable(RING_BUFFER_OVERFLOW_DEBUG);
} }
int16_t* bufferLast = _buffer + _bufferLength - 1; Sample* bufferLast = _buffer + _bufferLength - 1;
for (int i = 0; i < samplesToCopy; i++) { for (int i = 0; i < samplesToCopy; i++) {
*_endOfLastWrite = (int16_t)((float)(*source) * fade); *_endOfLastWrite = (Sample)((float)(*source) * fade);
_endOfLastWrite = (_endOfLastWrite == bufferLast) ? _buffer : _endOfLastWrite + 1; _endOfLastWrite = (_endOfLastWrite == bufferLast) ? _buffer : _endOfLastWrite + 1;
++source; ++source;
} }

View file

@ -21,15 +21,19 @@
const int DEFAULT_RING_BUFFER_FRAME_CAPACITY = 10; const int DEFAULT_RING_BUFFER_FRAME_CAPACITY = 10;
class AudioRingBuffer { template <class T>
class AudioRingBufferTemplate {
using Sample = T;
static size_t SampleSize = sizeof(Sample);
public: public:
AudioRingBuffer(int numFrameSamples, int numFramesCapacity = DEFAULT_RING_BUFFER_FRAME_CAPACITY); AudioRingBufferTemplate(int numFrameSamples, int numFramesCapacity = DEFAULT_RING_BUFFER_FRAME_CAPACITY);
~AudioRingBuffer(); ~AudioRingBufferTemplate();
// disallow copying // disallow copying
AudioRingBuffer(const AudioRingBuffer&) = delete; AudioRingBufferTemplate(const AudioRingBufferTemplate&) = delete;
AudioRingBuffer(AudioRingBuffer&&) = delete; AudioRingBufferTemplate(AudioRingBufferTemplate&&) = delete;
AudioRingBuffer& operator=(const AudioRingBuffer&) = delete; AudioRingBufferTemplate& operator=(const AudioRingBufferTemplate&) = delete;
/// Invalidate any data in the buffer /// Invalidate any data in the buffer
void clear(); void clear();
@ -43,11 +47,11 @@ public:
/// Read up to maxSamples into destination (will only read up to samplesAvailable()) /// Read up to maxSamples into destination (will only read up to samplesAvailable())
/// Returns number of read samples /// Returns number of read samples
int readSamples(int16_t* destination, int maxSamples); int readSamples(Sample* destination, int maxSamples);
/// Write up to maxSamples from source (will only write up to sample capacity) /// Write up to maxSamples from source (will only write up to sample capacity)
/// Returns number of written samples /// Returns number of written samples
int writeSamples(const int16_t* source, int maxSamples); int writeSamples(const Sample* source, int maxSamples);
/// Write up to maxSamples silent samples (will only write until other data exists in the buffer) /// Write up to maxSamples silent samples (will only write until other data exists in the buffer)
/// This method will not overwrite existing data in the buffer, instead dropping silent samples that would overflow /// This method will not overwrite existing data in the buffer, instead dropping silent samples that would overflow
@ -63,8 +67,8 @@ public:
int writeData(const char* source, int maxSize); int writeData(const char* source, int maxSize);
/// Returns a reference to the index-th sample offset from the current read sample /// Returns a reference to the index-th sample offset from the current read sample
int16_t& operator[](const int index) { return *shiftedPositionAccomodatingWrap(_nextOutput, index); } Sample& operator[](const int index) { return *shiftedPositionAccomodatingWrap(_nextOutput, index); }
const int16_t& operator[] (const int index) const { return *shiftedPositionAccomodatingWrap(_nextOutput, index); } const Sample& operator[] (const int index) const { return *shiftedPositionAccomodatingWrap(_nextOutput, index); }
/// Essentially discards the next numSamples from the ring buffer /// Essentially discards the next numSamples from the ring buffer
/// NOTE: This is not checked - it is possible to shift past written data /// NOTE: This is not checked - it is possible to shift past written data
@ -85,36 +89,36 @@ public:
class ConstIterator { class ConstIterator {
public: public:
ConstIterator(); ConstIterator();
ConstIterator(int16_t* bufferFirst, int capacity, int16_t* at); ConstIterator(Sample* bufferFirst, int capacity, Sample* at);
ConstIterator(const ConstIterator& rhs) = default; ConstIterator(const ConstIterator& rhs) = default;
bool isNull() const { return _at == NULL; } bool isNull() const { return _at == NULL; }
bool operator==(const ConstIterator& rhs) { return _at == rhs._at; } bool operator==(const ConstIterator& rhs) { return _at == rhs._at; }
bool operator!=(const ConstIterator& rhs) { return _at != rhs._at; } bool operator!=(const ConstIterator& rhs) { return _at != rhs._at; }
const int16_t& operator*() { return *_at; } const Sample& operator*() { return *_at; }
ConstIterator& operator=(const ConstIterator& rhs); ConstIterator& operator=(const ConstIterator& rhs);
ConstIterator& operator++(); ConstIterator& operator++();
ConstIterator operator++(int); ConstIterator operator++(int);
ConstIterator& operator--(); ConstIterator& operator--();
ConstIterator operator--(int); ConstIterator operator--(int);
const int16_t& operator[] (int i); const Sample& operator[] (int i);
ConstIterator operator+(int i); ConstIterator operator+(int i);
ConstIterator operator-(int i); ConstIterator operator-(int i);
void readSamples(int16_t* dest, int numSamples); void readSamples(Sample* dest, int numSamples);
void readSamplesWithFade(int16_t* dest, int numSamples, float fade); void readSamplesWithFade(Sample* dest, int numSamples, float fade);
void readSamplesWithUpmix(int16_t* dest, int numSamples, int numExtraChannels); void readSamplesWithUpmix(Sample* dest, int numSamples, int numExtraChannels);
void readSamplesWithDownmix(int16_t* dest, int numSamples); void readSamplesWithDownmix(Sample* dest, int numSamples);
private: private:
int16_t* atShiftedBy(int i); Sample* atShiftedBy(int i);
int _bufferLength; int _bufferLength;
int16_t* _bufferFirst; Sample* _bufferFirst;
int16_t* _bufferLast; Sample* _bufferLast;
int16_t* _at; Sample* _at;
}; };
ConstIterator nextOutput() const; ConstIterator nextOutput() const;
@ -126,8 +130,8 @@ public:
float getFrameLoudness(ConstIterator frameStart) const; float getFrameLoudness(ConstIterator frameStart) const;
protected: protected:
int16_t* shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const; Sample* shiftedPositionAccomodatingWrap(Sample* position, int numSamplesShift) const;
float getFrameLoudness(const int16_t* frameStart) const; float getFrameLoudness(const Sample* frameStart) const;
int _numFrameSamples; int _numFrameSamples;
int _frameCapacity; int _frameCapacity;
@ -135,25 +139,28 @@ protected:
int _bufferLength; // actual _buffer length (_sampleCapacity + 1) int _bufferLength; // actual _buffer length (_sampleCapacity + 1)
int _overflowCount{ 0 }; // times the ring buffer has overwritten data int _overflowCount{ 0 }; // times the ring buffer has overwritten data
int16_t* _nextOutput{ nullptr }; Sample* _nextOutput{ nullptr };
int16_t* _endOfLastWrite{ nullptr }; Sample* _endOfLastWrite{ nullptr };
int16_t* _buffer{ nullptr }; Sample* _buffer{ nullptr };
}; };
using AudioRingBuffer = AudioRingBufferTemplate<int16_t>;
using AudioRingMixBuffer = AudioRingBufferTemplate<float>;
// inline the iterator: // inline the iterator:
inline AudioRingBuffer::ConstIterator::ConstIterator() : inline AudioRingBufferTemplate<int16_t>::ConstIterator::ConstIterator() :
_bufferLength(0), _bufferLength(0),
_bufferFirst(NULL), _bufferFirst(NULL),
_bufferLast(NULL), _bufferLast(NULL),
_at(NULL) {} _at(NULL) {}
inline AudioRingBuffer::ConstIterator::ConstIterator(int16_t* bufferFirst, int capacity, int16_t* at) : inline AudioRingBufferTemplate<int16_t>::ConstIterator::ConstIterator(Sample* bufferFirst, int capacity, Sample* at) :
_bufferLength(capacity), _bufferLength(capacity),
_bufferFirst(bufferFirst), _bufferFirst(bufferFirst),
_bufferLast(bufferFirst + capacity - 1), _bufferLast(bufferFirst + capacity - 1),
_at(at) {} _at(at) {}
inline AudioRingBuffer::ConstIterator& AudioRingBuffer::ConstIterator::operator=(const ConstIterator& rhs) { inline AudioRingBufferTemplate<int16_t>::ConstIterator& AudioRingBufferTemplate<int16_t>::ConstIterator::operator=(const ConstIterator& rhs) {
_bufferLength = rhs._bufferLength; _bufferLength = rhs._bufferLength;
_bufferFirst = rhs._bufferFirst; _bufferFirst = rhs._bufferFirst;
_bufferLast = rhs._bufferLast; _bufferLast = rhs._bufferLast;
@ -161,41 +168,41 @@ inline AudioRingBuffer::ConstIterator& AudioRingBuffer::ConstIterator::operator=
return *this; return *this;
} }
inline AudioRingBuffer::ConstIterator& AudioRingBuffer::ConstIterator::operator++() { inline AudioRingBufferTemplate<int16_t>::ConstIterator& AudioRingBufferTemplate<int16_t>::ConstIterator::operator++() {
_at = (_at == _bufferLast) ? _bufferFirst : _at + 1; _at = (_at == _bufferLast) ? _bufferFirst : _at + 1;
return *this; return *this;
} }
inline AudioRingBuffer::ConstIterator AudioRingBuffer::ConstIterator::operator++(int) { inline AudioRingBufferTemplate<int16_t>::ConstIterator AudioRingBufferTemplate<int16_t>::ConstIterator::operator++(int) {
ConstIterator tmp(*this); ConstIterator tmp(*this);
++(*this); ++(*this);
return tmp; return tmp;
} }
inline AudioRingBuffer::ConstIterator& AudioRingBuffer::ConstIterator::operator--() { inline AudioRingBufferTemplate<int16_t>::ConstIterator& AudioRingBufferTemplate<int16_t>::ConstIterator::operator--() {
_at = (_at == _bufferFirst) ? _bufferLast : _at - 1; _at = (_at == _bufferFirst) ? _bufferLast : _at - 1;
return *this; return *this;
} }
inline AudioRingBuffer::ConstIterator AudioRingBuffer::ConstIterator::operator--(int) { inline AudioRingBufferTemplate<int16_t>::ConstIterator AudioRingBufferTemplate<int16_t>::ConstIterator::operator--(int) {
ConstIterator tmp(*this); ConstIterator tmp(*this);
--(*this); --(*this);
return tmp; return tmp;
} }
inline const int16_t& AudioRingBuffer::ConstIterator::operator[] (int i) { inline const int16_t& AudioRingBufferTemplate<int16_t>::ConstIterator::operator[] (int i) {
return *atShiftedBy(i); return *atShiftedBy(i);
} }
inline AudioRingBuffer::ConstIterator AudioRingBuffer::ConstIterator::operator+(int i) { inline AudioRingBufferTemplate<int16_t>::ConstIterator AudioRingBufferTemplate<int16_t>::ConstIterator::operator+(int i) {
return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(i)); return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(i));
} }
inline AudioRingBuffer::ConstIterator AudioRingBuffer::ConstIterator::operator-(int i) { inline AudioRingBufferTemplate<int16_t>::ConstIterator AudioRingBufferTemplate<int16_t>::ConstIterator::operator-(int i) {
return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(-i)); return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(-i));
} }
inline int16_t* AudioRingBuffer::ConstIterator::atShiftedBy(int i) { inline int16_t* AudioRingBufferTemplate<int16_t>::ConstIterator::atShiftedBy(int i) {
i = (_at - _bufferFirst + i) % _bufferLength; i = (_at - _bufferFirst + i) % _bufferLength;
if (i < 0) { if (i < 0) {
i += _bufferLength; i += _bufferLength;
@ -203,23 +210,23 @@ inline int16_t* AudioRingBuffer::ConstIterator::atShiftedBy(int i) {
return _bufferFirst + i; return _bufferFirst + i;
} }
inline void AudioRingBuffer::ConstIterator::readSamples(int16_t* dest, int numSamples) { inline void AudioRingBufferTemplate<int16_t>::ConstIterator::readSamples(Sample* dest, int numSamples) {
auto samplesToEnd = _bufferLast - _at + 1; auto samplesToEnd = _bufferLast - _at + 1;
if (samplesToEnd >= numSamples) { if (samplesToEnd >= numSamples) {
memcpy(dest, _at, numSamples * sizeof(int16_t)); memcpy(dest, _at, numSamples * SampleSize);
_at += numSamples; _at += numSamples;
} else { } else {
auto samplesFromStart = numSamples - samplesToEnd; auto samplesFromStart = numSamples - samplesToEnd;
memcpy(dest, _at, samplesToEnd * sizeof(int16_t)); memcpy(dest, _at, samplesToEnd * SampleSize);
memcpy(dest + samplesToEnd, _bufferFirst, samplesFromStart * sizeof(int16_t)); memcpy(dest + samplesToEnd, _bufferFirst, samplesFromStart * SampleSize);
_at = _bufferFirst + samplesFromStart; _at = _bufferFirst + samplesFromStart;
} }
} }
inline void AudioRingBuffer::ConstIterator::readSamplesWithFade(int16_t* dest, int numSamples, float fade) { inline void AudioRingBufferTemplate<int16_t>::ConstIterator::readSamplesWithFade(Sample* dest, int numSamples, float fade) {
int16_t* at = _at; Sample* at = _at;
for (int i = 0; i < numSamples; i++) { for (int i = 0; i < numSamples; i++) {
*dest = (float)*at * fade; *dest = (float)*at * fade;
++dest; ++dest;
@ -227,14 +234,14 @@ inline void AudioRingBuffer::ConstIterator::readSamplesWithFade(int16_t* dest, i
} }
} }
inline void AudioRingBuffer::ConstIterator::readSamplesWithUpmix(int16_t* dest, int numSamples, int numExtraChannels) { inline void AudioRingBufferTemplate<int16_t>::ConstIterator::readSamplesWithUpmix(Sample* dest, int numSamples, int numExtraChannels) {
int16_t* at = _at; Sample* at = _at;
for (int i = 0; i < numSamples/2; i++) { for (int i = 0; i < numSamples/2; i++) {
// read 2 samples // read 2 samples
int16_t left = *at; Sample left = *at;
at = (at == _bufferLast) ? _bufferFirst : at + 1; at = (at == _bufferLast) ? _bufferFirst : at + 1;
int16_t right = *at; Sample right = *at;
at = (at == _bufferLast) ? _bufferFirst : at + 1; at = (at == _bufferLast) ? _bufferFirst : at + 1;
// write 2 + N samples // write 2 + N samples
@ -246,26 +253,26 @@ inline void AudioRingBuffer::ConstIterator::readSamplesWithUpmix(int16_t* dest,
} }
} }
inline void AudioRingBuffer::ConstIterator::readSamplesWithDownmix(int16_t* dest, int numSamples) { inline void AudioRingBufferTemplate<int16_t>::ConstIterator::readSamplesWithDownmix(Sample* dest, int numSamples) {
int16_t* at = _at; Sample* at = _at;
for (int i = 0; i < numSamples/2; i++) { for (int i = 0; i < numSamples/2; i++) {
// read 2 samples // read 2 samples
int16_t left = *at; Sample left = *at;
at = (at == _bufferLast) ? _bufferFirst : at + 1; at = (at == _bufferLast) ? _bufferFirst : at + 1;
int16_t right = *at; Sample right = *at;
at = (at == _bufferLast) ? _bufferFirst : at + 1; at = (at == _bufferLast) ? _bufferFirst : at + 1;
// write 1 sample // write 1 sample
*dest++ = (int16_t)((left + right) / 2); *dest++ = (Sample)((left + right) / 2);
} }
} }
inline AudioRingBuffer::ConstIterator AudioRingBuffer::nextOutput() const { inline AudioRingBufferTemplate<int16_t>::ConstIterator AudioRingBufferTemplate<int16_t>::nextOutput() const {
return ConstIterator(_buffer, _bufferLength, _nextOutput); return ConstIterator(_buffer, _bufferLength, _nextOutput);
} }
inline AudioRingBuffer::ConstIterator AudioRingBuffer::lastFrameWritten() const { inline AudioRingBufferTemplate<int16_t>::ConstIterator AudioRingBufferTemplate<int16_t>::lastFrameWritten() const {
return ConstIterator(_buffer, _bufferLength, _endOfLastWrite) - _numFrameSamples; return ConstIterator(_buffer, _bufferLength, _endOfLastWrite) - _numFrameSamples;
} }