webrtc的自动增益模块在agc_legacy_c工程下:
analog_agc.c analog_agc.h digital_agc.c digital_agc.h gain_control.h
主要函数包括:
WebRtcAgc_AddMic
WebRtcAgc_AddFarend
WebRtcAgc_GetAddFarendError
WebRtcAgc_VirtualMic
WebRtcAgc_UpdateAgcThresholds
WebRtcAgc_SaturationCtrl
WebRtcAgc_ZeroCtrl
WebRtcAgc_SpeakerInactiveCtrl
WebRtcAgc_ExpCurve
WebRtcAgc_ProcessAnalog
WebRtcAgc_Process
WebRtcAgc_set_config
WebRtcAgc_get_config
WebRtcAgc_Create
WebRtcAgc_Free
WebRtcAgc_Init
WebRtcAgc_CalculateGainTable
WebRtcAgc_InitDigital
WebRtcAgc_AddFarendToDigital
WebRtcAgc_ProcessDigital
WebRtcAgc_InitVad
WebRtcAgc_ProcessVad
核心函数介绍:WebRtcAgc_Init
/* minLevel - Minimum volume level
* maxLevel - Maximum volume level
*/
int WebRtcAgc_Init(void* agcInst,
int32_t minLevel,
int32_t maxLevel,
int16_t agcMode,
uint32_t fs) {
int32_t max_add, tmp32;
int16_t i;
int tmpNorm;
LegacyAgc* stt;
/* typecast state pointer */
stt = (LegacyAgc*)agcInst;
if (WebRtcAgc_InitDigital(&stt->digitalAgc, agcMode) != 0) {
stt->lastError = AGC_UNINITIALIZED_ERROR;
return -1;
}
/* Analog AGC variables */
stt->envSum = 0;
/* mode = 0 - Only saturation protection
* 1 - Analog Automatic Gain Control [-targetLevelDbfs (default -3
* dBOv)]
* 2 - Digital Automatic Gain Control [-targetLevelDbfs (default -3
* dBOv)]
* 3 - Fixed Digital Gain [compressionGaindB (default 8 dB)]
*/
#ifdef WEBRTC_AGC_DEBUG_DUMP
stt->fcount = 0;
fprintf(stt->fpt, "AGC->Init\n");
#endif
if (agcMode < kAgcModeUnchanged || agcMode > kAgcModeFixedDigital) {
#ifdef WEBRTC_AGC_DEBUG_DUMP
fprintf(stt->fpt, "AGC->Init: error, incorrect mode\n\n");
#endif
return -1;
}
stt->agcMode = agcMode;
stt->fs = fs;
/* initialize input VAD */
WebRtcAgc_InitVad(&stt->vadMic);
/* If the volume range is smaller than 0-256 then
* the levels are shifted up to Q8-domain */
tmpNorm = WebRtcSpl_NormU32((uint32_t)maxLevel);
stt->scale = tmpNorm - 23;
if (stt->scale < 0) {
stt->scale = 0;
}
// TODO(bjornv): Investigate if we really need to scale up a small range now
// when we have
// a guard against zero-increments. For now, we do not support scale up (scale
// = 0).
stt->scale = 0;
maxLevel <<= stt->scale;
minLevel <<= stt->scale;
/* Make minLevel and maxLevel static in AdaptiveDigital */
if (stt->agcMode == kAgcModeAdaptiveDigital) {
minLevel = 0;
maxLevel = 255;
stt->scale = 0;
}
/* The maximum supplemental volume range is based on a vague idea
* of how much lower the gain will be than the real analog gain. */
max_add = (maxLevel - minLevel) / 4;
/* Minimum/maximum volume level that can be set */
stt->minLevel = minLevel;
stt->maxAnalog = maxLevel;
stt->maxLevel = maxLevel + max_add;
stt->maxInit = stt->maxLevel;
stt->zeroCtrlMax = stt->maxAnalog;
stt->lastInMicLevel = 0;
/* Initialize micVol parameter */
stt->micVol = stt->maxAnalog;
if (stt->agcMode == kAgcModeAdaptiveDigital) {
stt->micVol = 127; /* Mid-point of mic level */
}
stt->micRef = stt->micVol;
stt->micGainIdx = 127;
#ifdef MIC_LEVEL_FEEDBACK
stt->numBlocksMicLvlSat = 0;
stt->micLvlSat = 0;
#endif
#ifdef WEBRTC_AGC_DEBUG_DUMP
fprintf(stt->fpt, "AGC->Init: minLevel = %d, maxAnalog = %d, maxLevel = %d\n",
stt->minLevel, stt->maxAnalog, stt->maxLevel);
#endif
/* Minimum output volume is 4% higher than the available lowest volume level
*/
tmp32 = ((stt->maxLevel - stt->minLevel) * 10) >> 8;
stt->minOutput = (stt->minLevel + tmp32);
stt->msTooLow = 0;
stt->msTooHigh = 0;
stt->changeToSlowMode = 0;
stt->firstCall = 0;
stt->msZero = 0;
stt->muteGuardMs = 0;
stt->gainTableIdx = 0;
stt->msecSpeechInnerChange = kMsecSpeechInner;
stt->msecSpeechOuterChange = kMsecSpeechOuter;
stt->activeSpeech = 0;
stt->Rxx16_LPw32Max = 0;
stt->vadThreshold = kNormalVadThreshold;
stt->inActive = 0;
for (i = 0; i < RXX_BUFFER_LEN; i++) {
stt->Rxx16_vectorw32[i] = (int32_t)1000; /* -54dBm0 */
}
stt->Rxx160w32 =
125 * RXX_BUFFER_LEN; /* (stt->Rxx16_vectorw32[0]>>3) = 125 */
stt->Rxx16pos = 0;
stt->Rxx16_LPw32 = (int32_t)16284; /* Q(-4) */
for (i = 0; i < 5; i++) {
stt->Rxx16w32_array[0][i] = 0;
}
for (i = 0; i < 10; i++) {
stt->env[0][i] = 0;
stt->env[1][i] = 0;
}
stt->inQueue = 0;
#ifdef MIC_LEVEL_FEEDBACK
stt->targetIdxOffset = 0;
#endif
WebRtcSpl_MemSetW32(stt->filterState, 0, 8);
stt->initFlag = kInitCheck;
// Default config settings.
stt->defaultConfig.limiterEnable = kAgcTrue;
stt->defaultConfig.targetLevelDbfs = AGC_DEFAULT_TARGET_LEVEL;
stt->defaultConfig.compressionGaindB = AGC_DEFAULT_COMP_GAIN;
if (WebRtcAgc_set_config(stt, stt->defaultConfig) == -1) {
stt->lastError = AGC_UNSPECIFIED_ERROR;
return -1;
}
stt->Rxx160_LPw32 = stt->analogTargetLevel; // Initialize rms value
stt->lowLevelSignal = 0;
/* Only positive values are allowed that are not too large */
if ((minLevel >= maxLevel) || (maxLevel & 0xFC000000)) {
#ifdef WEBRTC_AGC_DEBUG_DUMP
fprintf(stt->fpt, "minLevel, maxLevel value(s) are invalid\n\n");
#endif
return -1;
} else {
#ifdef WEBRTC_AGC_DEBUG_DUMP
fprintf(stt->fpt, "\n");
#endif
return 0;
}
}
WebRtcAgc_InitDigital函数:
int32_t WebRtcAgc_InitDigital(DigitalAgc* stt, int16_t agcMode) {
if (agcMode == kAgcModeFixedDigital) {
// start at minimum to find correct gain faster
stt->capacitorSlow = 0;
} else {
// start out with 0 dB gain
stt->capacitorSlow = 134217728; // (int32_t)(0.125f * 32768.0f * 32768.0f);
}
stt->capacitorFast = 0;
stt->gain = 65536;
stt->gatePrevious = 0;
stt->agcMode = agcMode;
#ifdef WEBRTC_AGC_DEBUG_DUMP
stt->frameCounter = 0;
#endif
// initialize VADs
WebRtcAgc_InitVad(&stt->vadNearend);
WebRtcAgc_InitVad(&stt->vadFarend);
return 0;
}
WebRtcAgc_InitVad函数:
void WebRtcAgc_InitVad(AgcVad* state) {
int16_t k;
state->HPstate = 0; // state of high pass filter
state->logRatio = 0; // log( P(active) / P(inactive) )
// average input level (Q10)
state->meanLongTerm = 15 << 10;
// variance of input level (Q8)
state->varianceLongTerm = 500 << 8;
state->stdLongTerm = 0; // standard deviation of input level in dB
// short-term average input level (Q10)
state->meanShortTerm = 15 << 10;
// short-term variance of input level (Q8)
state->varianceShortTerm = 500 << 8;
state->stdShortTerm =
0; // short-term standard deviation of input level in dB
state->counter = 3; // counts updates
for (k = 0; k < 8; k++) {
// downsampling filter
state->downState[k] = 0;
}
}
WebRtcAgc_set_config函数:
int WebRtcAgc_set_config(void* agcInst, WebRtcAgcConfig agcConfig) {
LegacyAgc* stt;
stt = (LegacyAgc*)agcInst;
if (stt == NULL) {
return -1;
}
if (stt->initFlag != kInitCheck) {
stt->lastError = AGC_UNINITIALIZED_ERROR;
return -1;
}
if (agcConfig.limiterEnable != kAgcFalse &&
agcConfig.limiterEnable != kAgcTrue) {
stt->lastError = AGC_BAD_PARAMETER_ERROR;
return -1;
}
stt->limiterEnable = agcConfig.limiterEnable;
stt->compressionGaindB = agcConfig.compressionGaindB;
if ((agcConfig.targetLevelDbfs < 0) || (agcConfig.targetLevelDbfs > 31)) {
stt->lastError = AGC_BAD_PARAMETER_ERROR;
return -1;
}
stt->targetLevelDbfs = agcConfig.targetLevelDbfs;
if (stt->agcMode == kAgcModeFixedDigital) {
/* Adjust for different parameter interpretation in FixedDigital mode */
stt->compressionGaindB += agcConfig.targetLevelDbfs;
}
/* Update threshold levels for analog adaptation */
WebRtcAgc_UpdateAgcThresholds(stt);
/* Recalculate gain table */
if (WebRtcAgc_CalculateGainTable(
&(stt->digitalAgc.gainTable[0]), stt->compressionGaindB,
stt->targetLevelDbfs, stt->limiterEnable, stt->analogTarget) == -1) {
#ifdef WEBRTC_AGC_DEBUG_DUMP
fprintf(stt->fpt, "AGC->set_config, frame %d: Error from calcGainTable\n\n",
stt->fcount);
#endif
return -1;
}
/* Store the config in a WebRtcAgcConfig */
stt->usedConfig.compressionGaindB = agcConfig.compressionGaindB;
stt->usedConfig.limiterEnable = agcConfig.limiterEnable;
stt->usedConfig.targetLevelDbfs = agcConfig.targetLevelDbfs;
return 0;
}