diff --git a/src/mumble/AudioConfigDialog.cpp b/src/mumble/AudioConfigDialog.cpp index cf83d6fa812..a0f78c63fc6 100644 --- a/src/mumble/AudioConfigDialog.cpp +++ b/src/mumble/AudioConfigDialog.cpp @@ -586,7 +586,7 @@ void AudioInputDialog::showSpeexNoiseSuppressionSlider(bool show) { void AudioInputDialog::on_Tick_timeout() { AudioInputPtr ai = Global::get().ai; - if (!ai.get() || !ai->sppPreprocess) + if (!ai.get() || !ai->m_preprocessor) return; abSpeech->iBelow = qsTransmitMin->value(); diff --git a/src/mumble/AudioInput.cpp b/src/mumble/AudioInput.cpp index 0bb0337cdf3..3dc020c08b7 100644 --- a/src/mumble/AudioInput.cpp +++ b/src/mumble/AudioInput.cpp @@ -255,8 +255,7 @@ AudioInput::AudioInput() bEchoMulti = false; - sppPreprocess = nullptr; - sesEcho = nullptr; + sesEcho = nullptr; srsMic = srsEcho = nullptr; iEchoChannels = iMicChannels = 0; @@ -298,8 +297,6 @@ AudioInput::~AudioInput() { } #endif - if (sppPreprocess) - speex_preprocess_state_destroy(sppPreprocess); if (sesEcho) speex_echo_state_destroy(sesEcho); @@ -740,44 +737,34 @@ void AudioInput::resetAudioProcessor() { if (!bResetProcessor) return; - int iArg; - - if (sppPreprocess) - speex_preprocess_state_destroy(sppPreprocess); if (sesEcho) speex_echo_state_destroy(sesEcho); - sppPreprocess = speex_preprocess_state_init(iFrameSize, iSampleRate); + m_preprocessor.init(iSampleRate, iFrameSize); resync.reset(); selectNoiseCancel(); - iArg = 1; - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_VAD, &iArg); - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC, &iArg); - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_DEREVERB, &iArg); - - iArg = 30000; - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_TARGET, &iArg); + m_preprocessor.toggleVAD(true); + m_preprocessor.toggleAGC(true); + m_preprocessor.toggleDereverb(true); - float v = 30000.0f / static_cast< float >(Global::get().s.iMinLoudness); - iArg = static_cast< int >(floorf(20.0f * log10f(v))); - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_MAX_GAIN, &iArg); + m_preprocessor.setAGCTarget(30000); - iArg = -60; - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_DECREMENT, &iArg); + const float v = 30000.0f / static_cast< float >(Global::get().s.iMinLoudness); + m_preprocessor.setAGCMaxGain(static_cast< std::int32_t >(floorf(20.0f * log10f(v)))); + m_preprocessor.setAGCDecrement(-60); if (noiseCancel == Settings::NoiseCancelSpeex) { - iArg = Global::get().s.iSpeexNoiseCancelStrength; - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &iArg); + m_preprocessor.setNoiseSuppress(Global::get().s.iSpeexNoiseCancelStrength); } if (iEchoChannels > 0) { int filterSize = iFrameSize * (10 + resync.getNominalLag()); sesEcho = speex_echo_state_init_mc(iFrameSize, filterSize, 1, bEchoMulti ? static_cast< int >(iEchoChannels) : 1); - iArg = iSampleRate; + int iArg = iSampleRate; speex_echo_ctl(sesEcho, SPEEX_ECHO_SET_SAMPLING_RATE, &iArg); - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_ECHO_STATE, sesEcho); + m_preprocessor.setEchoState(sesEcho); qWarning("AudioInput: ECHO CANCELLER ACTIVE"); } else { @@ -821,24 +808,24 @@ void AudioInput::selectNoiseCancel() { #endif } - int iArg = 0; + bool preprocessorDenoise = false; switch (noiseCancel) { case Settings::NoiseCancelOff: qWarning("AudioInput: Noise canceller disabled"); break; case Settings::NoiseCancelSpeex: qWarning("AudioInput: Using Speex as noise canceller"); - iArg = 1; + preprocessorDenoise = true; break; case Settings::NoiseCancelRNN: qWarning("AudioInput: Using ReNameNoise as noise canceller"); break; case Settings::NoiseCancelBoth: - iArg = 1; + preprocessorDenoise = true; qWarning("AudioInput: Using ReNameNoise and Speex as noise canceller"); break; } - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_DENOISE, &iArg); + m_preprocessor.toggleDenoise(preprocessorDenoise); } int AudioInput::encodeOpusFrame(short *source, int size, EncodingOutputBuffer &buffer) { @@ -857,7 +844,6 @@ int AudioInput::encodeOpusFrame(short *source, int size, EncodingOutputBuffer &b } void AudioInput::encodeAudioFrame(AudioChunk chunk) { - int iArg; float sum; short max; @@ -897,11 +883,10 @@ void AudioInput::encodeAudioFrame(AudioChunk chunk) { QMutexLocker l(&qmSpeex); resetAudioProcessor(); - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_GET_AGC_GAIN, &iArg); - float gainValue = static_cast< float >(iArg); + const std::int32_t gainValue = m_preprocessor.getAGCGain(); + if (noiseCancel == Settings::NoiseCancelSpeex || noiseCancel == Settings::NoiseCancelBoth) { - iArg = Global::get().s.iSpeexNoiseCancelStrength - iArg; - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &iArg); + m_preprocessor.setNoiseSuppress(Global::get().s.iSpeexNoiseCancelStrength - gainValue); } short psClean[iFrameSize]; @@ -924,7 +909,7 @@ void AudioInput::encodeAudioFrame(AudioChunk chunk) { } #endif - speex_preprocess_run(sppPreprocess, psSource); + m_preprocessor.run(*psSource); sum = 1.0f; for (unsigned int i = 0; i < iFrameSize; i++) @@ -942,12 +927,10 @@ void AudioInput::encodeAudioFrame(AudioChunk chunk) { static_cast< std::streamsize >(iFrameSize * sizeof(short))); } - spx_int32_t prob = 0; - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_GET_PROB, &prob); - fSpeechProb = static_cast< float >(prob) / 100.0f; + fSpeechProb = static_cast< float >(m_preprocessor.getSpeechProb()) / 100.0f; // clean microphone level: peak of filtered signal attenuated by AGC gain - dPeakCleanMic = qMax(dPeakSignal - gainValue, -96.0f); + dPeakCleanMic = qMax(dPeakSignal - static_cast< float >(gainValue), -96.0f); float level = (Global::get().s.vsVAD == Settings::SignalToNoise) ? fSpeechProb : (1.0f + dPeakCleanMic / 96.0f); bool bIsSpeech = false; @@ -1075,12 +1058,10 @@ void AudioInput::encodeAudioFrame(AudioChunk chunk) { } } - spx_int32_t increment = 0; - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_INCREMENT, &increment); + m_preprocessor.setAGCIncrement(0); return; } else { - spx_int32_t increment = 12; - speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_INCREMENT, &increment); + m_preprocessor.setAGCIncrement(12); } if (bIsSpeech && !bPreviousVoice) { diff --git a/src/mumble/AudioInput.h b/src/mumble/AudioInput.h index 5598feda6aa..d8f09637389 100644 --- a/src/mumble/AudioInput.h +++ b/src/mumble/AudioInput.h @@ -21,11 +21,11 @@ #include #include -#include #include #include "Audio.h" #include "AudioOutputToken.h" +#include "AudioPreprocessor.h" #include "EchoCancelOption.h" #include "MumbleProtocol.h" #include "Settings.h" @@ -224,7 +224,7 @@ class AudioInput : public QThread { static const int iFrameSize = SAMPLE_RATE / 100; QMutex qmSpeex; - SpeexPreprocessState *sppPreprocess; + AudioPreprocessor m_preprocessor; SpeexEchoState *sesEcho; /// bResetEncoder is a flag that notifies diff --git a/src/mumble/AudioStats.cpp b/src/mumble/AudioStats.cpp index c75ee90ff92..4a3cf858070 100644 --- a/src/mumble/AudioStats.cpp +++ b/src/mumble/AudioStats.cpp @@ -216,34 +216,28 @@ void AudioNoiseWidget::paintEvent(QPaintEvent *) { paint.fillRect(rect(), pal.color(QPalette::Window)); AudioInputPtr ai = Global::get().ai; - if (!ai.get() || !ai->sppPreprocess) + if (!ai.get() || !ai->m_preprocessor) return; QPolygonF poly; ai->qmSpeex.lock(); - spx_int32_t ps_size = 0; - speex_preprocess_ctl(ai->sppPreprocess, SPEEX_PREPROCESS_GET_PSD_SIZE, &ps_size); - - static std::vector< spx_int32_t > noise; - noise.resize(static_cast< std::size_t >(ps_size)); - static std::vector< spx_int32_t > ps; - ps.resize(static_cast< std::size_t >(ps_size)); - - speex_preprocess_ctl(ai->sppPreprocess, SPEEX_PREPROCESS_GET_PSD, ps.data()); - speex_preprocess_ctl(ai->sppPreprocess, SPEEX_PREPROCESS_GET_NOISE_PSD, noise.data()); + const std::vector< std::int32_t > ps = ai->m_preprocessor.getPSD(); + const std::vector< std::int32_t > noise = ai->m_preprocessor.getNoisePSD(); ai->qmSpeex.unlock(); + assert(ps.size() == noise.size()); + qreal sx, sy; - sx = (static_cast< float >(width()) - 1.0f) / static_cast< float >(ps_size); + sx = (static_cast< float >(width()) - 1.0f) / static_cast< float >(ps.size()); sy = static_cast< float >(height()) - 1.0f; poly << QPointF(0.0f, height() - 1); float fftmul = 1.0 / (32768.0); - for (unsigned int i = 0; i < static_cast< unsigned int >(ps_size); i++) { + for (unsigned int i = 0; i < static_cast< unsigned int >(noise.size()); i++) { qreal xp, yp; xp = i * sx; yp = sqrtf(sqrtf(static_cast< float >(noise[i]))) - 1.0f; @@ -262,7 +256,7 @@ void AudioNoiseWidget::paintEvent(QPaintEvent *) { poly.clear(); - for (unsigned int i = 0; i < static_cast< unsigned int >(ps_size); i++) { + for (unsigned int i = 0; i < static_cast< unsigned int >(ps.size()); i++) { qreal xp, yp; xp = i * sx; yp = sqrtf(sqrtf(static_cast< float >(ps[i]))) - 1.0f; @@ -316,7 +310,7 @@ AudioStats::~AudioStats() { void AudioStats::on_Tick_timeout() { AudioInputPtr ai = Global::get().ai; - if (!ai.get() || !ai->sppPreprocess) + if (!ai.get() || !ai->m_preprocessor) return; bool nTalking = ai->isTransmitting(); @@ -332,22 +326,16 @@ void AudioStats::on_Tick_timeout() { FORMAT_TO_TXT("%06.2f dB", ai->dPeakSignal); qlSignalLevel->setText(txt); - spx_int32_t ps_size = 0; - speex_preprocess_ctl(ai->sppPreprocess, SPEEX_PREPROCESS_GET_PSD_SIZE, &ps_size); - - static std::vector< spx_int32_t > noise; - noise.resize(static_cast< std::size_t >(ps_size)); - static std::vector< spx_int32_t > ps; - ps.resize(static_cast< std::size_t >(ps_size)); + const std::vector< std::int32_t > ps = ai->m_preprocessor.getPSD(); + const std::vector< std::int32_t > noise = ai->m_preprocessor.getNoisePSD(); - speex_preprocess_ctl(ai->sppPreprocess, SPEEX_PREPROCESS_GET_PSD, ps.data()); - speex_preprocess_ctl(ai->sppPreprocess, SPEEX_PREPROCESS_GET_NOISE_PSD, noise.data()); + assert(ps.size() == noise.size()); float s = 0.0f; float n = 0.0001f; - unsigned int start = static_cast< unsigned int >(ps_size * 300) / SAMPLE_RATE; - unsigned int stop = static_cast< unsigned int >(ps_size * 2000) / SAMPLE_RATE; + unsigned int start = static_cast< unsigned int >(ps.size() * 300) / SAMPLE_RATE; + unsigned int stop = static_cast< unsigned int >(ps.size() * 2000) / SAMPLE_RATE; for (unsigned int i = start; i < stop; i++) { s += sqrtf(static_cast< float >(ps[i])); @@ -357,9 +345,7 @@ void AudioStats::on_Tick_timeout() { FORMAT_TO_TXT("%06.3f", s / n); qlMicSNR->setText(txt); - spx_int32_t v; - speex_preprocess_ctl(ai->sppPreprocess, SPEEX_PREPROCESS_GET_AGC_GAIN, &v); - float fv = powf(10.0f, (static_cast< float >(v) / 20.0f)); + float fv = powf(10.0f, (static_cast< float >(ai->m_preprocessor.getAGCGain()) / 20.0f)); FORMAT_TO_TXT("%03.0f%%", 100.0f / fv); qlMicVolume->setText(txt);