mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 08:49:05 +02:00
updated AudioRingBuffer bytes vs samples returns
This commit is contained in:
parent
f71e1edd30
commit
4ec84b32b0
3 changed files with 97 additions and 104 deletions
|
@ -20,18 +20,16 @@
|
||||||
|
|
||||||
|
|
||||||
AudioRingBuffer::AudioRingBuffer(int numFrameSamples, bool randomAccessMode, int numFramesCapacity) :
|
AudioRingBuffer::AudioRingBuffer(int numFrameSamples, bool randomAccessMode, int numFramesCapacity) :
|
||||||
_frameCapacity(numFramesCapacity),
|
_frameCapacity(numFramesCapacity),
|
||||||
_sampleCapacity(numFrameSamples * numFramesCapacity),
|
_sampleCapacity(numFrameSamples * numFramesCapacity),
|
||||||
_isFull(false),
|
_bufferLength(numFrameSamples * (numFramesCapacity + 1)),
|
||||||
_numFrameSamples(numFrameSamples),
|
_numFrameSamples(numFrameSamples),
|
||||||
_randomAccessMode(randomAccessMode),
|
_randomAccessMode(randomAccessMode),
|
||||||
_overflowCount(0)
|
_overflowCount(0)
|
||||||
{
|
{
|
||||||
if (numFrameSamples) {
|
if (numFrameSamples) {
|
||||||
_buffer = new int16_t[_sampleCapacity];
|
_buffer = new int16_t[_bufferLength];
|
||||||
if (_randomAccessMode) {
|
memset(_buffer, 0, _bufferLength * sizeof(int16_t));
|
||||||
memset(_buffer, 0, _sampleCapacity * sizeof(int16_t));
|
|
||||||
}
|
|
||||||
_nextOutput = _buffer;
|
_nextOutput = _buffer;
|
||||||
_endOfLastWrite = _buffer;
|
_endOfLastWrite = _buffer;
|
||||||
} else {
|
} else {
|
||||||
|
@ -53,28 +51,29 @@ void AudioRingBuffer::reset() {
|
||||||
void AudioRingBuffer::resizeForFrameSize(int numFrameSamples) {
|
void AudioRingBuffer::resizeForFrameSize(int numFrameSamples) {
|
||||||
delete[] _buffer;
|
delete[] _buffer;
|
||||||
_sampleCapacity = numFrameSamples * _frameCapacity;
|
_sampleCapacity = numFrameSamples * _frameCapacity;
|
||||||
|
_bufferLength = numFrameSamples * (_frameCapacity + 1);
|
||||||
_numFrameSamples = numFrameSamples;
|
_numFrameSamples = numFrameSamples;
|
||||||
_buffer = new int16_t[_sampleCapacity];
|
_buffer = new int16_t[_bufferLength];
|
||||||
|
memset(_buffer, 0, _bufferLength * sizeof(int16_t));
|
||||||
if (_randomAccessMode) {
|
if (_randomAccessMode) {
|
||||||
memset(_buffer, 0, _sampleCapacity * sizeof(int16_t));
|
memset(_buffer, 0, _bufferLength * sizeof(int16_t));
|
||||||
}
|
}
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioRingBuffer::clear() {
|
void AudioRingBuffer::clear() {
|
||||||
_isFull = false;
|
|
||||||
_endOfLastWrite = _buffer;
|
_endOfLastWrite = _buffer;
|
||||||
_nextOutput = _buffer;
|
_nextOutput = _buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudioRingBuffer::readSamples(int16_t* destination, int maxSamples) {
|
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) {
|
int AudioRingBuffer::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 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
|
// 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
|
// 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;
|
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
|
// 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
|
// read to the end of the buffer
|
||||||
int numSamplesToEnd = (_buffer + _sampleCapacity) - _nextOutput;
|
int numSamplesToEnd = (_buffer + _bufferLength) - _nextOutput;
|
||||||
memcpy(data, _nextOutput, numSamplesToEnd * sizeof(int16_t));
|
memcpy(data, _nextOutput, numSamplesToEnd * sizeof(int16_t));
|
||||||
if (_randomAccessMode) {
|
if (_randomAccessMode) {
|
||||||
memset(_nextOutput, 0, numSamplesToEnd * sizeof(int16_t)); // clear it
|
memset(_nextOutput, 0, numSamplesToEnd * sizeof(int16_t)); // clear it
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 * sizeof(int16_t)), _buffer, (numReadSamples - numSamplesToEnd) * sizeof(int16_t));
|
||||||
if (_randomAccessMode) {
|
if (_randomAccessMode) {
|
||||||
|
@ -108,22 +107,19 @@ int AudioRingBuffer::readData(char *data, int maxSize) {
|
||||||
|
|
||||||
// push the position of _nextOutput by the number of samples read
|
// push the position of _nextOutput by the number of samples read
|
||||||
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numReadSamples);
|
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numReadSamples);
|
||||||
if (numReadSamples > 0) {
|
|
||||||
_isFull = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return numReadSamples * sizeof(int16_t);
|
return numReadSamples * sizeof(int16_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudioRingBuffer::writeSamples(const int16_t* source, int maxSamples) {
|
int AudioRingBuffer::writeSamples(const int16_t* source, int maxSamples) {
|
||||||
return writeData((const char*) source, maxSamples * sizeof(int16_t));
|
return writeData((const char*)source, maxSamples * sizeof(int16_t)) / sizeof(int16_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudioRingBuffer::writeData(const char* data, int maxSize) {
|
int AudioRingBuffer::writeData(const char* data, int maxSize) {
|
||||||
// make sure we have enough bytes left for this to be the right amount of audio
|
// 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
|
// 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 samplesToCopy = std::min((int)(maxSize / sizeof(int16_t)), _sampleCapacity);
|
||||||
|
|
||||||
int samplesRoomFor = _sampleCapacity - samplesAvailable();
|
int samplesRoomFor = _sampleCapacity - samplesAvailable();
|
||||||
if (samplesToCopy > samplesRoomFor) {
|
if (samplesToCopy > samplesRoomFor) {
|
||||||
// there's not enough room for this write. erase old data to make room for this new data
|
// 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++;
|
_overflowCount++;
|
||||||
qDebug() << "Overflowed ring buffer! Overwriting old data";
|
qDebug() << "Overflowed ring buffer! Overwriting old data";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_endOfLastWrite + samplesToCopy <= _buffer + _sampleCapacity) {
|
if (_endOfLastWrite + samplesToCopy <= _buffer + _bufferLength) {
|
||||||
memcpy(_endOfLastWrite, data, samplesToCopy * sizeof(int16_t));
|
memcpy(_endOfLastWrite, data, samplesToCopy * sizeof(int16_t));
|
||||||
} else {
|
} else {
|
||||||
int numSamplesToEnd = (_buffer + _sampleCapacity) - _endOfLastWrite;
|
int numSamplesToEnd = (_buffer + _bufferLength) - _endOfLastWrite;
|
||||||
memcpy(_endOfLastWrite, data, numSamplesToEnd * sizeof(int16_t));
|
memcpy(_endOfLastWrite, data, numSamplesToEnd * sizeof(int16_t));
|
||||||
memcpy(_buffer, data + (numSamplesToEnd * sizeof(int16_t)), (samplesToCopy - numSamplesToEnd) * sizeof(int16_t));
|
memcpy(_buffer, data + (numSamplesToEnd * sizeof(int16_t)), (samplesToCopy - numSamplesToEnd) * sizeof(int16_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
_endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, samplesToCopy);
|
_endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, samplesToCopy);
|
||||||
if (samplesToCopy > 0 && _endOfLastWrite == _nextOutput) {
|
|
||||||
_isFull = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return samplesToCopy * sizeof(int16_t);
|
return samplesToCopy * sizeof(int16_t);
|
||||||
}
|
}
|
||||||
|
@ -158,61 +151,52 @@ const int16_t& AudioRingBuffer::operator[] (const int index) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioRingBuffer::shiftReadPosition(unsigned int numSamples) {
|
void AudioRingBuffer::shiftReadPosition(unsigned int numSamples) {
|
||||||
if (numSamples > 0) {
|
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numSamples);
|
||||||
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numSamples);
|
|
||||||
_isFull = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudioRingBuffer::samplesAvailable() const {
|
int AudioRingBuffer::samplesAvailable() const {
|
||||||
if (!_endOfLastWrite) {
|
if (!_endOfLastWrite) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (_isFull) {
|
|
||||||
return _sampleCapacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sampleDifference = _endOfLastWrite - _nextOutput;
|
int sampleDifference = _endOfLastWrite - _nextOutput;
|
||||||
if (sampleDifference < 0) {
|
if (sampleDifference < 0) {
|
||||||
sampleDifference += _sampleCapacity;
|
sampleDifference += _bufferLength;
|
||||||
}
|
}
|
||||||
return sampleDifference;
|
return sampleDifference;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudioRingBuffer::addSilentFrame(int numSilentSamples) {
|
int AudioRingBuffer::addSilentSamples(int silentSamples) {
|
||||||
|
|
||||||
int samplesRoomFor = _sampleCapacity - samplesAvailable();
|
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
|
// 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";
|
qDebug() << "Dropping some silent samples to prevent ring buffer overflow";
|
||||||
}
|
}
|
||||||
|
|
||||||
// memset zeroes into the buffer, accomodate a wrap around the end
|
// memset zeroes into the buffer, accomodate a wrap around the end
|
||||||
// push the _endOfLastWrite to the correct spot
|
// push the _endOfLastWrite to the correct spot
|
||||||
if (_endOfLastWrite + numSilentSamples <= _buffer + _sampleCapacity) {
|
if (_endOfLastWrite + silentSamples <= _buffer + _bufferLength) {
|
||||||
memset(_endOfLastWrite, 0, numSilentSamples * sizeof(int16_t));
|
memset(_endOfLastWrite, 0, silentSamples * sizeof(int16_t));
|
||||||
} else {
|
} else {
|
||||||
int numSamplesToEnd = (_buffer + _sampleCapacity) - _endOfLastWrite;
|
int numSamplesToEnd = (_buffer + _bufferLength) - _endOfLastWrite;
|
||||||
memset(_endOfLastWrite, 0, numSamplesToEnd * sizeof(int16_t));
|
memset(_endOfLastWrite, 0, numSamplesToEnd * sizeof(int16_t));
|
||||||
memset(_buffer, 0, (numSilentSamples - numSamplesToEnd) * sizeof(int16_t));
|
memset(_buffer, 0, (silentSamples - numSamplesToEnd) * sizeof(int16_t));
|
||||||
}
|
|
||||||
_endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, numSilentSamples);
|
|
||||||
if (numSilentSamples > 0 && _nextOutput == _endOfLastWrite) {
|
|
||||||
_isFull = true;
|
|
||||||
}
|
}
|
||||||
|
_endOfLastWrite = shiftedPositionAccomodatingWrap(_endOfLastWrite, silentSamples);
|
||||||
|
|
||||||
return numSilentSamples * sizeof(int16_t);
|
return silentSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t* AudioRingBuffer::shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const {
|
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
|
// 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) {
|
} else if (numSamplesShift < 0 && position + numSamplesShift < _buffer) {
|
||||||
// this shift will go around to the end of the ring
|
// this shift will go around to the end of the ring
|
||||||
return position + numSamplesShift + _sampleCapacity;
|
return position + numSamplesShift + _bufferLength;
|
||||||
} else {
|
} else {
|
||||||
return position + numSamplesShift;
|
return position + numSamplesShift;
|
||||||
}
|
}
|
||||||
|
@ -221,22 +205,22 @@ int16_t* AudioRingBuffer::shiftedPositionAccomodatingWrap(int16_t* position, int
|
||||||
float AudioRingBuffer::getFrameLoudness(const int16_t* frameStart) const {
|
float AudioRingBuffer::getFrameLoudness(const int16_t* frameStart) const {
|
||||||
float loudness = 0.0f;
|
float loudness = 0.0f;
|
||||||
const int16_t* sampleAt = frameStart;
|
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) {
|
for (int i = 0; i < _numFrameSamples; ++i) {
|
||||||
loudness += fabsf(*sampleAt);
|
loudness += fabsf(*sampleAt);
|
||||||
sampleAt = sampleAt == _bufferLastAt ? _buffer : sampleAt + 1;
|
sampleAt = sampleAt == _bufferLastAt ? _buffer : sampleAt + 1;
|
||||||
}
|
}
|
||||||
loudness /= _numFrameSamples;
|
loudness /= _numFrameSamples;
|
||||||
loudness /= MAX_SAMPLE_VALUE;
|
loudness /= MAX_SAMPLE_VALUE;
|
||||||
|
|
||||||
return loudness;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AudioRingBuffer::getNextOutputFrameLoudness() const {
|
return loudness;
|
||||||
return getFrameLoudness(_nextOutput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float AudioRingBuffer::getFrameLoudness(ConstIterator frameStart) const {
|
float AudioRingBuffer::getFrameLoudness(ConstIterator frameStart) const {
|
||||||
return getFrameLoudness(&(*frameStart));
|
return getFrameLoudness(&(*frameStart));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float AudioRingBuffer::getNextOutputFrameLoudness() const {
|
||||||
|
return getFrameLoudness(_nextOutput);
|
||||||
|
}
|
||||||
|
|
|
@ -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 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
|
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<int16_t>::max();
|
const int MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
|
||||||
const int MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
|
const int MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
|
||||||
|
@ -44,33 +44,33 @@ public:
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
void resizeForFrameSize(int numFrameSamples);
|
void resizeForFrameSize(int numFrameSamples);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
int getSampleCapacity() const { return _sampleCapacity; }
|
int getSampleCapacity() const { return _sampleCapacity; }
|
||||||
int getFrameCapacity() const { return _frameCapacity; }
|
int getFrameCapacity() const { return _frameCapacity; }
|
||||||
|
|
||||||
int readSamples(int16_t* destination, int maxSamples);
|
int readSamples(int16_t* destination, int maxSamples);
|
||||||
int writeSamples(const int16_t* source, int maxSamples);
|
int writeSamples(const int16_t* source, int maxSamples);
|
||||||
|
|
||||||
int readData(char* data, int maxSize);
|
int readData(char* data, int maxSize);
|
||||||
int writeData(const char* data, int maxSize);
|
int writeData(const char* data, int maxSize);
|
||||||
|
|
||||||
int16_t& operator[](const int index);
|
int16_t& operator[](const int index);
|
||||||
const int16_t& operator[] (const int index) const;
|
const int16_t& operator[] (const int index) const;
|
||||||
|
|
||||||
void shiftReadPosition(unsigned int numSamples);
|
void shiftReadPosition(unsigned int numSamples);
|
||||||
|
|
||||||
float getNextOutputFrameLoudness() const;
|
float getNextOutputFrameLoudness() const;
|
||||||
|
|
||||||
int samplesAvailable() const;
|
int samplesAvailable() const;
|
||||||
int framesAvailable() const { return samplesAvailable() / _numFrameSamples; }
|
int framesAvailable() const { return samplesAvailable() / _numFrameSamples; }
|
||||||
|
|
||||||
int getNumFrameSamples() const { return _numFrameSamples; }
|
int getNumFrameSamples() const { return _numFrameSamples; }
|
||||||
|
|
||||||
int getOverflowCount() const { return _overflowCount; } /// how many times has the ring buffer has overwritten old data
|
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:
|
private:
|
||||||
float getFrameLoudness(const int16_t* frameStart) const;
|
float getFrameLoudness(const int16_t* frameStart) const;
|
||||||
|
@ -79,12 +79,12 @@ protected:
|
||||||
// disallow copying of AudioRingBuffer objects
|
// disallow copying of AudioRingBuffer objects
|
||||||
AudioRingBuffer(const AudioRingBuffer&);
|
AudioRingBuffer(const AudioRingBuffer&);
|
||||||
AudioRingBuffer& operator= (const AudioRingBuffer&);
|
AudioRingBuffer& operator= (const AudioRingBuffer&);
|
||||||
|
|
||||||
int16_t* shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const;
|
int16_t* shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const;
|
||||||
|
|
||||||
int _frameCapacity;
|
int _frameCapacity;
|
||||||
int _sampleCapacity;
|
int _sampleCapacity;
|
||||||
bool _isFull;
|
int _bufferLength; // actual length of _buffer: will be one frame larger than _sampleCapacity
|
||||||
int _numFrameSamples;
|
int _numFrameSamples;
|
||||||
int16_t* _nextOutput;
|
int16_t* _nextOutput;
|
||||||
int16_t* _endOfLastWrite;
|
int16_t* _endOfLastWrite;
|
||||||
|
@ -97,13 +97,13 @@ public:
|
||||||
class ConstIterator { //public std::iterator < std::forward_iterator_tag, int16_t > {
|
class ConstIterator { //public std::iterator < std::forward_iterator_tag, int16_t > {
|
||||||
public:
|
public:
|
||||||
ConstIterator()
|
ConstIterator()
|
||||||
: _capacity(0),
|
: _bufferLength(0),
|
||||||
_bufferFirst(NULL),
|
_bufferFirst(NULL),
|
||||||
_bufferLast(NULL),
|
_bufferLast(NULL),
|
||||||
_at(NULL) {}
|
_at(NULL) {}
|
||||||
|
|
||||||
ConstIterator(int16_t* bufferFirst, int capacity, int16_t* at)
|
ConstIterator(int16_t* bufferFirst, int capacity, int16_t* at)
|
||||||
: _capacity(capacity),
|
: _bufferLength(capacity),
|
||||||
_bufferFirst(bufferFirst),
|
_bufferFirst(bufferFirst),
|
||||||
_bufferLast(bufferFirst + capacity - 1),
|
_bufferLast(bufferFirst + capacity - 1),
|
||||||
_at(at) {}
|
_at(at) {}
|
||||||
|
@ -113,7 +113,7 @@ public:
|
||||||
const int16_t& operator*() { return *_at; }
|
const int16_t& operator*() { return *_at; }
|
||||||
|
|
||||||
ConstIterator& operator=(const ConstIterator& rhs) {
|
ConstIterator& operator=(const ConstIterator& rhs) {
|
||||||
_capacity = rhs._capacity;
|
_bufferLength = rhs._bufferLength;
|
||||||
_bufferFirst = rhs._bufferFirst;
|
_bufferFirst = rhs._bufferFirst;
|
||||||
_bufferLast = rhs._bufferLast;
|
_bufferLast = rhs._bufferLast;
|
||||||
_at = rhs._at;
|
_at = rhs._at;
|
||||||
|
@ -147,40 +147,50 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstIterator operator+(int i) {
|
ConstIterator operator+(int i) {
|
||||||
return ConstIterator(_bufferFirst, _capacity, atShiftedBy(i));
|
return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
ConstIterator operator-(int i) {
|
ConstIterator operator-(int i) {
|
||||||
return ConstIterator(_bufferFirst, _capacity, atShiftedBy(-i));
|
return ConstIterator(_bufferFirst, _bufferLength, atShiftedBy(-i));
|
||||||
}
|
}
|
||||||
|
|
||||||
void readSamples(int16_t* dest, int numSamples) {
|
void readSamples(int16_t* dest, int numSamples) {
|
||||||
|
int16_t* at = _at;
|
||||||
for (int i = 0; i < numSamples; i++) {
|
for (int i = 0; i < numSamples; i++) {
|
||||||
*dest = *(*this);
|
*dest = *at;
|
||||||
++dest;
|
++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:
|
private:
|
||||||
int16_t* atShiftedBy(int i) {
|
int16_t* atShiftedBy(int i) {
|
||||||
i = (_at - _bufferFirst + i) % _capacity;
|
i = (_at - _bufferFirst + i) % _bufferLength;
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
i += _capacity;
|
i += _bufferLength;
|
||||||
}
|
}
|
||||||
return _bufferFirst + i;
|
return _bufferFirst + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _capacity;
|
int _bufferLength;
|
||||||
int16_t* _bufferFirst;
|
int16_t* _bufferFirst;
|
||||||
int16_t* _bufferLast;
|
int16_t* _bufferLast;
|
||||||
int16_t* _at;
|
int16_t* _at;
|
||||||
};
|
};
|
||||||
|
|
||||||
ConstIterator nextOutput() const { return ConstIterator(_buffer, _sampleCapacity, _nextOutput); }
|
ConstIterator nextOutput() const { return ConstIterator(_buffer, _bufferLength, _nextOutput); }
|
||||||
|
|
||||||
float getFrameLoudness(ConstIterator frameStart) const;
|
float getFrameLoudness(ConstIterator frameStart) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AudioRingBuffer_h
|
#endif // hifi_AudioRingBuffer_h
|
|
@ -27,28 +27,28 @@ void AudioRingBufferTests::runAllTests() {
|
||||||
|
|
||||||
int16_t readData[10000];
|
int16_t readData[10000];
|
||||||
int readIndexAt;
|
int readIndexAt;
|
||||||
|
|
||||||
|
|
||||||
AudioRingBuffer ringBuffer(10, false, 10); // makes buffer of 100 int16_t samples
|
AudioRingBuffer ringBuffer(10, false, 10); // makes buffer of 100 int16_t samples
|
||||||
for (int T = 0; T < 300; T++) {
|
for (int T = 0; T < 300; T++) {
|
||||||
|
|
||||||
writeIndexAt = 0;
|
writeIndexAt = 0;
|
||||||
readIndexAt = 0;
|
readIndexAt = 0;
|
||||||
|
|
||||||
// write 73 samples, 73 samples in buffer
|
// 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);
|
assertBufferSize(ringBuffer, 73);
|
||||||
|
|
||||||
// read 43 samples, 30 samples in buffer
|
// 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);
|
assertBufferSize(ringBuffer, 30);
|
||||||
|
|
||||||
// write 70 samples, 100 samples in buffer (full)
|
// 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);
|
assertBufferSize(ringBuffer, 100);
|
||||||
|
|
||||||
// read 100 samples, 0 samples in buffer (empty)
|
// 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);
|
assertBufferSize(ringBuffer, 0);
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,15 +65,15 @@ void AudioRingBufferTests::runAllTests() {
|
||||||
readIndexAt = 0;
|
readIndexAt = 0;
|
||||||
|
|
||||||
// write 59 samples, 59 samples in buffer
|
// 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);
|
assertBufferSize(ringBuffer, 59);
|
||||||
|
|
||||||
// write 99 samples, 100 samples in buffer
|
// 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);
|
assertBufferSize(ringBuffer, 100);
|
||||||
|
|
||||||
// read 100 samples, 0 samples in buffer
|
// 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);
|
assertBufferSize(ringBuffer, 0);
|
||||||
|
|
||||||
// verify 100 samples of read data
|
// verify 100 samples of read data
|
||||||
|
@ -88,23 +88,23 @@ void AudioRingBufferTests::runAllTests() {
|
||||||
readIndexAt = 0;
|
readIndexAt = 0;
|
||||||
|
|
||||||
// write 77 samples, 77 samples in buffer
|
// 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);
|
assertBufferSize(ringBuffer, 77);
|
||||||
|
|
||||||
// write 24 samples, 100 samples in buffer (overwrote one sample: "0")
|
// 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);
|
assertBufferSize(ringBuffer, 100);
|
||||||
|
|
||||||
// write 29 silent samples, 100 samples in buffer, make sure non were added
|
// write 29 silent samples, 100 samples in buffer, make sure non were added
|
||||||
int samplesWritten;
|
int samplesWritten;
|
||||||
if ((samplesWritten = ringBuffer.addSilentFrame(29)) != 0) {
|
if ((samplesWritten = ringBuffer.addSilentSamples(29)) != 0) {
|
||||||
qDebug("addSilentFrame(29) incorrect! Expected: 0 Actual: %d", samplesWritten);
|
qDebug("addSilentSamples(29) incorrect! Expected: 0 Actual: %d", samplesWritten);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assertBufferSize(ringBuffer, 100);
|
assertBufferSize(ringBuffer, 100);
|
||||||
|
|
||||||
// read 3 samples, 97 samples in buffer (expect to read "1", "2", "3")
|
// 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++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (readData[i] != i + 1) {
|
if (readData[i] != i + 1) {
|
||||||
qDebug("Second readData[%d] incorrect! Expcted: %d Actual: %d", i, i + 1, readData[i]);
|
qDebug("Second readData[%d] incorrect! Expcted: %d Actual: %d", i, i + 1, readData[i]);
|
||||||
|
@ -114,14 +114,14 @@ void AudioRingBufferTests::runAllTests() {
|
||||||
assertBufferSize(ringBuffer, 97);
|
assertBufferSize(ringBuffer, 97);
|
||||||
|
|
||||||
// write 4 silent samples, 100 samples in buffer
|
// write 4 silent samples, 100 samples in buffer
|
||||||
if ((samplesWritten = ringBuffer.addSilentFrame(4) / sizeof(int16_t)) != 3) {
|
if ((samplesWritten = ringBuffer.addSilentSamples(4)) != 3) {
|
||||||
qDebug("addSilentFrame(4) incorrect! Exptected: 3 Actual: %d", samplesWritten);
|
qDebug("addSilentSamples(4) incorrect! Exptected: 3 Actual: %d", samplesWritten);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assertBufferSize(ringBuffer, 100);
|
assertBufferSize(ringBuffer, 100);
|
||||||
|
|
||||||
// read back 97 samples (the non-silent samples), 3 samples in buffer (expect to read "4" thru "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++) {
|
for (int i = 3; i < 100; i++) {
|
||||||
if (readData[i] != i + 1) {
|
if (readData[i] != i + 1) {
|
||||||
qDebug("third readData[%d] incorrect! Expcted: %d Actual: %d", i, i + 1, readData[i]);
|
qDebug("third readData[%d] incorrect! Expcted: %d Actual: %d", i, i + 1, readData[i]);
|
||||||
|
@ -131,7 +131,7 @@ void AudioRingBufferTests::runAllTests() {
|
||||||
assertBufferSize(ringBuffer, 3);
|
assertBufferSize(ringBuffer, 3);
|
||||||
|
|
||||||
// read back 3 silent samples, 0 samples in buffer
|
// 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++) {
|
for (int i = 100; i < 103; i++) {
|
||||||
if (readData[i] != 0) {
|
if (readData[i] != 0) {
|
||||||
qDebug("Fourth readData[%d] incorrect! Expcted: %d Actual: %d", i, 0, readData[i]);
|
qDebug("Fourth readData[%d] incorrect! Expcted: %d Actual: %d", i, 0, readData[i]);
|
||||||
|
@ -143,4 +143,3 @@ void AudioRingBufferTests::runAllTests() {
|
||||||
|
|
||||||
qDebug() << "PASSED";
|
qDebug() << "PASSED";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue