From 6035374004794dc44d4dc5be052d219395e8dae2 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 26 Sep 2016 16:33:56 -0700 Subject: [PATCH] add graphs to audio stats --- scripts/developer/utilities/audio/Jitter.qml | 20 +-- .../developer/utilities/audio/MovingValue.qml | 15 ++- .../utilities/audio/MovingValuePair.qml | 20 +-- scripts/developer/utilities/audio/Stream.qml | 5 + scripts/developer/utilities/audio/stats.js | 2 +- scripts/developer/utilities/audio/stats.qml | 115 +++++++++++------- .../utilities/lib/plotperf/PlotPerf.qml | 13 +- 7 files changed, 126 insertions(+), 64 deletions(-) diff --git a/scripts/developer/utilities/audio/Jitter.qml b/scripts/developer/utilities/audio/Jitter.qml index 73a2a05741..5908c89399 100644 --- a/scripts/developer/utilities/audio/Jitter.qml +++ b/scripts/developer/utilities/audio/Jitter.qml @@ -13,24 +13,28 @@ import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 ColumnLayout { + id: jitter property var max property var avg property var maxWindow property var avgWindow + property bool showGraphs: false MovingValuePair { label: "Total" - label1: "Average" - label2: "Maximum" - source1: avg - source2: max + label1: "Maximum" + label2: "Average" + source1: max + source2: avg + showGraphs: jitter.showGraphs } MovingValuePair { label: "Window" - label1: "Average" - label2: "Maximum" - source1: avgWindow - source2: maxWindow + label1: "Maximum" + label2: "Average" + source1: maxWindow + source2: avgWindow + showGraphs: jitter.showGraphs } } diff --git a/scripts/developer/utilities/audio/MovingValue.qml b/scripts/developer/utilities/audio/MovingValue.qml index 770e585af5..ebeda3ed73 100644 --- a/scripts/developer/utilities/audio/MovingValue.qml +++ b/scripts/developer/utilities/audio/MovingValue.qml @@ -11,12 +11,14 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 +import "../lib/plotperf" RowLayout { id: value property string label property var source property string unit: "ms" + property bool showGraphs: false width: parent.width property int dataPixelWidth: 150 @@ -26,15 +28,20 @@ RowLayout { text: value.label } Label { + visible: !value.showGraphs Layout.preferredWidth: 0 horizontalAlignment: Text.AlignRight text: value.source + ' ' + unit } - Label { + PlotPerf { + visible: value.showGraphs Layout.fillWidth: true - horizontalAlignment: Text.AlignRight - Layout.alignment: Qt.AlignRight - text: "Placeholder" + height: 70 + + valueUnit: value.unit + valueNumDigits: 0 + + plots: [{ binding: "source" }] } } diff --git a/scripts/developer/utilities/audio/MovingValuePair.qml b/scripts/developer/utilities/audio/MovingValuePair.qml index f043b6348d..ad7913b34f 100644 --- a/scripts/developer/utilities/audio/MovingValuePair.qml +++ b/scripts/developer/utilities/audio/MovingValuePair.qml @@ -11,16 +11,17 @@ import QtQuick 2.5 import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 +import "../lib/plotperf" 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 bool showGraphs: false property int labelPixelWidth: 50 property int dataPixelWidth: 100 @@ -37,6 +38,7 @@ RowLayout { text: value.label1 } Label { + visible: !value.showGraphs Layout.preferredWidth: 0 horizontalAlignment: Text.AlignRight text: value.source1 + ' ' + unit @@ -48,18 +50,22 @@ RowLayout { text: value.label2 } Label { + visible: !value.showGraphs Layout.preferredWidth: 0 horizontalAlignment: Text.AlignRight text: value.source2 + ' ' + unit } } } - Label { + PlotPerf { + visible: value.showGraphs + Layout.fillWidth: true - horizontalAlignment: Text.AlignRight - Layout.alignment: Qt.AlignRight - text: "Placeholder" + height: 70 + + valueUnit: value.unit + valueNumDigits: 0 + + plots: [{ binding: "source1" }, { binding: "source2" }] } - } - diff --git a/scripts/developer/utilities/audio/Stream.qml b/scripts/developer/utilities/audio/Stream.qml index c638850243..71e4b9eedf 100644 --- a/scripts/developer/utilities/audio/Stream.qml +++ b/scripts/developer/utilities/audio/Stream.qml @@ -13,7 +13,9 @@ import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 ColumnLayout { + id: root property var stream + property bool showGraphs: false Label { Layout.alignment: Qt.AlignCenter @@ -24,10 +26,12 @@ ColumnLayout { label: "Desired" source: stream.framesDesired unit: "frames" + showGraphs: root.showGraphs } MovingValue { label: "Unplayed" source: stream.unplayedMsMax + showGraphs: root.showGraphs } Value { label: "Available (avg)" @@ -44,6 +48,7 @@ ColumnLayout { avg: stream.timegapMsAvg maxWindow: stream.timegapMsMaxWindow avgWindow: stream.timegapMsAvgWindow + showGraphs: root.showGraphs } Label { diff --git a/scripts/developer/utilities/audio/stats.js b/scripts/developer/utilities/audio/stats.js index af38092685..8d3bf8d637 100644 --- a/scripts/developer/utilities/audio/stats.js +++ b/scripts/developer/utilities/audio/stats.js @@ -17,7 +17,7 @@ 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 + width: 800, height: 720 // stats.qml may be too large for some screens }); window.setPosition(INITIAL_OFFSET, INITIAL_OFFSET); diff --git a/scripts/developer/utilities/audio/stats.qml b/scripts/developer/utilities/audio/stats.qml index 4698d6b977..5faa1a0e60 100644 --- a/scripts/developer/utilities/audio/stats.qml +++ b/scripts/developer/utilities/audio/stats.qml @@ -13,52 +13,85 @@ import QtQuick.Controls 1.4 import QtQuick.Layouts 1.3 Column { + id: stats width: parent.width height: parent.height + property bool showGraphs: toggleGraphs.checked - 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 + RowLayout { + width: parent.width + height: 30 + + Button { + id: toggleGraphs + property bool checked: false + + Layout.alignment: Qt.AlignCenter + + text: checked ? "Hide graphs" : "Show graphs" + onClicked: function() { checked = !checked; } + } + } + + Grid { + width: parent.width + height: parent.height - 30 + + Column { + width: parent.width / 2 + height: parent.height + + Section { + label: "Latency" + description: "Audio pipeline latency, broken out and summed" + control: ColumnLayout { + MovingValue { label: "Input Read"; source: AudioStats.inputReadMsMax; showGraphs: stats.showGraphs } + MovingValue { label: "Input Ring"; source: AudioStats.inputUnplayedMsMax; showGraphs: stats.showGraphs } + MovingValue { label: "Network (client->mixer)"; source: AudioStats.pingMs / 2; showGraphs: stats.showGraphs } + MovingValue { label: "Mixer Ring"; source: AudioStats.mixerStream.unplayedMsMax; showGraphs: stats.showGraphs } + MovingValue { label: "Network (mixer->client)"; source: AudioStats.pingMs / 2; showGraphs: stats.showGraphs } + MovingValue { label: "Output Ring"; source: AudioStats.clientStream.unplayedMsMax; showGraphs: stats.showGraphs } + MovingValue { label: "Output Read"; source: AudioStats.outputUnplayedMsMax; showGraphs: stats.showGraphs } + MovingValue { label: "TOTAL"; showGraphs: stats.showGraphs + 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 + showGraphs: stats.showGraphs + } + } + } + + Column { + width: parent.width / 2 + height: parent.height + + Section { + label: "Mixer (upstream)" + description: "This client's remote audio stream, as seen by the server's mixer" + control: Stream { stream: AudioStats.mixerStream; showGraphs: stats.showGraphs } + } + + Section { + label: "Client (downstream)" + description: "This client's received audio stream, between the network and the OS" + control: Stream { stream: AudioStats.clientStream; showGraphs: stats.showGraphs } } } } - - 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 } - } } diff --git a/scripts/developer/utilities/lib/plotperf/PlotPerf.qml b/scripts/developer/utilities/lib/plotperf/PlotPerf.qml index c6b95dca30..4edc71c343 100644 --- a/scripts/developer/utilities/lib/plotperf/PlotPerf.qml +++ b/scripts/developer/utilities/lib/plotperf/PlotPerf.qml @@ -55,9 +55,17 @@ Item { function createValues() { for (var i =0; i < plots.length; i++) { var plot = plots[i]; + var object = plot["object"] || root.object; + var value = plot["prop"]; + var isBinding = plot["binding"]; + if (isBinding) { + object = root.parent; + value = isBinding; + } _values.push( { - object: (plot["object"] !== undefined ? plot["object"] : root.object), - value: plot["prop"], + object: object, + value: value, + fromBinding: isBinding, valueMax: 1, numSamplesConstantMax: 0, valueHistory: new Array(), @@ -218,7 +226,6 @@ Item { anchors.rightMargin: -hitboxExtension onClicked: { - print("PerfPlot clicked!") resetMax(); } }