From 0f03585a22fb6263bc9403f09fc8d9a126a9466b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 7 Feb 2013 15:04:49 -0800 Subject: [PATCH 1/2] change ring buffer to wait for full frames --- Source/Audio.cpp | 94 ++++++++++++++---------------------------------- 1 file changed, 27 insertions(+), 67 deletions(-) diff --git a/Source/Audio.cpp b/Source/Audio.cpp index d0fe685894..034e8da34c 100644 --- a/Source/Audio.cpp +++ b/Source/Audio.cpp @@ -29,7 +29,7 @@ const short RING_BUFFER_FRAMES = 10; const short RING_BUFFER_SIZE_SAMPLES = RING_BUFFER_FRAMES * BUFFER_LENGTH_SAMPLES; const int SAMPLE_RATE = 22050; -const float JITTER_BUFFER_LENGTH_MSECS = 26.0; +const float JITTER_BUFFER_LENGTH_MSECS = 10.0; const short JITTER_BUFFER_SAMPLES = JITTER_BUFFER_LENGTH_MSECS * (SAMPLE_RATE / 1000.0); const short NUM_AUDIO_SOURCES = 2; @@ -105,31 +105,21 @@ int audioCallback (const void *inputBuffer, if (ringBuffer->endOfLastWrite != NULL) { - // play whatever we have in the audio buffer - short silentTail = 0; - - // if the end of the last write to the ring is in front of the current output pointer - // AND the difference between the two is less than a full output buffer - // we need to add some silence after the audio data, to avoid replaying old data - if ((ringBuffer->endOfLastWrite - ringBuffer->buffer) > (ringBuffer->nextOutput - ringBuffer->buffer) - && (ringBuffer->endOfLastWrite - ringBuffer->nextOutput) < BUFFER_LENGTH_SAMPLES) { - silentTail = BUFFER_LENGTH_SAMPLES - (ringBuffer->endOfLastWrite - ringBuffer->nextOutput); - } - - // no sample overlap, either a direct copy of the audio data, or a copy with some appended silence - memcpy(queueBuffer, ringBuffer->nextOutput, (BUFFER_LENGTH_SAMPLES - silentTail) * sizeof(int16_t)); - - ringBuffer->nextOutput += BUFFER_LENGTH_SAMPLES; - - if (ringBuffer->nextOutput == ringBuffer->buffer + RING_BUFFER_SIZE_SAMPLES) { - ringBuffer->nextOutput = ringBuffer->buffer; - } - - if (ringBuffer->diffLastWriteNextOutput() < BUFFER_LENGTH_SAMPLES) { + if (ringBuffer->diffLastWriteNextOutput() < PACKET_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) { starve_counter++; printf("Starved #%d\n", starve_counter); - data->wasStarved = 10; // Frames to render the indication that the system was starved. - ringBuffer->endOfLastWrite = NULL; + data->wasStarved = 10; // Frames to render the indication that the system was starved. + } else { + // play whatever we have in the audio buffer + + // no sample overlap, either a direct copy of the audio data, or a copy with some appended silence + memcpy(queueBuffer, ringBuffer->nextOutput, BUFFER_LENGTH_BYTES); + + ringBuffer->nextOutput += BUFFER_LENGTH_SAMPLES; + + if (ringBuffer->nextOutput == ringBuffer->buffer + RING_BUFFER_SIZE_SAMPLES) { + ringBuffer->nextOutput = ringBuffer->buffer; + } } } @@ -255,54 +245,24 @@ void *receiveAudioViaUDP(void *args) { AudioRingBuffer *ringBuffer = sharedAudioData->ringBuffer; - int16_t *copyToPointer; - bool needsJitterBuffer = ringBuffer->endOfLastWrite == NULL; - short bufferSampleOverlap = 0; - - if (!needsJitterBuffer && ringBuffer->diffLastWriteNextOutput() > RING_BUFFER_SIZE_SAMPLES - PACKET_LENGTH_SAMPLES) { + bool ringBufferReset = ringBuffer->endOfLastWrite == NULL; + + if (!ringBufferReset && ringBuffer->diffLastWriteNextOutput() > RING_BUFFER_SIZE_SAMPLES - PACKET_LENGTH_SAMPLES) { + std::cout << "D: " << ringBuffer->diffLastWriteNextOutput() << "\n"; std::cout << "Full\n"; - needsJitterBuffer = true; + ringBufferReset = true; } - if (needsJitterBuffer) { - // we'll need a jitter buffer - // reset the ring buffer and write - copyToPointer = ringBuffer->buffer; - //std::cout << "Writing jitter buffer\n"; - } else { - copyToPointer = ringBuffer->endOfLastWrite; - - // check for possibility of overlap - bufferSampleOverlap = ringBuffer->bufferOverlap(copyToPointer, PACKET_LENGTH_SAMPLES); - + if (ringBufferReset || ringBuffer->endOfLastWrite == ringBuffer->buffer + RING_BUFFER_SIZE_SAMPLES) { + // reset the ring buffer and write from beginning + ringBuffer->endOfLastWrite = ringBuffer->buffer; } - if (!bufferSampleOverlap) { - if (needsJitterBuffer) { - // we need to inject a jitter buffer - - // add silence for jitter buffer and then the received packet - memset(copyToPointer, 0, JITTER_BUFFER_SAMPLES * sizeof(int16_t)); - memcpy(copyToPointer + JITTER_BUFFER_SAMPLES, receivedData, PACKET_LENGTH_BYTES); - - // the end of the write is the pointer to the buffer + packet + jitter buffer - ringBuffer->endOfLastWrite = ringBuffer->buffer + PACKET_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES; - ringBuffer->nextOutput = ringBuffer->buffer; - } else { - // no jitter buffer, no overlap - // just copy the recieved data to the right spot and then add packet length to previous pointer - memcpy(copyToPointer, receivedData, PACKET_LENGTH_BYTES); - ringBuffer->endOfLastWrite += PACKET_LENGTH_SAMPLES; - } - } else { - // no jitter buffer, but overlap - // copy to the end, and then from the begining to the overlap - memcpy(copyToPointer, receivedData, (PACKET_LENGTH_SAMPLES - bufferSampleOverlap) * sizeof(int16_t)); - memcpy(ringBuffer->buffer, receivedData + (PACKET_LENGTH_SAMPLES - bufferSampleOverlap), bufferSampleOverlap * sizeof(int16_t)); - - // the end of the write is the amount of overlap - ringBuffer->endOfLastWrite = ringBuffer->buffer + bufferSampleOverlap; - } + int16_t *copyToPointer = ringBuffer->endOfLastWrite; + + // just copy the recieved data to the right spot and then add packet length to previous pointer + memcpy(copyToPointer, receivedData, PACKET_LENGTH_BYTES); + ringBuffer->endOfLastWrite += PACKET_LENGTH_SAMPLES; if (LOG_SAMPLE_DELAY) { gettimeofday(&previousReceiveTime, NULL); From 1a05094da026f482c0e278d8d2c63c20fa62e901 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 7 Feb 2013 15:29:02 -0800 Subject: [PATCH 2/2] fix ring buffer to only hold back on stream start --- Source/Audio.cpp | 28 +++++++++++++++++++--------- Source/AudioRingBuffer.cpp | 1 + Source/AudioRingBuffer.h | 1 + 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Source/Audio.cpp b/Source/Audio.cpp index 034e8da34c..c71a993d0d 100644 --- a/Source/Audio.cpp +++ b/Source/Audio.cpp @@ -105,11 +105,16 @@ int audioCallback (const void *inputBuffer, if (ringBuffer->endOfLastWrite != NULL) { - if (ringBuffer->diffLastWriteNextOutput() < PACKET_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) { + if (!ringBuffer->started && ringBuffer->diffLastWriteNextOutput() <= PACKET_LENGTH_SAMPLES + JITTER_BUFFER_SAMPLES) { + printf("Held back\n"); + } else if (ringBuffer->diffLastWriteNextOutput() < PACKET_LENGTH_SAMPLES) { + ringBuffer->started = false; + starve_counter++; printf("Starved #%d\n", starve_counter); data->wasStarved = 10; // Frames to render the indication that the system was starved. } else { + ringBuffer->started = true; // play whatever we have in the audio buffer // no sample overlap, either a direct copy of the audio data, or a copy with some appended silence @@ -245,17 +250,18 @@ void *receiveAudioViaUDP(void *args) { AudioRingBuffer *ringBuffer = sharedAudioData->ringBuffer; - bool ringBufferReset = ringBuffer->endOfLastWrite == NULL; - - if (!ringBufferReset && ringBuffer->diffLastWriteNextOutput() > RING_BUFFER_SIZE_SAMPLES - PACKET_LENGTH_SAMPLES) { + if (ringBuffer->endOfLastWrite == NULL) { + ringBuffer->endOfLastWrite = ringBuffer->buffer; + } else if (ringBuffer->diffLastWriteNextOutput() > RING_BUFFER_SIZE_SAMPLES - PACKET_LENGTH_SAMPLES) { + std::cout << "NAB: " << ringBuffer->nextOutput - ringBuffer->buffer << "\n"; + std::cout << "LAW: " << ringBuffer->endOfLastWrite - ringBuffer->buffer << "\n"; std::cout << "D: " << ringBuffer->diffLastWriteNextOutput() << "\n"; std::cout << "Full\n"; - ringBufferReset = true; - } - - if (ringBufferReset || ringBuffer->endOfLastWrite == ringBuffer->buffer + RING_BUFFER_SIZE_SAMPLES) { - // reset the ring buffer and write from beginning + + // reset us to started state ringBuffer->endOfLastWrite = ringBuffer->buffer; + ringBuffer->nextOutput = ringBuffer->buffer; + ringBuffer->started = false; } int16_t *copyToPointer = ringBuffer->endOfLastWrite; @@ -263,6 +269,10 @@ void *receiveAudioViaUDP(void *args) { // just copy the recieved data to the right spot and then add packet length to previous pointer memcpy(copyToPointer, receivedData, PACKET_LENGTH_BYTES); ringBuffer->endOfLastWrite += PACKET_LENGTH_SAMPLES; + + if (ringBuffer->endOfLastWrite == ringBuffer->buffer + RING_BUFFER_SIZE_SAMPLES) { + ringBuffer->endOfLastWrite = ringBuffer->buffer; + } if (LOG_SAMPLE_DELAY) { gettimeofday(&previousReceiveTime, NULL); diff --git a/Source/AudioRingBuffer.cpp b/Source/AudioRingBuffer.cpp index 3a34ef7454..f79df7945d 100644 --- a/Source/AudioRingBuffer.cpp +++ b/Source/AudioRingBuffer.cpp @@ -10,6 +10,7 @@ AudioRingBuffer::AudioRingBuffer(short ringBufferSamples) { ringBufferLengthSamples = ringBufferSamples; + started = false; endOfLastWrite = NULL; diff --git a/Source/AudioRingBuffer.h b/Source/AudioRingBuffer.h index c78038afb3..9d6b0d7dd8 100644 --- a/Source/AudioRingBuffer.h +++ b/Source/AudioRingBuffer.h @@ -17,6 +17,7 @@ class AudioRingBuffer { int16_t *endOfLastWrite; int16_t *buffer; short ringBufferLengthSamples; + bool started; short diffLastWriteNextOutput(); short bufferOverlap(int16_t *pointer, short addedDistance);