From 75281099bd480298d65fc1fddc0a12bea9df3452 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 20 Jan 2017 14:33:54 -0500 Subject: [PATCH] add conformant explicit instantiation for AudioRingBuffers --- libraries/audio/src/AudioRingBuffer.cpp | 395 ++++++++---------------- libraries/audio/src/AudioRingBuffer.h | 227 +++++--------- 2 files changed, 207 insertions(+), 415 deletions(-) diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index ab0948e328..4f64d4a4b0 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -26,8 +26,8 @@ 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." }; -template<> -AudioRingBufferTemplate::AudioRingBufferTemplate(int numFrameSamples, int numFramesCapacity) : +template +AudioRingBufferTemplate::AudioRingBufferTemplate(int numFrameSamples, int numFramesCapacity) : _numFrameSamples(numFrameSamples), _frameCapacity(numFramesCapacity), _sampleCapacity(numFrameSamples * numFramesCapacity), @@ -44,25 +44,25 @@ AudioRingBufferTemplate::AudioRingBufferTemplate(int numFrameSamples, i static QString repeatedDroppedMessage = LogHandler::getInstance().addRepeatedMessageRegex(DROPPED_SILENT_DEBUG); } -template<> -AudioRingBufferTemplate::~AudioRingBufferTemplate() { +template +AudioRingBufferTemplate::~AudioRingBufferTemplate() { delete[] _buffer; } -template<> -void AudioRingBufferTemplate::clear() { +template +void AudioRingBufferTemplate::clear() { _endOfLastWrite = _buffer; _nextOutput = _buffer; } -template<> -void AudioRingBufferTemplate::reset() { +template +void AudioRingBufferTemplate::reset() { clear(); _overflowCount = 0; } -template<> -void AudioRingBufferTemplate::resizeForFrameSize(int numFrameSamples) { +template +void AudioRingBufferTemplate::resizeForFrameSize(int numFrameSamples) { delete[] _buffer; _numFrameSamples = numFrameSamples; _sampleCapacity = numFrameSamples * _frameCapacity; @@ -78,255 +78,13 @@ void AudioRingBufferTemplate::resizeForFrameSize(int numFrameSamples) { reset(); } -template<> -int AudioRingBufferTemplate::readSamples(Sample* destination, int maxSamples) { +template +int AudioRingBufferTemplate::readSamples(Sample* destination, int maxSamples) { return readData((char*)destination, maxSamples * SampleSize) / SampleSize; } -template<> -int AudioRingBufferTemplate::writeSamples(const Sample* source, int maxSamples) { - return writeData((char*)source, maxSamples * SampleSize) / SampleSize; -} - -template<> -int AudioRingBufferTemplate::readData(char *data, int maxSize) { - // only copy up to the number of samples we have available - int maxSamples = maxSize / SampleSize; - int numReadSamples = std::min(maxSamples, samplesAvailable()); - - if (_nextOutput + numReadSamples > _buffer + _bufferLength) { - // we're going to need to do two reads to get this data, it wraps around the edge - int numSamplesToEnd = (_buffer + _bufferLength) - _nextOutput; - - // read to the end of the buffer - memcpy(data, _nextOutput, numSamplesToEnd * SampleSize); - - // read the rest from the beginning of the buffer - memcpy(data + (numSamplesToEnd * SampleSize), _buffer, (numReadSamples - numSamplesToEnd) * SampleSize); - } else { - memcpy(data, _nextOutput, numReadSamples * SampleSize); - } - - shiftReadPosition(numReadSamples); - - return numReadSamples * SampleSize; -} - -template<> -int AudioRingBufferTemplate::writeData(const char* data, int maxSize) { - // only copy up to the number of samples we have capacity for - int maxSamples = maxSize / SampleSize; - int numWriteSamples = std::min(maxSamples, _sampleCapacity); - int samplesRoomFor = _sampleCapacity - samplesAvailable(); - - if (numWriteSamples > samplesRoomFor) { - // there's not enough room for this write. erase old data to make room for this new data - int samplesToDelete = numWriteSamples - samplesRoomFor; - _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete); - _overflowCount++; - - qCDebug(audio) << qPrintable(RING_BUFFER_OVERFLOW_DEBUG); - } - - if (_endOfLastWrite + numWriteSamples > _buffer + _bufferLength) { - // we're going to need to do two writes to set this data, it wraps around the edge - int numSamplesToEnd = (_buffer + _bufferLength) - _endOfLastWrite; - - // write to the end of the buffer - memcpy(_endOfLastWrite, data, numSamplesToEnd * SampleSize); - - // write the rest to the beginning of the buffer - memcpy(_buffer, data + (numSamplesToEnd * SampleSize), (numWriteSamples - numSamplesToEnd) * SampleSize); - } else { - memcpy(_endOfLastWrite, data, numWriteSamples * SampleSize); - } - - _endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, numWriteSamples); - - return numWriteSamples * SampleSize; -} - -template<> -int AudioRingBufferTemplate::samplesAvailable() const { - if (!_endOfLastWrite) { - return 0; - } - - int sampleDifference = _endOfLastWrite - _nextOutput; - if (sampleDifference < 0) { - sampleDifference += _bufferLength; - } - return sampleDifference; -} - -template<> -int16_t* AudioRingBufferTemplate::shiftedPositionAccomodatingWrap(Sample* position, int numSamplesShift) const { - // 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) { - // this shift will wrap the position around to the beginning of the ring - return position + numSamplesShift - _bufferLength; - } else if (numSamplesShift < 0 && position + numSamplesShift < _buffer) { - // this shift will go around to the end of the ring - return position + numSamplesShift + _bufferLength; - } else { - return position + numSamplesShift; - } -} - -template<> -int AudioRingBufferTemplate::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; -} - -template<> -float AudioRingBufferTemplate::getFrameLoudness(const Sample* frameStart) const { - // FIXME: This is a bad measure of loudness - normal estimation uses sqrt(sum(x*x)) - float loudness = 0.0f; - const Sample* sampleAt = frameStart; - const Sample* bufferLastAt = _buffer + _bufferLength - 1; - - for (int i = 0; i < _numFrameSamples; ++i) { - loudness += (float) std::abs(*sampleAt); - // wrap if necessary - sampleAt = sampleAt == bufferLastAt ? _buffer : sampleAt + 1; - } - loudness /= _numFrameSamples; - loudness /= AudioConstants::MAX_SAMPLE_VALUE; - - return loudness; -} - -template<> -float AudioRingBufferTemplate::getFrameLoudness(ConstIterator frameStart) const { - if (frameStart.isNull()) { - return 0.0f; - } - return getFrameLoudness(&(*frameStart)); -} - -template<> -int AudioRingBufferTemplate::writeSamples(ConstIterator source, int maxSamples) { - int samplesToCopy = std::min(maxSamples, _sampleCapacity); - int samplesRoomFor = _sampleCapacity - samplesAvailable(); - if (samplesToCopy > samplesRoomFor) { - // there's not enough room for this write. erase old data to make room for this new data - int samplesToDelete = samplesToCopy - samplesRoomFor; - _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete); - _overflowCount++; - qCDebug(audio) << qPrintable(RING_BUFFER_OVERFLOW_DEBUG); - } - - Sample* bufferLast = _buffer + _bufferLength - 1; - for (int i = 0; i < samplesToCopy; i++) { - *_endOfLastWrite = *source; - _endOfLastWrite = (_endOfLastWrite == bufferLast) ? _buffer : _endOfLastWrite + 1; - ++source; - } - - return samplesToCopy; -} - -template<> -int AudioRingBufferTemplate::writeSamplesWithFade(ConstIterator source, int maxSamples, float fade) { - int samplesToCopy = std::min(maxSamples, _sampleCapacity); - int samplesRoomFor = _sampleCapacity - samplesAvailable(); - if (samplesToCopy > samplesRoomFor) { - // there's not enough room for this write. erase old data to make room for this new data - int samplesToDelete = samplesToCopy - samplesRoomFor; - _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete); - _overflowCount++; - qCDebug(audio) << qPrintable(RING_BUFFER_OVERFLOW_DEBUG); - } - - Sample* bufferLast = _buffer + _bufferLength - 1; - for (int i = 0; i < samplesToCopy; i++) { - *_endOfLastWrite = (Sample)((float)(*source) * fade); - _endOfLastWrite = (_endOfLastWrite == bufferLast) ? _buffer : _endOfLastWrite + 1; - ++source; - } - - return samplesToCopy; -} - -template<> -AudioRingBufferTemplate::AudioRingBufferTemplate(int numFrameSamples, int numFramesCapacity) : - _numFrameSamples(numFrameSamples), - _frameCapacity(numFramesCapacity), - _sampleCapacity(numFrameSamples * numFramesCapacity), - _bufferLength(numFrameSamples * (numFramesCapacity + 1)) -{ - if (numFrameSamples) { - _buffer = new Sample[_bufferLength]; - memset(_buffer, 0, _bufferLength * SampleSize); - _nextOutput = _buffer; - _endOfLastWrite = _buffer; - } - - static QString repeatedOverflowMessage = LogHandler::getInstance().addRepeatedMessageRegex(RING_BUFFER_OVERFLOW_DEBUG); - static QString repeatedDroppedMessage = LogHandler::getInstance().addRepeatedMessageRegex(DROPPED_SILENT_DEBUG); -} - -template<> -AudioRingBufferTemplate::~AudioRingBufferTemplate() { - delete[] _buffer; -} - -template<> -void AudioRingBufferTemplate::clear() { - _endOfLastWrite = _buffer; - _nextOutput = _buffer; -} - -template<> -void AudioRingBufferTemplate::reset() { - clear(); - _overflowCount = 0; -} - -template<> -void AudioRingBufferTemplate::resizeForFrameSize(int numFrameSamples) { - delete[] _buffer; - _numFrameSamples = numFrameSamples; - _sampleCapacity = numFrameSamples * _frameCapacity; - _bufferLength = numFrameSamples * (_frameCapacity + 1); - - if (numFrameSamples) { - _buffer = new Sample[_bufferLength]; - memset(_buffer, 0, _bufferLength * SampleSize); - } else { - _buffer = nullptr; - } - - reset(); -} - -template<> -int AudioRingBufferTemplate::readSamples(Sample* destination, int maxSamples) { - return readData((char*)destination, maxSamples * SampleSize) / SampleSize; -} - -template<> -int AudioRingBufferTemplate::appendSamples(Sample* destination, int maxSamples, bool append) { +template +int AudioRingBufferTemplate::appendSamples(Sample* destination, int maxSamples, bool append) { if (append) { return appendData((char*)destination, maxSamples * SampleSize) / SampleSize; } else { @@ -334,13 +92,13 @@ int AudioRingBufferTemplate::appendSamples(Sample* destination, int maxSa } } -template<> -int AudioRingBufferTemplate::writeSamples(const Sample* source, int maxSamples) { +template +int AudioRingBufferTemplate::writeSamples(const Sample* source, int maxSamples) { return writeData((char*)source, maxSamples * SampleSize) / SampleSize; } -template<> -int AudioRingBufferTemplate::readData(char *data, int maxSize) { +template +int AudioRingBufferTemplate::readData(char *data, int maxSize) { // only copy up to the number of samples we have available int maxSamples = maxSize / SampleSize; int numReadSamples = std::min(maxSamples, samplesAvailable()); @@ -363,8 +121,8 @@ int AudioRingBufferTemplate::readData(char *data, int maxSize) { return numReadSamples * SampleSize; } -template<> -int AudioRingBufferTemplate::appendData(char *data, int maxSize) { +template +int AudioRingBufferTemplate::appendData(char *data, int maxSize) { // only copy up to the number of samples we have available int maxSamples = maxSize / SampleSize; int numReadSamples = std::min(maxSamples, samplesAvailable()); @@ -396,8 +154,8 @@ int AudioRingBufferTemplate::appendData(char *data, int maxSize) { return numReadSamples * SampleSize; } -template<> -int AudioRingBufferTemplate::writeData(const char* data, int maxSize) { +template +int AudioRingBufferTemplate::writeData(const char* data, int maxSize) { // only copy up to the number of samples we have capacity for int maxSamples = maxSize / SampleSize; int numWriteSamples = std::min(maxSamples, _sampleCapacity); @@ -430,8 +188,8 @@ int AudioRingBufferTemplate::writeData(const char* data, int maxSize) { return numWriteSamples * SampleSize; } -template<> -int AudioRingBufferTemplate::samplesAvailable() const { +template +int AudioRingBufferTemplate::samplesAvailable() const { if (!_endOfLastWrite) { return 0; } @@ -443,8 +201,8 @@ int AudioRingBufferTemplate::samplesAvailable() const { return sampleDifference; } -template<> -float* AudioRingBufferTemplate::shiftedPositionAccomodatingWrap(Sample* position, int numSamplesShift) const { +template +typename AudioRingBufferTemplate::Sample* AudioRingBufferTemplate::shiftedPositionAccomodatingWrap(Sample* position, int numSamplesShift) const { // 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) { // this shift will wrap the position around to the beginning of the ring @@ -455,4 +213,103 @@ float* AudioRingBufferTemplate::shiftedPositionAccomodatingWrap(Sample* p } else { return position + numSamplesShift; } -} \ No newline at end of file +} + +template +int AudioRingBufferTemplate::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; +} + +template +float AudioRingBufferTemplate::getFrameLoudness(const Sample* frameStart) const { + // FIXME: This is a bad measure of loudness - normal estimation uses sqrt(sum(x*x)) + float loudness = 0.0f; + const Sample* sampleAt = frameStart; + const Sample* bufferLastAt = _buffer + _bufferLength - 1; + + for (int i = 0; i < _numFrameSamples; ++i) { + loudness += (float) std::abs(*sampleAt); + // wrap if necessary + sampleAt = sampleAt == bufferLastAt ? _buffer : sampleAt + 1; + } + loudness /= _numFrameSamples; + loudness /= AudioConstants::MAX_SAMPLE_VALUE; + + return loudness; +} + +template +float AudioRingBufferTemplate::getFrameLoudness(ConstIterator frameStart) const { + if (frameStart.isNull()) { + return 0.0f; + } + return getFrameLoudness(&(*frameStart)); +} + +template +int AudioRingBufferTemplate::writeSamples(ConstIterator source, int maxSamples) { + int samplesToCopy = std::min(maxSamples, _sampleCapacity); + int samplesRoomFor = _sampleCapacity - samplesAvailable(); + if (samplesToCopy > samplesRoomFor) { + // there's not enough room for this write. erase old data to make room for this new data + int samplesToDelete = samplesToCopy - samplesRoomFor; + _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete); + _overflowCount++; + qCDebug(audio) << qPrintable(RING_BUFFER_OVERFLOW_DEBUG); + } + + Sample* bufferLast = _buffer + _bufferLength - 1; + for (int i = 0; i < samplesToCopy; i++) { + *_endOfLastWrite = *source; + _endOfLastWrite = (_endOfLastWrite == bufferLast) ? _buffer : _endOfLastWrite + 1; + ++source; + } + + return samplesToCopy; +} + +template +int AudioRingBufferTemplate::writeSamplesWithFade(ConstIterator source, int maxSamples, float fade) { + int samplesToCopy = std::min(maxSamples, _sampleCapacity); + int samplesRoomFor = _sampleCapacity - samplesAvailable(); + if (samplesToCopy > samplesRoomFor) { + // there's not enough room for this write. erase old data to make room for this new data + int samplesToDelete = samplesToCopy - samplesRoomFor; + _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, samplesToDelete); + _overflowCount++; + qCDebug(audio) << qPrintable(RING_BUFFER_OVERFLOW_DEBUG); + } + + Sample* bufferLast = _buffer + _bufferLength - 1; + for (int i = 0; i < samplesToCopy; i++) { + *_endOfLastWrite = (Sample)((float)(*source) * fade); + _endOfLastWrite = (_endOfLastWrite == bufferLast) ? _buffer : _endOfLastWrite + 1; + ++source; + } + + return samplesToCopy; +} + +// explicit instantiations for scratch/mix buffers +template class AudioRingBufferTemplate; +template class AudioRingBufferTemplate; diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index 92c6dcc336..0208c8686e 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -100,8 +100,16 @@ public: class ConstIterator { public: - ConstIterator(); - ConstIterator(Sample* bufferFirst, int capacity, Sample* at); + ConstIterator() : + _bufferLength(0), + _bufferFirst(NULL), + _bufferLast(NULL), + _at(NULL) {} + ConstIterator(Sample* bufferFirst, int capacity, Sample* at) : + _bufferLength(capacity), + _bufferFirst(bufferFirst), + _bufferLast(bufferFirst + capacity - 1), + _at(at) {} ConstIterator(const ConstIterator& rhs) = default; bool isNull() const { return _at == NULL; } @@ -110,22 +118,73 @@ public: bool operator!=(const ConstIterator& rhs) { return _at != rhs._at; } const Sample& operator*() { return *_at; } - ConstIterator& operator=(const ConstIterator& rhs); - ConstIterator& operator++(); - ConstIterator operator++(int); - ConstIterator& operator--(); - ConstIterator operator--(int); - const Sample& operator[] (int i); - ConstIterator operator+(int i); - ConstIterator operator-(int i); + ConstIterator& operator=(const ConstIterator& rhs) { + _bufferLength = rhs._bufferLength; + _bufferFirst = rhs._bufferFirst; + _bufferLast = rhs._bufferLast; + _at = rhs._at; + return *this; + } + ConstIterator& operator++() { + _at = (_at == _bufferLast) ? _bufferFirst : _at + 1; + return *this; + } + ConstIterator operator++(int) { + ConstIterator tmp(*this); + ++(*this); + return tmp; + } + ConstIterator& operator--() { + _at = (_at == _bufferFirst) ? _bufferLast : _at - 1; + return *this; + } + ConstIterator operator--(int) { + ConstIterator tmp(*this); + --(*this); + return tmp; + } + const Sample& operator[] (int i) { + return *atShiftedBy(i); + } + ConstIterator operator+(int i) { + return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(i)); + } + ConstIterator operator-(int i) { + return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(-i)); + } + + void readSamples(Sample* dest, int numSamples) { + auto samplesToEnd = _bufferLast - _at + 1; + + if (samplesToEnd >= numSamples) { + memcpy(dest, _at, numSamples * SampleSize); + _at += numSamples; + } else { + auto samplesFromStart = numSamples - samplesToEnd; + memcpy(dest, _at, samplesToEnd * SampleSize); + memcpy(dest + samplesToEnd, _bufferFirst, samplesFromStart * SampleSize); + + _at = _bufferFirst + samplesFromStart; + } + } + void readSamplesWithFade(Sample* dest, int numSamples, float fade) { + Sample* at = _at; + for (int i = 0; i < numSamples; i++) { + *dest = (float)*at * fade; + ++dest; + at = (at == _bufferLast) ? _bufferFirst : at + 1; + } + } - void readSamples(Sample* dest, int numSamples); - void readSamplesWithFade(Sample* dest, int numSamples, float fade); - void readSamplesWithUpmix(Sample* dest, int numSamples, int numExtraChannels); - void readSamplesWithDownmix(Sample* dest, int numSamples); private: - Sample* atShiftedBy(int i); + Sample* atShiftedBy(int i) { + i = (_at - _bufferFirst + i) % _bufferLength; + if (i < 0) { + i += _bufferLength; + } + return _bufferFirst + i; + } int _bufferLength; Sample* _bufferFirst; @@ -133,8 +192,12 @@ public: Sample* _at; }; - ConstIterator nextOutput() const; - ConstIterator lastFrameWritten() const; + ConstIterator nextOutput() const { + return ConstIterator(_buffer, _bufferLength, _nextOutput); + } + ConstIterator lastFrameWritten() const { + return ConstIterator(_buffer, _bufferLength, _endOfLastWrite) - _numFrameSamples; + } int writeSamples(ConstIterator source, int maxSamples); int writeSamplesWithFade(ConstIterator source, int maxSamples, float fade); @@ -156,136 +219,8 @@ protected: Sample* _buffer{ nullptr }; }; +// expose explicit instantiations for scratch/mix buffers using AudioRingBuffer = AudioRingBufferTemplate; using AudioRingMixBuffer = AudioRingBufferTemplate; -// inline the iterator: -template<> inline AudioRingBufferTemplate::ConstIterator::ConstIterator() : - _bufferLength(0), - _bufferFirst(NULL), - _bufferLast(NULL), - _at(NULL) {} - -template<> inline AudioRingBufferTemplate::ConstIterator::ConstIterator(Sample* bufferFirst, int capacity, Sample* at) : - _bufferLength(capacity), - _bufferFirst(bufferFirst), - _bufferLast(bufferFirst + capacity - 1), - _at(at) {} - -template<> inline AudioRingBufferTemplate::ConstIterator& AudioRingBufferTemplate::ConstIterator::operator=(const ConstIterator& rhs) { - _bufferLength = rhs._bufferLength; - _bufferFirst = rhs._bufferFirst; - _bufferLast = rhs._bufferLast; - _at = rhs._at; - return *this; -} - -template<> inline AudioRingBufferTemplate::ConstIterator& AudioRingBufferTemplate::ConstIterator::operator++() { - _at = (_at == _bufferLast) ? _bufferFirst : _at + 1; - return *this; -} - -template<> inline AudioRingBufferTemplate::ConstIterator AudioRingBufferTemplate::ConstIterator::operator++(int) { - ConstIterator tmp(*this); - ++(*this); - return tmp; -} - -template<> inline AudioRingBufferTemplate::ConstIterator& AudioRingBufferTemplate::ConstIterator::operator--() { - _at = (_at == _bufferFirst) ? _bufferLast : _at - 1; - return *this; -} - -template<> inline AudioRingBufferTemplate::ConstIterator AudioRingBufferTemplate::ConstIterator::operator--(int) { - ConstIterator tmp(*this); - --(*this); - return tmp; -} - -template<> inline const int16_t& AudioRingBufferTemplate::ConstIterator::operator[] (int i) { - return *atShiftedBy(i); -} - -template<> inline AudioRingBufferTemplate::ConstIterator AudioRingBufferTemplate::ConstIterator::operator+(int i) { - return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(i)); -} - -template<> inline AudioRingBufferTemplate::ConstIterator AudioRingBufferTemplate::ConstIterator::operator-(int i) { - return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(-i)); -} - -template<> inline int16_t* AudioRingBufferTemplate::ConstIterator::atShiftedBy(int i) { - i = (_at - _bufferFirst + i) % _bufferLength; - if (i < 0) { - i += _bufferLength; - } - return _bufferFirst + i; -} - -template<> inline void AudioRingBufferTemplate::ConstIterator::readSamples(Sample* dest, int numSamples) { - auto samplesToEnd = _bufferLast - _at + 1; - - if (samplesToEnd >= numSamples) { - memcpy(dest, _at, numSamples * SampleSize); - _at += numSamples; - } else { - auto samplesFromStart = numSamples - samplesToEnd; - memcpy(dest, _at, samplesToEnd * SampleSize); - memcpy(dest + samplesToEnd, _bufferFirst, samplesFromStart * SampleSize); - - _at = _bufferFirst + samplesFromStart; - } -} - -template<> inline void AudioRingBufferTemplate::ConstIterator::readSamplesWithFade(Sample* dest, int numSamples, float fade) { - Sample* at = _at; - for (int i = 0; i < numSamples; i++) { - *dest = (float)*at * fade; - ++dest; - at = (at == _bufferLast) ? _bufferFirst : at + 1; - } -} - -template<> inline void AudioRingBufferTemplate::ConstIterator::readSamplesWithUpmix(Sample* dest, int numSamples, int numExtraChannels) { - Sample* at = _at; - for (int i = 0; i < numSamples/2; i++) { - - // read 2 samples - Sample left = *at; - at = (at == _bufferLast) ? _bufferFirst : at + 1; - Sample right = *at; - at = (at == _bufferLast) ? _bufferFirst : at + 1; - - // write 2 + N samples - *dest++ = left; - *dest++ = right; - for (int n = 0; n < numExtraChannels; n++) { - *dest++ = 0; - } - } -} - -template<> inline void AudioRingBufferTemplate::ConstIterator::readSamplesWithDownmix(Sample* dest, int numSamples) { - Sample* at = _at; - for (int i = 0; i < numSamples/2; i++) { - - // read 2 samples - Sample left = *at; - at = (at == _bufferLast) ? _bufferFirst : at + 1; - Sample right = *at; - at = (at == _bufferLast) ? _bufferFirst : at + 1; - - // write 1 sample - *dest++ = (Sample)((left + right) / 2); - } -} - -template<> inline AudioRingBufferTemplate::ConstIterator AudioRingBufferTemplate::nextOutput() const { - return ConstIterator(_buffer, _bufferLength, _nextOutput); -} - -template<> inline AudioRingBufferTemplate::ConstIterator AudioRingBufferTemplate::lastFrameWritten() const { - return ConstIterator(_buffer, _bufferLength, _endOfLastWrite) - _numFrameSamples; -} - #endif // hifi_AudioRingBuffer_h