2023-03-20 21:46:20 -04:00
|
|
|
"use strict";
|
2017-03-10 23:37:29 +00:00
|
|
|
//
|
|
|
|
// audioMuteOverlay.js
|
|
|
|
//
|
2023-03-20 21:46:20 -04:00
|
|
|
// Created by Triplelexx on March 9th, 2017
|
|
|
|
// Reworked by Seth Alves on February 17th, 2019
|
2017-03-10 23:37:29 +00:00
|
|
|
// Copyright 2017 High Fidelity, Inc.
|
2023-03-20 21:46:20 -04:00
|
|
|
// Copyright 2023 Overte e.V.
|
|
|
|
//
|
|
|
|
// client script that creates an overlay to provide mute feedback
|
2017-03-10 23:37:29 +00:00
|
|
|
//
|
|
|
|
// Distributed under the Apache License, Version 2.0.
|
|
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
|
|
//
|
|
|
|
|
2023-03-20 21:46:20 -04:00
|
|
|
/* global Audio, Script, Entities, Quat, MyAvatar, HMD */
|
2019-02-17 14:21:23 -08:00
|
|
|
|
2017-03-10 23:37:29 +00:00
|
|
|
(function() { // BEGIN LOCAL_SCOPE
|
2017-03-15 11:08:54 +00:00
|
|
|
|
2019-02-20 13:07:24 -08:00
|
|
|
var lastShortTermInputLoudness = 0.0;
|
|
|
|
var lastLongTermInputLoudness = 0.0;
|
2019-02-19 09:32:41 -08:00
|
|
|
var sampleRate = 8.0; // Hz
|
2019-02-20 13:07:24 -08:00
|
|
|
|
|
|
|
var shortTermAttackTC = Math.exp(-1.0 / (sampleRate * 0.500)); // 500 milliseconds attack
|
|
|
|
var shortTermReleaseTC = Math.exp(-1.0 / (sampleRate * 1.000)); // 1000 milliseconds release
|
|
|
|
|
|
|
|
var longTermAttackTC = Math.exp(-1.0 / (sampleRate * 5.0)); // 5 second attack
|
|
|
|
var longTermReleaseTC = Math.exp(-1.0 / (sampleRate * 10.0)); // 10 seconds release
|
|
|
|
|
|
|
|
var activationThreshold = 0.05; // how much louder short-term needs to be than long-term to trigger warning
|
|
|
|
|
2019-02-19 09:32:41 -08:00
|
|
|
var holdReset = 2.0 * sampleRate; // 2 seconds hold
|
|
|
|
var holdCount = 0;
|
|
|
|
var warningOverlayID = null;
|
|
|
|
var pollInterval = null;
|
|
|
|
var warningText = "Muted";
|
|
|
|
|
|
|
|
function showWarning() {
|
|
|
|
if (warningOverlayID) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (HMD.active) {
|
2023-03-20 21:46:20 -04:00
|
|
|
warningOverlayID = Entities.addEntity({
|
|
|
|
"type": "Text",
|
|
|
|
"name": "Muted-Warning",
|
|
|
|
"localPosition": { "x": 0.0, "y": -0.45, "z": -1.0 },
|
|
|
|
"localRotation": Quat.fromVec3Degrees({ "x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0 }),
|
|
|
|
"text": warningText,
|
|
|
|
"unlit": true,
|
|
|
|
"textAlpha": 1.0,
|
|
|
|
"textColor": { "red": 245, "green": 44, "blue": 74 },
|
|
|
|
"backgroundAlpha": 0.0,
|
|
|
|
"lineHeight": 0.042,
|
|
|
|
"dimensions": {"x": 0.11, "y": 0.05, "z": 0.01 },
|
|
|
|
"visible": true,
|
|
|
|
"ignorePickIntersection": true,
|
|
|
|
"renderLayer": "front",
|
|
|
|
"grab": {
|
|
|
|
"grabbable": false
|
|
|
|
},
|
|
|
|
"parentID": MyAvatar.SELF_ID,
|
|
|
|
"parentJointIndex": MyAvatar.getJointIndex("_CAMERA_MATRIX")
|
|
|
|
}, "local");
|
2019-02-19 09:32:41 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function hideWarning() {
|
|
|
|
if (!warningOverlayID) {
|
|
|
|
return;
|
|
|
|
}
|
2023-03-20 21:46:20 -04:00
|
|
|
Entities.deleteEntity(warningOverlayID);
|
2019-02-19 09:32:41 -08:00
|
|
|
warningOverlayID = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
function startPoll() {
|
|
|
|
if (pollInterval) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pollInterval = Script.setInterval(function() {
|
2019-02-20 13:07:24 -08:00
|
|
|
var shortTermInputLoudness = Audio.inputLevel;
|
|
|
|
var longTermInputLoudness = shortTermInputLoudness;
|
|
|
|
|
|
|
|
var shortTc = (shortTermInputLoudness > lastShortTermInputLoudness) ? shortTermAttackTC : shortTermReleaseTC;
|
|
|
|
var longTc = (longTermInputLoudness > lastLongTermInputLoudness) ? longTermAttackTC : longTermReleaseTC;
|
|
|
|
|
|
|
|
shortTermInputLoudness += shortTc * (lastShortTermInputLoudness - shortTermInputLoudness);
|
|
|
|
longTermInputLoudness += longTc * (lastLongTermInputLoudness - longTermInputLoudness);
|
|
|
|
|
|
|
|
lastShortTermInputLoudness = shortTermInputLoudness;
|
|
|
|
lastLongTermInputLoudness = longTermInputLoudness;
|
2019-02-19 09:32:41 -08:00
|
|
|
|
2019-02-20 13:07:24 -08:00
|
|
|
if (shortTermInputLoudness > lastLongTermInputLoudness + activationThreshold) {
|
2019-02-19 09:32:41 -08:00
|
|
|
holdCount = holdReset;
|
|
|
|
} else {
|
|
|
|
holdCount = Math.max(holdCount - 1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (holdCount > 0) {
|
|
|
|
showWarning();
|
|
|
|
} else {
|
|
|
|
hideWarning();
|
|
|
|
}
|
|
|
|
}, 1000.0 / sampleRate);
|
|
|
|
}
|
|
|
|
|
|
|
|
function stopPoll() {
|
|
|
|
if (!pollInterval) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Script.clearInterval(pollInterval);
|
|
|
|
pollInterval = null;
|
|
|
|
hideWarning();
|
|
|
|
}
|
|
|
|
|
|
|
|
function startOrStopPoll() {
|
|
|
|
if (Audio.warnWhenMuted && Audio.muted) {
|
|
|
|
startPoll();
|
|
|
|
} else {
|
|
|
|
stopPoll();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function cleanup() {
|
|
|
|
stopPoll();
|
|
|
|
}
|
2019-03-11 14:35:13 -07:00
|
|
|
|
2019-02-19 09:32:41 -08:00
|
|
|
Script.scriptEnding.connect(cleanup);
|
|
|
|
|
|
|
|
startOrStopPoll();
|
|
|
|
Audio.mutedChanged.connect(startOrStopPoll);
|
|
|
|
Audio.warnWhenMutedChanged.connect(startOrStopPoll);
|
2017-03-10 23:37:29 +00:00
|
|
|
|
2019-03-29 10:32:13 -07:00
|
|
|
}()); // END LOCAL_SCOPE
|