From 3905b0c45df36ad58a2b5b7f6ef66ee6760c94e8 Mon Sep 17 00:00:00 2001 From: "andrew@webrtc.org" Date: Wed, 4 Jan 2012 15:47:20 +0000 Subject: [PATCH] Protect against divide-by-zeros in AGC. TEST=audioproc_unittest Review URL: http://webrtc-codereview.appspot.com/333024 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1331 4adac7df-926f-26a2-2b94-8c16560cd09d --- src/modules/audio_processing/agc/analog_agc.c | 4 ++++ .../audio_processing/agc/digital_agc.c | 22 ++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/modules/audio_processing/agc/analog_agc.c b/src/modules/audio_processing/agc/analog_agc.c index 0c2ccee4f..40c556630 100644 --- a/src/modules/audio_processing/agc/analog_agc.c +++ b/src/modules/audio_processing/agc/analog_agc.c @@ -200,6 +200,10 @@ int WebRtcAgc_AddMic(void *state, WebRtc_Word16 *in_mic, WebRtc_Word16 *in_mic_H /* apply slowly varying digital gain */ if (stt->micVol > stt->maxAnalog) { + /* |maxLevel| is strictly >= |micVol|, so this condition should be + * satisfied here, ensuring there is no divide-by-zero. */ + assert(stt->maxLevel > stt->maxAnalog); + /* Q1 */ tmp16 = (WebRtc_Word16)(stt->micVol - stt->maxAnalog); tmp32 = WEBRTC_SPL_MUL_16_16(GAIN_TBL_LEN - 1, tmp16); diff --git a/src/modules/audio_processing/agc/digital_agc.c b/src/modules/audio_processing/agc/digital_agc.c index e303a92f9..a627b8d1f 100644 --- a/src/modules/audio_processing/agc/digital_agc.c +++ b/src/modules/audio_processing/agc/digital_agc.c @@ -12,11 +12,14 @@ * */ +#include "digital_agc.h" + +#include #include #ifdef AGC_DEBUG #include #endif -#include "digital_agc.h" + #include "gain_control.h" // To generate the gaintable, copy&paste the following lines to a Matlab window: @@ -33,7 +36,8 @@ // zoom on; // Generator table for y=log2(1+e^x) in Q8. -static const WebRtc_UWord16 kGenFuncTable[128] = { +static const int kGenFuncTableSize = 128; +static const WebRtc_UWord16 kGenFuncTable[kGenFuncTableSize] = { 256, 485, 786, 1126, 1484, 1849, 2217, 2586, 2955, 3324, 3693, 4063, 4432, 4801, 5171, 5540, 5909, 6279, 6648, 7017, 7387, 7756, 8125, 8495, @@ -102,8 +106,9 @@ WebRtc_Word32 WebRtcAgc_CalculateGainTable(WebRtc_Word32 *gainTable, // Q16 // = (compRatio-1)*digCompGaindB/compRatio tmp32no1 = WEBRTC_SPL_MUL_16_16(digCompGaindB, kCompRatio - 1); diffGain = WebRtcSpl_DivW32W16ResW16(tmp32no1 + (kCompRatio >> 1), kCompRatio); - if (diffGain < 0) + if (diffGain < 0 || diffGain >= kGenFuncTableSize) { + assert(0); return -1; } @@ -185,8 +190,15 @@ WebRtc_Word32 WebRtcAgc_CalculateGainTable(WebRtc_Word32 *gainTable, // Q16 numFIX -= WEBRTC_SPL_MUL_32_16((WebRtc_Word32)logApprox, diffGain); // Q14 // Calculate ratio - // Shift numFIX as much as possible - zeros = WebRtcSpl_NormW32(numFIX); + // Shift |numFIX| as much as possible. + // Ensure we avoid wrap-around in |den| as well. + if (numFIX > (den >> 8)) // |den| is Q8. + { + zeros = WebRtcSpl_NormW32(numFIX); + } else + { + zeros = WebRtcSpl_NormW32(den) + 8; + } numFIX = WEBRTC_SPL_LSHIFT_W32(numFIX, zeros); // Q(14+zeros) // Shift den so we end up in Qy1