diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8edc788833..689250b318 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2158,7 +2158,6 @@ void Application::updateMyAvatar(float deltaTime) { { quint64 sinceLastNack = now - _lastSendDownstreamAudioStats; - const quint64 TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS = 1 * USECS_PER_SECOND; if (sinceLastNack > TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS) { _lastSendDownstreamAudioStats = now; diff --git a/interface/src/Application.h b/interface/src/Application.h index b55a830e3e..d956a949ac 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -125,6 +125,8 @@ static const float MIRROR_REARVIEW_DISTANCE = 0.65f; static const float MIRROR_REARVIEW_BODY_DISTANCE = 2.3f; static const float MIRROR_FIELD_OF_VIEW = 30.0f; +static const quint64 TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS = 1 * USECS_PER_SECOND; + class Application : public QApplication { Q_OBJECT diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 7a445bf816..3689ff0143 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -48,15 +48,18 @@ static const float AUDIO_CALLBACK_MSECS = (float) NETWORK_BUFFER_LENGTH_SAMPLES_ static const int NUMBER_OF_NOISE_SAMPLE_FRAMES = 300; -static const int AUDIO_STREAM_STATS_HISTORY_SIZE = 30; - // audio frames time gap stats (min/max/avg) for last ~30 seconds are recalculated every ~1 second -const int TIME_GAPS_STATS_INTERVAL_SAMPLES = USECS_PER_SECOND / BUFFER_SEND_INTERVAL_USECS; -const int TIME_GAP_STATS_WINDOW_INTERVALS = 30; +static const int TIME_GAPS_STATS_INTERVAL_SAMPLES = USECS_PER_SECOND / BUFFER_SEND_INTERVAL_USECS; +static const int TIME_GAP_STATS_WINDOW_INTERVALS = 30; + +// incoming sequence number stats history will cover last 30s +static const int INCOMING_SEQ_STATS_HISTORY_LENGTH = INCOMING_SEQ_STATS_HISTORY_LENGTH_SECONDS / + (TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS / USECS_PER_SECOND); // Mute icon configration static const int MUTE_ICON_SIZE = 24; + Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) : AbstractAudioInterface(parent), _audioInput(NULL), @@ -110,9 +113,8 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) : _scopeOutputLeft(0), _scopeOutputRight(0), _audioMixerAvatarStreamAudioStats(), - _audioMixerAvatarStreamPacketStatsHistory(AUDIO_STREAM_STATS_HISTORY_SIZE), _outgoingAvatarAudioSequenceNumber(0), - _incomingStreamPacketStatsHistory(AUDIO_STREAM_STATS_HISTORY_SIZE), + _incomingMixedAudioSequenceNumberStats(INCOMING_SEQ_STATS_HISTORY_LENGTH), _interframeTimeGapStats(TIME_GAPS_STATS_INTERVAL_SAMPLES, TIME_GAP_STATS_WINDOW_INTERVALS), _starveCount(0), _consecutiveNotMixedCount(0) @@ -138,13 +140,8 @@ void Audio::reset() { _audioMixerAvatarStreamAudioStats = AudioStreamStats(); _audioMixerInjectedStreamAudioStatsMap.clear(); - _audioMixerAvatarStreamPacketStatsHistory.clear(); - _audioMixerInjectedStreamPacketStatsHistoryMap.clear(); - _outgoingAvatarAudioSequenceNumber = 0; _incomingMixedAudioSequenceNumberStats.reset(); - - _incomingStreamPacketStatsHistory.clear(); } QAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) { @@ -751,7 +748,6 @@ void Audio::parseAudioStreamStatsPacket(const QByteArray& packet) { dataAt += sizeof(quint8); if (!appendFlag) { _audioMixerInjectedStreamAudioStatsMap.clear(); - _audioMixerInjectedStreamPacketStatsHistoryMap.clear(); } // parse the number of stream stats structs to follow @@ -766,20 +762,10 @@ void Audio::parseAudioStreamStatsPacket(const QByteArray& packet) { if (streamStats._streamType == PositionalAudioRingBuffer::Microphone) { _audioMixerAvatarStreamAudioStats = streamStats; - _audioMixerAvatarStreamPacketStatsHistory.insert(streamStats._packetStreamStats); } else { - if (!_audioMixerInjectedStreamAudioStatsMap.contains(streamStats._streamIdentifier)) { - _audioMixerInjectedStreamPacketStatsHistoryMap.insert(streamStats._streamIdentifier, - RingBufferHistory(AUDIO_STREAM_STATS_HISTORY_SIZE)); - } _audioMixerInjectedStreamAudioStatsMap[streamStats._streamIdentifier] = streamStats; - _audioMixerInjectedStreamPacketStatsHistoryMap[streamStats._streamIdentifier].insert(streamStats._packetStreamStats); } } - - // when an audio stream stats packet is received, also record the downstream packets stats in the history - // for calculating packet loss rates - _incomingStreamPacketStatsHistory.insert(_incomingMixedAudioSequenceNumberStats.getStats()); } AudioStreamStats Audio::getDownstreamAudioStreamStats() const { @@ -803,12 +789,17 @@ AudioStreamStats Audio::getDownstreamAudioStreamStats() const { stats._ringBufferSilentFramesDropped = 0; stats._packetStreamStats = _incomingMixedAudioSequenceNumberStats.getStats(); + stats._packetStreamWindowStats = _incomingMixedAudioSequenceNumberStats.getStatsForHistoryWindow(); return stats; } void Audio::sendDownstreamAudioStatsPacket() { + // push the current seq number stats into history, which moves the history window forward 1s + // (since that's how often pushStatsToHistory() is called) + _incomingMixedAudioSequenceNumberStats.pushStatsToHistory(); + char packet[MAX_PACKET_SIZE]; // pack header @@ -1608,25 +1599,3 @@ int Audio::calculateNumberOfFrameSamples(int numBytes) { int frameSamples = (int)(numBytes * CALLBACK_ACCELERATOR_RATIO + 0.5f) / sizeof(int16_t); return frameSamples; } - -void Audio::calculatePacketLossRate(const RingBufferHistory& statsHistory, - float& overallLossRate, float& windowLossRate) const { - - int numHistoryEntries = statsHistory.getNumEntries(); - if (numHistoryEntries == 0) { - overallLossRate = 0.0f; - windowLossRate = 0.0f; - } else { - const PacketStreamStats& newestStats = *statsHistory.getNewestEntry(); - overallLossRate = (float)newestStats._numLost / newestStats._numReceived; - - if (numHistoryEntries == 1) { - windowLossRate = overallLossRate; - } else { - int age = std::min(numHistoryEntries-1, AUDIO_STREAM_STATS_HISTORY_SIZE-1); - const PacketStreamStats& oldestStats = *statsHistory.get(age); - windowLossRate = (float)(newestStats._numLost - oldestStats._numLost) - / (newestStats._numReceived - oldestStats._numReceived); - } - } -} diff --git a/interface/src/Audio.h b/interface/src/Audio.h index e8e92db1a0..b40355e714 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -36,6 +36,8 @@ static const int NUM_AUDIO_CHANNELS = 2; +static const int INCOMING_SEQ_STATS_HISTORY_LENGTH_SECONDS = 30; + class QAudioInput; class QAudioOutput; class QIODevice; @@ -121,14 +123,8 @@ public slots: const AudioStreamStats& getAudioMixerAvatarStreamAudioStats() const { return _audioMixerAvatarStreamAudioStats; } const QHash& getAudioMixerInjectedStreamAudioStatsMap() const { return _audioMixerInjectedStreamAudioStatsMap; } - const RingBufferHistory& getAudioMixerAvatarStreamPacketStatsHistory() const { return _audioMixerAvatarStreamPacketStatsHistory; } - const QHash >& getAudioMixerInjectedStreamPacketStatsHistoryMap() const {return _audioMixerInjectedStreamPacketStatsHistoryMap; } - const RingBufferHistory& getIncomingStreamPacketStatsHistory() const { return _incomingStreamPacketStatsHistory; } const MovingMinMaxAvg& getInterframeTimeGapStats() const { return _interframeTimeGapStats; } - void calculatePacketLossRate(const RingBufferHistory& statsHistory, - float& overallLossRate, float& windowLossRate) const; - signals: bool muteToggled(); void preProcessOriginalInboundAudio(unsigned int sampleTime, QByteArray& samples, const QAudioFormat& format); @@ -266,14 +262,9 @@ private: AudioStreamStats _audioMixerAvatarStreamAudioStats; QHash _audioMixerInjectedStreamAudioStatsMap; - RingBufferHistory _audioMixerAvatarStreamPacketStatsHistory; - QHash > _audioMixerInjectedStreamPacketStatsHistoryMap; - quint16 _outgoingAvatarAudioSequenceNumber; SequenceNumberStats _incomingMixedAudioSequenceNumberStats; - RingBufferHistory _incomingStreamPacketStatsHistory; - MovingMinMaxAvg _interframeTimeGapStats; };