From 7cfbf3a0ffc888e411a677a3402961792bba92aa Mon Sep 17 00:00:00 2001 From: Alex Loiko Date: Tue, 7 Nov 2017 16:34:32 +0100 Subject: [PATCH] Make energy calculation in AGC not overflow. An energy value is calculated by summing squares of processed audio samples. The expression 'out*out >> 6' could overflow. In this CL we change it to 'out*(out>>6) + out*(out*(out%(1<<6))>>6)'. The which is verified and proven to be equal, but doesn't overflow. The change also passes our change-detection tests in GainControlBitExactnessTest.* We verified with Godbolt that the modulo and divisions are converted into branch-free bitwise operations. NOTRY=True # changing comment, tests just passed. Bug: chromium:780638, chromium:780376 Change-Id: I415535193433a2fbc275c643fb4e4026ba3e0bdd Reviewed-on: https://webrtc-review.googlesource.com/20867 Commit-Queue: Alex Loiko Reviewed-by: Sam Zackrisson Cr-Commit-Position: refs/heads/master@{#20589} --- modules/audio_processing/agc/legacy/digital_agc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/audio_processing/agc/legacy/digital_agc.c b/modules/audio_processing/agc/legacy/digital_agc.c index c97f65efc4..3269a17ce4 100644 --- a/modules/audio_processing/agc/legacy/digital_agc.c +++ b/modules/audio_processing/agc/legacy/digital_agc.c @@ -607,7 +607,12 @@ int16_t WebRtcAgc_ProcessVad(AgcVad* state, // (i) VAD state out = buf2[k] + HPstate; tmp32 = 600 * out; HPstate = (int16_t)((tmp32 >> 10) - buf2[k]); - nrg += (out * out) >> 6; + + // Add 'out * out / 2**6' to 'nrg' in a non-overflowing + // way. Guaranteed to work as long as 'out * out / 2**6' fits in + // an int32_t. + nrg += out * (out / (1 << 6)); + nrg += out * (out % (1 << 6)) / (1 << 6); } } state->HPstate = HPstate;