From 19fdb33eef95b6a5cd7910438dfc5b3e40bc3a31 Mon Sep 17 00:00:00 2001 From: Thorvald Natvig Date: Mon, 28 May 2007 12:40:01 +0000 Subject: [PATCH] SNR based voice detect git-svn-id: https://mumble.svn.sourceforge.net/svnroot/mumble/trunk@452 05730e5d-ab1b-0410-a4ac-84af385074fa --- src/mumble/AudioInput.cpp | 17 ++++- src/mumble/AudioInput.h | 1 + src/mumble/AudioStats.cpp | 127 +------------------------------------- src/mumble/mumble_pch.h | 120 +++++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 127 deletions(-) diff --git a/src/mumble/AudioInput.cpp b/src/mumble/AudioInput.cpp index 33c28bfbb..7e835bcf3 100644 --- a/src/mumble/AudioInput.cpp +++ b/src/mumble/AudioInput.cpp @@ -236,6 +236,11 @@ void AudioInput::encodeAudioFrame() { double v = 20000.0 / g.s.iMinLoudness; iArg = floor(20.0 * log10(v)); + speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_AGC_MAX_GAIN, &iArg); + + iArg = -45; + speex_preprocess_ctl(sppPreprocess, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &iArg); + if (bHasSpeaker) { if (sesEcho) speex_echo_state_destroy(sesEcho); @@ -291,7 +296,17 @@ void AudioInput::encodeAudioFrame() { max=abs(psSource[i]); dPeakSignal=20.0*log10((max * 1.0L) / 32768.0L); - if (dPeakSignal > -20) + + CloneSpeexPreprocessState *st=reinterpret_cast(sppPreprocess); + float Zframe = 0; + int freq_start = static_cast(300.0f*2.f*st->ps_size/st->sampling_rate); + int freq_end = static_cast(2000.0f*2.f*st->ps_size/st->sampling_rate); + for (int i=freq_start;izeta[i]; + Zframe /= (freq_end-freq_start); + dSNR = Zframe; + + if (dSNR > 1.0) iIsSpeech = 1; else iIsSpeech = 0; diff --git a/src/mumble/AudioInput.h b/src/mumble/AudioInput.h index 677a3bfc3..b1a601657 100644 --- a/src/mumble/AudioInput.h +++ b/src/mumble/AudioInput.h @@ -84,6 +84,7 @@ class AudioInput : public QThread { int iBitrate; double dPeakMic, dPeakSpeaker, dPeakSignal; + double dSNR; bool isTransmitting() { return bPreviousVoice; }; diff --git a/src/mumble/AudioStats.cpp b/src/mumble/AudioStats.cpp index 17d54964e..5546750a4 100644 --- a/src/mumble/AudioStats.cpp +++ b/src/mumble/AudioStats.cpp @@ -32,125 +32,6 @@ #include "AudioInput.h" #include "Global.h" -/** Speex echo cancellation state; sync from mdf.c in Speex distribution. - */ - -typedef float spx_word16_t; -typedef float spx_word32_t; -typedef float spx_float_t; -typedef spx_word32_t spx_mem_t; -/** Speex echo cancellation state. */ -struct CloneSpeexEchoState { - int frame_size; /**< Number of samples processed each time */ - int window_size; - int M; - int cancel_count; - int adapted; - int saturated; - int screwed_up; - spx_int32_t sampling_rate; - spx_word16_t spec_average; - spx_word16_t beta0; - spx_word16_t beta_max; - spx_word32_t sum_adapt; - spx_word16_t leak_estimate; - - spx_word16_t *e; /* scratch */ - spx_word16_t *x; /* Far-end input buffer (2N) */ - spx_word16_t *X; /* Far-end buffer (M+1 frames) in frequency domain */ - spx_word16_t *input; /* scratch */ - spx_word16_t *y; /* scratch */ - spx_word16_t *last_y; - spx_word16_t *Y; /* scratch */ - spx_word16_t *E; - spx_word32_t *PHI; /* scratch */ - spx_word32_t *W; /* (Background) filter weights */ - spx_word16_t *foreground; /* Foreground filter weights */ - spx_word32_t Davg1; /* 1st recursive average of the residual power difference */ - spx_word32_t Davg2; /* 2nd recursive average of the residual power difference */ - spx_float_t Dvar1; /* Estimated variance of 1st estimator */ - spx_float_t Dvar2; /* Estimated variance of 2nd estimator */ - spx_word32_t *power; /* Power of the far-end signal */ - spx_float_t *power_1;/* Inverse power of far-end */ - spx_word16_t *wtmp; /* scratch */ - spx_word32_t *Rf; /* scratch */ - spx_word32_t *Yf; /* scratch */ - spx_word32_t *Xf; /* scratch */ - spx_word32_t *Eh; - spx_word32_t *Yh; - spx_float_t Pey; - spx_float_t Pyy; - spx_word16_t *window; - spx_word16_t *prop; - void *fft_table; - spx_word16_t memX, memD, memE; - spx_word16_t preemph; - spx_word16_t notch_radius; - spx_mem_t notch_mem[2]; -}; - -/** Speex pre-processor state. */ -struct CloneSpeexPreprocessState { - /* Basic info */ - int frame_size; /**< Number of samples processed each time */ - int ps_size; /**< Number of points in the power spectrum */ - int sampling_rate; /**< Sampling rate of the input/output */ - int nbands; - void *bank; - int denoise_enabled; - int vad_enabled; - int dereverb_enabled; - spx_word16_t reverb_decay; - spx_word16_t reverb_level; - spx_word16_t speech_prob_start; - spx_word16_t speech_prob_continue; - int noise_suppress; - int echo_suppress; - int echo_suppress_active; - CloneSpeexEchoState *echo_state; - spx_word16_t *frame; /**< Processing frame (2*ps_size) */ - spx_word16_t *ft; /**< Processing frame in freq domain (2*ps_size) */ - spx_word32_t *ps; /**< Current power spectrum */ - spx_word16_t *gain2; /**< Adjusted gains */ - spx_word16_t *gain_floor; /**< Minimum gain allowed */ - spx_word16_t *window; /**< Analysis/Synthesis window */ - spx_word32_t *noise; /**< Noise estimate */ - spx_word32_t *reverb_estimate; /**< Estimate of reverb energy */ - spx_word32_t *old_ps; /**< Power spectrum for last frame */ - spx_word16_t *gain; /**< Ephraim Malah gain */ - spx_word16_t *prior; /**< A-priori SNR */ - spx_word16_t *post; /**< A-posteriori SNR */ - - spx_word32_t *S; /**< Smoothed power spectrum */ - spx_word32_t *Smin; /**< See Cohen paper */ - spx_word32_t *Stmp; /**< See Cohen paper */ - int *update_prob; /**< Propability of speech presence for noise update */ - - spx_word16_t *zeta; /**< Smoothed a priori SNR */ - spx_word32_t *echo_noise; - spx_word32_t *residual_echo; - - spx_word16_t *inbuf; /**< Input buffer (overlapped analysis) */ - spx_word16_t *outbuf; /**< Output buffer (for overlap and add) */ - - int agc_enabled; - float agc_level; - float loudness_accum; - float *loudness_weight; /**< Perceptual loudness curve */ - float loudness; /**< Loudness estimate */ - float agc_gain; /**< Current AGC gain */ - int nb_loudness_adapt; /**< Number of frames used for loudness adaptation so far */ - float max_gain; /**< Maximum gain allowed */ - float max_increase_step; /**< Maximum increase in gain from one frame to another */ - float max_decrease_step; /**< Maximum decrease in gain from one frame to another */ - float prev_loudness; /**< Loudness of previous frame */ - float init_max; /**< Current gain limit during initialisation */ - int nb_adapt; /**< Number of frames used for adaptation so far */ - int was_speech; - int min_count; /**< Number of frames processed so far */ - void *fft_lookup; /**< Lookup table for the FFT */ -}; - AudioEchoWidget::AudioEchoWidget(QWidget *p) : QGLWidget(p) { setMinimumSize(100, 60); mode = MODULUS; @@ -514,13 +395,7 @@ void AudioStats::on_Tick_timeout() { txt.sprintf("%06.2f dB",ai->dPeakSignal); qlSignalLevel->setText(txt); - float Zframe = 0; - int freq_start = static_cast(300.0f*2.f*st->ps_size/st->sampling_rate); - int freq_end = static_cast(2000.0f*2.f*st->ps_size/st->sampling_rate); - for (int i=freq_start;izeta[i]; - Zframe /= (freq_end-freq_start); - txt.sprintf("%06.3f",Zframe); + txt.sprintf("%06.3f",ai->dSNR); qlMicSNR->setText(txt); txt.sprintf("%03.0f%%",nTalking ? 100.0 : 0.0); diff --git a/src/mumble/mumble_pch.h b/src/mumble/mumble_pch.h index 32a76ab4d..8fee3dbf4 100644 --- a/src/mumble/mumble_pch.h +++ b/src/mumble/mumble_pch.h @@ -27,6 +27,126 @@ #include #include +/** Speex echo cancellation state; sync from mdf.c in Speex distribution. + */ + +typedef float spx_word16_t; +typedef float spx_word32_t; +typedef float spx_float_t; +typedef spx_word32_t spx_mem_t; +/** Speex echo cancellation state. */ +struct CloneSpeexEchoState { + int frame_size; /**< Number of samples processed each time */ + int window_size; + int M; + int cancel_count; + int adapted; + int saturated; + int screwed_up; + spx_int32_t sampling_rate; + spx_word16_t spec_average; + spx_word16_t beta0; + spx_word16_t beta_max; + spx_word32_t sum_adapt; + spx_word16_t leak_estimate; + + spx_word16_t *e; /* scratch */ + spx_word16_t *x; /* Far-end input buffer (2N) */ + spx_word16_t *X; /* Far-end buffer (M+1 frames) in frequency domain */ + spx_word16_t *input; /* scratch */ + spx_word16_t *y; /* scratch */ + spx_word16_t *last_y; + spx_word16_t *Y; /* scratch */ + spx_word16_t *E; + spx_word32_t *PHI; /* scratch */ + spx_word32_t *W; /* (Background) filter weights */ + spx_word16_t *foreground; /* Foreground filter weights */ + spx_word32_t Davg1; /* 1st recursive average of the residual power difference */ + spx_word32_t Davg2; /* 2nd recursive average of the residual power difference */ + spx_float_t Dvar1; /* Estimated variance of 1st estimator */ + spx_float_t Dvar2; /* Estimated variance of 2nd estimator */ + spx_word32_t *power; /* Power of the far-end signal */ + spx_float_t *power_1;/* Inverse power of far-end */ + spx_word16_t *wtmp; /* scratch */ + spx_word32_t *Rf; /* scratch */ + spx_word32_t *Yf; /* scratch */ + spx_word32_t *Xf; /* scratch */ + spx_word32_t *Eh; + spx_word32_t *Yh; + spx_float_t Pey; + spx_float_t Pyy; + spx_word16_t *window; + spx_word16_t *prop; + void *fft_table; + spx_word16_t memX, memD, memE; + spx_word16_t preemph; + spx_word16_t notch_radius; + spx_mem_t notch_mem[2]; +}; + +/** Speex pre-processor state. */ +struct CloneSpeexPreprocessState { + /* Basic info */ + int frame_size; /**< Number of samples processed each time */ + int ps_size; /**< Number of points in the power spectrum */ + int sampling_rate; /**< Sampling rate of the input/output */ + int nbands; + void *bank; + int denoise_enabled; + int vad_enabled; + int dereverb_enabled; + spx_word16_t reverb_decay; + spx_word16_t reverb_level; + spx_word16_t speech_prob_start; + spx_word16_t speech_prob_continue; + int noise_suppress; + int echo_suppress; + int echo_suppress_active; + CloneSpeexEchoState *echo_state; + spx_word16_t *frame; /**< Processing frame (2*ps_size) */ + spx_word16_t *ft; /**< Processing frame in freq domain (2*ps_size) */ + spx_word32_t *ps; /**< Current power spectrum */ + spx_word16_t *gain2; /**< Adjusted gains */ + spx_word16_t *gain_floor; /**< Minimum gain allowed */ + spx_word16_t *window; /**< Analysis/Synthesis window */ + spx_word32_t *noise; /**< Noise estimate */ + spx_word32_t *reverb_estimate; /**< Estimate of reverb energy */ + spx_word32_t *old_ps; /**< Power spectrum for last frame */ + spx_word16_t *gain; /**< Ephraim Malah gain */ + spx_word16_t *prior; /**< A-priori SNR */ + spx_word16_t *post; /**< A-posteriori SNR */ + + spx_word32_t *S; /**< Smoothed power spectrum */ + spx_word32_t *Smin; /**< See Cohen paper */ + spx_word32_t *Stmp; /**< See Cohen paper */ + int *update_prob; /**< Propability of speech presence for noise update */ + + spx_word16_t *zeta; /**< Smoothed a priori SNR */ + spx_word32_t *echo_noise; + spx_word32_t *residual_echo; + + spx_word16_t *inbuf; /**< Input buffer (overlapped analysis) */ + spx_word16_t *outbuf; /**< Output buffer (for overlap and add) */ + + int agc_enabled; + float agc_level; + float loudness_accum; + float *loudness_weight; /**< Perceptual loudness curve */ + float loudness; /**< Loudness estimate */ + float agc_gain; /**< Current AGC gain */ + int nb_loudness_adapt; /**< Number of frames used for loudness adaptation so far */ + float max_gain; /**< Maximum gain allowed */ + float max_increase_step; /**< Maximum increase in gain from one frame to another */ + float max_decrease_step; /**< Maximum decrease in gain from one frame to another */ + float prev_loudness; /**< Loudness of previous frame */ + float init_max; /**< Current gain limit during initialisation */ + int nb_adapt; /**< Number of frames used for adaptation so far */ + int was_speech; + int min_count; /**< Number of frames processed so far */ + void *fft_lookup; /**< Lookup table for the FFT */ +}; + + #ifndef WIN32 typedef WId HWND; #endif