From 4ec84b32b076499ade294e297ef653b8aab12dc6 Mon Sep 17 00:00:00 2001 From: wangyix Date: Fri, 8 Aug 2014 17:00:39 -0700 Subject: [PATCH] updated AudioRingBuffer bytes vs samples returns --- libraries/audio/src/AudioRingBuffer.cpp | 104 ++++++++++------------- libraries/audio/src/AudioRingBuffer.h | 60 +++++++------ tests/audio/src/AudioRingBufferTests.cpp | 37 ++++---- 3 files changed, 97 insertions(+), 104 deletions(-) diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 2ad51e4a36..d9cb34ac1b 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -20,18 +20,16 @@ AudioRingBuffer::AudioRingBuffer(int numFrameSamples, bool randomAccessMode, int numFramesCapacity) : - _frameCapacity(numFramesCapacity), - _sampleCapacity(numFrameSamples * numFramesCapacity), - _isFull(false), - _numFrameSamples(numFrameSamples), - _randomAccessMode(randomAccessMode), - _overflowCount(0) +_frameCapacity(numFramesCapacity), +_sampleCapacity(numFrameSamples * numFramesCapacity), +_bufferLength(numFrameSamples * (numFramesCapacity + 1)), +_numFrameSamples(numFrameSamples), +_randomAccessMode(randomAccessMode), +_overflowCount(0) { if (numFrameSamples) { - _buffer = new int16_t[_sampleCapacity]; - if (_randomAccessMode) { - memset(_buffer, 0, _sampleCapacity * sizeof(int16_t)); - } + _buffer = new int16_t[_bufferLength]; + memset(_buffer, 0, _bufferLength * sizeof(int16_t)); _nextOutput = _buffer; _endOfLastWrite = _buffer; } else { @@ -53,28 +51,29 @@ void AudioRingBuffer::reset() { void AudioRingBuffer::resizeForFrameSize(int numFrameSamples) { delete[] _buffer; _sampleCapacity = numFrameSamples * _frameCapacity; + _bufferLength = numFrameSamples * (_frameCapacity + 1); _numFrameSamples = numFrameSamples; - _buffer = new int16_t[_sampleCapacity]; + _buffer = new int16_t[_bufferLength]; + memset(_buffer, 0, _bufferLength * sizeof(int16_t)); if (_randomAccessMode) { - memset(_buffer, 0, _sampleCapacity * sizeof(int16_t)); + memset(_buffer, 0, _bufferLength * sizeof(int16_t)); } reset(); } void AudioRingBuffer::clear() { - _isFull = false; _endOfLastWrite = _buffer; _nextOutput = _buffer; } int AudioRingBuffer::readSamples(int16_t* destination, int maxSamples) { - return readData((char*) destination, maxSamples * sizeof(int16_t)); + return readData((char*)destination, maxSamples * sizeof(int16_t)) / sizeof(int16_t); } int AudioRingBuffer::readData(char *data, int maxSize) { // only copy up to the number of samples we have available - int numReadSamples = std::min((int) (maxSize / sizeof(int16_t)), samplesAvailable()); + int numReadSamples = std::min((int)(maxSize / sizeof(int16_t)), samplesAvailable()); // If we're in random access mode, then we consider our number of available read samples slightly // differently. Namely, if anything has been written, we say we have as many samples as they ask for @@ -83,16 +82,16 @@ int AudioRingBuffer::readData(char *data, int maxSize) { numReadSamples = _endOfLastWrite ? (maxSize / sizeof(int16_t)) : 0; } - if (_nextOutput + numReadSamples > _buffer + _sampleCapacity) { + if (_nextOutput + numReadSamples > _buffer + _bufferLength) { // we're going to need to do two reads to get this data, it wraps around the edge // read to the end of the buffer - int numSamplesToEnd = (_buffer + _sampleCapacity) - _nextOutput; + int numSamplesToEnd = (_buffer + _bufferLength) - _nextOutput; memcpy(data, _nextOutput, numSamplesToEnd * sizeof(int16_t)); if (_randomAccessMode) { memset(_nextOutput, 0, numSamplesToEnd * sizeof(int16_t)); // clear it } - + // read the rest from the beginning of the buffer memcpy(data + (numSamplesToEnd * sizeof(int16_t)), _buffer, (numReadSamples - numSamplesToEnd) * sizeof(int16_t)); if (_randomAccessMode) { @@ -108,22 +107,19 @@ int AudioRingBuffer::readData(char *data, int maxSize) { // push the position of _nextOutput by the number of samples read _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numReadSamples); - if (numReadSamples > 0) { - _isFull = false; - } return numReadSamples * sizeof(int16_t); } -int AudioRingBuffer::writeSamples(const int16_t* source, int maxSamples) { - return writeData((const char*) source, maxSamples * sizeof(int16_t)); +int AudioRingBuffer::writeSamples(const int16_t* source, int maxSamples) { + return writeData((const char*)source, maxSamples * sizeof(int16_t)) / sizeof(int16_t); } int AudioRingBuffer::writeData(const char* data, int maxSize) { // make sure we have enough bytes left for this to be the right amount of audio // otherwise we should not copy that data, and leave the buffer pointers where they are int samplesToCopy = std::min((int)(maxSize / sizeof(int16_t)), _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 @@ -132,19 +128,16 @@ int AudioRingBuffer::writeData(const char* data, int maxSize) { _overflowCount++; qDebug() << "Overflowed ring buffer! Overwriting old data"; } - - if (_endOfLastWrite + samplesToCopy <= _buffer + _sampleCapacity) { + + if (_endOfLastWrite + samplesToCopy <= _buffer + _bufferLength) { memcpy(_endOfLastWrite, data, samplesToCopy * sizeof(int16_t)); } else { - int numSamplesToEnd = (_buffer + _sampleCapacity) - _endOfLastWrite; + int numSamplesToEnd = (_buffer + _bufferLength) - _endOfLastWrite; memcpy(_endOfLastWrite, data, numSamplesToEnd * sizeof(int16_t)); memcpy(_buffer, data + (numSamplesToEnd * sizeof(int16_t)), (samplesToCopy - numSamplesToEnd) * sizeof(int16_t)); } _endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, samplesToCopy); - if (samplesToCopy > 0 && _endOfLastWrite == _nextOutput) { - _isFull = true; - } return samplesToCopy * sizeof(int16_t); } @@ -158,61 +151,52 @@ const int16_t& AudioRingBuffer::operator[] (const int index) const { } void AudioRingBuffer::shiftReadPosition(unsigned int numSamples) { - if (numSamples > 0) { - _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numSamples); - _isFull = false; - } + _nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numSamples); } int AudioRingBuffer::samplesAvailable() const { if (!_endOfLastWrite) { return 0; } - if (_isFull) { - return _sampleCapacity; - } int sampleDifference = _endOfLastWrite - _nextOutput; if (sampleDifference < 0) { - sampleDifference += _sampleCapacity; + sampleDifference += _bufferLength; } return sampleDifference; } -int AudioRingBuffer::addSilentFrame(int numSilentSamples) { +int AudioRingBuffer::addSilentSamples(int silentSamples) { int samplesRoomFor = _sampleCapacity - samplesAvailable(); - if (numSilentSamples > samplesRoomFor) { + if (silentSamples > samplesRoomFor) { // there's not enough room for this write. write as many silent samples as we have room for - numSilentSamples = samplesRoomFor; + silentSamples = samplesRoomFor; qDebug() << "Dropping some silent samples to prevent ring buffer overflow"; } // memset zeroes into the buffer, accomodate a wrap around the end // push the _endOfLastWrite to the correct spot - if (_endOfLastWrite + numSilentSamples <= _buffer + _sampleCapacity) { - memset(_endOfLastWrite, 0, numSilentSamples * sizeof(int16_t)); + if (_endOfLastWrite + silentSamples <= _buffer + _bufferLength) { + memset(_endOfLastWrite, 0, silentSamples * sizeof(int16_t)); } else { - int numSamplesToEnd = (_buffer + _sampleCapacity) - _endOfLastWrite; + int numSamplesToEnd = (_buffer + _bufferLength) - _endOfLastWrite; memset(_endOfLastWrite, 0, numSamplesToEnd * sizeof(int16_t)); - memset(_buffer, 0, (numSilentSamples - numSamplesToEnd) * sizeof(int16_t)); - } - _endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, numSilentSamples); - if (numSilentSamples > 0 && _nextOutput == _endOfLastWrite) { - _isFull = true; + memset(_buffer, 0, (silentSamples - numSamplesToEnd) * sizeof(int16_t)); } + _endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, silentSamples); - return numSilentSamples * sizeof(int16_t); + return silentSamples; } int16_t* AudioRingBuffer::shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const { - if (numSamplesShift > 0 && position + numSamplesShift >= _buffer + _sampleCapacity) { + if (numSamplesShift > 0 && position + numSamplesShift >= _buffer + _bufferLength) { // this shift will wrap the position around to the beginning of the ring - return position + numSamplesShift - _sampleCapacity; + 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 + _sampleCapacity; + return position + numSamplesShift + _bufferLength; } else { return position + numSamplesShift; } @@ -221,22 +205,22 @@ int16_t* AudioRingBuffer::shiftedPositionAccomodatingWrap(int16_t* position, int float AudioRingBuffer::getFrameLoudness(const int16_t* frameStart) const { float loudness = 0.0f; const int16_t* sampleAt = frameStart; - const int16_t* _bufferLastAt = _buffer + _sampleCapacity - 1; - + const int16_t* _bufferLastAt = _buffer + _bufferLength - 1; + for (int i = 0; i < _numFrameSamples; ++i) { loudness += fabsf(*sampleAt); sampleAt = sampleAt == _bufferLastAt ? _buffer : sampleAt + 1; } loudness /= _numFrameSamples; loudness /= MAX_SAMPLE_VALUE; - - return loudness; -} -float AudioRingBuffer::getNextOutputFrameLoudness() const { - return getFrameLoudness(_nextOutput); + return loudness; } float AudioRingBuffer::getFrameLoudness(ConstIterator frameStart) const { return getFrameLoudness(&(*frameStart)); } + +float AudioRingBuffer::getNextOutputFrameLoudness() const { + return getFrameLoudness(_nextOutput); +} diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index 4dd258b2c5..be4dcaf545 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -30,7 +30,7 @@ const int NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL = 512; const int NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL = NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL / sizeof(int16_t); const unsigned int BUFFER_SEND_INTERVAL_USECS = floorf((NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL - / (float) SAMPLE_RATE) * USECS_PER_SECOND); + / (float)SAMPLE_RATE) * USECS_PER_SECOND); const int MAX_SAMPLE_VALUE = std::numeric_limits::max(); const int MIN_SAMPLE_VALUE = std::numeric_limits::min(); @@ -44,33 +44,33 @@ public: void reset(); void resizeForFrameSize(int numFrameSamples); - + void clear(); int getSampleCapacity() const { return _sampleCapacity; } int getFrameCapacity() const { return _frameCapacity; } - + int readSamples(int16_t* destination, int maxSamples); int writeSamples(const int16_t* source, int maxSamples); - + int readData(char* data, int maxSize); int writeData(const char* data, int maxSize); - + int16_t& operator[](const int index); const int16_t& operator[] (const int index) const; - + void shiftReadPosition(unsigned int numSamples); float getNextOutputFrameLoudness() const; - + int samplesAvailable() const; int framesAvailable() const { return samplesAvailable() / _numFrameSamples; } int getNumFrameSamples() const { return _numFrameSamples; } - + int getOverflowCount() const { return _overflowCount; } /// how many times has the ring buffer has overwritten old data - - int addSilentFrame(int numSilentSamples); + + int addSilentSamples(int samples); private: float getFrameLoudness(const int16_t* frameStart) const; @@ -79,12 +79,12 @@ protected: // disallow copying of AudioRingBuffer objects AudioRingBuffer(const AudioRingBuffer&); AudioRingBuffer& operator= (const AudioRingBuffer&); - + int16_t* shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const; int _frameCapacity; int _sampleCapacity; - bool _isFull; + int _bufferLength; // actual length of _buffer: will be one frame larger than _sampleCapacity int _numFrameSamples; int16_t* _nextOutput; int16_t* _endOfLastWrite; @@ -97,13 +97,13 @@ public: class ConstIterator { //public std::iterator < std::forward_iterator_tag, int16_t > { public: ConstIterator() - : _capacity(0), + : _bufferLength(0), _bufferFirst(NULL), _bufferLast(NULL), _at(NULL) {} ConstIterator(int16_t* bufferFirst, int capacity, int16_t* at) - : _capacity(capacity), + : _bufferLength(capacity), _bufferFirst(bufferFirst), _bufferLast(bufferFirst + capacity - 1), _at(at) {} @@ -113,7 +113,7 @@ public: const int16_t& operator*() { return *_at; } ConstIterator& operator=(const ConstIterator& rhs) { - _capacity = rhs._capacity; + _bufferLength = rhs._bufferLength; _bufferFirst = rhs._bufferFirst; _bufferLast = rhs._bufferLast; _at = rhs._at; @@ -147,40 +147,50 @@ public: } ConstIterator operator+(int i) { - return ConstIterator(_bufferFirst, _capacity, atShiftedBy(i)); + return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(i)); } ConstIterator operator-(int i) { - return ConstIterator(_bufferFirst, _capacity, atShiftedBy(-i)); + return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(-i)); } void readSamples(int16_t* dest, int numSamples) { + int16_t* at = _at; for (int i = 0; i < numSamples; i++) { - *dest = *(*this); + *dest = *at; ++dest; - ++(*this); + at = (at == _bufferLast) ? _bufferFirst : at + 1; } } - + + void readSamplesWithFade(int16_t* dest, int numSamples, float fade) { + int16_t* at = _at; + for (int i = 0; i < numSamples; i++) { + *dest = (float)*at * fade; + ++dest; + at = (at == _bufferLast) ? _bufferFirst : at + 1; + } + } + private: int16_t* atShiftedBy(int i) { - i = (_at - _bufferFirst + i) % _capacity; + i = (_at - _bufferFirst + i) % _bufferLength; if (i < 0) { - i += _capacity; + i += _bufferLength; } return _bufferFirst + i; } private: - int _capacity; + int _bufferLength; int16_t* _bufferFirst; int16_t* _bufferLast; int16_t* _at; }; - ConstIterator nextOutput() const { return ConstIterator(_buffer, _sampleCapacity, _nextOutput); } + ConstIterator nextOutput() const { return ConstIterator(_buffer, _bufferLength, _nextOutput); } float getFrameLoudness(ConstIterator frameStart) const; }; -#endif // hifi_AudioRingBuffer_h +#endif // hifi_AudioRingBuffer_h \ No newline at end of file diff --git a/tests/audio/src/AudioRingBufferTests.cpp b/tests/audio/src/AudioRingBufferTests.cpp index b9ed596e52..f31f9988d6 100644 --- a/tests/audio/src/AudioRingBufferTests.cpp +++ b/tests/audio/src/AudioRingBufferTests.cpp @@ -27,28 +27,28 @@ void AudioRingBufferTests::runAllTests() { int16_t readData[10000]; int readIndexAt; - + AudioRingBuffer ringBuffer(10, false, 10); // makes buffer of 100 int16_t samples for (int T = 0; T < 300; T++) { - + writeIndexAt = 0; readIndexAt = 0; // write 73 samples, 73 samples in buffer - writeIndexAt += ringBuffer.writeSamples(&writeData[writeIndexAt], 73) / sizeof(int16_t); + writeIndexAt += ringBuffer.writeSamples(&writeData[writeIndexAt], 73); assertBufferSize(ringBuffer, 73); // read 43 samples, 30 samples in buffer - readIndexAt += ringBuffer.readSamples(&readData[readIndexAt], 43) / sizeof(int16_t); + readIndexAt += ringBuffer.readSamples(&readData[readIndexAt], 43); assertBufferSize(ringBuffer, 30); // write 70 samples, 100 samples in buffer (full) - writeIndexAt += ringBuffer.writeSamples(&writeData[writeIndexAt], 70) / sizeof(int16_t); + writeIndexAt += ringBuffer.writeSamples(&writeData[writeIndexAt], 70); assertBufferSize(ringBuffer, 100); // read 100 samples, 0 samples in buffer (empty) - readIndexAt += ringBuffer.readSamples(&readData[readIndexAt], 100) / sizeof(int16_t); + readIndexAt += ringBuffer.readSamples(&readData[readIndexAt], 100); assertBufferSize(ringBuffer, 0); @@ -65,15 +65,15 @@ void AudioRingBufferTests::runAllTests() { readIndexAt = 0; // write 59 samples, 59 samples in buffer - writeIndexAt += ringBuffer.writeSamples(&writeData[writeIndexAt], 59) / sizeof(int16_t); + writeIndexAt += ringBuffer.writeSamples(&writeData[writeIndexAt], 59); assertBufferSize(ringBuffer, 59); // write 99 samples, 100 samples in buffer - writeIndexAt += ringBuffer.writeSamples(&writeData[writeIndexAt], 99) / sizeof(int16_t); + writeIndexAt += ringBuffer.writeSamples(&writeData[writeIndexAt], 99); assertBufferSize(ringBuffer, 100); // read 100 samples, 0 samples in buffer - readIndexAt += ringBuffer.readSamples(&readData[readIndexAt], 100) / sizeof(int16_t); + readIndexAt += ringBuffer.readSamples(&readData[readIndexAt], 100); assertBufferSize(ringBuffer, 0); // verify 100 samples of read data @@ -88,23 +88,23 @@ void AudioRingBufferTests::runAllTests() { readIndexAt = 0; // write 77 samples, 77 samples in buffer - writeIndexAt += ringBuffer.writeSamples(&writeData[writeIndexAt], 77) / sizeof(int16_t); + writeIndexAt += ringBuffer.writeSamples(&writeData[writeIndexAt], 77); assertBufferSize(ringBuffer, 77); // write 24 samples, 100 samples in buffer (overwrote one sample: "0") - writeIndexAt += ringBuffer.writeSamples(&writeData[writeIndexAt], 24) / sizeof(int16_t); + writeIndexAt += ringBuffer.writeSamples(&writeData[writeIndexAt], 24); assertBufferSize(ringBuffer, 100); // write 29 silent samples, 100 samples in buffer, make sure non were added int samplesWritten; - if ((samplesWritten = ringBuffer.addSilentFrame(29)) != 0) { - qDebug("addSilentFrame(29) incorrect! Expected: 0 Actual: %d", samplesWritten); + if ((samplesWritten = ringBuffer.addSilentSamples(29)) != 0) { + qDebug("addSilentSamples(29) incorrect! Expected: 0 Actual: %d", samplesWritten); return; } assertBufferSize(ringBuffer, 100); // read 3 samples, 97 samples in buffer (expect to read "1", "2", "3") - readIndexAt += ringBuffer.readSamples(&readData[readIndexAt], 3) / sizeof(int16_t); + readIndexAt += ringBuffer.readSamples(&readData[readIndexAt], 3); for (int i = 0; i < 3; i++) { if (readData[i] != i + 1) { qDebug("Second readData[%d] incorrect! Expcted: %d Actual: %d", i, i + 1, readData[i]); @@ -114,14 +114,14 @@ void AudioRingBufferTests::runAllTests() { assertBufferSize(ringBuffer, 97); // write 4 silent samples, 100 samples in buffer - if ((samplesWritten = ringBuffer.addSilentFrame(4) / sizeof(int16_t)) != 3) { - qDebug("addSilentFrame(4) incorrect! Exptected: 3 Actual: %d", samplesWritten); + if ((samplesWritten = ringBuffer.addSilentSamples(4)) != 3) { + qDebug("addSilentSamples(4) incorrect! Exptected: 3 Actual: %d", samplesWritten); return; } assertBufferSize(ringBuffer, 100); // read back 97 samples (the non-silent samples), 3 samples in buffer (expect to read "4" thru "100") - readIndexAt += ringBuffer.readSamples(&readData[readIndexAt], 97) / sizeof(int16_t); + readIndexAt += ringBuffer.readSamples(&readData[readIndexAt], 97); for (int i = 3; i < 100; i++) { if (readData[i] != i + 1) { qDebug("third readData[%d] incorrect! Expcted: %d Actual: %d", i, i + 1, readData[i]); @@ -131,7 +131,7 @@ void AudioRingBufferTests::runAllTests() { assertBufferSize(ringBuffer, 3); // read back 3 silent samples, 0 samples in buffer - readIndexAt += ringBuffer.readSamples(&readData[readIndexAt], 3) / sizeof(int16_t); + readIndexAt += ringBuffer.readSamples(&readData[readIndexAt], 3); for (int i = 100; i < 103; i++) { if (readData[i] != 0) { qDebug("Fourth readData[%d] incorrect! Expcted: %d Actual: %d", i, 0, readData[i]); @@ -143,4 +143,3 @@ void AudioRingBufferTests::runAllTests() { qDebug() << "PASSED"; } -