diff --git a/modules/audio_processing/aecm/aecm_core.cc b/modules/audio_processing/aecm/aecm_core.cc index 78d8dfdafd..09c55be81a 100644 --- a/modules/audio_processing/aecm/aecm_core.cc +++ b/modules/audio_processing/aecm/aecm_core.cc @@ -24,11 +24,35 @@ extern "C" { #include "rtc_base/checks.h" #include "rtc_base/numerics/safe_conversions.h" +namespace webrtc { + +namespace { + #ifdef AEC_DEBUG FILE* dfile; FILE* testfile; #endif +// Initialization table for echo channel in 8 kHz +static const int16_t kChannelStored8kHz[PART_LEN1] = { + 2040, 1815, 1590, 1498, 1405, 1395, 1385, 1418, 1451, 1506, 1562, + 1644, 1726, 1804, 1882, 1918, 1953, 1982, 2010, 2025, 2040, 2034, + 2027, 2021, 2014, 1997, 1980, 1925, 1869, 1800, 1732, 1683, 1635, + 1604, 1572, 1545, 1517, 1481, 1444, 1405, 1367, 1331, 1294, 1270, + 1245, 1239, 1233, 1247, 1260, 1282, 1303, 1338, 1373, 1407, 1441, + 1470, 1499, 1524, 1549, 1565, 1582, 1601, 1621, 1649, 1676}; + +// Initialization table for echo channel in 16 kHz +static const int16_t kChannelStored16kHz[PART_LEN1] = { + 2040, 1590, 1405, 1385, 1451, 1562, 1726, 1882, 1953, 2010, 2040, + 2027, 2014, 1980, 1869, 1732, 1635, 1572, 1517, 1444, 1367, 1294, + 1245, 1233, 1260, 1303, 1373, 1441, 1499, 1549, 1582, 1621, 1676, + 1741, 1802, 1861, 1921, 1983, 2040, 2102, 2170, 2265, 2375, 2515, + 2651, 2781, 2922, 3075, 3253, 3471, 3738, 3976, 4151, 4258, 4308, + 4288, 4270, 4253, 4237, 4179, 4086, 3947, 3757, 3484, 3153}; + +} // namespace + const int16_t WebRtcAecm_kCosTable[] = { 8192, 8190, 8187, 8180, 8172, 8160, 8147, 8130, 8112, 8091, 8067, 8041, 8012, 7982, 7948, 7912, 7874, 7834, 7791, 7745, 7697, 7647, @@ -99,23 +123,6 @@ const int16_t WebRtcAecm_kSinTable[] = { -2667, -2531, -2395, -2258, -2120, -1981, -1842, -1703, -1563, -1422, -1281, -1140, -998, -856, -713, -571, -428, -285, -142}; -// Initialization table for echo channel in 8 kHz -static const int16_t kChannelStored8kHz[PART_LEN1] = { - 2040, 1815, 1590, 1498, 1405, 1395, 1385, 1418, 1451, 1506, 1562, - 1644, 1726, 1804, 1882, 1918, 1953, 1982, 2010, 2025, 2040, 2034, - 2027, 2021, 2014, 1997, 1980, 1925, 1869, 1800, 1732, 1683, 1635, - 1604, 1572, 1545, 1517, 1481, 1444, 1405, 1367, 1331, 1294, 1270, - 1245, 1239, 1233, 1247, 1260, 1282, 1303, 1338, 1373, 1407, 1441, - 1470, 1499, 1524, 1549, 1565, 1582, 1601, 1621, 1649, 1676}; - -// Initialization table for echo channel in 16 kHz -static const int16_t kChannelStored16kHz[PART_LEN1] = { - 2040, 1590, 1405, 1385, 1451, 1562, 1726, 1882, 1953, 2010, 2040, - 2027, 2014, 1980, 1869, 1732, 1635, 1572, 1517, 1444, 1367, 1294, - 1245, 1233, 1260, 1303, 1373, 1441, 1499, 1549, 1582, 1621, 1676, - 1741, 1802, 1861, 1921, 1983, 2040, 2102, 2170, 2265, 2375, 2515, - 2651, 2781, 2922, 3075, 3253, 3471, 3738, 3976, 4151, 4258, 4308, - 4288, 4270, 4253, 4237, 4179, 4086, 3947, 3757, 3484, 3153}; // Moves the pointer to the next entry and inserts |far_spectrum| and // corresponding Q-domain in its buffer. @@ -1113,3 +1120,5 @@ void WebRtcAecm_FetchFarFrame(AecmCore* const aecm, sizeof(int16_t) * readLen); aecm->farBufReadPos += readLen; } + +} // namespace webrtc diff --git a/modules/audio_processing/aecm/aecm_core.h b/modules/audio_processing/aecm/aecm_core.h index 1681d2a92f..aaa74e1721 100644 --- a/modules/audio_processing/aecm/aecm_core.h +++ b/modules/audio_processing/aecm/aecm_core.h @@ -19,6 +19,10 @@ extern "C" { } #include "modules/audio_processing/aecm/aecm_defines.h" +struct RealFFT; + +namespace webrtc { + #ifdef _MSC_VER // visual c++ #define ALIGN8_BEG __declspec(align(8)) #define ALIGN8_END @@ -432,4 +436,6 @@ void WebRtcAecm_ResetAdaptiveChannel_mips(AecmCore* aecm); #endif #endif +} // namespace webrtc + #endif diff --git a/modules/audio_processing/aecm/aecm_core_c.cc b/modules/audio_processing/aecm/aecm_core_c.cc index 2727182ae1..7b6ca59371 100644 --- a/modules/audio_processing/aecm/aecm_core_c.cc +++ b/modules/audio_processing/aecm/aecm_core_c.cc @@ -27,6 +27,10 @@ extern "C" { #include "rtc_base/numerics/safe_conversions.h" #include "rtc_base/sanitizer.h" +namespace webrtc { + +namespace { + // Square root of Hanning window in Q14. static const ALIGN8_BEG int16_t WebRtcAecm_kSqrtHanning[] ALIGN8_END = { 0, 399, 798, 1196, 1594, 1990, 2386, 2780, 3172, 3562, 3951, @@ -57,7 +61,115 @@ static const int16_t kNoiseEstIncCount = 5; static void ComfortNoise(AecmCore* aecm, const uint16_t* dfa, ComplexInt16* out, - const int16_t* lambda); + const int16_t* lambda) { + int16_t i; + int16_t tmp16; + int32_t tmp32; + + int16_t randW16[PART_LEN]; + int16_t uReal[PART_LEN1]; + int16_t uImag[PART_LEN1]; + int32_t outLShift32; + int16_t noiseRShift16[PART_LEN1]; + + int16_t shiftFromNearToNoise = kNoiseEstQDomain - aecm->dfaCleanQDomain; + int16_t minTrackShift; + + RTC_DCHECK_GE(shiftFromNearToNoise, 0); + RTC_DCHECK_LT(shiftFromNearToNoise, 16); + + if (aecm->noiseEstCtr < 100) { + // Track the minimum more quickly initially. + aecm->noiseEstCtr++; + minTrackShift = 6; + } else { + minTrackShift = 9; + } + + // Estimate noise power. + for (i = 0; i < PART_LEN1; i++) { + // Shift to the noise domain. + tmp32 = (int32_t)dfa[i]; + outLShift32 = tmp32 << shiftFromNearToNoise; + + if (outLShift32 < aecm->noiseEst[i]) { + // Reset "too low" counter + aecm->noiseEstTooLowCtr[i] = 0; + // Track the minimum. + if (aecm->noiseEst[i] < (1 << minTrackShift)) { + // For small values, decrease noiseEst[i] every + // |kNoiseEstIncCount| block. The regular approach below can not + // go further down due to truncation. + aecm->noiseEstTooHighCtr[i]++; + if (aecm->noiseEstTooHighCtr[i] >= kNoiseEstIncCount) { + aecm->noiseEst[i]--; + aecm->noiseEstTooHighCtr[i] = 0; // Reset the counter + } + } else { + aecm->noiseEst[i] -= + ((aecm->noiseEst[i] - outLShift32) >> minTrackShift); + } + } else { + // Reset "too high" counter + aecm->noiseEstTooHighCtr[i] = 0; + // Ramp slowly upwards until we hit the minimum again. + if ((aecm->noiseEst[i] >> 19) > 0) { + // Avoid overflow. + // Multiplication with 2049 will cause wrap around. Scale + // down first and then multiply + aecm->noiseEst[i] >>= 11; + aecm->noiseEst[i] *= 2049; + } else if ((aecm->noiseEst[i] >> 11) > 0) { + // Large enough for relative increase + aecm->noiseEst[i] *= 2049; + aecm->noiseEst[i] >>= 11; + } else { + // Make incremental increases based on size every + // |kNoiseEstIncCount| block + aecm->noiseEstTooLowCtr[i]++; + if (aecm->noiseEstTooLowCtr[i] >= kNoiseEstIncCount) { + aecm->noiseEst[i] += (aecm->noiseEst[i] >> 9) + 1; + aecm->noiseEstTooLowCtr[i] = 0; // Reset counter + } + } + } + } + + for (i = 0; i < PART_LEN1; i++) { + tmp32 = aecm->noiseEst[i] >> shiftFromNearToNoise; + if (tmp32 > 32767) { + tmp32 = 32767; + aecm->noiseEst[i] = tmp32 << shiftFromNearToNoise; + } + noiseRShift16[i] = (int16_t)tmp32; + + tmp16 = ONE_Q14 - lambda[i]; + noiseRShift16[i] = (int16_t)((tmp16 * noiseRShift16[i]) >> 14); + } + + // Generate a uniform random array on [0 2^15-1]. + WebRtcSpl_RandUArray(randW16, PART_LEN, &aecm->seed); + + // Generate noise according to estimated energy. + uReal[0] = 0; // Reject LF noise. + uImag[0] = 0; + for (i = 1; i < PART_LEN1; i++) { + // Get a random index for the cos and sin tables over [0 359]. + tmp16 = (int16_t)((359 * randW16[i - 1]) >> 15); + + // Tables are in Q13. + uReal[i] = + (int16_t)((noiseRShift16[i] * WebRtcAecm_kCosTable[tmp16]) >> 13); + uImag[i] = + (int16_t)((-noiseRShift16[i] * WebRtcAecm_kSinTable[tmp16]) >> 13); + } + uImag[PART_LEN] = 0; + + for (i = 0; i < PART_LEN1; i++) { + out[i].real = WebRtcSpl_AddSatW16(out[i].real, uReal[i]); + out[i].imag = WebRtcSpl_AddSatW16(out[i].imag, uImag[i]); + } +} static void WindowAndFFT(AecmCore* aecm, int16_t* fft, @@ -255,6 +367,8 @@ static int TimeToFrequencyDomain(AecmCore* aecm, return time_signal_scaling; } +} // namespace + int RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/8200 WebRtcAecm_ProcessBlock(AecmCore* aecm, const int16_t* farend, @@ -554,115 +668,4 @@ int RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/8200 return 0; } -static void ComfortNoise(AecmCore* aecm, - const uint16_t* dfa, - ComplexInt16* out, - const int16_t* lambda) { - int16_t i; - int16_t tmp16; - int32_t tmp32; - - int16_t randW16[PART_LEN]; - int16_t uReal[PART_LEN1]; - int16_t uImag[PART_LEN1]; - int32_t outLShift32; - int16_t noiseRShift16[PART_LEN1]; - - int16_t shiftFromNearToNoise = kNoiseEstQDomain - aecm->dfaCleanQDomain; - int16_t minTrackShift; - - RTC_DCHECK_GE(shiftFromNearToNoise, 0); - RTC_DCHECK_LT(shiftFromNearToNoise, 16); - - if (aecm->noiseEstCtr < 100) { - // Track the minimum more quickly initially. - aecm->noiseEstCtr++; - minTrackShift = 6; - } else { - minTrackShift = 9; - } - - // Estimate noise power. - for (i = 0; i < PART_LEN1; i++) { - // Shift to the noise domain. - tmp32 = (int32_t)dfa[i]; - outLShift32 = tmp32 << shiftFromNearToNoise; - - if (outLShift32 < aecm->noiseEst[i]) { - // Reset "too low" counter - aecm->noiseEstTooLowCtr[i] = 0; - // Track the minimum. - if (aecm->noiseEst[i] < (1 << minTrackShift)) { - // For small values, decrease noiseEst[i] every - // |kNoiseEstIncCount| block. The regular approach below can not - // go further down due to truncation. - aecm->noiseEstTooHighCtr[i]++; - if (aecm->noiseEstTooHighCtr[i] >= kNoiseEstIncCount) { - aecm->noiseEst[i]--; - aecm->noiseEstTooHighCtr[i] = 0; // Reset the counter - } - } else { - aecm->noiseEst[i] -= - ((aecm->noiseEst[i] - outLShift32) >> minTrackShift); - } - } else { - // Reset "too high" counter - aecm->noiseEstTooHighCtr[i] = 0; - // Ramp slowly upwards until we hit the minimum again. - if ((aecm->noiseEst[i] >> 19) > 0) { - // Avoid overflow. - // Multiplication with 2049 will cause wrap around. Scale - // down first and then multiply - aecm->noiseEst[i] >>= 11; - aecm->noiseEst[i] *= 2049; - } else if ((aecm->noiseEst[i] >> 11) > 0) { - // Large enough for relative increase - aecm->noiseEst[i] *= 2049; - aecm->noiseEst[i] >>= 11; - } else { - // Make incremental increases based on size every - // |kNoiseEstIncCount| block - aecm->noiseEstTooLowCtr[i]++; - if (aecm->noiseEstTooLowCtr[i] >= kNoiseEstIncCount) { - aecm->noiseEst[i] += (aecm->noiseEst[i] >> 9) + 1; - aecm->noiseEstTooLowCtr[i] = 0; // Reset counter - } - } - } - } - - for (i = 0; i < PART_LEN1; i++) { - tmp32 = aecm->noiseEst[i] >> shiftFromNearToNoise; - if (tmp32 > 32767) { - tmp32 = 32767; - aecm->noiseEst[i] = tmp32 << shiftFromNearToNoise; - } - noiseRShift16[i] = (int16_t)tmp32; - - tmp16 = ONE_Q14 - lambda[i]; - noiseRShift16[i] = (int16_t)((tmp16 * noiseRShift16[i]) >> 14); - } - - // Generate a uniform random array on [0 2^15-1]. - WebRtcSpl_RandUArray(randW16, PART_LEN, &aecm->seed); - - // Generate noise according to estimated energy. - uReal[0] = 0; // Reject LF noise. - uImag[0] = 0; - for (i = 1; i < PART_LEN1; i++) { - // Get a random index for the cos and sin tables over [0 359]. - tmp16 = (int16_t)((359 * randW16[i - 1]) >> 15); - - // Tables are in Q13. - uReal[i] = - (int16_t)((noiseRShift16[i] * WebRtcAecm_kCosTable[tmp16]) >> 13); - uImag[i] = - (int16_t)((-noiseRShift16[i] * WebRtcAecm_kSinTable[tmp16]) >> 13); - } - uImag[PART_LEN] = 0; - - for (i = 0; i < PART_LEN1; i++) { - out[i].real = WebRtcSpl_AddSatW16(out[i].real, uReal[i]); - out[i].imag = WebRtcSpl_AddSatW16(out[i].imag, uImag[i]); - } -} +} // namespace webrtc diff --git a/modules/audio_processing/aecm/aecm_core_mips.cc b/modules/audio_processing/aecm/aecm_core_mips.cc index 75aee91ab6..f2f43e1146 100644 --- a/modules/audio_processing/aecm/aecm_core_mips.cc +++ b/modules/audio_processing/aecm/aecm_core_mips.cc @@ -14,6 +14,10 @@ #include "rtc_base/checks.h" #include "rtc_base/numerics/safe_conversions.h" +namespace webrtc { + +namespace { + static const ALIGN8_BEG int16_t WebRtcAecm_kSqrtHanning[] ALIGN8_END = { 0, 399, 798, 1196, 1594, 1990, 2386, 2780, 3172, 3562, 3951, 4337, 4720, 5101, 5478, 5853, 6224, 6591, 6954, 7313, 7668, 8019, @@ -47,6 +51,8 @@ static int16_t coefTable_ifft[] = { 100, 344, 420, 216, 164, 472, 292, 56, 36, 312, 452, 184, 196, 440, 324, 120, 68, 376, 388, 248, 132, 504, 260}; +} // namespace + static void ComfortNoise(AecmCore* aecm, const uint16_t* dfa, ComplexInt16* out, @@ -1646,3 +1652,5 @@ static void ComfortNoise(AecmCore* aecm, sgn = ((int)tt) >> 31; out[PART_LEN].imag = sgn == (int16_t)(tt >> 15) ? (int16_t)tt : (16384 ^ sgn); } + +} // namespace webrtc diff --git a/modules/audio_processing/aecm/aecm_core_neon.cc b/modules/audio_processing/aecm/aecm_core_neon.cc index 94a318b305..584110d3af 100644 --- a/modules/audio_processing/aecm/aecm_core_neon.cc +++ b/modules/audio_processing/aecm/aecm_core_neon.cc @@ -14,6 +14,10 @@ #include "modules/audio_processing/aecm/aecm_core.h" #include "rtc_base/checks.h" +namespace webrtc { + +namespace { + // TODO(kma): Re-write the corresponding assembly file, the offset // generating script and makefile, to replace these C functions. @@ -28,6 +32,8 @@ static inline void AddLanes(uint32_t* ptr, uint32x4_t v) { #endif } +} // namespace + void WebRtcAecm_CalcLinearEnergiesNeon(AecmCore* aecm, const uint16_t* far_spectrum, int32_t* echo_est, @@ -196,3 +202,5 @@ void WebRtcAecm_ResetAdaptiveChannelNeon(AecmCore* aecm) { aecm->channelAdapt16[PART_LEN] = aecm->channelStored[PART_LEN]; aecm->channelAdapt32[PART_LEN] = (int32_t)aecm->channelStored[PART_LEN] << 16; } + +} // namespace webrtc diff --git a/modules/audio_processing/aecm/echo_control_mobile.cc b/modules/audio_processing/aecm/echo_control_mobile.cc index f556a3067b..506c7930df 100644 --- a/modules/audio_processing/aecm/echo_control_mobile.cc +++ b/modules/audio_processing/aecm/echo_control_mobile.cc @@ -23,6 +23,10 @@ extern "C" { } #include "modules/audio_processing/aecm/aecm_core.h" +namespace webrtc { + +namespace { + #define BUF_SIZE_FRAMES 50 // buffer size (frames) // Maximum length of resampled signal. Must be an integer multiple of frames // (ceil(1/(1 + MIN_SKEW)*2) + 1)*FRAME_LEN @@ -75,6 +79,8 @@ typedef struct { AecmCore* aecmCore; } AecMobile; +} // namespace + // Estimates delay to set the position of the farend buffer read pointer // (controlled by knownDelay) static int WebRtcAecm_EstBufDelay(AecMobile* aecm, short msInSndCardBuf); @@ -590,3 +596,5 @@ static int WebRtcAecm_DelayComp(AecMobile* aecm) { return 0; } + +} // namespace webrtc diff --git a/modules/audio_processing/aecm/echo_control_mobile.h b/modules/audio_processing/aecm/echo_control_mobile.h index cea13b8b5e..ee780524de 100644 --- a/modules/audio_processing/aecm/echo_control_mobile.h +++ b/modules/audio_processing/aecm/echo_control_mobile.h @@ -14,6 +14,8 @@ #include #include +namespace webrtc { + enum { AecmFalse = 0, AecmTrue }; // Errors @@ -201,4 +203,7 @@ size_t WebRtcAecm_echo_path_size_bytes(); #ifdef __cplusplus } #endif + +} // namespace webrtc + #endif // MODULES_AUDIO_PROCESSING_AECM_ECHO_CONTROL_MOBILE_H_