diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index d0a19a592e..304fc6b2cf 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -28,10 +28,12 @@ AudioRingBuffer::AudioRingBuffer(int numFrameSamples, bool randomAccessMode) : _hasStarted(false), _randomAccessMode(randomAccessMode) { + _arrayLength = _sampleCapacity + 1; + if (numFrameSamples) { - _buffer = new int16_t[_sampleCapacity]; + _buffer = new int16_t[_arrayLength]; if (_randomAccessMode) { - memset(_buffer, 0, _sampleCapacity * sizeof(int16_t)); + memset(_buffer, 0, _arrayLength * sizeof(int16_t)); } _nextOutput = _buffer; _endOfLastWrite = _buffer; @@ -55,9 +57,10 @@ void AudioRingBuffer::reset() { void AudioRingBuffer::resizeForFrameSize(qint64 numFrameSamples) { delete[] _buffer; _sampleCapacity = numFrameSamples * RING_BUFFER_LENGTH_FRAMES; - _buffer = new int16_t[_sampleCapacity]; + _arrayLength = _sampleCapacity + 1; + _buffer = new int16_t[_arrayLength]; if (_randomAccessMode) { - memset(_buffer, 0, _sampleCapacity * sizeof(int16_t)); + memset(_buffer, 0, _arrayLength * sizeof(int16_t)); } _nextOutput = _buffer; _endOfLastWrite = _buffer; @@ -87,11 +90,11 @@ qint64 AudioRingBuffer::readData(char *data, qint64 maxSize) { 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 // read to the end of the buffer - int numSamplesToEnd = (_buffer + _sampleCapacity) - _nextOutput; + int numSamplesToEnd = (_buffer + _arrayLength) - _nextOutput; memcpy(data, _nextOutput, numSamplesToEnd * sizeof(int16_t)); if (_randomAccessMode) { 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 int samplesToCopy = std::min((quint64)(maxSize / sizeof(int16_t)), (quint64)_sampleCapacity); - + /* if (_hasStarted && samplesToCopy > _sampleCapacity - samplesAvailable()) { - // this read will cross the next output, so call us starved and reset the buffer - qDebug() << "Filled the ring buffer. Resetting."; + // this write would overflow the buffer, so call us starved and reset the buffer + qDebug() << "Overflowed the ring buffer. Resetting."; _endOfLastWrite = _buffer; _nextOutput = _buffer; _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)); } else { - int numSamplesToEnd = (_buffer + _sampleCapacity) - _endOfLastWrite; + int numSamplesToEnd = (_buffer + _arrayLength) - _endOfLastWrite; memcpy(_endOfLastWrite, data, 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) { _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 { @@ -166,7 +180,7 @@ unsigned int AudioRingBuffer::samplesAvailable() const { int sampleDifference = _endOfLastWrite - _nextOutput; if (sampleDifference < 0) { - sampleDifference += _sampleCapacity; + sampleDifference += _arrayLength; } return sampleDifference; @@ -174,13 +188,22 @@ unsigned int AudioRingBuffer::samplesAvailable() const { } 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 // push the _endOfLastWrite to the correct spot - if (_endOfLastWrite + numSilentSamples <= _buffer + _sampleCapacity) { + if (_endOfLastWrite + numSilentSamples <= _buffer + _arrayLength) { memset(_endOfLastWrite, 0, numSilentSamples * sizeof(int16_t)); _endOfLastWrite += numSilentSamples; } else { - int numSamplesToEnd = (_buffer + _sampleCapacity) - _endOfLastWrite; + int numSamplesToEnd = (_buffer + _arrayLength) - _endOfLastWrite; memset(_endOfLastWrite, 0, 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 { - 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 - return position + numSamplesShift - _sampleCapacity; + return position + numSamplesShift - _arrayLength; } 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 + _arrayLength; } else { return position + numSamplesShift; } diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index 04cc67c8ac..33f9ada0bd 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -82,6 +82,7 @@ protected: int16_t* shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const; int _sampleCapacity; + int _arrayLength; int _numFrameSamples; int16_t* _nextOutput; int16_t* _endOfLastWrite; diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index 764624cd39..acc1bc0ee4 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -148,6 +148,8 @@ int PositionalAudioRingBuffer::parseData(const QByteArray& packet) { // there is audio data to read 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; } @@ -200,7 +202,7 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() { if (!isNotStarvedOrHasMinimumSamples(samplesPerFrame + desiredJitterBufferSamples)) { // 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 - +printf("NOT MIXED! waiting to refill after starve\n"); if (_shouldOutputStarveDebug) { _shouldOutputStarveDebug = false; } @@ -209,7 +211,7 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() { } else if (samplesAvailable() < samplesPerFrame) { // if the buffer doesn't have a full frame of samples to take for mixing, it is starved _isStarved = true; - +printf("NOT MIXED! buffer is now starved\n"); // set to 0 to indicate the jitter buffer is starved _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 _currentJitterBufferFrames = samplesAvailable() / samplesPerFrame - 1; _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 @@ -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; - 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; - + if (_interframeTimeGapStats.hasNewWindowMaxGapAvailable()) { _desiredJitterBufferFrames = ceilf((float)_interframeTimeGapStats.getWindowMaxGap() / USECS_PER_FRAME); if (_desiredJitterBufferFrames < 1) { _desiredJitterBufferFrames = 1; @@ -251,6 +249,5 @@ void PositionalAudioRingBuffer::updateDesiredJitterBufferFrames() { if (_desiredJitterBufferFrames > maxDesired) { _desiredJitterBufferFrames = maxDesired; } - */ } }