overte-HifiExperiments/libraries/audio-client/src/AudioIOStats.h
2018-04-22 08:51:47 -07:00

213 lines
7.2 KiB
C++

//
// AudioIOStats.h
// interface/src/audio
//
// Created by Stephen Birarda on 2014-12-16.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_AudioIOStats_h
#define hifi_AudioIOStats_h
#include "MovingMinMaxAvg.h"
#include <QObject>
#include <AudioStreamStats.h>
#include <Node.h>
#include <NLPacket.h>
class MixedProcessedAudioStream;
#define AUDIO_PROPERTY(TYPE, NAME) \
Q_PROPERTY(TYPE NAME READ NAME NOTIFY NAME##Changed) \
public: \
TYPE NAME() const { return _##NAME; } \
void NAME(TYPE value) { \
if (_##NAME != value) { \
_##NAME = value; \
emit NAME##Changed(value); \
} \
} \
Q_SIGNAL void NAME##Changed(TYPE value); \
private: \
TYPE _##NAME{ (TYPE)0 };
class AudioStreamStatsInterface : public QObject {
Q_OBJECT
/**jsdoc
* Audio stats from the Audio Mixer
* @namespace AudioStats.mixerStream
* @param {number} lossRate - To Be Completed
* @param {number} lossCount - To Be Completed
* @param {number} lossRateWindow - To Be Completed
* @param {number} lossCountWindow - To Be Completed
* @param {number} framesDesired - To Be Completed
* @param {number} framesAvailable - To Be Completed
* @param {number} framesAvailableAvg - To Be Completed
* @param {number} unplayedMsMax - To Be Completed
* @param {number} starveCount - To Be Completed
* @param {number} lastStarveDurationCount - To Be Completed
* @param {number} dropCount - To Be Completed
* @param {number} overflowCount - To Be Completed
* @param {number} timegapMsMax - To Be Completed
* @param {number} timegapMsAvg - To Be Completed
* @param {number} timegapMsMaxWindow - To Be Completed
* @param {number} timegapMsAvgWindow - To Be Completed
*/
/**jsdoc
* Audio stats from the Client Mixer
* @namespace AudioStats.clientMixer
* @param {number} lossRate - To Be Completed
* @param {number} lossCount - To Be Completed
* @param {number} lossRateWindow - To Be Completed
* @param {number} lossCountWindow - To Be Completed
* @param {number} framesDesired - To Be Completed
* @param {number} framesAvailable - To Be Completed
* @param {number} framesAvailableAvg - To Be Completed
* @param {number} unplayedMsMax - To Be Completed
* @param {number} starveCount - To Be Completed
* @param {number} lastStarveDurationCount - To Be Completed
* @param {number} dropCount - To Be Completed
* @param {number} overflowCount - To Be Completed
* @param {number} timegapMsMax - To Be Completed
* @param {number} timegapMsAvg - To Be Completed
* @param {number} timegapMsMaxWindow - To Be Completed
* @param {number} timegapMsAvgWindow - To Be Completed
*/
AUDIO_PROPERTY(float, lossRate)
AUDIO_PROPERTY(float, lossCount)
AUDIO_PROPERTY(float, lossRateWindow)
AUDIO_PROPERTY(float, lossCountWindow)
AUDIO_PROPERTY(int, framesDesired)
AUDIO_PROPERTY(int, framesAvailable)
AUDIO_PROPERTY(int, framesAvailableAvg)
AUDIO_PROPERTY(float, unplayedMsMax)
AUDIO_PROPERTY(int, starveCount)
AUDIO_PROPERTY(int, lastStarveDurationCount)
AUDIO_PROPERTY(int, dropCount)
AUDIO_PROPERTY(int, overflowCount)
AUDIO_PROPERTY(quint64, timegapMsMax)
AUDIO_PROPERTY(quint64, timegapMsAvg)
AUDIO_PROPERTY(quint64, timegapMsMaxWindow)
AUDIO_PROPERTY(quint64, timegapMsAvgWindow)
public:
void updateStream(const AudioStreamStats& stats);
private:
friend class AudioStatsInterface;
AudioStreamStatsInterface(QObject* parent);
};
class AudioStatsInterface : public QObject {
Q_OBJECT
/**jsdoc
* Audio stats from the client
* @namespace AudioStats
* @param {number} pingMs - To Be Completed
* @param {number} inputReadMsMax - To Be Completed
* @param {number} inputUnplayedMsMax - To Be Completed
* @param {number} outputUnplayedMsMax - To Be Completed
* @param {number} sentTimegapMsMax - To Be Completed
* @param {number} sentTimegapMsAvg - To Be Completed
* @param {number} sentTimegapMsMaxWindow - To Be Completed
* @param {number} sentTimegapMsAvgWindow - To Be Completed
*/
AUDIO_PROPERTY(float, pingMs);
AUDIO_PROPERTY(float, inputReadMsMax);
AUDIO_PROPERTY(float, inputUnplayedMsMax);
AUDIO_PROPERTY(float, outputUnplayedMsMax);
AUDIO_PROPERTY(quint64, sentTimegapMsMax);
AUDIO_PROPERTY(quint64, sentTimegapMsAvg);
AUDIO_PROPERTY(quint64, sentTimegapMsMaxWindow);
AUDIO_PROPERTY(quint64, sentTimegapMsAvgWindow);
Q_PROPERTY(AudioStreamStatsInterface* mixerStream READ getMixerStream NOTIFY mixerStreamChanged);
Q_PROPERTY(AudioStreamStatsInterface* clientStream READ getClientStream NOTIFY clientStreamChanged);
Q_PROPERTY(QObject* injectorStreams READ getInjectorStreams NOTIFY injectorStreamsChanged);
public:
AudioStreamStatsInterface* getMixerStream() const { return _mixer; }
AudioStreamStatsInterface* getClientStream() const { return _client; }
QObject* getInjectorStreams() const { return _injectors; }
void updateLocalBuffers(const MovingMinMaxAvg<float>& inputMsRead,
const MovingMinMaxAvg<float>& inputMsUnplayed,
const MovingMinMaxAvg<float>& outputMsUnplayed,
const MovingMinMaxAvg<quint64>& timegaps);
void updateMixerStream(const AudioStreamStats& stats) { _mixer->updateStream(stats); emit mixerStreamChanged(); }
void updateClientStream(const AudioStreamStats& stats) { _client->updateStream(stats); emit clientStreamChanged(); }
void updateInjectorStreams(const QHash<QUuid, AudioStreamStats>& stats);
signals:
/**jsdoc
* To Be Completed
* @function AudioStats.mixerStreamChanged
* @returns {Signal}
*/
void mixerStreamChanged();
/**jsdoc
* To Be Completed
* @function AudioStats.clientStreamChanged
* @returns {Signal}
*/
void clientStreamChanged();
/**jsdoc
* To Be Completed
* @function AudioStats.injectorStreamsChanged
* @returns {Signal}
*/
void injectorStreamsChanged();
private:
friend class AudioIOStats;
AudioStatsInterface(QObject* parent);
AudioStreamStatsInterface* _client;
AudioStreamStatsInterface* _mixer;
QObject* _injectors;
};
class AudioIOStats : public QObject {
Q_OBJECT
public:
AudioIOStats(MixedProcessedAudioStream* receivedAudioStream);
void reset();
AudioStatsInterface* data() const { return _interface; }
void updateInputMsRead(float ms) const { _inputMsRead.update(ms); }
void updateInputMsUnplayed(float ms) const { _inputMsUnplayed.update(ms); }
void updateOutputMsUnplayed(float ms) const { _outputMsUnplayed.update(ms); }
void sentPacket() const;
void publish();
public slots:
void processStreamStatsPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer sendingNode);
private:
AudioStatsInterface* _interface;
mutable MovingMinMaxAvg<float> _inputMsRead;
mutable MovingMinMaxAvg<float> _inputMsUnplayed;
mutable MovingMinMaxAvg<float> _outputMsUnplayed;
mutable quint64 _lastSentPacketTime;
mutable MovingMinMaxAvg<quint64> _packetTimegaps;
MixedProcessedAudioStream* _receivedAudioStream;
QHash<QUuid, AudioStreamStats> _injectorStreams;
};
#endif // hifi_AudioIOStats_h