diff --git a/interface/resources/qml/hifi/tablet/Tablet.qml b/interface/resources/qml/hifi/tablet/Tablet.qml index 9a4be95b64..d19fc4ffdd 100644 --- a/interface/resources/qml/hifi/tablet/Tablet.qml +++ b/interface/resources/qml/hifi/tablet/Tablet.qml @@ -5,11 +5,16 @@ Item { id: tablet objectName: "tablet" - property double miclevel: 0.8 + property double micLevel: 0.8 width: parent.width height: parent.height + // called by C++ code to keep audio bar updated + function setMicLevel(newMicLevel) { + tablet.micLevel = newMicLevel; + } + // used to look up a button by its uuid function findButtonIndex(uuid) { if (!uuid) { @@ -101,7 +106,7 @@ Item { } Rectangle { id: audioBarMask - width: parent.width * tablet.miclevel + width: parent.width * tablet.micLevel color: "#333333" radius: 5 anchors.bottom: parent.bottom @@ -183,7 +188,7 @@ Item { PropertyChanges { target: tablet - miclevel: 0 + micLevel: 0 } } ] diff --git a/libraries/script-engine/src/TabletScriptingInterface.cpp b/libraries/script-engine/src/TabletScriptingInterface.cpp index bafa9ab4b4..3831e6cf05 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.cpp +++ b/libraries/script-engine/src/TabletScriptingInterface.cpp @@ -141,6 +141,15 @@ void TabletProxy::removeButton(QObject* tabletButtonProxy) { } } +void TabletProxy::updateAudioBar(const double micLevel) { + auto tablet = getQmlTablet(); + if (!tablet) { + qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml"; + } else { + QMetaObject::invokeMethod(tablet, "setMicLevel", Qt::AutoConnection, Q_ARG(QVariant, QVariant(micLevel))); + } +} + void TabletProxy::addButtonsToHomeScreen() { auto tablet = getQmlTablet(); if (!tablet) { diff --git a/libraries/script-engine/src/TabletScriptingInterface.h b/libraries/script-engine/src/TabletScriptingInterface.h index 9739066c17..5ccd4689e3 100644 --- a/libraries/script-engine/src/TabletScriptingInterface.h +++ b/libraries/script-engine/src/TabletScriptingInterface.h @@ -84,6 +84,13 @@ public: */ Q_INVOKABLE void removeButton(QObject* tabletButtonProxy); + /**jsdoc + * @function TabletProxy#updateAudioBar + * Updates the audio bar in tablet to reflect latest mic level + * @param micLevel {double} mic level value between 0 and 1 + */ + Q_INVOKABLE void updateAudioBar(const double micLevel); + QString getName() const { return _name; } protected: diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 784d7727d5..4c365836a2 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -55,4 +55,39 @@ Script.update.connect(updateShowTablet); // Script.setInterval(updateShowTablet, 1000); + // Initialise variables used to calculate audio level + var accumulatedLevel = 0.0; + // Note: Might have to tweak the following two based on the rate we're getting the data + var AVERAGING_RATIO = 0.05; + var MIC_LEVEL_UPDATE_INTERVAL_MS = 100; + + // Calculate microphone level with the same scaling equation (log scale, exponentially averaged) in AvatarInputs and pal.js + function getMicLevel() { + var LOUDNESS_FLOOR = 11.0; + var LOUDNESS_SCALE = 2.8 / 5.0; + var LOG2 = Math.log(2.0); + var micLevel = 0.0; + accumulatedLevel = AVERAGING_RATIO * accumulatedLevel + (1 - AVERAGING_RATIO) * (MyAvatar.audioLoudness); + // Convert to log base 2 + var logLevel = Math.log(accumulatedLevel + 1) / LOG2; + + if (logLevel <= LOUDNESS_FLOOR) { + micLevel = logLevel / LOUDNESS_FLOOR * LOUDNESS_SCALE; + } else { + micLevel = (logLevel - (LOUDNESS_FLOOR - 1.0)) * LOUDNESS_SCALE; + } + if (micLevel > 1.0) { + micLevel = 1.0; + } + return micLevel; + } + + Script.setInterval(function() { + if (tabletShown) { + var currentMicLevel = getMicLevel(); + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet.updateAudioBar(currentMicLevel); + } + }, MIC_LEVEL_UPDATE_INTERVAL_MS); + }()); // END LOCAL_SCOPE