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 <aleloi@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20589}
This commit is contained in:
Alex Loiko
2017-11-07 16:34:32 +01:00
committed by Commit Bot
parent fbb3b7d004
commit 7cfbf3a0ff

View File

@ -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;