From 621f0725ccee64908a4c545b9ee79aa3abbb6865 Mon Sep 17 00:00:00 2001 From: wangyix Date: Mon, 21 Jul 2014 15:39:33 -0700 Subject: [PATCH 1/3] added input ring buffer stats to interface --- interface/src/Audio.cpp | 24 ++++++++++++------- interface/src/Audio.h | 18 +++++++++----- interface/src/ui/Stats.cpp | 18 +++++++++++--- .../audio/src/PositionalAudioRingBuffer.h | 4 ++-- 4 files changed, 45 insertions(+), 19 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index ae4caa76f5..e5e71b8dcb 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -130,7 +130,8 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) : _outgoingAvatarAudioSequenceNumber(0), _incomingMixedAudioSequenceNumberStats(INCOMING_SEQ_STATS_HISTORY_LENGTH), _interframeTimeGapStats(TIME_GAPS_STATS_INTERVAL_SAMPLES, TIME_GAP_STATS_WINDOW_INTERVALS), - _ringBufferFramesAvailableStats(1, FRAMES_AVAILABLE_STATS_WINDOW_SECONDS), + _inputRingBufferFramesAvailableStats(1, FRAMES_AVAILABLE_STATS_WINDOW_SECONDS), + _outputRingBufferFramesAvailableStats(1, FRAMES_AVAILABLE_STATS_WINDOW_SECONDS), _audioOutputBufferFramesAvailableStats(1, FRAMES_AVAILABLE_STATS_WINDOW_SECONDS) { // clear the array of locally injected samples @@ -795,7 +796,7 @@ AudioStreamStats Audio::getDownstreamAudioStreamStats() const { stats._timeGapWindowAverage = _interframeTimeGapStats.getWindowAverage(); stats._ringBufferFramesAvailable = _ringBuffer.framesAvailable(); - stats._ringBufferFramesAvailableAverage = _ringBufferFramesAvailableStats.getWindowAverage(); + stats._ringBufferFramesAvailableAverage = _outputRingBufferFramesAvailableStats.getWindowAverage(); stats._ringBufferDesiredJitterBufferFrames = getDesiredJitterBufferFrames(); stats._ringBufferStarveCount = _starveCount; stats._ringBufferConsecutiveNotMixedCount = _consecutiveNotMixedCount; @@ -810,9 +811,11 @@ AudioStreamStats Audio::getDownstreamAudioStreamStats() const { void Audio::sendDownstreamAudioStatsPacket() { + _inputRingBufferFramesAvailableStats.update(getInputRingBufferFramesAvailable()); + // since this function is called every second, we'll sample the number of audio frames available here. - _ringBufferFramesAvailableStats.update(_ringBuffer.framesAvailable()); - _audioOutputBufferFramesAvailableStats.update(getFramesAvailableInAudioOutputBuffer()); + _outputRingBufferFramesAvailableStats.update(_ringBuffer.framesAvailable()); + _audioOutputBufferFramesAvailableStats.update(getOutputRingBufferFramesAvailable()); // push the current seq number stats into history, which moves the history window forward 1s // (since that's how often pushStatsToHistory() is called) @@ -1596,7 +1599,7 @@ const float Audio::CALLBACK_ACCELERATOR_RATIO = 2.0f; const float Audio::CALLBACK_ACCELERATOR_RATIO = 2.0f; #endif -int Audio::calculateNumberOfInputCallbackBytes(const QAudioFormat& format) { +int Audio::calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const { int numInputCallbackBytes = (int)(((NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL * format.channelCount() * (format.sampleRate() / SAMPLE_RATE)) @@ -1605,7 +1608,7 @@ int Audio::calculateNumberOfInputCallbackBytes(const QAudioFormat& format) { return numInputCallbackBytes; } -float Audio::calculateDeviceToNetworkInputRatio(int numBytes) { +float Audio::calculateDeviceToNetworkInputRatio(int numBytes) const { float inputToNetworkInputRatio = (int)((_numInputCallbackBytes * CALLBACK_ACCELERATOR_RATIO / NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL) + 0.5f); @@ -1613,15 +1616,20 @@ float Audio::calculateDeviceToNetworkInputRatio(int numBytes) { return inputToNetworkInputRatio; } -int Audio::calculateNumberOfFrameSamples(int numBytes) { +int Audio::calculateNumberOfFrameSamples(int numBytes) const { int frameSamples = (int)(numBytes * CALLBACK_ACCELERATOR_RATIO + 0.5f) / sizeof(int16_t); return frameSamples; } -int Audio::getFramesAvailableInAudioOutputBuffer() const { +int Audio::getOutputRingBufferFramesAvailable() const { float networkOutputToOutputRatio = (_desiredOutputFormat.sampleRate() / (float)_outputFormat.sampleRate()) * (_desiredOutputFormat.channelCount() / (float)_outputFormat.channelCount()); return (_audioOutput->bufferSize() - _audioOutput->bytesFree()) * networkOutputToOutputRatio / (sizeof(int16_t) * _ringBuffer.getNumFrameSamples()); } + +int Audio::getInputRingBufferFramesAvailable() const { + float inputToNetworkInputRatio = calculateDeviceToNetworkInputRatio(_numInputCallbackBytes); + return _inputRingBuffer.samplesAvailable() / inputToNetworkInputRatio / _inputRingBuffer.getNumFrameSamples(); +} \ No newline at end of file diff --git a/interface/src/Audio.h b/interface/src/Audio.h index 9bc0ecef93..ed50815d78 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -79,8 +79,11 @@ public: const SequenceNumberStats& getIncomingMixedAudioSequenceNumberStats() const { return _incomingMixedAudioSequenceNumberStats; } - int getFramesAvailableInAudioOutputBuffer() const; - int getAverageFramesAvailableInAudioOutputBuffer() const { return (int)_audioOutputBufferFramesAvailableStats.getWindowAverage(); } + int getInputRingBufferFramesAvailable() const; + int getInputRingBufferAverageFramesAvailable() const { return (int)_inputRingBufferFramesAvailableStats.getWindowAverage(); } + + int getOutputRingBufferFramesAvailable() const; + int getOutputRingBufferAverageFramesAvailable() const { return (int)_audioOutputBufferFramesAvailableStats.getWindowAverage(); } public slots: void start(); @@ -224,9 +227,9 @@ private: // Callback acceleration dependent calculations static const float CALLBACK_ACCELERATOR_RATIO; - int calculateNumberOfInputCallbackBytes(const QAudioFormat& format); - int calculateNumberOfFrameSamples(int numBytes); - float calculateDeviceToNetworkInputRatio(int numBytes); + int calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const; + int calculateNumberOfFrameSamples(int numBytes) const; + float calculateDeviceToNetworkInputRatio(int numBytes) const; // Audio scope methods for allocation/deallocation void allocateScope(); @@ -269,7 +272,10 @@ private: SequenceNumberStats _incomingMixedAudioSequenceNumberStats; MovingMinMaxAvg _interframeTimeGapStats; - MovingMinMaxAvg _ringBufferFramesAvailableStats; + + MovingMinMaxAvg _inputRingBufferFramesAvailableStats; + + MovingMinMaxAvg _outputRingBufferFramesAvailableStats; MovingMinMaxAvg _audioOutputBufferFramesAvailableStats; }; diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index aabfe08869..5d6682e413 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -280,7 +280,7 @@ void Stats::display( Audio* audio = Application::getInstance()->getAudio(); const QHash& audioMixerInjectedStreamAudioStatsMap = audio->getAudioMixerInjectedStreamAudioStatsMap(); - lines = _expanded ? 11 + (audioMixerInjectedStreamAudioStatsMap.size() + 2) * 3 : 3; + lines = _expanded ? 13 + (audioMixerInjectedStreamAudioStatsMap.size() + 2) * 3 : 3; drawBackground(backgroundColor, horizontalOffset, 0, _pingStatsWidth, lines * STATS_PELS_PER_LINE + 10); horizontalOffset += 5; @@ -314,6 +314,18 @@ void Stats::display( verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, voxelMaxPing, color); + char inputAudioLabelString[] = "Input: (avail_avg_10s/avail)"; + + verticalOffset += STATS_PELS_PER_LINE; + drawText(horizontalOffset, verticalOffset, scale, rotation, font, inputAudioLabelString, color); + + char inputAudioStatsString[512]; + sprintf(inputAudioStatsString, " %d/%d", audio->getInputRingBufferFramesAvailable(), + audio->getInputRingBufferAverageFramesAvailable()); + + verticalOffset += STATS_PELS_PER_LINE; + drawText(horizontalOffset, verticalOffset, scale, rotation, font, inputAudioStatsString, color); + char audioMixerStatsLabelString[] = "AudioMixer stats:"; char streamStatsFormatLabelString[] = "lost%/lost_30s%"; char streamStatsFormatLabelString2[] = "desired/avail_avg_10s/avail"; @@ -342,8 +354,8 @@ void Stats::display( sprintf(downstreamAudioStatsString, " mix: %.2f%%/%.2f%%, %u/%u+%d/%u+%d", downstreamAudioStreamStats._packetStreamStats.getLostRate()*100.0f, downstreamAudioStreamStats._packetStreamWindowStats.getLostRate() * 100.0f, downstreamAudioStreamStats._ringBufferDesiredJitterBufferFrames, downstreamAudioStreamStats._ringBufferFramesAvailableAverage, - audio->getAverageFramesAvailableInAudioOutputBuffer(), - downstreamAudioStreamStats._ringBufferFramesAvailable, audio->getFramesAvailableInAudioOutputBuffer()); + audio->getOutputRingBufferAverageFramesAvailable(), + downstreamAudioStreamStats._ringBufferFramesAvailable, audio->getOutputRingBufferFramesAvailable()); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, downstreamAudioStatsString, color); diff --git a/libraries/audio/src/PositionalAudioRingBuffer.h b/libraries/audio/src/PositionalAudioRingBuffer.h index c4645c362c..f0d6aff80b 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.h +++ b/libraries/audio/src/PositionalAudioRingBuffer.h @@ -30,9 +30,9 @@ const int TIME_GAPS_FOR_STATS_PACKET_INTERVAL_SAMPLES = USECS_PER_SECOND / BUFFE const int TIME_GAPS_FOR_STATS_PACKET_WINDOW_INTERVALS = 30; // the stats for calculating the average frames available will recalculate every ~1 second -// and will include data for the past ~2 seconds +// and will include data for the past ~10 seconds const int FRAMES_AVAILABLE_STATS_INTERVAL_SAMPLES = USECS_PER_SECOND / BUFFER_SEND_INTERVAL_USECS; -const int FRAMES_AVAILABLE_STATS_WINDOW_INTERVALS = 2; +const int FRAMES_AVAILABLE_STATS_WINDOW_INTERVALS = 10; const int AUDIOMIXER_INBOUND_RING_BUFFER_FRAME_CAPACITY = 100; From 0bcc13aec96c19e84cf0632a8b85218a213c8d22 Mon Sep 17 00:00:00 2001 From: wangyix Date: Mon, 21 Jul 2014 17:12:03 -0700 Subject: [PATCH 2/3] made Audio always push a whole number of frames to the audio output --- interface/src/Audio.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index e5e71b8dcb..478c0d0c55 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -977,8 +977,9 @@ void Audio::processReceivedAudio(const QByteArray& audioByteArray) { if (Menu::getInstance()->isOptionChecked(MenuOption::DisableQAudioOutputOverflowCheck)) { numNetworkOutputSamples = _ringBuffer.samplesAvailable(); } else { - int numSamplesAudioOutputRoomFor = _audioOutput->bytesFree() / sizeof(int16_t); - numNetworkOutputSamples = std::min(_ringBuffer.samplesAvailable(), (int)(numSamplesAudioOutputRoomFor * networkOutputToOutputRatio)); + // make sure to push a whole number of frames to the audio output + int numFramesAudioOutputRoomFor = _audioOutput->bytesFree() / sizeof(int16_t) * networkOutputToOutputRatio / _ringBuffer.getNumFrameSamples(); + numNetworkOutputSamples = std::min(_ringBuffer.samplesAvailable(), numFramesAudioOutputRoomFor * _ringBuffer.getNumFrameSamples()); } // if there is data in the ring buffer and room in the audio output, decide what to do From f6ef61e76a9ed534e99de8419a238e653a3fd4ec Mon Sep 17 00:00:00 2001 From: wangyix Date: Mon, 21 Jul 2014 17:15:08 -0700 Subject: [PATCH 3/3] fixed some typos --- interface/src/Audio.cpp | 2 +- interface/src/ui/Stats.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 478c0d0c55..be348ab635 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -1633,4 +1633,4 @@ int Audio::getOutputRingBufferFramesAvailable() const { int Audio::getInputRingBufferFramesAvailable() const { float inputToNetworkInputRatio = calculateDeviceToNetworkInputRatio(_numInputCallbackBytes); return _inputRingBuffer.samplesAvailable() / inputToNetworkInputRatio / _inputRingBuffer.getNumFrameSamples(); -} \ No newline at end of file +} diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 5d6682e413..412de6e7b0 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -314,14 +314,14 @@ void Stats::display( verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, voxelMaxPing, color); - char inputAudioLabelString[] = "Input: (avail_avg_10s/avail)"; + char inputAudioLabelString[] = "Input: avail_avg_10s/avail"; verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, inputAudioLabelString, color); char inputAudioStatsString[512]; - sprintf(inputAudioStatsString, " %d/%d", audio->getInputRingBufferFramesAvailable(), - audio->getInputRingBufferAverageFramesAvailable()); + sprintf(inputAudioStatsString, " %d/%d", audio->getInputRingBufferAverageFramesAvailable(), + audio->getInputRingBufferFramesAvailable()); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, inputAudioStatsString, color);