Merge pull request #1007 from digisomni/feature/manual-noise-reduction-gate

Add manual mode to noise reduction + add noise reduction threshold
This commit is contained in:
Kalila 2021-03-03 21:18:59 -05:00 committed by GitHub
commit 672bceee1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 408 additions and 50 deletions

View file

@ -15,6 +15,7 @@
import QtQuick 2.10
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
import stylesUit 1.0
import controlsUit 1.0 as HifiControlsUit
@ -104,6 +105,11 @@ Rectangle {
AudioScriptingInterface.setSystemInjectorGain(sliderValue);
}
}
function updateNoiseReductionThresholdFromQML(sliderValue) {
if (AudioScriptingInterface.getNoiseReductionThreshold() !== sliderValue) {
AudioScriptingInterface.setNoiseReductionThreshold(sliderValue);
}
}
Component.onCompleted: {
enablePeakValues();
@ -164,7 +170,7 @@ Rectangle {
x: 2 * margins.paddings;
width: parent.width;
// switch heights + 2 * top margins
height: (root.switchHeight) * 6 + 48;
height: (bar.currentIndex === 0) ? (root.switchHeight) * 2 + 48 : (root.switchHeight) * 4 + 48;
anchors.top: firstSeparator.bottom;
anchors.topMargin: 10;
@ -175,6 +181,7 @@ Rectangle {
height: parent.height;
anchors.top: parent.top
anchors.left: parent.left;
HifiControlsUit.Switch {
id: muteMic;
height: root.switchHeight;
@ -193,45 +200,11 @@ Rectangle {
}
}
HifiControlsUit.Switch {
id: noiseReductionSwitch;
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: muteMic.bottom;
anchors.topMargin: 24
anchors.left: parent.left
labelTextOn: "Noise Reduction";
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: AudioScriptingInterface.noiseReduction;
onCheckedChanged: {
AudioScriptingInterface.noiseReduction = checked;
checked = Qt.binding(function() { return AudioScriptingInterface.noiseReduction; }); // restore binding
}
}
HifiControlsUit.Switch {
id: acousticEchoCancellationSwitch;
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: noiseReductionSwitch.bottom
anchors.topMargin: 24
anchors.left: parent.left
labelTextOn: "Echo Cancellation";
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: AudioScriptingInterface.acousticEchoCancellation;
onCheckedChanged: {
AudioScriptingInterface.acousticEchoCancellation = checked;
checked = Qt.binding(function() { return AudioScriptingInterface.acousticEchoCancellation; });
}
}
HifiControlsUit.Switch {
id: pttSwitch
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: acousticEchoCancellationSwitch.bottom;
anchors.top: muteMic.bottom;
anchors.topMargin: 24
anchors.left: parent.left
labelTextOn: (bar.currentIndex === 0) ? qsTr("Push To Talk (T)") : qsTr("Push To Talk");
@ -254,6 +227,7 @@ Rectangle {
height: parent.height;
anchors.top: parent.top
anchors.left: switchContainer.right;
HifiControlsUit.Switch {
id: warnMutedSwitch
height: root.switchHeight;
@ -271,7 +245,6 @@ Rectangle {
}
}
HifiControlsUit.Switch {
id: audioLevelSwitch
height: root.switchHeight;
@ -519,13 +492,264 @@ Rectangle {
anchors.top: systemInjectorGainContainer.bottom;
anchors.topMargin: 10;
}
Item {
id: noiseReductionHeader
x: margins.paddings;
width: parent.width - margins.paddings * 2;
height: 36;
anchors.top: secondSeparator.bottom;
anchors.topMargin: 10;
HiFiGlyphs {
width: margins.sizeCheckBox;
text: hifi.glyphs.mic;
color: hifi.colors.white;
anchors.left: parent.left;
anchors.leftMargin: -size / 4; // The glyph has empty space at left about 25%
anchors.verticalCenter: parent.verticalCenter;
size: 30;
}
RalewayRegular {
anchors.verticalCenter: parent.verticalCenter;
width: margins.sizeText + margins.sizeLevel;
anchors.left: parent.left;
anchors.leftMargin: margins.sizeCheckBox;
size: 22;
color: hifi.colors.white;
text: qsTr("Noise Reduction");
}
}
Item {
id: noiseReductionSwitches;
x: 2 * margins.paddings;
width: parent.width;
// switch heights + 2 * top margins
height: (root.switchHeight) * 5 + 48;
anchors.top: noiseReductionHeader.bottom;
anchors.topMargin: 0;
Item {
id: noiseReductionSwitchContainer;
x: margins.paddings;
width: parent.width / 2;
height: parent.height;
anchors.top: parent.top;
anchors.left: parent.left;
HifiControlsUit.Switch {
id: acousticEchoCancellationSwitch;
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: noiseReductionSwitchContainer.top
anchors.topMargin: 24
anchors.left: parent.left
labelTextOn: "Echo Cancellation";
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: AudioScriptingInterface.acousticEchoCancellation;
onCheckedChanged: {
AudioScriptingInterface.acousticEchoCancellation = checked;
checked = Qt.binding(function () { return AudioScriptingInterface.acousticEchoCancellation; });
}
}
HifiControlsUit.Switch {
id: noiseReductionSwitch;
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: acousticEchoCancellationSwitch.bottom;
anchors.topMargin: 24
anchors.left: parent.left
labelTextOn: "Noise Reduction";
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: AudioScriptingInterface.noiseReduction;
onCheckedChanged: {
AudioScriptingInterface.noiseReduction = checked;
checked = Qt.binding(function () { return AudioScriptingInterface.noiseReduction; }); // restore binding
}
}
HifiControlsUit.Switch {
id: noiseReductionAutomaticSwitch;
height: root.switchHeight;
switchWidth: root.switchWidth;
anchors.top: noiseReductionSwitch.bottom;
anchors.topMargin: 24;
anchors.left: parent.left;
labelTextOn: "Manual Noise Reduction";
labelTextSize: 16;
backgroundOnColor: "#E3E3E3";
checked: !AudioScriptingInterface.noiseReductionAutomatic;
visible: AudioScriptingInterface.noiseReduction;
onCheckedChanged: {
AudioScriptingInterface.noiseReductionAutomatic = !checked;
checked = Qt.binding(function () { return !AudioScriptingInterface.noiseReductionAutomatic; }); // restore binding
}
}
}
}
Item {
id: noiseReductionThresholdContainer
x: margins.paddings;
anchors.top: noiseReductionSwitches.bottom;
anchors.topMargin: 16;
width: parent.width - margins.paddings * 2;
height: avatarGainSliderTextMetrics.height + 10;
visible: AudioScriptingInterface.noiseReduction && !AudioScriptingInterface.noiseReductionAutomatic;
HifiControlsUit.Slider {
id: noiseReductionThresholdSlider
anchors.right: parent.right
height: noiseReductionThresholdSliderTextMetrics.height
width: 200
minimumValue: 0.0
maximumValue: 1.0
stepSize: 0.05
value: AudioScriptingInterface.getNoiseReductionThreshold()
onValueChanged: {
updateNoiseReductionThresholdFromQML(value);
}
onPressedChanged: {
if (!pressed) {
updateNoiseReductionThresholdFromQML(value);
}
}
MouseArea {
anchors.fill: parent
onWheel: {
// Do nothing.
}
onDoubleClicked: {
noiseReductionThresholdSlider.value = 0.0;
}
onPressed: {
// Pass through to Slider
mouse.accepted = false;
}
onReleased: {
// the above mouse.accepted seems to make this
// never get called, nonetheless...
mouse.accepted = false;
}
}
}
TextMetrics {
id: noiseReductionThresholdSliderTextMetrics
text: noiseReductionThresholdSliderText.text
font: noiseReductionThresholdSliderText.font
}
RalewayRegular {
// The slider for my card is special, it controls the master gain
id: noiseReductionThresholdSliderText;
text: "Audio input threshold";
size: 16;
anchors.left: parent.left;
color: hifi.colors.white;
horizontalAlignment: Text.AlignLeft;
verticalAlignment: Text.AlignTop;
}
Item {
id: noisePeak
anchors.right: parent.right
anchors.rightMargin: 5;
anchors.top: noiseReductionThresholdSlider.bottom;
width: noiseReductionThresholdSlider.width - 10;
height: 8;
Text {
id: status;
anchors {
horizontalCenter: parent.horizontalCenter;
verticalCenter: parent.verticalCenter;
}
visible: AudioScriptingInterface.muted;
color: "#E2334D";
text: "MUTED";
font.pointSize: 10;
}
Item {
id: noiseBar;
property bool gated: false;
property var level: AudioScriptingInterface.inputLevel;
width: parent.width;
height: parent.height;
anchors { fill: parent }
visible: !status.visible;
Component.onCompleted: {
AudioScriptingInterface.noiseGateOpened.connect(function () { noiseBar.gated = false; });
AudioScriptingInterface.noiseGateClosed.connect(function () { noiseBar.gated = true; });
AudioScriptingInterface.inputLevelChanged.connect(function () { noiseBar.level = AudioScriptingInterface.inputLevel; });
}
Rectangle { // base
radius: 4;
anchors { fill: parent }
color: colors.gutter;
}
Rectangle { // noiseMask
id: noiseMask;
width: parent.width * noiseBar.level;
radius: 5;
anchors {
bottom: parent.bottom;
bottomMargin: 0;
top: parent.top;
topMargin: 0;
left: parent.left;
leftMargin: 0;
}
}
LinearGradient {
anchors { fill: noiseMask }
source: noiseMask
start: Qt.point(0, 0);
end: Qt.point(noiseBar.width, 0);
gradient: Gradient {
GradientStop {
position: 0;
color: noiseBar.gated ? "#E2334D" : "#39A38F";
}
GradientStop {
position: 1;
color: noiseBar.gated ? "#E2334D" : "#39A38F";
}
}
}
}
}
}
Separator {
id: thirdSeparator;
anchors.top: noiseReductionThresholdContainer.bottom;
anchors.topMargin: 14;
}
Item {
id: inputDeviceHeader
x: margins.paddings;
width: parent.width - margins.paddings*2;
height: 36;
anchors.top: secondSeparator.bottom;
anchors.top: thirdSeparator.bottom;
anchors.topMargin: 10;
HiFiGlyphs {
@ -597,19 +821,19 @@ Rectangle {
}
}
AudioControls.InputPeak {
id: inputLevel
anchors.right: parent.right
peak: model.peak;
anchors.verticalCenter: parent.verticalCenter
visible: ((bar.currentIndex === 1 && isVR) ||
(bar.currentIndex === 0 && !isVR)) &&
AudioScriptingInterface.devices.input.peakValuesAvailable;
id: inputLevel
anchors.right: parent.right
peak: model.peak;
anchors.verticalCenter: parent.verticalCenter
visible: ((bar.currentIndex === 1 && isVR) ||
(bar.currentIndex === 0 && !isVR)) &&
AudioScriptingInterface.devices.input.peakValuesAvailable;
}
}
}
Separator {
id: thirdSeparator;
id: fourthSeparator;
anchors.top: inputView.bottom;
anchors.topMargin: 10;
}
@ -617,7 +841,7 @@ Rectangle {
Item {
id: outputDeviceHeader;
anchors.topMargin: 10;
anchors.top: thirdSeparator.bottom;
anchors.top: fourthSeparator.bottom;
x: margins.paddings;
width: parent.width - margins.paddings*2
height: 36
@ -684,4 +908,4 @@ Rectangle {
}
}
}
}
}

View file

@ -25,6 +25,8 @@ QString Audio::DESKTOP { "Desktop" };
QString Audio::HMD { "VR" };
Setting::Handle<bool> enableNoiseReductionSetting { QStringList { Audio::AUDIO, "NoiseReduction" }, true };
Setting::Handle<bool> enableNoiseReductionAutomaticSetting { QStringList { Audio::AUDIO, "NoiseReductionAutomatic" }, true };
Setting::Handle<float> setNoiseReductionThresholdSetting { QStringList { Audio::AUDIO, "NoiseReductionThreshold" }, 0.1f };
Setting::Handle<bool> enableWarnWhenMutedSetting { QStringList { Audio::AUDIO, "WarnWhenMuted" }, true };
Setting::Handle<bool> enableAcousticEchoCancellationSetting { QStringList { Audio::AUDIO, "AcousticEchoCancellation" }, true };
@ -40,6 +42,8 @@ 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::noiseReductionAutomaticChanged, this, &Audio::enableNoiseReductionAutomatic);
connect(client, &AudioClient::noiseReductionThresholdChanged, this, &Audio::setNoiseReductionThreshold);
connect(client, &AudioClient::warnWhenMutedChanged, this, &Audio::enableWarnWhenMuted);
connect(client, &AudioClient::acousticEchoCancellationChanged, this, &Audio::enableAcousticEchoCancellation);
connect(client, &AudioClient::inputLoudnessChanged, this, &Audio::onInputLoudnessChanged);
@ -47,6 +51,8 @@ Audio::Audio() : _devices(_contextIsHMD) {
connect(this, &Audio::contextChanged, &_devices, &AudioDevices::onContextChanged);
connect(this, &Audio::pushingToTalkChanged, this, &Audio::handlePushedToTalk);
enableNoiseReduction(enableNoiseReductionSetting.get());
enableNoiseReductionAutomatic(enableNoiseReductionAutomaticSetting.get());
setNoiseReductionThreshold(setNoiseReductionThresholdSetting.get());
enableWarnWhenMuted(enableWarnWhenMutedSetting.get());
enableAcousticEchoCancellation(enableAcousticEchoCancellationSetting.get());
onContextChanged();
@ -286,6 +292,50 @@ void Audio::enableNoiseReduction(bool enable) {
}
}
bool Audio::noiseReductionAutomatic() const {
return resultWithReadLock<bool>([&] {
return _noiseReductionAutomatic;
});
}
void Audio::enableNoiseReductionAutomatic(bool enable) {
bool changed = false;
withWriteLock([&] {
if (_noiseReductionAutomatic != enable) {
_noiseReductionAutomatic = enable;
auto client = DependencyManager::get<AudioClient>().data();
QMetaObject::invokeMethod(client, "setNoiseReductionAutomatic", Q_ARG(bool, enable), Q_ARG(bool, false));
enableNoiseReductionAutomaticSetting.set(enable);
changed = true;
}
});
if (changed) {
emit noiseReductionAutomaticChanged(enable);
}
}
float Audio::getNoiseReductionThreshold() {
return resultWithReadLock<float>([&] {
return _noiseReductionThreshold;
});
}
void Audio::setNoiseReductionThreshold(float threshold) {
bool changed = false;
withWriteLock([&] {
if (_noiseReductionThreshold != threshold) {
_noiseReductionThreshold = threshold;
auto client = DependencyManager::get<AudioClient>().data();
QMetaObject::invokeMethod(client, "setNoiseReductionThreshold", Q_ARG(float, threshold), Q_ARG(bool, false));
setNoiseReductionThresholdSetting.set(threshold);
changed = true;
}
});
if (changed) {
emit noiseReductionThresholdChanged(threshold);
}
}
bool Audio::warnWhenMutedEnabled() const {
return resultWithReadLock<bool>([&] {
return _enableWarnWhenMuted;

View file

@ -50,6 +50,11 @@ class Audio : public AudioScriptingInterface, protected ReadWriteLockable {
* @property {boolean} noiseReduction - <code>true</code> if noise reduction is enabled, otherwise <code>false</code>. When
* enabled, the input audio signal is blocked (fully attenuated) when it falls below an adaptive threshold set just
* above the noise floor.
* @property {boolean} noiseReductionAutomatic - <code>true</code> if audio input noise reduction automatic mode is enabled,
* <code>false</code> if in manual mode. Manual mode allows you to use <code>Audio.noiseReductionThreshold</code>
* to set a manual sensitivity for the noise gate.
* @property {number} noiseReductionThreshold - Sets the noise gate threshold before your mic audio is transmitted.
* (Applies only if <code>Audio.noiseReductionAutomatic</code> is <code>false</code>.)
* @property {number} inputVolume - Adjusts the volume of the input audio, range <code>0.0</code> &ndash; <code>1.0</code>.
* If set to a value, the resulting value depends on the input device: for example, the volume can't be changed on some
* devices, and others might only support values of <code>0.0</code> and <code>1.0</code>.
@ -92,6 +97,8 @@ 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 noiseReductionAutomatic READ noiseReductionAutomatic WRITE enableNoiseReductionAutomatic NOTIFY noiseReductionAutomaticChanged)
Q_PROPERTY(float noiseReductionThreshold READ getNoiseReductionThreshold WRITE setNoiseReductionThreshold NOTIFY noiseReductionThresholdChanged)
Q_PROPERTY(bool warnWhenMuted READ warnWhenMutedEnabled WRITE enableWarnWhenMuted NOTIFY warnWhenMutedChanged)
Q_PROPERTY(bool acousticEchoCancellation
READ acousticEchoCancellationEnabled WRITE enableAcousticEchoCancellation NOTIFY acousticEchoCancellationChanged)
@ -124,6 +131,7 @@ public:
bool isMuted() const;
bool noiseReductionEnabled() const;
bool noiseReductionAutomatic() const;
bool warnWhenMutedEnabled() const;
bool acousticEchoCancellationEnabled() const;
float getInputVolume() const;
@ -270,6 +278,20 @@ public:
* @returns {number} The injector gain (dB) in the client.
*/
Q_INVOKABLE float getSystemInjectorGain();
/**jsdoc
* Sets the noise gate threshold before your mic audio is transmitted. (Applies only if <code>Audio.noiseReductionAutomatic</code> is <code>false</code>.)
* @function Audio.setNoiseReductionThreshold
* @param {number} threshold - The level that your input must surpass to be transmitted. <code>0.0</code> (open the gate completely) &ndash; <code>1.0</code>
*/
Q_INVOKABLE void setNoiseReductionThreshold(float threshold);
/**jsdoc
* Gets the noise reduction threshold.
* @function Audio.getNoiseReductionThreshold
* @returns {number} The noise reduction threshold. <code>0.0</code> &ndash; <code>1.0</code>
*/
Q_INVOKABLE float getNoiseReductionThreshold();
/**jsdoc
* Starts making an audio recording of the audio being played in-world (i.e., not local-only audio) to a file in WAV format.
@ -398,6 +420,23 @@ signals:
* @returns {Signal}
*/
void noiseReductionChanged(bool isEnabled);
/**jsdoc
* Triggered when the audio input noise reduction mode is changed.
* @function Audio.noiseReductionAutomaticChanged
* @param {boolean} isEnabled - <code>true</code> if audio input noise reduction automatic mode is enabled, <code>false</code> if in manual mode.
* @returns {Signal}
*/
void noiseReductionAutomaticChanged(bool isEnabled);
/**jsdoc
* Triggered when the audio input noise reduction threshold is changed.
* @function Audio.noiseReductionThresholdChanged
* @param {number} threshold - The threshold for the audio input noise reduction, range <code>0.0</code> (open the gate completely) &ndash; <code>1.0</code>
* (close the gate completely).
* @returns {Signal}
*/
void noiseReductionThresholdChanged(float threshold);
/**jsdoc
* Triggered when "warn when muted" is enabled or disabled.
@ -512,6 +551,7 @@ public slots:
private slots:
void setMuted(bool muted);
void enableNoiseReduction(bool enable);
void enableNoiseReductionAutomatic(bool enable);
void enableWarnWhenMuted(bool enable);
void enableAcousticEchoCancellation(bool enable);
void setInputVolume(float volume);
@ -533,8 +573,10 @@ private:
float _localInjectorGain { 0.0f }; // in dB
float _systemInjectorGain { 0.0f }; // in dB
float _pttOutputGainDesktop { 0.0f }; // in dB
float _noiseReductionThreshold { 0.1f }; // Match default value of AudioClient::_noiseReductionThreshold.
bool _isClipping { false };
bool _enableNoiseReduction { true }; // Match default value of AudioClient::_isNoiseGateEnabled.
bool _noiseReductionAutomatic { true }; // Match default value of AudioClient::_noiseReductionAutomatic.
bool _enableWarnWhenMuted { true };
bool _enableAcousticEchoCancellation { true }; // AudioClient::_isAECEnabled
bool _contextIsHMD { false };

View file

@ -1266,7 +1266,7 @@ void AudioClient::processWebrtcNearEnd(int16_t* samples, int numFrames, int numC
void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) {
// If there is server echo, reverb will be applied to the recieved audio stream so no need to have it here.
bool hasReverb = _reverb || _receivedAudioStream.hasReverb();
if ((_muted && !_shouldEchoLocally) || !_audioOutput || (!_shouldEchoLocally && !hasReverb)) {
if ((_muted && !_shouldEchoLocally) || !_audioOutput || (!_shouldEchoLocally && !hasReverb) || !_audioGateOpen) {
return;
}
@ -1342,6 +1342,13 @@ void AudioClient::handleLocalEchoAndReverb(QByteArray& inputByteArray) {
}
}
float AudioClient::loudnessToLevel(float loudness) {
float level = loudness * (1 / 32768.0f); // level in [0, 1]
level = 6.02059991f * fastLog2f(level); // convert to dBFS
level = (level + 48.0f) * (1 / 42.0f); // map [-48, -6] dBFS to [0, 1]
return glm::clamp(level, 0.0f, 1.0f);
}
void AudioClient::handleAudioInput(QByteArray& audioBuffer) {
if (!_audioPaused) {
@ -1352,9 +1359,14 @@ void AudioClient::handleAudioInput(QByteArray& audioBuffer) {
int numSamples = audioBuffer.size() / AudioConstants::SAMPLE_SIZE;
int numFrames = numSamples / (_isStereoInput ? AudioConstants::STEREO : AudioConstants::MONO);
if (_isNoiseGateEnabled) {
if (_isNoiseGateEnabled && _isNoiseReductionAutomatic) {
// The audio gate includes DC removal
audioGateOpen = _audioGate->render(samples, samples, numFrames);
} else if (_isNoiseGateEnabled && !_isNoiseReductionAutomatic &&
loudnessToLevel(_lastSmoothedRawInputLoudness) >= _noiseReductionThreshold) {
audioGateOpen = _audioGate->removeDC(samples, samples, numFrames);
} else if (_isNoiseGateEnabled && !_isNoiseReductionAutomatic) {
audioGateOpen = false;
} else {
audioGateOpen = _audioGate->removeDC(samples, samples, numFrames);
}
@ -1750,6 +1762,24 @@ void AudioClient::setNoiseReduction(bool enable, bool emitSignal) {
}
}
void AudioClient::setNoiseReductionAutomatic(bool enable, bool emitSignal) {
if (_isNoiseReductionAutomatic != enable) {
_isNoiseReductionAutomatic = enable;
if (emitSignal) {
emit noiseReductionAutomaticChanged(_isNoiseReductionAutomatic);
}
}
}
void AudioClient::setNoiseReductionThreshold(float threshold, bool emitSignal) {
if (_noiseReductionThreshold != threshold) {
_noiseReductionThreshold = threshold;
if (emitSignal) {
emit noiseReductionThresholdChanged(_noiseReductionThreshold);
}
}
}
void AudioClient::setWarnWhenMuted(bool enable, bool emitSignal) {
if (_warnWhenMuted != enable) {
_warnWhenMuted = enable;

View file

@ -217,6 +217,12 @@ public slots:
void setNoiseReduction(bool isNoiseGateEnabled, bool emitSignal = true);
bool isNoiseReductionEnabled() const { return _isNoiseGateEnabled; }
void setNoiseReductionAutomatic(bool isNoiseGateAutomatic, bool emitSignal = true);
bool isNoiseReductionAutomatic() const { return _isNoiseReductionAutomatic; }
void setNoiseReductionThreshold(float noiseReductionThreshold, bool emitSignal = true);
float noiseReductionThreshold() const { return _noiseReductionThreshold; }
void setWarnWhenMuted(bool isNoiseGateEnabled, bool emitSignal = true);
bool isWarnWhenMutedEnabled() const { return _warnWhenMuted; }
@ -265,6 +271,8 @@ signals:
void inputVolumeChanged(float volume);
void muteToggled(bool muted);
void noiseReductionChanged(bool noiseReductionEnabled);
void noiseReductionAutomaticChanged(bool noiseReductionAutomatic);
void noiseReductionThresholdChanged(bool noiseReductionThreshold);
void warnWhenMutedChanged(bool warnWhenMutedEnabled);
void acousticEchoCancellationChanged(bool acousticEchoCancellationEnabled);
void mutedByMixer();
@ -310,6 +318,8 @@ private:
friend class CheckDevicesThread;
friend class LocalInjectorsThread;
float loudnessToLevel(float loudness);
// background tasks
void checkDevices();
void checkPeakValues();
@ -397,6 +407,8 @@ private:
bool _shouldEchoLocally{ false };
bool _shouldEchoToServer{ false };
bool _isNoiseGateEnabled{ true };
bool _isNoiseReductionAutomatic{ true };
float _noiseReductionThreshold{ 0.1f };
bool _warnWhenMuted;
bool _isAECEnabled{ true };