diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-0.svg b/interface/resources/images/Audio-Loudness-Icons/vol-0.svg
new file mode 100755
index 0000000000..72f247c238
--- /dev/null
+++ b/interface/resources/images/Audio-Loudness-Icons/vol-0.svg
@@ -0,0 +1,12 @@
+
+
+
diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-1.svg b/interface/resources/images/Audio-Loudness-Icons/vol-1.svg
new file mode 100755
index 0000000000..9570b9ae6c
--- /dev/null
+++ b/interface/resources/images/Audio-Loudness-Icons/vol-1.svg
@@ -0,0 +1,13 @@
+
+
+
diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-2.svg b/interface/resources/images/Audio-Loudness-Icons/vol-2.svg
new file mode 100755
index 0000000000..a2175be39e
--- /dev/null
+++ b/interface/resources/images/Audio-Loudness-Icons/vol-2.svg
@@ -0,0 +1,16 @@
+
+
+
diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-3.svg b/interface/resources/images/Audio-Loudness-Icons/vol-3.svg
new file mode 100755
index 0000000000..21b1095941
--- /dev/null
+++ b/interface/resources/images/Audio-Loudness-Icons/vol-3.svg
@@ -0,0 +1,19 @@
+
+
+
diff --git a/interface/resources/images/Audio-Loudness-Icons/vol-4.svg b/interface/resources/images/Audio-Loudness-Icons/vol-4.svg
new file mode 100755
index 0000000000..de0b4027eb
--- /dev/null
+++ b/interface/resources/images/Audio-Loudness-Icons/vol-4.svg
@@ -0,0 +1,21 @@
+
+
+
diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml
index e0f2df76ce..4735ae9312 100644
--- a/interface/resources/qml/hifi/Pal.qml
+++ b/interface/resources/qml/hifi/Pal.qml
@@ -13,6 +13,7 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
+import QtGraphicalEffects 1.0
import "../styles-uit"
import "../controls-uit" as HifiControls
@@ -163,6 +164,14 @@ Rectangle {
onSortIndicatorColumnChanged: sortModel()
onSortIndicatorOrderChanged: sortModel()
+ TableViewColumn {
+ role: "avgAudioLevel"
+ title: "VOL"
+ width: actionButtonWidth
+ movable: false
+ resizable: false
+ }
+
TableViewColumn {
id: displayNameHeader
role: "displayName"
@@ -185,13 +194,6 @@ Rectangle {
movable: false
resizable: false
}
- TableViewColumn {
- role: "avgAudioLevel"
- title: "VOL"
- width: actionButtonWidth
- movable: false
- resizable: false
- }
TableViewColumn {
visible: iAmAdmin
role: "mute"
@@ -226,7 +228,8 @@ Rectangle {
id: itemCell
property bool isCheckBox: styleData.role === "personalMute" || styleData.role === "ignore"
property bool isButton: styleData.role === "mute" || styleData.role === "kick"
- property bool isText: styleData.role == "avgAudioLevel"
+ property bool isAvgAudio: styleData.role === "avgAudioLevel"
+
// This NameCard refers to the cell that contains an avatar's
// DisplayName and UserName
NameCard {
@@ -236,7 +239,7 @@ Rectangle {
userName: model ? model.userName : ""
audioLevel: model ? model.audioLevel : 0.0
avgAudioLevel: model ? model.avgAudioLevel : 0.0
- visible: !isCheckBox && !isButton && !isText
+ visible: !isCheckBox && !isButton && !isAvgAudio
uuid: model ? model.sessionId : ""
selected: styleData.selected
isAdmin: model && model.admin
@@ -246,14 +249,19 @@ Rectangle {
// Anchors
anchors.left: parent.left
}
- Text {
+ Image {
+ visible: isAvgAudio
+ function getImage() {
+ var fileName = "../../../images/Audio-Loudness-Icons/vol-";
+ fileName += (4.0*(model ? model.avgAudioLevel : 0.0)).toFixed(0);
+ fileName += ".svg";
+ return fileName;
+ }
id: avgAudioVolume
- text: model ? (10 * model.avgAudioLevel).toFixed(0) : 0.0
- visible: isText
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- width: parent.width
- height: parent.height
+ width: hifi.dimensions.tableHeaderHeight
+ fillMode: Image.PreserveAspectFit
+ source: getImage()
+ anchors.verticalCenter: parent.verticalCenter
}
// This CheckBox belongs in the columns that contain the stateful action buttons ("Mute" & "Ignore" for now)
diff --git a/scripts/system/pal.js b/scripts/system/pal.js
index e9f5ba0a67..fe4eea48a4 100644
--- a/scripts/system/pal.js
+++ b/scripts/system/pal.js
@@ -197,6 +197,17 @@ HighlightedEntity.updateOverlays = function updateHighlightedEntities() {
});
};
+/* this contains current gain for a given node (by session id). More efficient than
+ * querying it, plus there isn't a getGain function so why write one */
+var sessionGains = {};
+function convertDbToLinear(decibels) {
+ // +20db = 10x, 0dB = 1x, -10dB = 0.1x, etc...
+ // but, your perception is that something 2x as loud is +10db
+ // so we go from -60 to +20 or 1/64x to 4x. For now, we can
+ // maybe scale the signal this way??
+ return Math.pow(2, decibels/10.0);
+}
+
function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml.
var data;
switch (message.method) {
@@ -242,6 +253,8 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
UserActivityLogger.palAction("avatar_gain_changed", data['sessionId']);
} else {
Users.setAvatarGain(data['sessionId'], data['gain']);
+ sessionGains[data['sessionId']] = convertDbToLinear(data['gain']);
+ print("set " + data['sessionId'] + " to " + sessionGains[data['sessionId']]);
}
break;
case 'displayNameUpdate':
@@ -576,6 +589,7 @@ function scaleAudio(val) {
}
return audioLevel;
}
+
function getAudioLevel(id) {
// the VU meter should work similarly to the one in AvatarInputs: log scale, exponentially averaged
// But of course it gets the data at a different rate, so we tweak the averaging ratio and frequency
@@ -594,9 +608,10 @@ function getAudioLevel(id) {
// natural log, so to get log base 2, just divide by ln(2).
audioLevel = scaleAudio(Math.log(data.accumulatedLevel + 1) / LOG2);
avgAudioLevel = scaleAudio(Math.log(data.longAccumulatedLevel + 1) / LOG2);
-
+ // scale avgAudioLevel given that there can be a gain (4x to 1/64x)
+ avgAudioLevel = Math.min(1.0, avgAudioLevel *(sessionGains[id] || 0.75));
+ data.avgAudioLevel = avgAudioLevel;
data.audioLevel = audioLevel;
- data.averageAudioLevel = avgAudioLevel;
}
return [audioLevel, avgAudioLevel];
}