[Speex-dev] Proposed AGC additions

tgrand at canvaslink.com tgrand
Fri Jul 2 14:44:51 PDT 2004


I've been using Speex's AGC in my VoIP program with mixed
results.  One of the problems I had was:  At the beginning
of the call, if the user hadn't spoken yet and there weren't
any background sounds for the AGC to lock on to, most of the
time the AGC would almost immediately jump way up to 200x gain
(the default max).  This is undesirable and usually results in
nasty feedback.

If there ARE any background sounds occurring before this AGC
jump, and they survive the noise filter, then AGC behaves
nicely and hangs out around 1.33x to start with, gradually
rising as it listens for something useful.  For example,
as I tested this today, the faint sound of birds chirping
outside was enough to prevent the AGC from spazzing out!

Anyway, what I propose are the following commands to let
an application interface a little more with the AGC:

SPEEX_PREPROCESS_GET_AGC_GAIN
SPEEX_PREPROCESS_GET_AGC_MAX_GAIN
SPEEX_PREPROCESS_SET_AGC_MAX_GAIN

I've implemented these and use them for the following:

1) I display the current AGC gain to the user.
2) If the AGC gain has reached its maximum, I don't transmit
any audio.  This condition indicates to me that the AGC has
not found any usable signal and it's very likely that the
result of such extreme amplification is unwanted noise.  Once
the user says something, the gain will back off and I can
resume transmission.

In the future, I might adjust the max AGC gain based on the
results of a "mic setup wizard" type of thing, and/or the
highest gain reached (and sustained) during the previous call.
So that's where the SPEEX_PREPROCESS_SET_AGC_MAX_GAIN would
come in.  I don't think there's any point in trying to do a
SPEEX_PREPROCESS_SET_AGC_GAIN so I didn't list it here,
but if anyone can think of a reason please say so.

It's easy to implement these commands:

In preprocess.h, SpeexPreprocessState:
float  agc_gain;
float  agc_max_gain;

In preprocess.h, #defines at the end:
#define SPEEX_PREPROCESS_GET_AGC_GAIN 14
#define SPEEX_PREPROCESS_SET_AGC_MAX_GAIN 15
#define SPEEX_PREPROCESS_GET_AGC_MAX_GAIN 16

In preprocess.c, speex_preprocess_state_init():
st->agc_gain = 1;
st->agc_max_gain = 200;

In preprocess.c, speex_compute_agc(), before last for loop:
if (agc_gain > st->agc_max_gain)
agc_gain = st->agc_max_gain;
st->agc_gain = agc_gain;

In preprocess.c, speex_preprocess_ctl():
case SPEEX_PREPROCESS_GET_AGC_GAIN:
(*(float*)ptr) = st->agc_gain;
break;
case SPEEX_PREPROCESS_GET_AGC_MAX_GAIN:
(*(float*)ptr) = st->agc_max_gain;
break;
case SPEEX_PREPROCESS_SET_AGC_MAX_GAIN:
st->agc_max_gain = (*(float*)ptr);
break;

And that should do it.

Tom

P.S. That problem I was having the other day with state being
retained was my own fault, of course. :)  Speex was working
just fine!  Sorry for wasting time on the list with it.



More information about the Speex-dev mailing list