From 1d390faad877e1b5be734e3980100f2306bc0a6a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 24 Jun 2014 10:29:38 -0700 Subject: [PATCH] add support for commandline/config value for dynamic jitter buffers --- assignment-client/src/audio/AudioMixer.cpp | 12 +++++++ assignment-client/src/audio/AudioMixer.h | 4 +++ .../src/audio/AudioMixerClientData.cpp | 14 ++++++--- .../src/audio/AvatarAudioRingBuffer.cpp | 4 +-- .../src/audio/AvatarAudioRingBuffer.h | 2 +- libraries/audio/src/AudioRingBuffer.cpp | 2 ++ libraries/audio/src/AudioRingBuffer.h | 3 ++ .../audio/src/InjectedAudioRingBuffer.cpp | 4 +-- libraries/audio/src/InjectedAudioRingBuffer.h | 2 +- .../audio/src/PositionalAudioRingBuffer.cpp | 31 ++++++++++--------- .../audio/src/PositionalAudioRingBuffer.h | 3 +- 11 files changed, 56 insertions(+), 25 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 1d0b51a437..8e4ce04f0b 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -64,6 +64,8 @@ void attachNewBufferToNode(Node *newNode) { } } +bool AudioMixer::_useDynamicJitterBuffers = false; + AudioMixer::AudioMixer(const QByteArray& packet) : ThreadedAssignment(packet), _trailingSleepRatio(1.0f), @@ -502,6 +504,16 @@ void AudioMixer::run() { << QString("%1, %2, %3").arg(destinationCenter.x).arg(destinationCenter.y).arg(destinationCenter.z); } + // check the payload to see if we have asked for dynamicJitterBuffer support + const QString DYNAMIC_JITTER_BUFFER_REGEX_STRING = "--dynamicJitterBuffer"; + QRegExp dynamicJitterBufferMatch(DYNAMIC_JITTER_BUFFER_REGEX_STRING); + if (dynamicJitterBufferMatch.indexIn(_payload) != -1) { + qDebug() << "Enable dynamic jitter buffers."; + _useDynamicJitterBuffers = true; + } else { + qDebug() << "Dynamic jitter buffers disabled, using old behavior."; + } + int nextFrame = 0; QElapsedTimer timer; timer.start(); diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 39f8cf63ae..8560978689 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -34,6 +34,9 @@ public slots: void readPendingDatagrams(); void sendStatsPacket(); + + static bool getUseDynamicJitterBuffers() { return _useDynamicJitterBuffers; } + private: /// adds one buffer to the mix for a listening node void addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd, @@ -54,6 +57,7 @@ private: int _sumMixes; AABox* _sourceUnattenuatedZone; AABox* _listenerUnattenuatedZone; + static bool _useDynamicJitterBuffers; }; #endif // hifi_AudioMixer_h diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index def9b8c953..395cebf9c2 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -16,6 +16,7 @@ #include "InjectedAudioRingBuffer.h" +#include "AudioMixer.h" #include "AudioMixerClientData.h" AudioMixerClientData::AudioMixerClientData() : @@ -65,7 +66,7 @@ int AudioMixerClientData::parseData(const QByteArray& packet) { if (!avatarRingBuffer) { // we don't have an AvatarAudioRingBuffer yet, so add it - avatarRingBuffer = new AvatarAudioRingBuffer(isStereo); + avatarRingBuffer = new AvatarAudioRingBuffer(isStereo, AudioMixer::getUseDynamicJitterBuffers()); _ringBuffers.push_back(avatarRingBuffer); } @@ -88,7 +89,8 @@ int AudioMixerClientData::parseData(const QByteArray& packet) { if (!matchingInjectedRingBuffer) { // we don't have a matching injected audio ring buffer, so add it - matchingInjectedRingBuffer = new InjectedAudioRingBuffer(streamIdentifier); + matchingInjectedRingBuffer = new InjectedAudioRingBuffer(streamIdentifier, + AudioMixer::getUseDynamicJitterBuffers()); _ringBuffers.push_back(matchingInjectedRingBuffer); } @@ -146,13 +148,15 @@ QString AudioMixerClientData::getJitterBufferStats() const { int desiredJitterBuffer = avatarRingBuffer->getDesiredJitterBufferFrames(); int calculatedJitterBuffer = avatarRingBuffer->getCalculatedDesiredJitterBufferFrames(); int currentJitterBuffer = avatarRingBuffer->getCurrentJitterBufferFrames(); + int resetCount = avatarRingBuffer->getResetCount(); int samplesAvailable = avatarRingBuffer->samplesAvailable(); int framesAvailable = (samplesAvailable / avatarRingBuffer->getSamplesPerFrame()); result += "mic.desired:" + QString::number(desiredJitterBuffer) + " calculated:" + QString::number(calculatedJitterBuffer) + " current:" + QString::number(currentJitterBuffer) + " available:" + QString::number(framesAvailable) - + " samples:" + QString::number(samplesAvailable); + + " samples:" + QString::number(samplesAvailable) + + " resets:" + QString::number(resetCount); } else { result = "mic unknown"; } @@ -162,13 +166,15 @@ QString AudioMixerClientData::getJitterBufferStats() const { int desiredJitterBuffer = _ringBuffers[i]->getDesiredJitterBufferFrames(); int calculatedJitterBuffer = _ringBuffers[i]->getCalculatedDesiredJitterBufferFrames(); int currentJitterBuffer = _ringBuffers[i]->getCurrentJitterBufferFrames(); + int resetCount = _ringBuffers[i]->getResetCount(); int samplesAvailable = _ringBuffers[i]->samplesAvailable(); int framesAvailable = (samplesAvailable / _ringBuffers[i]->getSamplesPerFrame()); result += "| injected["+QString::number(i)+"].desired:" + QString::number(desiredJitterBuffer) + " calculated:" + QString::number(calculatedJitterBuffer) + " current:" + QString::number(currentJitterBuffer) + " available:" + QString::number(framesAvailable) - + " samples:" + QString::number(samplesAvailable); + + " samples:" + QString::number(samplesAvailable) + + " resets:" + QString::number(resetCount); } } diff --git a/assignment-client/src/audio/AvatarAudioRingBuffer.cpp b/assignment-client/src/audio/AvatarAudioRingBuffer.cpp index 79ad7ae411..9c6cc32f57 100644 --- a/assignment-client/src/audio/AvatarAudioRingBuffer.cpp +++ b/assignment-client/src/audio/AvatarAudioRingBuffer.cpp @@ -13,8 +13,8 @@ #include "AvatarAudioRingBuffer.h" -AvatarAudioRingBuffer::AvatarAudioRingBuffer(bool isStereo) : - PositionalAudioRingBuffer(PositionalAudioRingBuffer::Microphone, isStereo) { +AvatarAudioRingBuffer::AvatarAudioRingBuffer(bool isStereo, bool dynamicJitterBuffer) : + PositionalAudioRingBuffer(PositionalAudioRingBuffer::Microphone, isStereo, dynamicJitterBuffer) { } diff --git a/assignment-client/src/audio/AvatarAudioRingBuffer.h b/assignment-client/src/audio/AvatarAudioRingBuffer.h index f842c2aa33..e227e70958 100644 --- a/assignment-client/src/audio/AvatarAudioRingBuffer.h +++ b/assignment-client/src/audio/AvatarAudioRingBuffer.h @@ -18,7 +18,7 @@ class AvatarAudioRingBuffer : public PositionalAudioRingBuffer { public: - AvatarAudioRingBuffer(bool isStereo = false); + AvatarAudioRingBuffer(bool isStereo = false, bool dynamicJitterBuffer = false); int parseData(const QByteArray& packet); private: diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 71fd2fe19d..ee4027841b 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -21,6 +21,7 @@ AudioRingBuffer::AudioRingBuffer(int numFrameSamples, bool randomAccessMode) : NodeData(), + _resetCount(0), _sampleCapacity(numFrameSamples * RING_BUFFER_LENGTH_FRAMES), _numFrameSamples(numFrameSamples), _isStarved(true), @@ -128,6 +129,7 @@ qint64 AudioRingBuffer::writeData(const char* data, qint64 maxSize) { _endOfLastWrite = _buffer; _nextOutput = _buffer; _isStarved = true; + _resetCount++; } if (_endOfLastWrite + samplesToCopy <= _buffer + _sampleCapacity) { diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index 04cc67c8ac..1ddcadeceb 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -71,6 +71,7 @@ public: bool isStarved() const { return _isStarved; } void setIsStarved(bool isStarved) { _isStarved = isStarved; } + int getResetCount() const { return _resetCount; } /// how many times has the ring buffer written past the end and reset bool hasStarted() const { return _hasStarted; } void addSilentFrame(int numSilentSamples); @@ -80,6 +81,8 @@ protected: AudioRingBuffer& operator= (const AudioRingBuffer&); int16_t* shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const; + + int _resetCount; /// how many times has the ring buffer written past the end and done a reset int _sampleCapacity; int _numFrameSamples; diff --git a/libraries/audio/src/InjectedAudioRingBuffer.cpp b/libraries/audio/src/InjectedAudioRingBuffer.cpp index ed0476f6bd..9b6529b49f 100644 --- a/libraries/audio/src/InjectedAudioRingBuffer.cpp +++ b/libraries/audio/src/InjectedAudioRingBuffer.cpp @@ -19,8 +19,8 @@ #include "InjectedAudioRingBuffer.h" -InjectedAudioRingBuffer::InjectedAudioRingBuffer(const QUuid& streamIdentifier) : - PositionalAudioRingBuffer(PositionalAudioRingBuffer::Injector), +InjectedAudioRingBuffer::InjectedAudioRingBuffer(const QUuid& streamIdentifier, bool dynamicJitterBuffer) : + PositionalAudioRingBuffer(PositionalAudioRingBuffer::Injector, /* isStereo=*/ false , dynamicJitterBuffer), _streamIdentifier(streamIdentifier), _radius(0.0f), _attenuationRatio(0) diff --git a/libraries/audio/src/InjectedAudioRingBuffer.h b/libraries/audio/src/InjectedAudioRingBuffer.h index fd766e2848..4e3fea672b 100644 --- a/libraries/audio/src/InjectedAudioRingBuffer.h +++ b/libraries/audio/src/InjectedAudioRingBuffer.h @@ -18,7 +18,7 @@ class InjectedAudioRingBuffer : public PositionalAudioRingBuffer { public: - InjectedAudioRingBuffer(const QUuid& streamIdentifier = QUuid()); + InjectedAudioRingBuffer(const QUuid& streamIdentifier = QUuid(), bool dynamicJitterBuffer = false); int parseData(const QByteArray& packet); diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index e3c123e592..23e258fe87 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -85,7 +85,9 @@ quint64 InterframeTimeGapStats::getWindowMaxGap() { } -PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer::Type type, bool isStereo) : +PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer::Type type, + bool isStereo, bool dynamicJitterBuffers) : + AudioRingBuffer(isStereo ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL), _type(type), _position(0.0f, 0.0f, 0.0f), @@ -96,7 +98,8 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer:: _isStereo(isStereo), _listenerUnattenuatedZone(NULL), _desiredJitterBufferFrames(1), - _currentJitterBufferFrames(0) + _currentJitterBufferFrames(0), + _dynamicJitterBuffers(dynamicJitterBuffers) { } @@ -246,19 +249,19 @@ int PositionalAudioRingBuffer::getCalculatedDesiredJitterBufferFrames() const { void PositionalAudioRingBuffer::updateDesiredJitterBufferFrames() { 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 (!_dynamicJitterBuffers) { + _desiredJitterBufferFrames = 1; // HACK to see if this fixes the audio silence + } else { + 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); - if (_desiredJitterBufferFrames < 1) { - _desiredJitterBufferFrames = 1; + _desiredJitterBufferFrames = ceilf((float)_interframeTimeGapStats.getWindowMaxGap() / USECS_PER_FRAME); + if (_desiredJitterBufferFrames < 1) { + _desiredJitterBufferFrames = 1; + } + const int maxDesired = RING_BUFFER_LENGTH_FRAMES - 1; + if (_desiredJitterBufferFrames > maxDesired) { + _desiredJitterBufferFrames = maxDesired; + } } - const int maxDesired = RING_BUFFER_LENGTH_FRAMES - 1; - if (_desiredJitterBufferFrames > maxDesired) { - _desiredJitterBufferFrames = maxDesired; - } - */ } } diff --git a/libraries/audio/src/PositionalAudioRingBuffer.h b/libraries/audio/src/PositionalAudioRingBuffer.h index b9caeff605..b204dc766b 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.h +++ b/libraries/audio/src/PositionalAudioRingBuffer.h @@ -50,7 +50,7 @@ public: Injector }; - PositionalAudioRingBuffer(PositionalAudioRingBuffer::Type type, bool isStereo = false); + PositionalAudioRingBuffer(PositionalAudioRingBuffer::Type type, bool isStereo = false, bool dynamicJitterBuffers = false); int parseData(const QByteArray& packet); int parsePositionalData(const QByteArray& positionalByteArray); @@ -102,6 +102,7 @@ protected: InterframeTimeGapStats _interframeTimeGapStats; int _desiredJitterBufferFrames; int _currentJitterBufferFrames; + bool _dynamicJitterBuffers; }; #endif // hifi_PositionalAudioRingBuffer_h