mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 16:18:05 +02:00
Merge pull request #9261 from davidkelly/dk/workingVUMetersInPal
Working VU meters in PAL
This commit is contained in:
commit
68fb81902b
3 changed files with 69 additions and 4 deletions
|
@ -33,6 +33,7 @@ Row {
|
||||||
property string userName: ""
|
property string userName: ""
|
||||||
property int displayTextHeight: 18
|
property int displayTextHeight: 18
|
||||||
property int usernameTextHeight: 12
|
property int usernameTextHeight: 12
|
||||||
|
property real audioLevel: 0.0
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
id: avatarImage
|
id: avatarImage
|
||||||
|
@ -91,7 +92,6 @@ Row {
|
||||||
// VU Meter
|
// VU Meter
|
||||||
Rectangle { // CHANGEME to the appropriate type!
|
Rectangle { // CHANGEME to the appropriate type!
|
||||||
id: nameCardVUMeter
|
id: nameCardVUMeter
|
||||||
objectName: "AvatarInputs"
|
|
||||||
// Size
|
// Size
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 8
|
height: 8
|
||||||
|
@ -110,7 +110,7 @@ Row {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: vuMeterLevel
|
id: vuMeterLevel
|
||||||
// Size
|
// Size
|
||||||
width: (nameCardVUMeter.audioLevel) * parent.width
|
width: (thisNameCard.audioLevel) * parent.width
|
||||||
// Style
|
// Style
|
||||||
color: "#dbdbdb" // Very appropriate hex value here
|
color: "#dbdbdb" // Very appropriate hex value here
|
||||||
radius: parent.radius
|
radius: parent.radius
|
||||||
|
|
|
@ -58,6 +58,7 @@ Item {
|
||||||
// Properties
|
// Properties
|
||||||
displayName: myData.displayName
|
displayName: myData.displayName
|
||||||
userName: myData.userName
|
userName: myData.userName
|
||||||
|
audioLevel: myData.audioLevel
|
||||||
// Size
|
// Size
|
||||||
width: nameCardWidth
|
width: nameCardWidth
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
@ -190,6 +191,7 @@ Item {
|
||||||
// Properties
|
// Properties
|
||||||
displayName: styleData.value
|
displayName: styleData.value
|
||||||
userName: model.userName
|
userName: model.userName
|
||||||
|
audioLevel: model.audioLevel
|
||||||
visible: !isCheckBox
|
visible: !isCheckBox
|
||||||
// Size
|
// Size
|
||||||
width: nameCardWidth
|
width: nameCardWidth
|
||||||
|
@ -292,7 +294,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
property var userData: []
|
property var userData: []
|
||||||
property var myData: ({displayName: "", userName: ""}) // valid dummy until set
|
property var myData: ({displayName: "", userName: "", audioLevel: 0.0}) // valid dummy until set
|
||||||
property bool iAmAdmin: false
|
property bool iAmAdmin: false
|
||||||
function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
||||||
var i, data = optionalData || userData, length = data.length;
|
var i, data = optionalData || userData, length = data.length;
|
||||||
|
@ -343,6 +345,21 @@ Item {
|
||||||
userData[userIndex].userName = userName; // Defensive programming
|
userData[userIndex].userName = userName; // Defensive programming
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'updateAudioLevel':
|
||||||
|
for (var userId in message.params) {
|
||||||
|
var audioLevel = message.params[userId];
|
||||||
|
// If the userId is 0, we're updating "myData".
|
||||||
|
if (userId == 0) {
|
||||||
|
myData.audioLevel = audioLevel;
|
||||||
|
myCard.audioLevel = audioLevel; // Defensive programming
|
||||||
|
} else {
|
||||||
|
console.log("userid:" + userId);
|
||||||
|
var userIndex = findSessionIndex(userId);
|
||||||
|
userModel.get(userIndex).audioLevel = audioLevel;
|
||||||
|
userData[userIndex].audioLevel = audioLevel; // Defensive programming
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
console.log('Unrecognized message:', JSON.stringify(message));
|
console.log('Unrecognized message:', JSON.stringify(message));
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,8 @@ function populateUserList() {
|
||||||
var avatarPalDatum = {
|
var avatarPalDatum = {
|
||||||
displayName: avatar.sessionDisplayName,
|
displayName: avatar.sessionDisplayName,
|
||||||
userName: '',
|
userName: '',
|
||||||
sessionId: id || ''
|
sessionId: id || '',
|
||||||
|
audioLevel: 0.0
|
||||||
};
|
};
|
||||||
// If the current user is an admin OR
|
// If the current user is an admin OR
|
||||||
// they're requesting their own username ("id" is blank)...
|
// they're requesting their own username ("id" is blank)...
|
||||||
|
@ -262,6 +263,53 @@ function onClicked() {
|
||||||
pal.setVisible(!pal.visible);
|
pal.setVisible(!pal.visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var AVERAGING_RATIO = 0.05
|
||||||
|
var LOUDNESS_FLOOR = 11.0;
|
||||||
|
var LOUDNESS_SCALE = 2.8 / 5.0;
|
||||||
|
var LOG2 = Math.log(2.0);
|
||||||
|
var AUDIO_LEVEL_UPDATE_INTERVAL_MS = 100; // 10hz for now (change this and change the AVERAGING_RATIO too)
|
||||||
|
var accumulatedLevels = {};
|
||||||
|
|
||||||
|
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
|
||||||
|
// of updating (the latter for efficiency too).
|
||||||
|
var avatar = AvatarList.getAvatar(id);
|
||||||
|
var audioLevel = 0.0;
|
||||||
|
|
||||||
|
// we will do exponential moving average by taking some the last loudness and averaging
|
||||||
|
accumulatedLevels[id] = AVERAGING_RATIO * (accumulatedLevels[id] || 0 ) + (1 - AVERAGING_RATIO) * (avatar.audioLoudness);
|
||||||
|
|
||||||
|
// add 1 to insure we don't go log() and hit -infinity. Math.log is
|
||||||
|
// natural log, so to get log base 2, just divide by ln(2).
|
||||||
|
var logLevel = Math.log(accumulatedLevels[id] + 1) / LOG2;
|
||||||
|
|
||||||
|
if (logLevel <= LOUDNESS_FLOOR) {
|
||||||
|
audioLevel = logLevel / LOUDNESS_FLOOR * LOUDNESS_SCALE;
|
||||||
|
} else {
|
||||||
|
audioLevel = (logLevel - (LOUDNESS_FLOOR - 1.0)) * LOUDNESS_SCALE;
|
||||||
|
}
|
||||||
|
if (audioLevel > 1.0) {
|
||||||
|
audioLevel = 1;
|
||||||
|
}
|
||||||
|
return audioLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// we will update the audioLevels periodically
|
||||||
|
// TODO: tune for efficiency - expecially with large numbers of avatars
|
||||||
|
Script.setInterval(function () {
|
||||||
|
if (pal.visible) {
|
||||||
|
var param = {};
|
||||||
|
AvatarList.getAvatarIdentifiers().sort().forEach(function (id) {
|
||||||
|
var level = getAudioLevel(id);
|
||||||
|
// qml didn't like an object with null/empty string for a key, so...
|
||||||
|
var userId = id || 0;
|
||||||
|
param[userId]= level;
|
||||||
|
});
|
||||||
|
pal.sendToQml({method: 'updateAudioLevel', params: param});
|
||||||
|
}
|
||||||
|
}, AUDIO_LEVEL_UPDATE_INTERVAL_MS);
|
||||||
//
|
//
|
||||||
// Button state.
|
// Button state.
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in a new issue