mirror of
https://github.com/lubosz/overte.git
synced 2025-04-14 14:46:55 +02:00
culling mute state
This commit is contained in:
parent
9614216006
commit
4187104b17
6 changed files with 81 additions and 189 deletions
|
@ -159,19 +159,6 @@ Rectangle {
|
|||
onXChanged: rightMostInputLevelPos = x + width
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: muteMic.spacing*2;
|
||||
AudioControls.CheckBox {
|
||||
spacing: muteMic.spacing
|
||||
text: qsTr("Warn when muted");
|
||||
checked: AudioScriptingInterface.warnWhenMuted;
|
||||
onClicked: {
|
||||
AudioScriptingInterface.warnWhenMuted = checked;
|
||||
checked = Qt.binding(function() { return AudioScriptingInterface.warnWhenMuted; }); // restore binding
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Separator {}
|
||||
|
|
|
@ -25,9 +25,6 @@ QString Audio::DESKTOP { "Desktop" };
|
|||
QString Audio::HMD { "VR" };
|
||||
|
||||
Setting::Handle<bool> enableNoiseReductionSetting { QStringList { Audio::AUDIO, "NoiseReduction" }, true };
|
||||
Setting::Handle<bool> enableWarnWhenMutedSetting { QStringList { Audio::AUDIO, "WarnWhenMuted" }, true };
|
||||
Setting::Handle<bool> mutedSetting { QStringList{ Audio::AUDIO, "MuteMicrophone" }, false };
|
||||
|
||||
|
||||
float Audio::loudnessToLevel(float loudness) {
|
||||
float level = loudness * (1/32768.0f); // level in [0, 1]
|
||||
|
@ -40,14 +37,11 @@ Audio::Audio() : _devices(_contextIsHMD) {
|
|||
auto client = DependencyManager::get<AudioClient>().data();
|
||||
connect(client, &AudioClient::muteToggled, this, &Audio::setMuted);
|
||||
connect(client, &AudioClient::noiseReductionChanged, this, &Audio::enableNoiseReduction);
|
||||
connect(client, &AudioClient::warnWhenMutedChanged, this, &Audio::enableWarnWhenMuted);
|
||||
connect(client, &AudioClient::inputLoudnessChanged, this, &Audio::onInputLoudnessChanged);
|
||||
connect(client, &AudioClient::inputVolumeChanged, this, &Audio::setInputVolume);
|
||||
connect(this, &Audio::contextChanged, &_devices, &AudioDevices::onContextChanged);
|
||||
enableNoiseReduction(enableNoiseReductionSetting.get());
|
||||
enableWarnWhenMuted(enableWarnWhenMutedSetting.get());
|
||||
onContextChanged();
|
||||
setMuted(mutedSetting.get());
|
||||
}
|
||||
|
||||
bool Audio::startRecording(const QString& filepath) {
|
||||
|
@ -79,7 +73,6 @@ void Audio::setMuted(bool isMuted) {
|
|||
withWriteLock([&] {
|
||||
if (_isMuted != isMuted) {
|
||||
_isMuted = isMuted;
|
||||
mutedSetting.set(_isMuted);
|
||||
auto client = DependencyManager::get<AudioClient>().data();
|
||||
QMetaObject::invokeMethod(client, "setMuted", Q_ARG(bool, isMuted), Q_ARG(bool, false));
|
||||
changed = true;
|
||||
|
@ -112,28 +105,6 @@ void Audio::enableNoiseReduction(bool enable) {
|
|||
}
|
||||
}
|
||||
|
||||
bool Audio::warnWhenMutedEnabled() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _enableWarnWhenMuted;
|
||||
});
|
||||
}
|
||||
|
||||
void Audio::enableWarnWhenMuted(bool enable) {
|
||||
bool changed = false;
|
||||
withWriteLock([&] {
|
||||
if (_enableWarnWhenMuted != enable) {
|
||||
_enableWarnWhenMuted = enable;
|
||||
auto client = DependencyManager::get<AudioClient>().data();
|
||||
QMetaObject::invokeMethod(client, "setWarnWhenMuted", Q_ARG(bool, enable), Q_ARG(bool, false));
|
||||
enableWarnWhenMutedSetting.set(enable);
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
if (changed) {
|
||||
emit warnWhenMutedChanged(enable);
|
||||
}
|
||||
}
|
||||
|
||||
float Audio::getInputVolume() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _inputVolume;
|
||||
|
|
|
@ -58,7 +58,6 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable {
|
|||
|
||||
Q_PROPERTY(bool muted READ isMuted WRITE setMuted NOTIFY mutedChanged)
|
||||
Q_PROPERTY(bool noiseReduction READ noiseReductionEnabled WRITE enableNoiseReduction NOTIFY noiseReductionChanged)
|
||||
Q_PROPERTY(bool warnWhenMuted READ warnWhenMutedEnabled WRITE enableWarnWhenMuted NOTIFY warnWhenMutedChanged)
|
||||
Q_PROPERTY(float inputVolume READ getInputVolume WRITE setInputVolume NOTIFY inputVolumeChanged)
|
||||
Q_PROPERTY(float inputLevel READ getInputLevel NOTIFY inputLevelChanged)
|
||||
Q_PROPERTY(bool clipping READ isClipping NOTIFY clippingChanged)
|
||||
|
@ -76,7 +75,6 @@ public:
|
|||
|
||||
bool isMuted() const;
|
||||
bool noiseReductionEnabled() const;
|
||||
bool warnWhenMutedEnabled() const;
|
||||
float getInputVolume() const;
|
||||
float getInputLevel() const;
|
||||
bool isClipping() const;
|
||||
|
@ -203,14 +201,6 @@ signals:
|
|||
*/
|
||||
void noiseReductionChanged(bool isEnabled);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when "warn when muted" is enabled or disabled.
|
||||
* @function Audio.warnWhenMutedChanged
|
||||
* @param {boolean} isEnabled - <code>true</code> if "warn when muted" is enabled, otherwise <code>false</code>.
|
||||
* @returns {Signal}
|
||||
*/
|
||||
void warnWhenMutedChanged(bool isEnabled);
|
||||
|
||||
/**jsdoc
|
||||
* Triggered when the input audio volume changes.
|
||||
* @function Audio.inputVolumeChanged
|
||||
|
@ -258,7 +248,6 @@ public slots:
|
|||
private slots:
|
||||
void setMuted(bool muted);
|
||||
void enableNoiseReduction(bool enable);
|
||||
void enableWarnWhenMuted(bool enable);
|
||||
void setInputVolume(float volume);
|
||||
void onInputLoudnessChanged(float loudness, bool isClipping);
|
||||
|
||||
|
@ -273,7 +262,6 @@ private:
|
|||
bool _isClipping { false };
|
||||
bool _isMuted { false };
|
||||
bool _enableNoiseReduction { true }; // Match default value of AudioClient::_isNoiseGateEnabled.
|
||||
bool _enableWarnWhenMuted { true };
|
||||
bool _contextIsHMD { false };
|
||||
AudioDevices* getDevices() { return &_devices; }
|
||||
AudioDevices _devices;
|
||||
|
|
|
@ -1531,15 +1531,6 @@ void AudioClient::setNoiseReduction(bool enable, bool emitSignal) {
|
|||
}
|
||||
}
|
||||
|
||||
void AudioClient::setWarnWhenMuted(bool enable, bool emitSignal) {
|
||||
if (_warnWhenMuted != enable) {
|
||||
_warnWhenMuted = enable;
|
||||
if (emitSignal) {
|
||||
emit warnWhenMutedChanged(_warnWhenMuted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioClient::setIsStereoInput(bool isStereoInput) {
|
||||
bool stereoInputChanged = false;
|
||||
if (isStereoInput != _isStereoInput && _inputDeviceInfo.supportedChannelCounts().contains(2)) {
|
||||
|
|
|
@ -210,9 +210,6 @@ public slots:
|
|||
void setNoiseReduction(bool isNoiseGateEnabled, bool emitSignal = true);
|
||||
bool isNoiseReductionEnabled() const { return _isNoiseGateEnabled; }
|
||||
|
||||
void setWarnWhenMuted(bool isNoiseGateEnabled, bool emitSignal = true);
|
||||
bool isWarnWhenMutedEnabled() const { return _warnWhenMuted; }
|
||||
|
||||
virtual bool getLocalEcho() override { return _shouldEchoLocally; }
|
||||
virtual void setLocalEcho(bool localEcho) override { _shouldEchoLocally = localEcho; }
|
||||
virtual void toggleLocalEcho() override { _shouldEchoLocally = !_shouldEchoLocally; }
|
||||
|
@ -249,7 +246,6 @@ signals:
|
|||
void inputVolumeChanged(float volume);
|
||||
void muteToggled(bool muted);
|
||||
void noiseReductionChanged(bool noiseReductionEnabled);
|
||||
void warnWhenMutedChanged(bool warnWhenMutedEnabled);
|
||||
void mutedByMixer();
|
||||
void inputReceived(const QByteArray& inputSamples);
|
||||
void inputLoudnessChanged(float loudness, bool isClipping);
|
||||
|
@ -369,7 +365,6 @@ private:
|
|||
bool _shouldEchoLocally;
|
||||
bool _shouldEchoToServer;
|
||||
bool _isNoiseGateEnabled;
|
||||
bool _warnWhenMuted;
|
||||
|
||||
bool _reverb;
|
||||
AudioEffectOptions _scriptReverbOptions;
|
||||
|
|
|
@ -1,144 +1,104 @@
|
|||
"use strict";
|
||||
/* jslint vars: true, plusplus: true, forin: true*/
|
||||
/* globals Tablet, Script, AvatarList, Users, Entities, MyAvatar, Camera, Overlays, Vec3, Quat, Controller, print, getControllerWorldLocation */
|
||||
/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */
|
||||
//
|
||||
// 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";
|
||||
(function () { // BEGIN LOCAL_SCOPE
|
||||
var utilsPath = Script.resolvePath('../developer/libraries/utils.js');
|
||||
Script.include(utilsPath);
|
||||
|
||||
/* global Audio, Script, Overlays, Quat, MyAvatar, HMD */
|
||||
var TWEEN_SPEED = 0.025;
|
||||
var MIX_AMOUNT = 0.25;
|
||||
|
||||
(function() { // BEGIN LOCAL_SCOPE
|
||||
var overlayPosition = Vec3.ZERO;
|
||||
var tweenPosition = 0;
|
||||
var startColor = {
|
||||
red: 170,
|
||||
green: 170,
|
||||
blue: 170
|
||||
};
|
||||
var endColor = {
|
||||
red: 255,
|
||||
green: 0,
|
||||
blue: 0
|
||||
};
|
||||
var overlayID;
|
||||
|
||||
var lastShortTermInputLoudness = 0.0;
|
||||
var lastLongTermInputLoudness = 0.0;
|
||||
var sampleRate = 8.0; // Hz
|
||||
Script.update.connect(update);
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
|
||||
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, y: 0, 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")
|
||||
});
|
||||
} else {
|
||||
var textDimensions = { x: 100, y: 50 };
|
||||
warningOverlayID = Overlays.addOverlay("text", {
|
||||
name: "Muted-Warning",
|
||||
font: { size: 36 },
|
||||
text: warningText,
|
||||
x: Window.innerWidth / 2 - textDimensions.x / 2,
|
||||
y: Window.innerHeight / 2 - textDimensions.y / 2,
|
||||
width: textDimensions.x,
|
||||
height: textDimensions.y,
|
||||
textColor: { red: 226, green: 51, blue: 77 },
|
||||
backgroundAlpha: 0,
|
||||
visible: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
function update(dt) {
|
||||
if (!Audio.muted) {
|
||||
if (hasOverlay()) {
|
||||
deleteOverlay();
|
||||
}
|
||||
|
||||
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 if (!hasOverlay()) {
|
||||
createOverlay();
|
||||
} else {
|
||||
stopPoll();
|
||||
updateOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
function getOffsetPosition() {
|
||||
return Vec3.sum(Camera.position, Quat.getFront(Camera.orientation));
|
||||
}
|
||||
|
||||
function createOverlay() {
|
||||
overlayPosition = getOffsetPosition();
|
||||
overlayID = Overlays.addOverlay("sphere", {
|
||||
position: overlayPosition,
|
||||
rotation: Camera.orientation,
|
||||
alpha: 0.9,
|
||||
dimensions: 0.1,
|
||||
solid: true,
|
||||
ignoreRayIntersection: true
|
||||
});
|
||||
}
|
||||
|
||||
function hasOverlay() {
|
||||
return Overlays.getProperty(overlayID, "position") !== undefined;
|
||||
}
|
||||
|
||||
function updateOverlay() {
|
||||
// increase by TWEEN_SPEED until completion
|
||||
if (tweenPosition < 1) {
|
||||
tweenPosition += TWEEN_SPEED;
|
||||
} else {
|
||||
// after tween completion reset to zero and flip values to ping pong
|
||||
tweenPosition = 0;
|
||||
for (var component in startColor) {
|
||||
var storedColor = startColor[component];
|
||||
startColor[component] = endColor[component];
|
||||
endColor[component] = storedColor;
|
||||
}
|
||||
}
|
||||
// mix previous position with new and mix colors
|
||||
overlayPosition = Vec3.mix(overlayPosition, getOffsetPosition(), MIX_AMOUNT);
|
||||
Overlays.editOverlay(overlayID, {
|
||||
color: colorMix(startColor, endColor, easeIn(tweenPosition)),
|
||||
position: overlayPosition,
|
||||
rotation: Camera.orientation
|
||||
});
|
||||
}
|
||||
|
||||
function deleteOverlay() {
|
||||
Overlays.deleteOverlay(overlayID);
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
stopPoll();
|
||||
deleteOverlay();
|
||||
Audio.muted.disconnect(onMuteToggled);
|
||||
Script.update.disconnect(update);
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
|
||||
startOrStopPoll();
|
||||
Audio.mutedChanged.connect(startOrStopPoll);
|
||||
Audio.warnWhenMutedChanged.connect(startOrStopPoll);
|
||||
|
||||
}()); // END LOCAL_SCOPE
|
||||
}()); // END LOCAL_SCOPE
|
Loading…
Reference in a new issue