From e6c0baa1ff8a492a964c6f310cfd4e78e8e1328e Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 26 Sep 2016 15:35:45 -0700 Subject: [PATCH] remake audio stats in qml --- scripts/developer/utilities/audio/Jitter.qml | 36 ++++++++++ .../developer/utilities/audio/MovingValue.qml | 40 ++++++++++++ .../utilities/audio/MovingValuePair.qml | 65 +++++++++++++++++++ scripts/developer/utilities/audio/Section.qml | 56 ++++++++++++++++ scripts/developer/utilities/audio/Stream.qml | 63 ++++++++++++++++++ scripts/developer/utilities/audio/Value.qml | 33 ++++++++++ scripts/developer/utilities/audio/stats.js | 25 +++++++ scripts/developer/utilities/audio/stats.qml | 64 ++++++++++++++++++ 8 files changed, 382 insertions(+) create mode 100644 scripts/developer/utilities/audio/Jitter.qml create mode 100644 scripts/developer/utilities/audio/MovingValue.qml create mode 100644 scripts/developer/utilities/audio/MovingValuePair.qml create mode 100644 scripts/developer/utilities/audio/Section.qml create mode 100644 scripts/developer/utilities/audio/Stream.qml create mode 100644 scripts/developer/utilities/audio/Value.qml create mode 100644 scripts/developer/utilities/audio/stats.js create mode 100644 scripts/developer/utilities/audio/stats.qml diff --git a/scripts/developer/utilities/audio/Jitter.qml b/scripts/developer/utilities/audio/Jitter.qml new file mode 100644 index 0000000000..73a2a05741 --- /dev/null +++ b/scripts/developer/utilities/audio/Jitter.qml @@ -0,0 +1,36 @@ +// +// Jitter.qml +// scripts/developer/utilities/audio +// +// Created by Zach Pomerantz on 9/22/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +ColumnLayout { + property var max + property var avg + property var maxWindow + property var avgWindow + + MovingValuePair { + label: "Total" + label1: "Average" + label2: "Maximum" + source1: avg + source2: max + } + MovingValuePair { + label: "Window" + label1: "Average" + label2: "Maximum" + source1: avgWindow + source2: maxWindow + } +} + diff --git a/scripts/developer/utilities/audio/MovingValue.qml b/scripts/developer/utilities/audio/MovingValue.qml new file mode 100644 index 0000000000..770e585af5 --- /dev/null +++ b/scripts/developer/utilities/audio/MovingValue.qml @@ -0,0 +1,40 @@ +// +// MovingValue.qml +// scripts/developer/utilities/audio +// +// Created by Zach Pomerantz on 9/22/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +RowLayout { + id: value + property string label + property var source + property string unit: "ms" + + width: parent.width + property int dataPixelWidth: 150 + + Label { + Layout.preferredWidth: dataPixelWidth + text: value.label + } + Label { + Layout.preferredWidth: 0 + horizontalAlignment: Text.AlignRight + text: value.source + ' ' + unit + } + Label { + Layout.fillWidth: true + horizontalAlignment: Text.AlignRight + Layout.alignment: Qt.AlignRight + text: "Placeholder" + } +} + diff --git a/scripts/developer/utilities/audio/MovingValuePair.qml b/scripts/developer/utilities/audio/MovingValuePair.qml new file mode 100644 index 0000000000..f043b6348d --- /dev/null +++ b/scripts/developer/utilities/audio/MovingValuePair.qml @@ -0,0 +1,65 @@ +// +// MovingValuePair.qml +// scripts/developer/utilities/audio +// +// Created by Zach Pomerantz on 9/22/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +RowLayout { + id: value + property string label + property string label1 + property string label2 + property var source + property var source1 + property var source2 + property string unit: "ms" + + property int labelPixelWidth: 50 + property int dataPixelWidth: 100 + + Label { + Layout.preferredWidth: labelPixelWidth - value.spacing + text: value.label + } + + ColumnLayout { + RowLayout { + Label { + Layout.preferredWidth: dataPixelWidth + text: value.label1 + } + Label { + Layout.preferredWidth: 0 + horizontalAlignment: Text.AlignRight + text: value.source1 + ' ' + unit + } + } + RowLayout { + Label { + Layout.preferredWidth: dataPixelWidth + text: value.label2 + } + Label { + Layout.preferredWidth: 0 + horizontalAlignment: Text.AlignRight + text: value.source2 + ' ' + unit + } + } + } + Label { + Layout.fillWidth: true + horizontalAlignment: Text.AlignRight + Layout.alignment: Qt.AlignRight + text: "Placeholder" + } + +} + diff --git a/scripts/developer/utilities/audio/Section.qml b/scripts/developer/utilities/audio/Section.qml new file mode 100644 index 0000000000..100d05f6b2 --- /dev/null +++ b/scripts/developer/utilities/audio/Section.qml @@ -0,0 +1,56 @@ +// +// Section.qml +// scripts/developer/utilities/audio +// +// Created by Zach Pomerantz on 9/22/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +Rectangle { + id: section + property string label: "Section" + property string description: "Description" + property alias control : loader.sourceComponent + + width: parent.width + height: content.height + border.width * 2 + content.spacing * 2 + border.color: "black" + border.width: 5 + radius: border.width * 2 + + ColumnLayout { + id: content + x: section.radius; y: section.radius + spacing: section.border.width + width: section.width - 2 * x + + // label + Label { + Layout.alignment: Qt.AlignCenter + text: hoverArea.containsMouse ? section.description : section.label + font.bold: true + + MouseArea { + id: hoverArea + anchors.fill: parent + hoverEnabled: true + } + } + + // spacer + Item { } + + // control + Loader { + id: loader + Layout.preferredWidth: parent.width + } + } +} + diff --git a/scripts/developer/utilities/audio/Stream.qml b/scripts/developer/utilities/audio/Stream.qml new file mode 100644 index 0000000000..c638850243 --- /dev/null +++ b/scripts/developer/utilities/audio/Stream.qml @@ -0,0 +1,63 @@ +// +// Stream.qml +// scripts/developer/utilities/audio +// +// Created by Zach Pomerantz on 9/22/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +ColumnLayout { + property var stream + + Label { + Layout.alignment: Qt.AlignCenter + text: "Ring Buffer" + font.italic: true + } + MovingValue { + label: "Desired" + source: stream.framesDesired + unit: "frames" + } + MovingValue { + label: "Unplayed" + source: stream.unplayedMsMax + } + Value { + label: "Available (avg)" + source: stream.framesAvailable + " (" + stream.framesAvailableAvg + ") frames" + } + + Label { + Layout.alignment: Qt.AlignCenter + text: "Jitter" + font.italic: true + } + Jitter { + max: stream.timegapMsMax + avg: stream.timegapMsAvg + maxWindow: stream.timegapMsMaxWindow + avgWindow: stream.timegapMsAvgWindow + } + + Label { + Layout.alignment: Qt.AlignCenter + text: "Packet Loss" + font.italic: true + } + Value { + label: "Overall" + source: stream.lossRate + "% (" + stream.lossCount + " lost)" + } + Value { + label: "Window" + source: stream.lossRateWindow + "% (" + stream.lossCountWindow + " lost)" + } +} + diff --git a/scripts/developer/utilities/audio/Value.qml b/scripts/developer/utilities/audio/Value.qml new file mode 100644 index 0000000000..cb88ceb1e3 --- /dev/null +++ b/scripts/developer/utilities/audio/Value.qml @@ -0,0 +1,33 @@ +// +// Value.qml +// scripts/developer/utilities/audio +// +// Created by Zach Pomerantz on 9/22/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +RowLayout { + id: value + property string label + property var source + + width: parent.width + property int dataPixelWidth: 150 + + Label { + Layout.preferredWidth: dataPixelWidth + text: value.label + } + Label { + Layout.preferredWidth: 0 + horizontalAlignment: Text.AlignRight + text: value.source + } +} + diff --git a/scripts/developer/utilities/audio/stats.js b/scripts/developer/utilities/audio/stats.js new file mode 100644 index 0000000000..af38092685 --- /dev/null +++ b/scripts/developer/utilities/audio/stats.js @@ -0,0 +1,25 @@ +// +// stats.js +// scripts/developer/utilities/audio +// +// Zach Pomerantz, created on 9/22/2016. +// Copyright 2016 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 +// + +var INITIAL_WIDTH = 400; +var INITIAL_OFFSET = 50; + +// Set up the qml ui +var qml = Script.resolvePath('stats.qml'); +var window = new OverlayWindow({ + title: 'Audio Interface Statistics', + source: qml, + width: 400, height: 720 // stats.qml may be too large for some screens +}); +window.setPosition(INITIAL_OFFSET, INITIAL_OFFSET); + +window.closed.connect(function() { Script.stop(); }); + diff --git a/scripts/developer/utilities/audio/stats.qml b/scripts/developer/utilities/audio/stats.qml new file mode 100644 index 0000000000..4698d6b977 --- /dev/null +++ b/scripts/developer/utilities/audio/stats.qml @@ -0,0 +1,64 @@ +// +// stats.qml +// scripts/developer/utilities/audio +// +// Created by Zach Pomerantz on 9/22/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +Column { + width: parent.width + height: parent.height + + Section { + label: "Latency" + description: "Audio pipeline latency, broken out and summed" + control: ColumnLayout { + MovingValue { label: "Input Read"; source: AudioStats.inputReadMsMax } + MovingValue { label: "Input Ring"; source: AudioStats.inputUnplayedMsMax } + MovingValue { label: "Network (client->mixer)"; source: AudioStats.pingMs / 2 } + MovingValue { label: "Mixer Ring"; source: AudioStats.mixerStream.unplayedMsMax } + MovingValue { label: "Network (mixer->client)"; source: AudioStats.pingMs / 2 } + MovingValue { label: "Output Ring"; source: AudioStats.clientStream.unplayedMsMax } + MovingValue { label: "Output Read"; source: AudioStats.outputUnplayedMsMax } + MovingValue { label: "TOTAL" + source: AudioStats.inputReadMsMax + + AudioStats.inputUnplayedMsMax + + AudioStats.outputUnplayedMsMax + + AudioStats.mixerStream.unplayedMsMax + + AudioStats.clientStream.unplayedMsMax + + AudioStats.pingMs + } + } + } + + Section { + label: "Upstream Jitter" + description: "Timegaps in packets sent to the mixer" + control: Jitter { + max: AudioStats.sentTimegapMsMax + avg: AudioStats.sentTimegapMsAvg + maxWindow: AudioStats.sentTimegapMsMaxWindow + avgWindow: AudioStats.sentTimegapMsAvgWindow + } + } + + Section { + label: "Mixer (upstream)" + description: "This client's remote audio stream, as seen by the server's mixer" + control: Stream { stream: AudioStats.mixerStream } + } + + Section { + label: "Client (downstream)" + description: "This client's received audio stream, between the network and the OS" + control: Stream { stream: AudioStats.clientStream } + } +} +