From aa3602f0fb5fa0def615377e25dd52e2f33e5a3f Mon Sep 17 00:00:00 2001 From: wangyix Date: Thu, 19 Jun 2014 14:34:55 -0700 Subject: [PATCH] added InterframeTimeGapHistory and frameReceived() calls --- .../src/audio/AvatarAudioRingBuffer.cpp | 2 + libraries/audio/src/AudioRingBuffer.cpp | 57 +++++++++++++++++++ libraries/audio/src/AudioRingBuffer.h | 28 +++++++++ .../audio/src/InjectedAudioRingBuffer.cpp | 2 + 4 files changed, 89 insertions(+) diff --git a/assignment-client/src/audio/AvatarAudioRingBuffer.cpp b/assignment-client/src/audio/AvatarAudioRingBuffer.cpp index 5613a64cc4..47a0ecbea8 100644 --- a/assignment-client/src/audio/AvatarAudioRingBuffer.cpp +++ b/assignment-client/src/audio/AvatarAudioRingBuffer.cpp @@ -19,6 +19,8 @@ AvatarAudioRingBuffer::AvatarAudioRingBuffer(bool isStereo) : } int AvatarAudioRingBuffer::parseData(const QByteArray& packet) { + _timeGapHistory.frameReceived(); + _shouldLoopbackForNode = (packetTypeForPacket(packet) == PacketTypeMicrophoneAudioWithEcho); return PositionalAudioRingBuffer::parseData(packet); } diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 2101fcb9cd..ea15e27ef5 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -12,6 +12,7 @@ #include #include #include +#include "SharedUtil.h" #include @@ -19,6 +20,62 @@ #include "AudioRingBuffer.h" +InterframeTimeGapHistory::InterframeTimeGapHistory() + : _lastFrameReceivedTime(0), + _numSamplesInCurrentInterval(0), + _currentIntervalMaxGap(0), + _newestIntervalMaxGapAt(0), + _windowMaxGap(0), + _newWindowMaxGapAvailable(false) +{ + memset(_intervalMaxGaps, 0, TIME_GAP_NUM_INTERVALS_IN_WINDOW*sizeof(quint64)); +} + +void InterframeTimeGapHistory::frameReceived() { + quint64 now = usecTimestampNow(); + + // make sure this isn't the first time frameReceived() is called, meaning there's actually a gap to calculate. + if (_lastFrameReceivedTime != 0) { + quint64 gap = now - _lastFrameReceivedTime; + + // update the current interval max + if (gap > _currentIntervalMaxGap) { + _currentIntervalMaxGap = gap; + } + _numSamplesInCurrentInterval++; + + // if the current interval of samples is now full, record it in our interval maxes + if (_numSamplesInCurrentInterval == TIME_GAP_NUM_SAMPLES_IN_INTERVAL) { + + // find location to insert this interval's max (increment index cyclically) + _newestIntervalMaxGapAt = _newestIntervalMaxGapAt == TIME_GAP_NUM_INTERVALS_IN_WINDOW - 1 ? 0 : _newestIntervalMaxGapAt + 1; + + // record the current interval's max gap as the newest + _intervalMaxGaps[_newestIntervalMaxGapAt] = _currentIntervalMaxGap; + + // update the window max gap, which is the max out of all the past intervals' max gaps + _windowMaxGap = 0; + for (int i = 0; i < TIME_GAP_NUM_INTERVALS_IN_WINDOW; i++) { + if (_intervalMaxGaps[i] > _windowMaxGap) { + _windowMaxGap = _intervalMaxGaps[i]; + } + } + _newWindowMaxGapAvailable = true; + + // reset the current interval + _numSamplesInCurrentInterval = 0; + _currentIntervalMaxGap = 0; + } + } + _lastFrameReceivedTime = now; +} + +quint64 InterframeTimeGapHistory::getPastWindowMaxGap() { + _newWindowMaxGapAvailable = false; + return _windowMaxGap; +} + + AudioRingBuffer::AudioRingBuffer(int numFrameSamples, bool randomAccessMode) : NodeData(), _sampleCapacity(numFrameSamples * RING_BUFFER_LENGTH_FRAMES), diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index 04cc67c8ac..105e3761ae 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -21,6 +21,30 @@ #include "NodeData.h" +// this means that every 500 samples, the max for the past 10*500 samples will be calculated +const int TIME_GAP_NUM_SAMPLES_IN_INTERVAL = 500; +const int TIME_GAP_NUM_INTERVALS_IN_WINDOW = 10; + +class InterframeTimeGapHistory { +public: + InterframeTimeGapHistory(); + + void frameReceived(); + bool isNewWindowMaxGapAvailable() const { return _newWindowMaxGapAvailable; } + quint64 getPastWindowMaxGap(); + +private: + quint64 _lastFrameReceivedTime; + + int _numSamplesInCurrentInterval; + quint64 _currentIntervalMaxGap; + quint64 _intervalMaxGaps[TIME_GAP_NUM_INTERVALS_IN_WINDOW]; + int _newestIntervalMaxGapAt; + quint64 _windowMaxGap; + bool _newWindowMaxGapAvailable; +}; + + const int SAMPLE_RATE = 24000; const int NETWORK_BUFFER_LENGTH_BYTES_STEREO = 1024; @@ -74,6 +98,8 @@ public: bool hasStarted() const { return _hasStarted; } void addSilentFrame(int numSilentSamples); + + InterframeTimeGapHistory& getInterframeTimeGapHistory() { return _timeGapHistory; } protected: // disallow copying of AudioRingBuffer objects AudioRingBuffer(const AudioRingBuffer&); @@ -89,6 +115,8 @@ protected: bool _isStarved; bool _hasStarted; bool _randomAccessMode; /// will this ringbuffer be used for random access? if so, do some special processing + + InterframeTimeGapHistory _timeGapHistory; }; #endif // hifi_AudioRingBuffer_h diff --git a/libraries/audio/src/InjectedAudioRingBuffer.cpp b/libraries/audio/src/InjectedAudioRingBuffer.cpp index 2658b4c336..103d0d8d2e 100644 --- a/libraries/audio/src/InjectedAudioRingBuffer.cpp +++ b/libraries/audio/src/InjectedAudioRingBuffer.cpp @@ -31,6 +31,8 @@ InjectedAudioRingBuffer::InjectedAudioRingBuffer(const QUuid& streamIdentifier) const uchar MAX_INJECTOR_VOLUME = 255; int InjectedAudioRingBuffer::parseData(const QByteArray& packet) { + _timeGapHistory.frameReceived(); + // setup a data stream to read from this packet QDataStream packetStream(packet); packetStream.skipRawData(numBytesForPacketHeader(packet));