1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "modules/audio_processing/aecm/aecm_core.h"
12
13 #include <stddef.h>
14 #include <stdlib.h>
15 #include <string.h>
16
17 extern "C" {
18 #include "common_audio/ring_buffer.h"
19 #include "common_audio/signal_processing/include/real_fft.h"
20 }
21 #include "common_audio/signal_processing/include/signal_processing_library.h"
22 #include "modules/audio_processing/aecm/echo_control_mobile.h"
23 #include "modules/audio_processing/utility/delay_estimator_wrapper.h"
24 #include "rtc_base/checks.h"
25 #include "rtc_base/numerics/safe_conversions.h"
26
27 namespace webrtc {
28
29 namespace {
30
31 #ifdef AEC_DEBUG
32 FILE* dfile;
33 FILE* testfile;
34 #endif
35
36 // Initialization table for echo channel in 8 kHz
37 static const int16_t kChannelStored8kHz[PART_LEN1] = {
38 2040, 1815, 1590, 1498, 1405, 1395, 1385, 1418, 1451, 1506, 1562,
39 1644, 1726, 1804, 1882, 1918, 1953, 1982, 2010, 2025, 2040, 2034,
40 2027, 2021, 2014, 1997, 1980, 1925, 1869, 1800, 1732, 1683, 1635,
41 1604, 1572, 1545, 1517, 1481, 1444, 1405, 1367, 1331, 1294, 1270,
42 1245, 1239, 1233, 1247, 1260, 1282, 1303, 1338, 1373, 1407, 1441,
43 1470, 1499, 1524, 1549, 1565, 1582, 1601, 1621, 1649, 1676};
44
45 // Initialization table for echo channel in 16 kHz
46 static const int16_t kChannelStored16kHz[PART_LEN1] = {
47 2040, 1590, 1405, 1385, 1451, 1562, 1726, 1882, 1953, 2010, 2040,
48 2027, 2014, 1980, 1869, 1732, 1635, 1572, 1517, 1444, 1367, 1294,
49 1245, 1233, 1260, 1303, 1373, 1441, 1499, 1549, 1582, 1621, 1676,
50 1741, 1802, 1861, 1921, 1983, 2040, 2102, 2170, 2265, 2375, 2515,
51 2651, 2781, 2922, 3075, 3253, 3471, 3738, 3976, 4151, 4258, 4308,
52 4288, 4270, 4253, 4237, 4179, 4086, 3947, 3757, 3484, 3153};
53
54 } // namespace
55
56 const int16_t WebRtcAecm_kCosTable[] = {
57 8192, 8190, 8187, 8180, 8172, 8160, 8147, 8130, 8112, 8091, 8067,
58 8041, 8012, 7982, 7948, 7912, 7874, 7834, 7791, 7745, 7697, 7647,
59 7595, 7540, 7483, 7424, 7362, 7299, 7233, 7164, 7094, 7021, 6947,
60 6870, 6791, 6710, 6627, 6542, 6455, 6366, 6275, 6182, 6087, 5991,
61 5892, 5792, 5690, 5586, 5481, 5374, 5265, 5155, 5043, 4930, 4815,
62 4698, 4580, 4461, 4341, 4219, 4096, 3971, 3845, 3719, 3591, 3462,
63 3331, 3200, 3068, 2935, 2801, 2667, 2531, 2395, 2258, 2120, 1981,
64 1842, 1703, 1563, 1422, 1281, 1140, 998, 856, 713, 571, 428,
65 285, 142, 0, -142, -285, -428, -571, -713, -856, -998, -1140,
66 -1281, -1422, -1563, -1703, -1842, -1981, -2120, -2258, -2395, -2531, -2667,
67 -2801, -2935, -3068, -3200, -3331, -3462, -3591, -3719, -3845, -3971, -4095,
68 -4219, -4341, -4461, -4580, -4698, -4815, -4930, -5043, -5155, -5265, -5374,
69 -5481, -5586, -5690, -5792, -5892, -5991, -6087, -6182, -6275, -6366, -6455,
70 -6542, -6627, -6710, -6791, -6870, -6947, -7021, -7094, -7164, -7233, -7299,
71 -7362, -7424, -7483, -7540, -7595, -7647, -7697, -7745, -7791, -7834, -7874,
72 -7912, -7948, -7982, -8012, -8041, -8067, -8091, -8112, -8130, -8147, -8160,
73 -8172, -8180, -8187, -8190, -8191, -8190, -8187, -8180, -8172, -8160, -8147,
74 -8130, -8112, -8091, -8067, -8041, -8012, -7982, -7948, -7912, -7874, -7834,
75 -7791, -7745, -7697, -7647, -7595, -7540, -7483, -7424, -7362, -7299, -7233,
76 -7164, -7094, -7021, -6947, -6870, -6791, -6710, -6627, -6542, -6455, -6366,
77 -6275, -6182, -6087, -5991, -5892, -5792, -5690, -5586, -5481, -5374, -5265,
78 -5155, -5043, -4930, -4815, -4698, -4580, -4461, -4341, -4219, -4096, -3971,
79 -3845, -3719, -3591, -3462, -3331, -3200, -3068, -2935, -2801, -2667, -2531,
80 -2395, -2258, -2120, -1981, -1842, -1703, -1563, -1422, -1281, -1140, -998,
81 -856, -713, -571, -428, -285, -142, 0, 142, 285, 428, 571,
82 713, 856, 998, 1140, 1281, 1422, 1563, 1703, 1842, 1981, 2120,
83 2258, 2395, 2531, 2667, 2801, 2935, 3068, 3200, 3331, 3462, 3591,
84 3719, 3845, 3971, 4095, 4219, 4341, 4461, 4580, 4698, 4815, 4930,
85 5043, 5155, 5265, 5374, 5481, 5586, 5690, 5792, 5892, 5991, 6087,
86 6182, 6275, 6366, 6455, 6542, 6627, 6710, 6791, 6870, 6947, 7021,
87 7094, 7164, 7233, 7299, 7362, 7424, 7483, 7540, 7595, 7647, 7697,
88 7745, 7791, 7834, 7874, 7912, 7948, 7982, 8012, 8041, 8067, 8091,
89 8112, 8130, 8147, 8160, 8172, 8180, 8187, 8190};
90
91 const int16_t WebRtcAecm_kSinTable[] = {
92 0, 142, 285, 428, 571, 713, 856, 998, 1140, 1281, 1422,
93 1563, 1703, 1842, 1981, 2120, 2258, 2395, 2531, 2667, 2801, 2935,
94 3068, 3200, 3331, 3462, 3591, 3719, 3845, 3971, 4095, 4219, 4341,
95 4461, 4580, 4698, 4815, 4930, 5043, 5155, 5265, 5374, 5481, 5586,
96 5690, 5792, 5892, 5991, 6087, 6182, 6275, 6366, 6455, 6542, 6627,
97 6710, 6791, 6870, 6947, 7021, 7094, 7164, 7233, 7299, 7362, 7424,
98 7483, 7540, 7595, 7647, 7697, 7745, 7791, 7834, 7874, 7912, 7948,
99 7982, 8012, 8041, 8067, 8091, 8112, 8130, 8147, 8160, 8172, 8180,
100 8187, 8190, 8191, 8190, 8187, 8180, 8172, 8160, 8147, 8130, 8112,
101 8091, 8067, 8041, 8012, 7982, 7948, 7912, 7874, 7834, 7791, 7745,
102 7697, 7647, 7595, 7540, 7483, 7424, 7362, 7299, 7233, 7164, 7094,
103 7021, 6947, 6870, 6791, 6710, 6627, 6542, 6455, 6366, 6275, 6182,
104 6087, 5991, 5892, 5792, 5690, 5586, 5481, 5374, 5265, 5155, 5043,
105 4930, 4815, 4698, 4580, 4461, 4341, 4219, 4096, 3971, 3845, 3719,
106 3591, 3462, 3331, 3200, 3068, 2935, 2801, 2667, 2531, 2395, 2258,
107 2120, 1981, 1842, 1703, 1563, 1422, 1281, 1140, 998, 856, 713,
108 571, 428, 285, 142, 0, -142, -285, -428, -571, -713, -856,
109 -998, -1140, -1281, -1422, -1563, -1703, -1842, -1981, -2120, -2258, -2395,
110 -2531, -2667, -2801, -2935, -3068, -3200, -3331, -3462, -3591, -3719, -3845,
111 -3971, -4095, -4219, -4341, -4461, -4580, -4698, -4815, -4930, -5043, -5155,
112 -5265, -5374, -5481, -5586, -5690, -5792, -5892, -5991, -6087, -6182, -6275,
113 -6366, -6455, -6542, -6627, -6710, -6791, -6870, -6947, -7021, -7094, -7164,
114 -7233, -7299, -7362, -7424, -7483, -7540, -7595, -7647, -7697, -7745, -7791,
115 -7834, -7874, -7912, -7948, -7982, -8012, -8041, -8067, -8091, -8112, -8130,
116 -8147, -8160, -8172, -8180, -8187, -8190, -8191, -8190, -8187, -8180, -8172,
117 -8160, -8147, -8130, -8112, -8091, -8067, -8041, -8012, -7982, -7948, -7912,
118 -7874, -7834, -7791, -7745, -7697, -7647, -7595, -7540, -7483, -7424, -7362,
119 -7299, -7233, -7164, -7094, -7021, -6947, -6870, -6791, -6710, -6627, -6542,
120 -6455, -6366, -6275, -6182, -6087, -5991, -5892, -5792, -5690, -5586, -5481,
121 -5374, -5265, -5155, -5043, -4930, -4815, -4698, -4580, -4461, -4341, -4219,
122 -4096, -3971, -3845, -3719, -3591, -3462, -3331, -3200, -3068, -2935, -2801,
123 -2667, -2531, -2395, -2258, -2120, -1981, -1842, -1703, -1563, -1422, -1281,
124 -1140, -998, -856, -713, -571, -428, -285, -142};
125
126
127 // Moves the pointer to the next entry and inserts `far_spectrum` and
128 // corresponding Q-domain in its buffer.
129 //
130 // Inputs:
131 // - self : Pointer to the delay estimation instance
132 // - far_spectrum : Pointer to the far end spectrum
133 // - far_q : Q-domain of far end spectrum
134 //
WebRtcAecm_UpdateFarHistory(AecmCore * self,uint16_t * far_spectrum,int far_q)135 void WebRtcAecm_UpdateFarHistory(AecmCore* self,
136 uint16_t* far_spectrum,
137 int far_q) {
138 // Get new buffer position
139 self->far_history_pos++;
140 if (self->far_history_pos >= MAX_DELAY) {
141 self->far_history_pos = 0;
142 }
143 // Update Q-domain buffer
144 self->far_q_domains[self->far_history_pos] = far_q;
145 // Update far end spectrum buffer
146 memcpy(&(self->far_history[self->far_history_pos * PART_LEN1]), far_spectrum,
147 sizeof(uint16_t) * PART_LEN1);
148 }
149
150 // Returns a pointer to the far end spectrum aligned to current near end
151 // spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been
152 // called before AlignedFarend(...). Otherwise, you get the pointer to the
153 // previous frame. The memory is only valid until the next call of
154 // WebRtc_DelayEstimatorProcessFix(...).
155 //
156 // Inputs:
157 // - self : Pointer to the AECM instance.
158 // - delay : Current delay estimate.
159 //
160 // Output:
161 // - far_q : The Q-domain of the aligned far end spectrum
162 //
163 // Return value:
164 // - far_spectrum : Pointer to the aligned far end spectrum
165 // NULL - Error
166 //
WebRtcAecm_AlignedFarend(AecmCore * self,int * far_q,int delay)167 const uint16_t* WebRtcAecm_AlignedFarend(AecmCore* self,
168 int* far_q,
169 int delay) {
170 int buffer_position = 0;
171 RTC_DCHECK(self);
172 buffer_position = self->far_history_pos - delay;
173
174 // Check buffer position
175 if (buffer_position < 0) {
176 buffer_position += MAX_DELAY;
177 }
178 // Get Q-domain
179 *far_q = self->far_q_domains[buffer_position];
180 // Return far end spectrum
181 return &(self->far_history[buffer_position * PART_LEN1]);
182 }
183
184 // Declare function pointers.
185 CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
186 StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
187 ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
188
WebRtcAecm_CreateCore()189 AecmCore* WebRtcAecm_CreateCore() {
190 // Allocate zero-filled memory.
191 AecmCore* aecm = static_cast<AecmCore*>(calloc(1, sizeof(AecmCore)));
192
193 aecm->farFrameBuf =
194 WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(int16_t));
195 if (!aecm->farFrameBuf) {
196 WebRtcAecm_FreeCore(aecm);
197 return NULL;
198 }
199
200 aecm->nearNoisyFrameBuf =
201 WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(int16_t));
202 if (!aecm->nearNoisyFrameBuf) {
203 WebRtcAecm_FreeCore(aecm);
204 return NULL;
205 }
206
207 aecm->nearCleanFrameBuf =
208 WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(int16_t));
209 if (!aecm->nearCleanFrameBuf) {
210 WebRtcAecm_FreeCore(aecm);
211 return NULL;
212 }
213
214 aecm->outFrameBuf =
215 WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(int16_t));
216 if (!aecm->outFrameBuf) {
217 WebRtcAecm_FreeCore(aecm);
218 return NULL;
219 }
220
221 aecm->delay_estimator_farend =
222 WebRtc_CreateDelayEstimatorFarend(PART_LEN1, MAX_DELAY);
223 if (aecm->delay_estimator_farend == NULL) {
224 WebRtcAecm_FreeCore(aecm);
225 return NULL;
226 }
227 aecm->delay_estimator =
228 WebRtc_CreateDelayEstimator(aecm->delay_estimator_farend, 0);
229 if (aecm->delay_estimator == NULL) {
230 WebRtcAecm_FreeCore(aecm);
231 return NULL;
232 }
233 // TODO(bjornv): Explicitly disable robust delay validation until no
234 // performance regression has been established. Then remove the line.
235 WebRtc_enable_robust_validation(aecm->delay_estimator, 0);
236
237 aecm->real_fft = WebRtcSpl_CreateRealFFT(PART_LEN_SHIFT);
238 if (aecm->real_fft == NULL) {
239 WebRtcAecm_FreeCore(aecm);
240 return NULL;
241 }
242
243 // Init some aecm pointers. 16 and 32 byte alignment is only necessary
244 // for Neon code currently.
245 aecm->xBuf = (int16_t*)(((uintptr_t)aecm->xBuf_buf + 31) & ~31);
246 aecm->dBufClean = (int16_t*)(((uintptr_t)aecm->dBufClean_buf + 31) & ~31);
247 aecm->dBufNoisy = (int16_t*)(((uintptr_t)aecm->dBufNoisy_buf + 31) & ~31);
248 aecm->outBuf = (int16_t*)(((uintptr_t)aecm->outBuf_buf + 15) & ~15);
249 aecm->channelStored =
250 (int16_t*)(((uintptr_t)aecm->channelStored_buf + 15) & ~15);
251 aecm->channelAdapt16 =
252 (int16_t*)(((uintptr_t)aecm->channelAdapt16_buf + 15) & ~15);
253 aecm->channelAdapt32 =
254 (int32_t*)(((uintptr_t)aecm->channelAdapt32_buf + 31) & ~31);
255
256 return aecm;
257 }
258
WebRtcAecm_InitEchoPathCore(AecmCore * aecm,const int16_t * echo_path)259 void WebRtcAecm_InitEchoPathCore(AecmCore* aecm, const int16_t* echo_path) {
260 int i = 0;
261
262 // Reset the stored channel
263 memcpy(aecm->channelStored, echo_path, sizeof(int16_t) * PART_LEN1);
264 // Reset the adapted channels
265 memcpy(aecm->channelAdapt16, echo_path, sizeof(int16_t) * PART_LEN1);
266 for (i = 0; i < PART_LEN1; i++) {
267 aecm->channelAdapt32[i] = (int32_t)aecm->channelAdapt16[i] << 16;
268 }
269
270 // Reset channel storing variables
271 aecm->mseAdaptOld = 1000;
272 aecm->mseStoredOld = 1000;
273 aecm->mseThreshold = WEBRTC_SPL_WORD32_MAX;
274 aecm->mseChannelCount = 0;
275 }
276
CalcLinearEnergiesC(AecmCore * aecm,const uint16_t * far_spectrum,int32_t * echo_est,uint32_t * far_energy,uint32_t * echo_energy_adapt,uint32_t * echo_energy_stored)277 static void CalcLinearEnergiesC(AecmCore* aecm,
278 const uint16_t* far_spectrum,
279 int32_t* echo_est,
280 uint32_t* far_energy,
281 uint32_t* echo_energy_adapt,
282 uint32_t* echo_energy_stored) {
283 int i;
284
285 // Get energy for the delayed far end signal and estimated
286 // echo using both stored and adapted channels.
287 for (i = 0; i < PART_LEN1; i++) {
288 echo_est[i] =
289 WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i], far_spectrum[i]);
290 (*far_energy) += (uint32_t)(far_spectrum[i]);
291 *echo_energy_adapt += aecm->channelAdapt16[i] * far_spectrum[i];
292 (*echo_energy_stored) += (uint32_t)echo_est[i];
293 }
294 }
295
StoreAdaptiveChannelC(AecmCore * aecm,const uint16_t * far_spectrum,int32_t * echo_est)296 static void StoreAdaptiveChannelC(AecmCore* aecm,
297 const uint16_t* far_spectrum,
298 int32_t* echo_est) {
299 int i;
300
301 // During startup we store the channel every block.
302 memcpy(aecm->channelStored, aecm->channelAdapt16,
303 sizeof(int16_t) * PART_LEN1);
304 // Recalculate echo estimate
305 for (i = 0; i < PART_LEN; i += 4) {
306 echo_est[i] =
307 WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i], far_spectrum[i]);
308 echo_est[i + 1] =
309 WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 1], far_spectrum[i + 1]);
310 echo_est[i + 2] =
311 WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 2], far_spectrum[i + 2]);
312 echo_est[i + 3] =
313 WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i + 3], far_spectrum[i + 3]);
314 }
315 echo_est[i] = WEBRTC_SPL_MUL_16_U16(aecm->channelStored[i], far_spectrum[i]);
316 }
317
ResetAdaptiveChannelC(AecmCore * aecm)318 static void ResetAdaptiveChannelC(AecmCore* aecm) {
319 int i;
320
321 // The stored channel has a significantly lower MSE than the adaptive one for
322 // two consecutive calculations. Reset the adaptive channel.
323 memcpy(aecm->channelAdapt16, aecm->channelStored,
324 sizeof(int16_t) * PART_LEN1);
325 // Restore the W32 channel
326 for (i = 0; i < PART_LEN; i += 4) {
327 aecm->channelAdapt32[i] = (int32_t)aecm->channelStored[i] << 16;
328 aecm->channelAdapt32[i + 1] = (int32_t)aecm->channelStored[i + 1] << 16;
329 aecm->channelAdapt32[i + 2] = (int32_t)aecm->channelStored[i + 2] << 16;
330 aecm->channelAdapt32[i + 3] = (int32_t)aecm->channelStored[i + 3] << 16;
331 }
332 aecm->channelAdapt32[i] = (int32_t)aecm->channelStored[i] << 16;
333 }
334
335 // Initialize function pointers for ARM Neon platform.
336 #if defined(WEBRTC_HAS_NEON)
WebRtcAecm_InitNeon(void)337 static void WebRtcAecm_InitNeon(void) {
338 WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannelNeon;
339 WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannelNeon;
340 WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergiesNeon;
341 }
342 #endif
343
344 // Initialize function pointers for MIPS platform.
345 #if defined(MIPS32_LE)
WebRtcAecm_InitMips(void)346 static void WebRtcAecm_InitMips(void) {
347 #if defined(MIPS_DSP_R1_LE)
348 WebRtcAecm_StoreAdaptiveChannel = WebRtcAecm_StoreAdaptiveChannel_mips;
349 WebRtcAecm_ResetAdaptiveChannel = WebRtcAecm_ResetAdaptiveChannel_mips;
350 #endif
351 WebRtcAecm_CalcLinearEnergies = WebRtcAecm_CalcLinearEnergies_mips;
352 }
353 #endif
354
355 // WebRtcAecm_InitCore(...)
356 //
357 // This function initializes the AECM instant created with
358 // WebRtcAecm_CreateCore(...) Input:
359 // - aecm : Pointer to the Echo Suppression instance
360 // - samplingFreq : Sampling Frequency
361 //
362 // Output:
363 // - aecm : Initialized instance
364 //
365 // Return value : 0 - Ok
366 // -1 - Error
367 //
WebRtcAecm_InitCore(AecmCore * const aecm,int samplingFreq)368 int WebRtcAecm_InitCore(AecmCore* const aecm, int samplingFreq) {
369 int i = 0;
370 int32_t tmp32 = PART_LEN1 * PART_LEN1;
371 int16_t tmp16 = PART_LEN1;
372
373 if (samplingFreq != 8000 && samplingFreq != 16000) {
374 samplingFreq = 8000;
375 return -1;
376 }
377 // sanity check of sampling frequency
378 aecm->mult = (int16_t)samplingFreq / 8000;
379
380 aecm->farBufWritePos = 0;
381 aecm->farBufReadPos = 0;
382 aecm->knownDelay = 0;
383 aecm->lastKnownDelay = 0;
384
385 WebRtc_InitBuffer(aecm->farFrameBuf);
386 WebRtc_InitBuffer(aecm->nearNoisyFrameBuf);
387 WebRtc_InitBuffer(aecm->nearCleanFrameBuf);
388 WebRtc_InitBuffer(aecm->outFrameBuf);
389
390 memset(aecm->xBuf_buf, 0, sizeof(aecm->xBuf_buf));
391 memset(aecm->dBufClean_buf, 0, sizeof(aecm->dBufClean_buf));
392 memset(aecm->dBufNoisy_buf, 0, sizeof(aecm->dBufNoisy_buf));
393 memset(aecm->outBuf_buf, 0, sizeof(aecm->outBuf_buf));
394
395 aecm->seed = 666;
396 aecm->totCount = 0;
397
398 if (WebRtc_InitDelayEstimatorFarend(aecm->delay_estimator_farend) != 0) {
399 return -1;
400 }
401 if (WebRtc_InitDelayEstimator(aecm->delay_estimator) != 0) {
402 return -1;
403 }
404 // Set far end histories to zero
405 memset(aecm->far_history, 0, sizeof(uint16_t) * PART_LEN1 * MAX_DELAY);
406 memset(aecm->far_q_domains, 0, sizeof(int) * MAX_DELAY);
407 aecm->far_history_pos = MAX_DELAY;
408
409 aecm->nlpFlag = 1;
410 aecm->fixedDelay = -1;
411
412 aecm->dfaCleanQDomain = 0;
413 aecm->dfaCleanQDomainOld = 0;
414 aecm->dfaNoisyQDomain = 0;
415 aecm->dfaNoisyQDomainOld = 0;
416
417 memset(aecm->nearLogEnergy, 0, sizeof(aecm->nearLogEnergy));
418 aecm->farLogEnergy = 0;
419 memset(aecm->echoAdaptLogEnergy, 0, sizeof(aecm->echoAdaptLogEnergy));
420 memset(aecm->echoStoredLogEnergy, 0, sizeof(aecm->echoStoredLogEnergy));
421
422 // Initialize the echo channels with a stored shape.
423 if (samplingFreq == 8000) {
424 WebRtcAecm_InitEchoPathCore(aecm, kChannelStored8kHz);
425 } else {
426 WebRtcAecm_InitEchoPathCore(aecm, kChannelStored16kHz);
427 }
428
429 memset(aecm->echoFilt, 0, sizeof(aecm->echoFilt));
430 memset(aecm->nearFilt, 0, sizeof(aecm->nearFilt));
431 aecm->noiseEstCtr = 0;
432
433 aecm->cngMode = AecmTrue;
434
435 memset(aecm->noiseEstTooLowCtr, 0, sizeof(aecm->noiseEstTooLowCtr));
436 memset(aecm->noiseEstTooHighCtr, 0, sizeof(aecm->noiseEstTooHighCtr));
437 // Shape the initial noise level to an approximate pink noise.
438 for (i = 0; i < (PART_LEN1 >> 1) - 1; i++) {
439 aecm->noiseEst[i] = (tmp32 << 8);
440 tmp16--;
441 tmp32 -= (int32_t)((tmp16 << 1) + 1);
442 }
443 for (; i < PART_LEN1; i++) {
444 aecm->noiseEst[i] = (tmp32 << 8);
445 }
446
447 aecm->farEnergyMin = WEBRTC_SPL_WORD16_MAX;
448 aecm->farEnergyMax = WEBRTC_SPL_WORD16_MIN;
449 aecm->farEnergyMaxMin = 0;
450 aecm->farEnergyVAD = FAR_ENERGY_MIN; // This prevents false speech detection
451 // at the beginning.
452 aecm->farEnergyMSE = 0;
453 aecm->currentVADValue = 0;
454 aecm->vadUpdateCount = 0;
455 aecm->firstVAD = 1;
456
457 aecm->startupState = 0;
458 aecm->supGain = SUPGAIN_DEFAULT;
459 aecm->supGainOld = SUPGAIN_DEFAULT;
460
461 aecm->supGainErrParamA = SUPGAIN_ERROR_PARAM_A;
462 aecm->supGainErrParamD = SUPGAIN_ERROR_PARAM_D;
463 aecm->supGainErrParamDiffAB = SUPGAIN_ERROR_PARAM_A - SUPGAIN_ERROR_PARAM_B;
464 aecm->supGainErrParamDiffBD = SUPGAIN_ERROR_PARAM_B - SUPGAIN_ERROR_PARAM_D;
465
466 // Assert a preprocessor definition at compile-time. It's an assumption
467 // used in assembly code, so check the assembly files before any change.
468 static_assert(PART_LEN % 16 == 0, "PART_LEN is not a multiple of 16");
469
470 // Initialize function pointers.
471 WebRtcAecm_CalcLinearEnergies = CalcLinearEnergiesC;
472 WebRtcAecm_StoreAdaptiveChannel = StoreAdaptiveChannelC;
473 WebRtcAecm_ResetAdaptiveChannel = ResetAdaptiveChannelC;
474
475 #if defined(WEBRTC_HAS_NEON)
476 WebRtcAecm_InitNeon();
477 #endif
478
479 #if defined(MIPS32_LE)
480 WebRtcAecm_InitMips();
481 #endif
482 return 0;
483 }
484
485 // TODO(bjornv): This function is currently not used. Add support for these
486 // parameters from a higher level
WebRtcAecm_Control(AecmCore * aecm,int delay,int nlpFlag)487 int WebRtcAecm_Control(AecmCore* aecm, int delay, int nlpFlag) {
488 aecm->nlpFlag = nlpFlag;
489 aecm->fixedDelay = delay;
490
491 return 0;
492 }
493
WebRtcAecm_FreeCore(AecmCore * aecm)494 void WebRtcAecm_FreeCore(AecmCore* aecm) {
495 if (aecm == NULL) {
496 return;
497 }
498
499 WebRtc_FreeBuffer(aecm->farFrameBuf);
500 WebRtc_FreeBuffer(aecm->nearNoisyFrameBuf);
501 WebRtc_FreeBuffer(aecm->nearCleanFrameBuf);
502 WebRtc_FreeBuffer(aecm->outFrameBuf);
503
504 WebRtc_FreeDelayEstimator(aecm->delay_estimator);
505 WebRtc_FreeDelayEstimatorFarend(aecm->delay_estimator_farend);
506 WebRtcSpl_FreeRealFFT(aecm->real_fft);
507
508 free(aecm);
509 }
510
WebRtcAecm_ProcessFrame(AecmCore * aecm,const int16_t * farend,const int16_t * nearendNoisy,const int16_t * nearendClean,int16_t * out)511 int WebRtcAecm_ProcessFrame(AecmCore* aecm,
512 const int16_t* farend,
513 const int16_t* nearendNoisy,
514 const int16_t* nearendClean,
515 int16_t* out) {
516 int16_t outBlock_buf[PART_LEN + 8]; // Align buffer to 8-byte boundary.
517 int16_t* outBlock = (int16_t*)(((uintptr_t)outBlock_buf + 15) & ~15);
518
519 int16_t farFrame[FRAME_LEN];
520 const int16_t* out_ptr = NULL;
521 int size = 0;
522
523 // Buffer the current frame.
524 // Fetch an older one corresponding to the delay.
525 WebRtcAecm_BufferFarFrame(aecm, farend, FRAME_LEN);
526 WebRtcAecm_FetchFarFrame(aecm, farFrame, FRAME_LEN, aecm->knownDelay);
527
528 // Buffer the synchronized far and near frames,
529 // to pass the smaller blocks individually.
530 WebRtc_WriteBuffer(aecm->farFrameBuf, farFrame, FRAME_LEN);
531 WebRtc_WriteBuffer(aecm->nearNoisyFrameBuf, nearendNoisy, FRAME_LEN);
532 if (nearendClean != NULL) {
533 WebRtc_WriteBuffer(aecm->nearCleanFrameBuf, nearendClean, FRAME_LEN);
534 }
535
536 // Process as many blocks as possible.
537 while (WebRtc_available_read(aecm->farFrameBuf) >= PART_LEN) {
538 int16_t far_block[PART_LEN];
539 const int16_t* far_block_ptr = NULL;
540 int16_t near_noisy_block[PART_LEN];
541 const int16_t* near_noisy_block_ptr = NULL;
542
543 WebRtc_ReadBuffer(aecm->farFrameBuf, (void**)&far_block_ptr, far_block,
544 PART_LEN);
545 WebRtc_ReadBuffer(aecm->nearNoisyFrameBuf, (void**)&near_noisy_block_ptr,
546 near_noisy_block, PART_LEN);
547 if (nearendClean != NULL) {
548 int16_t near_clean_block[PART_LEN];
549 const int16_t* near_clean_block_ptr = NULL;
550
551 WebRtc_ReadBuffer(aecm->nearCleanFrameBuf, (void**)&near_clean_block_ptr,
552 near_clean_block, PART_LEN);
553 if (WebRtcAecm_ProcessBlock(aecm, far_block_ptr, near_noisy_block_ptr,
554 near_clean_block_ptr, outBlock) == -1) {
555 return -1;
556 }
557 } else {
558 if (WebRtcAecm_ProcessBlock(aecm, far_block_ptr, near_noisy_block_ptr,
559 NULL, outBlock) == -1) {
560 return -1;
561 }
562 }
563
564 WebRtc_WriteBuffer(aecm->outFrameBuf, outBlock, PART_LEN);
565 }
566
567 // Stuff the out buffer if we have less than a frame to output.
568 // This should only happen for the first frame.
569 size = (int)WebRtc_available_read(aecm->outFrameBuf);
570 if (size < FRAME_LEN) {
571 WebRtc_MoveReadPtr(aecm->outFrameBuf, size - FRAME_LEN);
572 }
573
574 // Obtain an output frame.
575 WebRtc_ReadBuffer(aecm->outFrameBuf, (void**)&out_ptr, out, FRAME_LEN);
576 if (out_ptr != out) {
577 // ReadBuffer() hasn't copied to `out` in this case.
578 memcpy(out, out_ptr, FRAME_LEN * sizeof(int16_t));
579 }
580
581 return 0;
582 }
583
584 // WebRtcAecm_AsymFilt(...)
585 //
586 // Performs asymmetric filtering.
587 //
588 // Inputs:
589 // - filtOld : Previous filtered value.
590 // - inVal : New input value.
591 // - stepSizePos : Step size when we have a positive contribution.
592 // - stepSizeNeg : Step size when we have a negative contribution.
593 //
594 // Output:
595 //
596 // Return: - Filtered value.
597 //
WebRtcAecm_AsymFilt(const int16_t filtOld,const int16_t inVal,const int16_t stepSizePos,const int16_t stepSizeNeg)598 int16_t WebRtcAecm_AsymFilt(const int16_t filtOld,
599 const int16_t inVal,
600 const int16_t stepSizePos,
601 const int16_t stepSizeNeg) {
602 int16_t retVal;
603
604 if ((filtOld == WEBRTC_SPL_WORD16_MAX) | (filtOld == WEBRTC_SPL_WORD16_MIN)) {
605 return inVal;
606 }
607 retVal = filtOld;
608 if (filtOld > inVal) {
609 retVal -= (filtOld - inVal) >> stepSizeNeg;
610 } else {
611 retVal += (inVal - filtOld) >> stepSizePos;
612 }
613
614 return retVal;
615 }
616
617 // ExtractFractionPart(a, zeros)
618 //
619 // returns the fraction part of `a`, with `zeros` number of leading zeros, as an
620 // int16_t scaled to Q8. There is no sanity check of `a` in the sense that the
621 // number of zeros match.
ExtractFractionPart(uint32_t a,int zeros)622 static int16_t ExtractFractionPart(uint32_t a, int zeros) {
623 return (int16_t)(((a << zeros) & 0x7FFFFFFF) >> 23);
624 }
625
626 // Calculates and returns the log of `energy` in Q8. The input `energy` is
627 // supposed to be in Q(`q_domain`).
LogOfEnergyInQ8(uint32_t energy,int q_domain)628 static int16_t LogOfEnergyInQ8(uint32_t energy, int q_domain) {
629 static const int16_t kLogLowValue = PART_LEN_SHIFT << 7;
630 int16_t log_energy_q8 = kLogLowValue;
631 if (energy > 0) {
632 int zeros = WebRtcSpl_NormU32(energy);
633 int16_t frac = ExtractFractionPart(energy, zeros);
634 // log2 of `energy` in Q8.
635 log_energy_q8 += ((31 - zeros) << 8) + frac - (q_domain << 8);
636 }
637 return log_energy_q8;
638 }
639
640 // WebRtcAecm_CalcEnergies(...)
641 //
642 // This function calculates the log of energies for nearend, farend and
643 // estimated echoes. There is also an update of energy decision levels, i.e.
644 // internal VAD.
645 //
646 //
647 // @param aecm [i/o] Handle of the AECM instance.
648 // @param far_spectrum [in] Pointer to farend spectrum.
649 // @param far_q [in] Q-domain of farend spectrum.
650 // @param nearEner [in] Near end energy for current block in
651 // Q(aecm->dfaQDomain).
652 // @param echoEst [out] Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16).
653 //
WebRtcAecm_CalcEnergies(AecmCore * aecm,const uint16_t * far_spectrum,const int16_t far_q,const uint32_t nearEner,int32_t * echoEst)654 void WebRtcAecm_CalcEnergies(AecmCore* aecm,
655 const uint16_t* far_spectrum,
656 const int16_t far_q,
657 const uint32_t nearEner,
658 int32_t* echoEst) {
659 // Local variables
660 uint32_t tmpAdapt = 0;
661 uint32_t tmpStored = 0;
662 uint32_t tmpFar = 0;
663
664 int i;
665
666 int16_t tmp16;
667 int16_t increase_max_shifts = 4;
668 int16_t decrease_max_shifts = 11;
669 int16_t increase_min_shifts = 11;
670 int16_t decrease_min_shifts = 3;
671
672 // Get log of near end energy and store in buffer
673
674 // Shift buffer
675 memmove(aecm->nearLogEnergy + 1, aecm->nearLogEnergy,
676 sizeof(int16_t) * (MAX_BUF_LEN - 1));
677
678 // Logarithm of integrated magnitude spectrum (nearEner)
679 aecm->nearLogEnergy[0] = LogOfEnergyInQ8(nearEner, aecm->dfaNoisyQDomain);
680
681 WebRtcAecm_CalcLinearEnergies(aecm, far_spectrum, echoEst, &tmpFar, &tmpAdapt,
682 &tmpStored);
683
684 // Shift buffers
685 memmove(aecm->echoAdaptLogEnergy + 1, aecm->echoAdaptLogEnergy,
686 sizeof(int16_t) * (MAX_BUF_LEN - 1));
687 memmove(aecm->echoStoredLogEnergy + 1, aecm->echoStoredLogEnergy,
688 sizeof(int16_t) * (MAX_BUF_LEN - 1));
689
690 // Logarithm of delayed far end energy
691 aecm->farLogEnergy = LogOfEnergyInQ8(tmpFar, far_q);
692
693 // Logarithm of estimated echo energy through adapted channel
694 aecm->echoAdaptLogEnergy[0] =
695 LogOfEnergyInQ8(tmpAdapt, RESOLUTION_CHANNEL16 + far_q);
696
697 // Logarithm of estimated echo energy through stored channel
698 aecm->echoStoredLogEnergy[0] =
699 LogOfEnergyInQ8(tmpStored, RESOLUTION_CHANNEL16 + far_q);
700
701 // Update farend energy levels (min, max, vad, mse)
702 if (aecm->farLogEnergy > FAR_ENERGY_MIN) {
703 if (aecm->startupState == 0) {
704 increase_max_shifts = 2;
705 decrease_min_shifts = 2;
706 increase_min_shifts = 8;
707 }
708
709 aecm->farEnergyMin =
710 WebRtcAecm_AsymFilt(aecm->farEnergyMin, aecm->farLogEnergy,
711 increase_min_shifts, decrease_min_shifts);
712 aecm->farEnergyMax =
713 WebRtcAecm_AsymFilt(aecm->farEnergyMax, aecm->farLogEnergy,
714 increase_max_shifts, decrease_max_shifts);
715 aecm->farEnergyMaxMin = (aecm->farEnergyMax - aecm->farEnergyMin);
716
717 // Dynamic VAD region size
718 tmp16 = 2560 - aecm->farEnergyMin;
719 if (tmp16 > 0) {
720 tmp16 = (int16_t)((tmp16 * FAR_ENERGY_VAD_REGION) >> 9);
721 } else {
722 tmp16 = 0;
723 }
724 tmp16 += FAR_ENERGY_VAD_REGION;
725
726 if ((aecm->startupState == 0) | (aecm->vadUpdateCount > 1024)) {
727 // In startup phase or VAD update halted
728 aecm->farEnergyVAD = aecm->farEnergyMin + tmp16;
729 } else {
730 if (aecm->farEnergyVAD > aecm->farLogEnergy) {
731 aecm->farEnergyVAD +=
732 (aecm->farLogEnergy + tmp16 - aecm->farEnergyVAD) >> 6;
733 aecm->vadUpdateCount = 0;
734 } else {
735 aecm->vadUpdateCount++;
736 }
737 }
738 // Put MSE threshold higher than VAD
739 aecm->farEnergyMSE = aecm->farEnergyVAD + (1 << 8);
740 }
741
742 // Update VAD variables
743 if (aecm->farLogEnergy > aecm->farEnergyVAD) {
744 if ((aecm->startupState == 0) | (aecm->farEnergyMaxMin > FAR_ENERGY_DIFF)) {
745 // We are in startup or have significant dynamics in input speech level
746 aecm->currentVADValue = 1;
747 }
748 } else {
749 aecm->currentVADValue = 0;
750 }
751 if ((aecm->currentVADValue) && (aecm->firstVAD)) {
752 aecm->firstVAD = 0;
753 if (aecm->echoAdaptLogEnergy[0] > aecm->nearLogEnergy[0]) {
754 // The estimated echo has higher energy than the near end signal.
755 // This means that the initialization was too aggressive. Scale
756 // down by a factor 8
757 for (i = 0; i < PART_LEN1; i++) {
758 aecm->channelAdapt16[i] >>= 3;
759 }
760 // Compensate the adapted echo energy level accordingly.
761 aecm->echoAdaptLogEnergy[0] -= (3 << 8);
762 aecm->firstVAD = 1;
763 }
764 }
765 }
766
767 // WebRtcAecm_CalcStepSize(...)
768 //
769 // This function calculates the step size used in channel estimation
770 //
771 //
772 // @param aecm [in] Handle of the AECM instance.
773 // @param mu [out] (Return value) Stepsize in log2(), i.e. number of
774 // shifts.
775 //
776 //
WebRtcAecm_CalcStepSize(AecmCore * const aecm)777 int16_t WebRtcAecm_CalcStepSize(AecmCore* const aecm) {
778 int32_t tmp32;
779 int16_t tmp16;
780 int16_t mu = MU_MAX;
781
782 // Here we calculate the step size mu used in the
783 // following NLMS based Channel estimation algorithm
784 if (!aecm->currentVADValue) {
785 // Far end energy level too low, no channel update
786 mu = 0;
787 } else if (aecm->startupState > 0) {
788 if (aecm->farEnergyMin >= aecm->farEnergyMax) {
789 mu = MU_MIN;
790 } else {
791 tmp16 = (aecm->farLogEnergy - aecm->farEnergyMin);
792 tmp32 = tmp16 * MU_DIFF;
793 tmp32 = WebRtcSpl_DivW32W16(tmp32, aecm->farEnergyMaxMin);
794 mu = MU_MIN - 1 - (int16_t)(tmp32);
795 // The -1 is an alternative to rounding. This way we get a larger
796 // stepsize, so we in some sense compensate for truncation in NLMS
797 }
798 if (mu < MU_MAX) {
799 mu = MU_MAX; // Equivalent with maximum step size of 2^-MU_MAX
800 }
801 }
802
803 return mu;
804 }
805
806 // WebRtcAecm_UpdateChannel(...)
807 //
808 // This function performs channel estimation. NLMS and decision on channel
809 // storage.
810 //
811 //
812 // @param aecm [i/o] Handle of the AECM instance.
813 // @param far_spectrum [in] Absolute value of the farend signal in Q(far_q)
814 // @param far_q [in] Q-domain of the farend signal
815 // @param dfa [in] Absolute value of the nearend signal
816 // (Q[aecm->dfaQDomain])
817 // @param mu [in] NLMS step size.
818 // @param echoEst [i/o] Estimated echo in Q(far_q+RESOLUTION_CHANNEL16).
819 //
WebRtcAecm_UpdateChannel(AecmCore * aecm,const uint16_t * far_spectrum,const int16_t far_q,const uint16_t * const dfa,const int16_t mu,int32_t * echoEst)820 void WebRtcAecm_UpdateChannel(AecmCore* aecm,
821 const uint16_t* far_spectrum,
822 const int16_t far_q,
823 const uint16_t* const dfa,
824 const int16_t mu,
825 int32_t* echoEst) {
826 uint32_t tmpU32no1, tmpU32no2;
827 int32_t tmp32no1, tmp32no2;
828 int32_t mseStored;
829 int32_t mseAdapt;
830
831 int i;
832
833 int16_t zerosFar, zerosNum, zerosCh, zerosDfa;
834 int16_t shiftChFar, shiftNum, shift2ResChan;
835 int16_t tmp16no1;
836 int16_t xfaQ, dfaQ;
837
838 // This is the channel estimation algorithm. It is base on NLMS but has a
839 // variable step length, which was calculated above.
840 if (mu) {
841 for (i = 0; i < PART_LEN1; i++) {
842 // Determine norm of channel and farend to make sure we don't get overflow
843 // in multiplication
844 zerosCh = WebRtcSpl_NormU32(aecm->channelAdapt32[i]);
845 zerosFar = WebRtcSpl_NormU32((uint32_t)far_spectrum[i]);
846 if (zerosCh + zerosFar > 31) {
847 // Multiplication is safe
848 tmpU32no1 =
849 WEBRTC_SPL_UMUL_32_16(aecm->channelAdapt32[i], far_spectrum[i]);
850 shiftChFar = 0;
851 } else {
852 // We need to shift down before multiplication
853 shiftChFar = 32 - zerosCh - zerosFar;
854 // If zerosCh == zerosFar == 0, shiftChFar is 32. A
855 // right shift of 32 is undefined. To avoid that, we
856 // do this check.
857 tmpU32no1 =
858 rtc::dchecked_cast<uint32_t>(
859 shiftChFar >= 32 ? 0 : aecm->channelAdapt32[i] >> shiftChFar) *
860 far_spectrum[i];
861 }
862 // Determine Q-domain of numerator
863 zerosNum = WebRtcSpl_NormU32(tmpU32no1);
864 if (dfa[i]) {
865 zerosDfa = WebRtcSpl_NormU32((uint32_t)dfa[i]);
866 } else {
867 zerosDfa = 32;
868 }
869 tmp16no1 = zerosDfa - 2 + aecm->dfaNoisyQDomain - RESOLUTION_CHANNEL32 -
870 far_q + shiftChFar;
871 if (zerosNum > tmp16no1 + 1) {
872 xfaQ = tmp16no1;
873 dfaQ = zerosDfa - 2;
874 } else {
875 xfaQ = zerosNum - 2;
876 dfaQ = RESOLUTION_CHANNEL32 + far_q - aecm->dfaNoisyQDomain -
877 shiftChFar + xfaQ;
878 }
879 // Add in the same Q-domain
880 tmpU32no1 = WEBRTC_SPL_SHIFT_W32(tmpU32no1, xfaQ);
881 tmpU32no2 = WEBRTC_SPL_SHIFT_W32((uint32_t)dfa[i], dfaQ);
882 tmp32no1 = (int32_t)tmpU32no2 - (int32_t)tmpU32no1;
883 zerosNum = WebRtcSpl_NormW32(tmp32no1);
884 if ((tmp32no1) && (far_spectrum[i] > (CHANNEL_VAD << far_q))) {
885 //
886 // Update is needed
887 //
888 // This is what we would like to compute
889 //
890 // tmp32no1 = dfa[i] - (aecm->channelAdapt[i] * far_spectrum[i])
891 // tmp32norm = (i + 1)
892 // aecm->channelAdapt[i] += (2^mu) * tmp32no1
893 // / (tmp32norm * far_spectrum[i])
894 //
895
896 // Make sure we don't get overflow in multiplication.
897 if (zerosNum + zerosFar > 31) {
898 if (tmp32no1 > 0) {
899 tmp32no2 =
900 (int32_t)WEBRTC_SPL_UMUL_32_16(tmp32no1, far_spectrum[i]);
901 } else {
902 tmp32no2 =
903 -(int32_t)WEBRTC_SPL_UMUL_32_16(-tmp32no1, far_spectrum[i]);
904 }
905 shiftNum = 0;
906 } else {
907 shiftNum = 32 - (zerosNum + zerosFar);
908 if (tmp32no1 > 0) {
909 tmp32no2 = (tmp32no1 >> shiftNum) * far_spectrum[i];
910 } else {
911 tmp32no2 = -((-tmp32no1 >> shiftNum) * far_spectrum[i]);
912 }
913 }
914 // Normalize with respect to frequency bin
915 tmp32no2 = WebRtcSpl_DivW32W16(tmp32no2, i + 1);
916 // Make sure we are in the right Q-domain
917 shift2ResChan =
918 shiftNum + shiftChFar - xfaQ - mu - ((30 - zerosFar) << 1);
919 if (WebRtcSpl_NormW32(tmp32no2) < shift2ResChan) {
920 tmp32no2 = WEBRTC_SPL_WORD32_MAX;
921 } else {
922 tmp32no2 = WEBRTC_SPL_SHIFT_W32(tmp32no2, shift2ResChan);
923 }
924 aecm->channelAdapt32[i] =
925 WebRtcSpl_AddSatW32(aecm->channelAdapt32[i], tmp32no2);
926 if (aecm->channelAdapt32[i] < 0) {
927 // We can never have negative channel gain
928 aecm->channelAdapt32[i] = 0;
929 }
930 aecm->channelAdapt16[i] = (int16_t)(aecm->channelAdapt32[i] >> 16);
931 }
932 }
933 }
934 // END: Adaptive channel update
935
936 // Determine if we should store or restore the channel
937 if ((aecm->startupState == 0) & (aecm->currentVADValue)) {
938 // During startup we store the channel every block,
939 // and we recalculate echo estimate
940 WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst);
941 } else {
942 if (aecm->farLogEnergy < aecm->farEnergyMSE) {
943 aecm->mseChannelCount = 0;
944 } else {
945 aecm->mseChannelCount++;
946 }
947 // Enough data for validation. Store channel if we can.
948 if (aecm->mseChannelCount >= (MIN_MSE_COUNT + 10)) {
949 // We have enough data.
950 // Calculate MSE of "Adapt" and "Stored" versions.
951 // It is actually not MSE, but average absolute error.
952 mseStored = 0;
953 mseAdapt = 0;
954 for (i = 0; i < MIN_MSE_COUNT; i++) {
955 tmp32no1 = ((int32_t)aecm->echoStoredLogEnergy[i] -
956 (int32_t)aecm->nearLogEnergy[i]);
957 tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1);
958 mseStored += tmp32no2;
959
960 tmp32no1 = ((int32_t)aecm->echoAdaptLogEnergy[i] -
961 (int32_t)aecm->nearLogEnergy[i]);
962 tmp32no2 = WEBRTC_SPL_ABS_W32(tmp32no1);
963 mseAdapt += tmp32no2;
964 }
965 if (((mseStored << MSE_RESOLUTION) < (MIN_MSE_DIFF * mseAdapt)) &
966 ((aecm->mseStoredOld << MSE_RESOLUTION) <
967 (MIN_MSE_DIFF * aecm->mseAdaptOld))) {
968 // The stored channel has a significantly lower MSE than the adaptive
969 // one for two consecutive calculations. Reset the adaptive channel.
970 WebRtcAecm_ResetAdaptiveChannel(aecm);
971 } else if (((MIN_MSE_DIFF * mseStored) > (mseAdapt << MSE_RESOLUTION)) &
972 (mseAdapt < aecm->mseThreshold) &
973 (aecm->mseAdaptOld < aecm->mseThreshold)) {
974 // The adaptive channel has a significantly lower MSE than the stored
975 // one. The MSE for the adaptive channel has also been low for two
976 // consecutive calculations. Store the adaptive channel.
977 WebRtcAecm_StoreAdaptiveChannel(aecm, far_spectrum, echoEst);
978
979 // Update threshold
980 if (aecm->mseThreshold == WEBRTC_SPL_WORD32_MAX) {
981 aecm->mseThreshold = (mseAdapt + aecm->mseAdaptOld);
982 } else {
983 int scaled_threshold = aecm->mseThreshold * 5 / 8;
984 aecm->mseThreshold += ((mseAdapt - scaled_threshold) * 205) >> 8;
985 }
986 }
987
988 // Reset counter
989 aecm->mseChannelCount = 0;
990
991 // Store the MSE values.
992 aecm->mseStoredOld = mseStored;
993 aecm->mseAdaptOld = mseAdapt;
994 }
995 }
996 // END: Determine if we should store or reset channel estimate.
997 }
998
999 // CalcSuppressionGain(...)
1000 //
1001 // This function calculates the suppression gain that is used in the Wiener
1002 // filter.
1003 //
1004 //
1005 // @param aecm [i/n] Handle of the AECM instance.
1006 // @param supGain [out] (Return value) Suppression gain with which to scale
1007 // the noise
1008 // level (Q14).
1009 //
1010 //
WebRtcAecm_CalcSuppressionGain(AecmCore * const aecm)1011 int16_t WebRtcAecm_CalcSuppressionGain(AecmCore* const aecm) {
1012 int32_t tmp32no1;
1013
1014 int16_t supGain = SUPGAIN_DEFAULT;
1015 int16_t tmp16no1;
1016 int16_t dE = 0;
1017
1018 // Determine suppression gain used in the Wiener filter. The gain is based on
1019 // a mix of far end energy and echo estimation error. Adjust for the far end
1020 // signal level. A low signal level indicates no far end signal, hence we set
1021 // the suppression gain to 0
1022 if (!aecm->currentVADValue) {
1023 supGain = 0;
1024 } else {
1025 // Adjust for possible double talk. If we have large variations in
1026 // estimation error we likely have double talk (or poor channel).
1027 tmp16no1 = (aecm->nearLogEnergy[0] - aecm->echoStoredLogEnergy[0] -
1028 ENERGY_DEV_OFFSET);
1029 dE = WEBRTC_SPL_ABS_W16(tmp16no1);
1030
1031 if (dE < ENERGY_DEV_TOL) {
1032 // Likely no double talk. The better estimation, the more we can suppress
1033 // signal. Update counters
1034 if (dE < SUPGAIN_EPC_DT) {
1035 tmp32no1 = aecm->supGainErrParamDiffAB * dE;
1036 tmp32no1 += (SUPGAIN_EPC_DT >> 1);
1037 tmp16no1 = (int16_t)WebRtcSpl_DivW32W16(tmp32no1, SUPGAIN_EPC_DT);
1038 supGain = aecm->supGainErrParamA - tmp16no1;
1039 } else {
1040 tmp32no1 = aecm->supGainErrParamDiffBD * (ENERGY_DEV_TOL - dE);
1041 tmp32no1 += ((ENERGY_DEV_TOL - SUPGAIN_EPC_DT) >> 1);
1042 tmp16no1 = (int16_t)WebRtcSpl_DivW32W16(
1043 tmp32no1, (ENERGY_DEV_TOL - SUPGAIN_EPC_DT));
1044 supGain = aecm->supGainErrParamD + tmp16no1;
1045 }
1046 } else {
1047 // Likely in double talk. Use default value
1048 supGain = aecm->supGainErrParamD;
1049 }
1050 }
1051
1052 if (supGain > aecm->supGainOld) {
1053 tmp16no1 = supGain;
1054 } else {
1055 tmp16no1 = aecm->supGainOld;
1056 }
1057 aecm->supGainOld = supGain;
1058 if (tmp16no1 < aecm->supGain) {
1059 aecm->supGain += (int16_t)((tmp16no1 - aecm->supGain) >> 4);
1060 } else {
1061 aecm->supGain += (int16_t)((tmp16no1 - aecm->supGain) >> 4);
1062 }
1063
1064 // END: Update suppression gain
1065
1066 return aecm->supGain;
1067 }
1068
WebRtcAecm_BufferFarFrame(AecmCore * const aecm,const int16_t * const farend,const int farLen)1069 void WebRtcAecm_BufferFarFrame(AecmCore* const aecm,
1070 const int16_t* const farend,
1071 const int farLen) {
1072 int writeLen = farLen, writePos = 0;
1073
1074 // Check if the write position must be wrapped
1075 while (aecm->farBufWritePos + writeLen > FAR_BUF_LEN) {
1076 // Write to remaining buffer space before wrapping
1077 writeLen = FAR_BUF_LEN - aecm->farBufWritePos;
1078 memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos,
1079 sizeof(int16_t) * writeLen);
1080 aecm->farBufWritePos = 0;
1081 writePos = writeLen;
1082 writeLen = farLen - writeLen;
1083 }
1084
1085 memcpy(aecm->farBuf + aecm->farBufWritePos, farend + writePos,
1086 sizeof(int16_t) * writeLen);
1087 aecm->farBufWritePos += writeLen;
1088 }
1089
WebRtcAecm_FetchFarFrame(AecmCore * const aecm,int16_t * const farend,const int farLen,const int knownDelay)1090 void WebRtcAecm_FetchFarFrame(AecmCore* const aecm,
1091 int16_t* const farend,
1092 const int farLen,
1093 const int knownDelay) {
1094 int readLen = farLen;
1095 int readPos = 0;
1096 int delayChange = knownDelay - aecm->lastKnownDelay;
1097
1098 aecm->farBufReadPos -= delayChange;
1099
1100 // Check if delay forces a read position wrap
1101 while (aecm->farBufReadPos < 0) {
1102 aecm->farBufReadPos += FAR_BUF_LEN;
1103 }
1104 while (aecm->farBufReadPos > FAR_BUF_LEN - 1) {
1105 aecm->farBufReadPos -= FAR_BUF_LEN;
1106 }
1107
1108 aecm->lastKnownDelay = knownDelay;
1109
1110 // Check if read position must be wrapped
1111 while (aecm->farBufReadPos + readLen > FAR_BUF_LEN) {
1112 // Read from remaining buffer space before wrapping
1113 readLen = FAR_BUF_LEN - aecm->farBufReadPos;
1114 memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos,
1115 sizeof(int16_t) * readLen);
1116 aecm->farBufReadPos = 0;
1117 readPos = readLen;
1118 readLen = farLen - readLen;
1119 }
1120 memcpy(farend + readPos, aecm->farBuf + aecm->farBufReadPos,
1121 sizeof(int16_t) * readLen);
1122 aecm->farBufReadPos += readLen;
1123 }
1124
1125 } // namespace webrtc
1126