mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 20:31:29 +02:00
added input ring buffer stats to interface
This commit is contained in:
parent
05ea5f8d21
commit
621f0725cc
4 changed files with 45 additions and 19 deletions
|
@ -130,7 +130,8 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) :
|
||||||
_outgoingAvatarAudioSequenceNumber(0),
|
_outgoingAvatarAudioSequenceNumber(0),
|
||||||
_incomingMixedAudioSequenceNumberStats(INCOMING_SEQ_STATS_HISTORY_LENGTH),
|
_incomingMixedAudioSequenceNumberStats(INCOMING_SEQ_STATS_HISTORY_LENGTH),
|
||||||
_interframeTimeGapStats(TIME_GAPS_STATS_INTERVAL_SAMPLES, TIME_GAP_STATS_WINDOW_INTERVALS),
|
_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)
|
_audioOutputBufferFramesAvailableStats(1, FRAMES_AVAILABLE_STATS_WINDOW_SECONDS)
|
||||||
{
|
{
|
||||||
// clear the array of locally injected samples
|
// clear the array of locally injected samples
|
||||||
|
@ -795,7 +796,7 @@ AudioStreamStats Audio::getDownstreamAudioStreamStats() const {
|
||||||
stats._timeGapWindowAverage = _interframeTimeGapStats.getWindowAverage();
|
stats._timeGapWindowAverage = _interframeTimeGapStats.getWindowAverage();
|
||||||
|
|
||||||
stats._ringBufferFramesAvailable = _ringBuffer.framesAvailable();
|
stats._ringBufferFramesAvailable = _ringBuffer.framesAvailable();
|
||||||
stats._ringBufferFramesAvailableAverage = _ringBufferFramesAvailableStats.getWindowAverage();
|
stats._ringBufferFramesAvailableAverage = _outputRingBufferFramesAvailableStats.getWindowAverage();
|
||||||
stats._ringBufferDesiredJitterBufferFrames = getDesiredJitterBufferFrames();
|
stats._ringBufferDesiredJitterBufferFrames = getDesiredJitterBufferFrames();
|
||||||
stats._ringBufferStarveCount = _starveCount;
|
stats._ringBufferStarveCount = _starveCount;
|
||||||
stats._ringBufferConsecutiveNotMixedCount = _consecutiveNotMixedCount;
|
stats._ringBufferConsecutiveNotMixedCount = _consecutiveNotMixedCount;
|
||||||
|
@ -810,9 +811,11 @@ AudioStreamStats Audio::getDownstreamAudioStreamStats() const {
|
||||||
|
|
||||||
void Audio::sendDownstreamAudioStatsPacket() {
|
void Audio::sendDownstreamAudioStatsPacket() {
|
||||||
|
|
||||||
|
_inputRingBufferFramesAvailableStats.update(getInputRingBufferFramesAvailable());
|
||||||
|
|
||||||
// since this function is called every second, we'll sample the number of audio frames available here.
|
// since this function is called every second, we'll sample the number of audio frames available here.
|
||||||
_ringBufferFramesAvailableStats.update(_ringBuffer.framesAvailable());
|
_outputRingBufferFramesAvailableStats.update(_ringBuffer.framesAvailable());
|
||||||
_audioOutputBufferFramesAvailableStats.update(getFramesAvailableInAudioOutputBuffer());
|
_audioOutputBufferFramesAvailableStats.update(getOutputRingBufferFramesAvailable());
|
||||||
|
|
||||||
// push the current seq number stats into history, which moves the history window forward 1s
|
// push the current seq number stats into history, which moves the history window forward 1s
|
||||||
// (since that's how often pushStatsToHistory() is called)
|
// (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;
|
const float Audio::CALLBACK_ACCELERATOR_RATIO = 2.0f;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int Audio::calculateNumberOfInputCallbackBytes(const QAudioFormat& format) {
|
int Audio::calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const {
|
||||||
int numInputCallbackBytes = (int)(((NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL
|
int numInputCallbackBytes = (int)(((NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL
|
||||||
* format.channelCount()
|
* format.channelCount()
|
||||||
* (format.sampleRate() / SAMPLE_RATE))
|
* (format.sampleRate() / SAMPLE_RATE))
|
||||||
|
@ -1605,7 +1608,7 @@ int Audio::calculateNumberOfInputCallbackBytes(const QAudioFormat& format) {
|
||||||
return numInputCallbackBytes;
|
return numInputCallbackBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Audio::calculateDeviceToNetworkInputRatio(int numBytes) {
|
float Audio::calculateDeviceToNetworkInputRatio(int numBytes) const {
|
||||||
float inputToNetworkInputRatio = (int)((_numInputCallbackBytes
|
float inputToNetworkInputRatio = (int)((_numInputCallbackBytes
|
||||||
* CALLBACK_ACCELERATOR_RATIO
|
* CALLBACK_ACCELERATOR_RATIO
|
||||||
/ NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL) + 0.5f);
|
/ NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL) + 0.5f);
|
||||||
|
@ -1613,15 +1616,20 @@ float Audio::calculateDeviceToNetworkInputRatio(int numBytes) {
|
||||||
return inputToNetworkInputRatio;
|
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);
|
int frameSamples = (int)(numBytes * CALLBACK_ACCELERATOR_RATIO + 0.5f) / sizeof(int16_t);
|
||||||
return frameSamples;
|
return frameSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Audio::getFramesAvailableInAudioOutputBuffer() const {
|
int Audio::getOutputRingBufferFramesAvailable() const {
|
||||||
float networkOutputToOutputRatio = (_desiredOutputFormat.sampleRate() / (float)_outputFormat.sampleRate())
|
float networkOutputToOutputRatio = (_desiredOutputFormat.sampleRate() / (float)_outputFormat.sampleRate())
|
||||||
* (_desiredOutputFormat.channelCount() / (float)_outputFormat.channelCount());
|
* (_desiredOutputFormat.channelCount() / (float)_outputFormat.channelCount());
|
||||||
|
|
||||||
return (_audioOutput->bufferSize() - _audioOutput->bytesFree()) * networkOutputToOutputRatio
|
return (_audioOutput->bufferSize() - _audioOutput->bytesFree()) * networkOutputToOutputRatio
|
||||||
/ (sizeof(int16_t) * _ringBuffer.getNumFrameSamples());
|
/ (sizeof(int16_t) * _ringBuffer.getNumFrameSamples());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Audio::getInputRingBufferFramesAvailable() const {
|
||||||
|
float inputToNetworkInputRatio = calculateDeviceToNetworkInputRatio(_numInputCallbackBytes);
|
||||||
|
return _inputRingBuffer.samplesAvailable() / inputToNetworkInputRatio / _inputRingBuffer.getNumFrameSamples();
|
||||||
|
}
|
|
@ -79,8 +79,11 @@ public:
|
||||||
|
|
||||||
const SequenceNumberStats& getIncomingMixedAudioSequenceNumberStats() const { return _incomingMixedAudioSequenceNumberStats; }
|
const SequenceNumberStats& getIncomingMixedAudioSequenceNumberStats() const { return _incomingMixedAudioSequenceNumberStats; }
|
||||||
|
|
||||||
int getFramesAvailableInAudioOutputBuffer() const;
|
int getInputRingBufferFramesAvailable() const;
|
||||||
int getAverageFramesAvailableInAudioOutputBuffer() const { return (int)_audioOutputBufferFramesAvailableStats.getWindowAverage(); }
|
int getInputRingBufferAverageFramesAvailable() const { return (int)_inputRingBufferFramesAvailableStats.getWindowAverage(); }
|
||||||
|
|
||||||
|
int getOutputRingBufferFramesAvailable() const;
|
||||||
|
int getOutputRingBufferAverageFramesAvailable() const { return (int)_audioOutputBufferFramesAvailableStats.getWindowAverage(); }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void start();
|
void start();
|
||||||
|
@ -224,9 +227,9 @@ private:
|
||||||
|
|
||||||
// Callback acceleration dependent calculations
|
// Callback acceleration dependent calculations
|
||||||
static const float CALLBACK_ACCELERATOR_RATIO;
|
static const float CALLBACK_ACCELERATOR_RATIO;
|
||||||
int calculateNumberOfInputCallbackBytes(const QAudioFormat& format);
|
int calculateNumberOfInputCallbackBytes(const QAudioFormat& format) const;
|
||||||
int calculateNumberOfFrameSamples(int numBytes);
|
int calculateNumberOfFrameSamples(int numBytes) const;
|
||||||
float calculateDeviceToNetworkInputRatio(int numBytes);
|
float calculateDeviceToNetworkInputRatio(int numBytes) const;
|
||||||
|
|
||||||
// Audio scope methods for allocation/deallocation
|
// Audio scope methods for allocation/deallocation
|
||||||
void allocateScope();
|
void allocateScope();
|
||||||
|
@ -269,7 +272,10 @@ private:
|
||||||
SequenceNumberStats _incomingMixedAudioSequenceNumberStats;
|
SequenceNumberStats _incomingMixedAudioSequenceNumberStats;
|
||||||
|
|
||||||
MovingMinMaxAvg<quint64> _interframeTimeGapStats;
|
MovingMinMaxAvg<quint64> _interframeTimeGapStats;
|
||||||
MovingMinMaxAvg<int> _ringBufferFramesAvailableStats;
|
|
||||||
|
MovingMinMaxAvg<int> _inputRingBufferFramesAvailableStats;
|
||||||
|
|
||||||
|
MovingMinMaxAvg<int> _outputRingBufferFramesAvailableStats;
|
||||||
MovingMinMaxAvg<int> _audioOutputBufferFramesAvailableStats;
|
MovingMinMaxAvg<int> _audioOutputBufferFramesAvailableStats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -280,7 +280,7 @@ void Stats::display(
|
||||||
Audio* audio = Application::getInstance()->getAudio();
|
Audio* audio = Application::getInstance()->getAudio();
|
||||||
const QHash<QUuid, AudioStreamStats>& audioMixerInjectedStreamAudioStatsMap = audio->getAudioMixerInjectedStreamAudioStatsMap();
|
const QHash<QUuid, AudioStreamStats>& 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);
|
drawBackground(backgroundColor, horizontalOffset, 0, _pingStatsWidth, lines * STATS_PELS_PER_LINE + 10);
|
||||||
horizontalOffset += 5;
|
horizontalOffset += 5;
|
||||||
|
|
||||||
|
@ -314,6 +314,18 @@ void Stats::display(
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, voxelMaxPing, color);
|
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 audioMixerStatsLabelString[] = "AudioMixer stats:";
|
||||||
char streamStatsFormatLabelString[] = "lost%/lost_30s%";
|
char streamStatsFormatLabelString[] = "lost%/lost_30s%";
|
||||||
char streamStatsFormatLabelString2[] = "desired/avail_avg_10s/avail";
|
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,
|
sprintf(downstreamAudioStatsString, " mix: %.2f%%/%.2f%%, %u/%u+%d/%u+%d", downstreamAudioStreamStats._packetStreamStats.getLostRate()*100.0f,
|
||||||
downstreamAudioStreamStats._packetStreamWindowStats.getLostRate() * 100.0f,
|
downstreamAudioStreamStats._packetStreamWindowStats.getLostRate() * 100.0f,
|
||||||
downstreamAudioStreamStats._ringBufferDesiredJitterBufferFrames, downstreamAudioStreamStats._ringBufferFramesAvailableAverage,
|
downstreamAudioStreamStats._ringBufferDesiredJitterBufferFrames, downstreamAudioStreamStats._ringBufferFramesAvailableAverage,
|
||||||
audio->getAverageFramesAvailableInAudioOutputBuffer(),
|
audio->getOutputRingBufferAverageFramesAvailable(),
|
||||||
downstreamAudioStreamStats._ringBufferFramesAvailable, audio->getFramesAvailableInAudioOutputBuffer());
|
downstreamAudioStreamStats._ringBufferFramesAvailable, audio->getOutputRingBufferFramesAvailable());
|
||||||
|
|
||||||
verticalOffset += STATS_PELS_PER_LINE;
|
verticalOffset += STATS_PELS_PER_LINE;
|
||||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, downstreamAudioStatsString, color);
|
drawText(horizontalOffset, verticalOffset, scale, rotation, font, downstreamAudioStatsString, color);
|
||||||
|
|
|
@ -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;
|
const int TIME_GAPS_FOR_STATS_PACKET_WINDOW_INTERVALS = 30;
|
||||||
|
|
||||||
// the stats for calculating the average frames available will recalculate every ~1 second
|
// 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_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;
|
const int AUDIOMIXER_INBOUND_RING_BUFFER_FRAME_CAPACITY = 100;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue