mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-30 13:03:10 +02:00
added extra sample in AudioRingBuffer...
changed buffer overflow behavior to overwrite old data in writeData; added overflow behavior to drop silent samples in addSilentFrame
This commit is contained in:
parent
c2b22c0aa2
commit
8e2bb130f7
3 changed files with 47 additions and 26 deletions
|
@ -28,10 +28,12 @@ AudioRingBuffer::AudioRingBuffer(int numFrameSamples, bool randomAccessMode) :
|
||||||
_hasStarted(false),
|
_hasStarted(false),
|
||||||
_randomAccessMode(randomAccessMode)
|
_randomAccessMode(randomAccessMode)
|
||||||
{
|
{
|
||||||
|
_arrayLength = _sampleCapacity + 1;
|
||||||
|
|
||||||
if (numFrameSamples) {
|
if (numFrameSamples) {
|
||||||
_buffer = new int16_t[_sampleCapacity];
|
_buffer = new int16_t[_arrayLength];
|
||||||
if (_randomAccessMode) {
|
if (_randomAccessMode) {
|
||||||
memset(_buffer, 0, _sampleCapacity * sizeof(int16_t));
|
memset(_buffer, 0, _arrayLength * sizeof(int16_t));
|
||||||
}
|
}
|
||||||
_nextOutput = _buffer;
|
_nextOutput = _buffer;
|
||||||
_endOfLastWrite = _buffer;
|
_endOfLastWrite = _buffer;
|
||||||
|
@ -55,9 +57,10 @@ void AudioRingBuffer::reset() {
|
||||||
void AudioRingBuffer::resizeForFrameSize(qint64 numFrameSamples) {
|
void AudioRingBuffer::resizeForFrameSize(qint64 numFrameSamples) {
|
||||||
delete[] _buffer;
|
delete[] _buffer;
|
||||||
_sampleCapacity = numFrameSamples * RING_BUFFER_LENGTH_FRAMES;
|
_sampleCapacity = numFrameSamples * RING_BUFFER_LENGTH_FRAMES;
|
||||||
_buffer = new int16_t[_sampleCapacity];
|
_arrayLength = _sampleCapacity + 1;
|
||||||
|
_buffer = new int16_t[_arrayLength];
|
||||||
if (_randomAccessMode) {
|
if (_randomAccessMode) {
|
||||||
memset(_buffer, 0, _sampleCapacity * sizeof(int16_t));
|
memset(_buffer, 0, _arrayLength * sizeof(int16_t));
|
||||||
}
|
}
|
||||||
_nextOutput = _buffer;
|
_nextOutput = _buffer;
|
||||||
_endOfLastWrite = _buffer;
|
_endOfLastWrite = _buffer;
|
||||||
|
@ -87,11 +90,11 @@ qint64 AudioRingBuffer::readData(char *data, qint64 maxSize) {
|
||||||
numReadSamples = _endOfLastWrite ? (maxSize / sizeof(int16_t)) : 0;
|
numReadSamples = _endOfLastWrite ? (maxSize / sizeof(int16_t)) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_nextOutput + numReadSamples > _buffer + _sampleCapacity) {
|
if (_nextOutput + numReadSamples > _buffer + _arrayLength) {
|
||||||
// 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 + _arrayLength) - _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
|
||||||
|
@ -125,19 +128,28 @@ qint64 AudioRingBuffer::writeData(const char* data, qint64 maxSize) {
|
||||||
// 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((quint64)(maxSize / sizeof(int16_t)), (quint64)_sampleCapacity);
|
int samplesToCopy = std::min((quint64)(maxSize / sizeof(int16_t)), (quint64)_sampleCapacity);
|
||||||
|
/*
|
||||||
if (_hasStarted && samplesToCopy > _sampleCapacity - samplesAvailable()) {
|
if (_hasStarted && samplesToCopy > _sampleCapacity - samplesAvailable()) {
|
||||||
// this read will cross the next output, so call us starved and reset the buffer
|
// this write would overflow the buffer, so call us starved and reset the buffer
|
||||||
qDebug() << "Filled the ring buffer. Resetting.";
|
qDebug() << "Overflowed the ring buffer. Resetting.";
|
||||||
_endOfLastWrite = _buffer;
|
_endOfLastWrite = _buffer;
|
||||||
_nextOutput = _buffer;
|
_nextOutput = _buffer;
|
||||||
_isStarved = true;
|
_isStarved = true;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
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);
|
||||||
|
qDebug() << "Overflowed ring buffer! Overwriting old data";
|
||||||
|
printf("_nextOutput at index %d\n", _nextOutput - _buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_endOfLastWrite + samplesToCopy <= _buffer + _sampleCapacity) {
|
if (_endOfLastWrite + samplesToCopy <= _buffer + _arrayLength) {
|
||||||
memcpy(_endOfLastWrite, data, samplesToCopy * sizeof(int16_t));
|
memcpy(_endOfLastWrite, data, samplesToCopy * sizeof(int16_t));
|
||||||
} else {
|
} else {
|
||||||
int numSamplesToEnd = (_buffer + _sampleCapacity) - _endOfLastWrite;
|
int numSamplesToEnd = (_buffer + _arrayLength) - _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));
|
||||||
}
|
}
|
||||||
|
@ -157,6 +169,8 @@ const int16_t& AudioRingBuffer::operator[] (const int index) const {
|
||||||
|
|
||||||
void AudioRingBuffer::shiftReadPosition(unsigned int numSamples) {
|
void AudioRingBuffer::shiftReadPosition(unsigned int numSamples) {
|
||||||
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numSamples);
|
_nextOutput = shiftedPositionAccomodatingWrap(_nextOutput, numSamples);
|
||||||
|
printf("\n<<< mixed! %d samples remaining\n", samplesAvailable());
|
||||||
|
printf("_nextOutput at index %d\n", _nextOutput - _buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int AudioRingBuffer::samplesAvailable() const {
|
unsigned int AudioRingBuffer::samplesAvailable() const {
|
||||||
|
@ -166,7 +180,7 @@ unsigned int AudioRingBuffer::samplesAvailable() const {
|
||||||
int sampleDifference = _endOfLastWrite - _nextOutput;
|
int sampleDifference = _endOfLastWrite - _nextOutput;
|
||||||
|
|
||||||
if (sampleDifference < 0) {
|
if (sampleDifference < 0) {
|
||||||
sampleDifference += _sampleCapacity;
|
sampleDifference += _arrayLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sampleDifference;
|
return sampleDifference;
|
||||||
|
@ -174,13 +188,22 @@ unsigned int AudioRingBuffer::samplesAvailable() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioRingBuffer::addSilentFrame(int numSilentSamples) {
|
void AudioRingBuffer::addSilentFrame(int numSilentSamples) {
|
||||||
|
|
||||||
|
int samplesRoomFor = _sampleCapacity - samplesAvailable();
|
||||||
|
if (numSilentSamples > samplesRoomFor) {
|
||||||
|
// there's not enough room for this write. write as many silent samples as we have room for
|
||||||
|
numSilentSamples = samplesRoomFor;
|
||||||
|
qDebug() << "Dropping some silent samples to prevent ring buffer overflow";
|
||||||
|
printf("_nextOutput at index %d\n", _nextOutput - _buffer);
|
||||||
|
}
|
||||||
|
|
||||||
// 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 + numSilentSamples <= _buffer + _arrayLength) {
|
||||||
memset(_endOfLastWrite, 0, numSilentSamples * sizeof(int16_t));
|
memset(_endOfLastWrite, 0, numSilentSamples * sizeof(int16_t));
|
||||||
_endOfLastWrite += numSilentSamples;
|
_endOfLastWrite += numSilentSamples;
|
||||||
} else {
|
} else {
|
||||||
int numSamplesToEnd = (_buffer + _sampleCapacity) - _endOfLastWrite;
|
int numSamplesToEnd = (_buffer + _arrayLength) - _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, (numSilentSamples - numSamplesToEnd) * sizeof(int16_t));
|
||||||
|
|
||||||
|
@ -198,12 +221,12 @@ bool AudioRingBuffer::isNotStarvedOrHasMinimumSamples(unsigned int numRequiredSa
|
||||||
|
|
||||||
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 + _arrayLength) {
|
||||||
// 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 - _arrayLength;
|
||||||
} 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 + _arrayLength;
|
||||||
} else {
|
} else {
|
||||||
return position + numSamplesShift;
|
return position + numSamplesShift;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,7 @@ protected:
|
||||||
int16_t* shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const;
|
int16_t* shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const;
|
||||||
|
|
||||||
int _sampleCapacity;
|
int _sampleCapacity;
|
||||||
|
int _arrayLength;
|
||||||
int _numFrameSamples;
|
int _numFrameSamples;
|
||||||
int16_t* _nextOutput;
|
int16_t* _nextOutput;
|
||||||
int16_t* _endOfLastWrite;
|
int16_t* _endOfLastWrite;
|
||||||
|
|
|
@ -148,6 +148,8 @@ int PositionalAudioRingBuffer::parseData(const QByteArray& packet) {
|
||||||
// there is audio data to read
|
// there is audio data to read
|
||||||
readBytes += writeData(packet.data() + readBytes, packet.size() - readBytes);
|
readBytes += writeData(packet.data() + readBytes, packet.size() - readBytes);
|
||||||
}
|
}
|
||||||
|
printf("\n >>> parse data. %d samples available\n", samplesAvailable());
|
||||||
|
printf("_endOfLastWrite at index %d\n", _endOfLastWrite - _buffer);
|
||||||
return readBytes;
|
return readBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +202,7 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
|
||||||
if (!isNotStarvedOrHasMinimumSamples(samplesPerFrame + desiredJitterBufferSamples)) {
|
if (!isNotStarvedOrHasMinimumSamples(samplesPerFrame + desiredJitterBufferSamples)) {
|
||||||
// if the buffer was starved, allow it to accrue at least the desired number of
|
// if the buffer was starved, allow it to accrue at least the desired number of
|
||||||
// jitter buffer frames before we start taking frames from it for mixing
|
// jitter buffer frames before we start taking frames from it for mixing
|
||||||
|
printf("NOT MIXED! waiting to refill after starve\n");
|
||||||
if (_shouldOutputStarveDebug) {
|
if (_shouldOutputStarveDebug) {
|
||||||
_shouldOutputStarveDebug = false;
|
_shouldOutputStarveDebug = false;
|
||||||
}
|
}
|
||||||
|
@ -209,7 +211,7 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
|
||||||
} else if (samplesAvailable() < samplesPerFrame) {
|
} else if (samplesAvailable() < samplesPerFrame) {
|
||||||
// if the buffer doesn't have a full frame of samples to take for mixing, it is starved
|
// if the buffer doesn't have a full frame of samples to take for mixing, it is starved
|
||||||
_isStarved = true;
|
_isStarved = true;
|
||||||
|
printf("NOT MIXED! buffer is now starved\n");
|
||||||
// set to 0 to indicate the jitter buffer is starved
|
// set to 0 to indicate the jitter buffer is starved
|
||||||
_currentJitterBufferFrames = 0;
|
_currentJitterBufferFrames = 0;
|
||||||
|
|
||||||
|
@ -225,6 +227,7 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
|
||||||
// minus one (since a frame will be read immediately after this) is the length of the jitter buffer
|
// minus one (since a frame will be read immediately after this) is the length of the jitter buffer
|
||||||
_currentJitterBufferFrames = samplesAvailable() / samplesPerFrame - 1;
|
_currentJitterBufferFrames = samplesAvailable() / samplesPerFrame - 1;
|
||||||
_isStarved = false;
|
_isStarved = false;
|
||||||
|
printf("buffer has been refilled. current jbuffer frames: %d\n", _currentJitterBufferFrames);
|
||||||
}
|
}
|
||||||
|
|
||||||
// since we've read data from ring buffer at least once - we've started
|
// since we've read data from ring buffer at least once - we've started
|
||||||
|
@ -237,12 +240,7 @@ void PositionalAudioRingBuffer::updateDesiredJitterBufferFrames() {
|
||||||
|
|
||||||
static const float USECS_PER_FRAME = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * USECS_PER_SECOND / (float)SAMPLE_RATE;
|
static const float USECS_PER_FRAME = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * USECS_PER_SECOND / (float)SAMPLE_RATE;
|
||||||
|
|
||||||
if (_interframeTimeGapStats.hasNewWindowMaxGapAvailable()) {
|
if (_interframeTimeGapStats.hasNewWindowMaxGapAvailable()) {
|
||||||
|
|
||||||
_desiredJitterBufferFrames = 1; // HACK to see if this fixes the audio silence
|
|
||||||
/*
|
|
||||||
const float USECS_PER_FRAME = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * USECS_PER_SECOND / (float)SAMPLE_RATE;
|
|
||||||
|
|
||||||
_desiredJitterBufferFrames = ceilf((float)_interframeTimeGapStats.getWindowMaxGap() / USECS_PER_FRAME);
|
_desiredJitterBufferFrames = ceilf((float)_interframeTimeGapStats.getWindowMaxGap() / USECS_PER_FRAME);
|
||||||
if (_desiredJitterBufferFrames < 1) {
|
if (_desiredJitterBufferFrames < 1) {
|
||||||
_desiredJitterBufferFrames = 1;
|
_desiredJitterBufferFrames = 1;
|
||||||
|
@ -251,6 +249,5 @@ void PositionalAudioRingBuffer::updateDesiredJitterBufferFrames() {
|
||||||
if (_desiredJitterBufferFrames > maxDesired) {
|
if (_desiredJitterBufferFrames > maxDesired) {
|
||||||
_desiredJitterBufferFrames = maxDesired;
|
_desiredJitterBufferFrames = maxDesired;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue