// // audioMuteOverlay.js // // client script that creates an overlay to provide mute feedback // // Created by Triplelexx on 17/03/09 // Reworked by Seth Alves on 2019-2-17 // Copyright 2017 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 // "use strict"; /* global Audio, Script, Overlays, Quat, MyAvatar, HMD */ (function() { // BEGIN LOCAL_SCOPE var lastShortTermInputLoudness = 0.0; var lastLongTermInputLoudness = 0.0; var sampleRate = 8.0; // Hz 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 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) { warningOverlayID = Overlays.addOverlay("text3d", { name: "Muted-Warning", localPosition: { x: 0.0, y: -0.45, z: -1.0 }, localOrientation: Quat.fromVec3Degrees({ x: 0.0, y: 0.0, z: 0.0, w: 1.0 }), text: warningText, textAlpha: 1, textColor: { red: 226, green: 51, blue: 77 }, backgroundAlpha: 0, lineHeight: 0.042, dimensions: { x: 0.11, y: 0.05 }, visible: true, ignoreRayIntersection: true, drawInFront: true, grabbable: false, parentID: MyAvatar.SELF_ID, parentJointIndex: MyAvatar.getJointIndex("_CAMERA_MATRIX") }); } } function hideWarning() { if (!warningOverlayID) { return; } Overlays.deleteOverlay(warningOverlayID); warningOverlayID = null; } function startPoll() { if (pollInterval) { return; } pollInterval = Script.setInterval(function() { 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; if (shortTermInputLoudness > lastLongTermInputLoudness + activationThreshold) { 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(); } Script.scriptEnding.connect(cleanup); startOrStopPoll(); Audio.mutedChanged.connect(startOrStopPoll); Audio.warnWhenMutedChanged.connect(startOrStopPoll); }()); // END LOCAL_SCOPE