1 /*
2  *  Copyright (c) 2011 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 // Performs echo control (suppression) with fft routines in fixed-point
12 
13 #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_SOURCE_AECM_CORE_H_
14 #define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_MAIN_SOURCE_AECM_CORE_H_
15 
16 #define AECM_DYNAMIC_Q // turn on/off dynamic Q-domain
17 //#define AECM_WITH_ABS_APPROX
18 //#define AECM_SHORT                // for 32 sample partition length (otherwise 64)
19 
20 #include "typedefs.h"
21 #include "signal_processing_library.h"
22 
23 // Algorithm parameters
24 
25 #define FRAME_LEN       80              // Total frame length, 10 ms
26 #ifdef AECM_SHORT
27 
28 #define PART_LEN        32              // Length of partition
29 #define PART_LEN_SHIFT  6               // Length of (PART_LEN * 2) in base 2
30 
31 #else
32 
33 #define PART_LEN        64              // Length of partition
34 #define PART_LEN_SHIFT  7               // Length of (PART_LEN * 2) in base 2
35 
36 #endif
37 
38 #define PART_LEN1       (PART_LEN + 1)  // Unique fft coefficients
39 #define PART_LEN2       (PART_LEN << 1) // Length of partition * 2
40 #define PART_LEN4       (PART_LEN << 2) // Length of partition * 4
41 #define FAR_BUF_LEN     PART_LEN4       // Length of buffers
42 #define MAX_DELAY 100
43 
44 // Counter parameters
45 #ifdef AECM_SHORT
46 
47 #define CONV_LEN        1024            // Convergence length used at startup
48 #else
49 
50 #define CONV_LEN        512             // Convergence length used at startup
51 #endif
52 
53 #define CONV_LEN2       (CONV_LEN << 1) // Convergence length * 2 used at startup
54 // Energy parameters
55 #define MAX_BUF_LEN     64              // History length of energy signals
56 
57 #define FAR_ENERGY_MIN  1025            // Lowest Far energy level: At least 2 in energy
58 #define FAR_ENERGY_DIFF 929             // Allowed difference between max and min
59 
60 #define ENERGY_DEV_OFFSET       0       // The energy error offset in Q8
61 #define ENERGY_DEV_TOL  400             // The energy estimation tolerance in Q8
62 #define FAR_ENERGY_VAD_REGION   230     // Far VAD tolerance region
63 // Stepsize parameters
64 #define MU_MIN          10              // Min stepsize 2^-MU_MIN (far end energy dependent)
65 #define MU_MAX          1               // Max stepsize 2^-MU_MAX (far end energy dependent)
66 #define MU_DIFF         9               // MU_MIN - MU_MAX
67 // Channel parameters
68 #define MIN_MSE_COUNT   20              // Min number of consecutive blocks with enough far end
69                                         // energy to compare channel estimates
70 #define MIN_MSE_DIFF    29              // The ratio between adapted and stored channel to
71                                         // accept a new storage (0.8 in Q-MSE_RESOLUTION)
72 #define MSE_RESOLUTION  5               // MSE parameter resolution
73 #define RESOLUTION_CHANNEL16    12      // W16 Channel in Q-RESOLUTION_CHANNEL16
74 #define RESOLUTION_CHANNEL32    28      // W32 Channel in Q-RESOLUTION_CHANNEL
75 #define CHANNEL_VAD     16              // Minimum energy in frequency band to update channel
76 // Suppression gain parameters: SUPGAIN_ parameters in Q-(RESOLUTION_SUPGAIN)
77 #define RESOLUTION_SUPGAIN      8       // Channel in Q-(RESOLUTION_SUPGAIN)
78 #define SUPGAIN_DEFAULT (1 << RESOLUTION_SUPGAIN)   // Default suppression gain
79 #define SUPGAIN_ERROR_PARAM_A   3072    // Estimation error parameter (Maximum gain) (8 in Q8)
80 #define SUPGAIN_ERROR_PARAM_B   1536    // Estimation error parameter (Gain before going down)
81 #define SUPGAIN_ERROR_PARAM_D   SUPGAIN_DEFAULT // Estimation error parameter
82                                                 // (Should be the same as Default) (1 in Q8)
83 #define SUPGAIN_EPC_DT  200             // = SUPGAIN_ERROR_PARAM_C * ENERGY_DEV_TOL
84 // Defines for "check delay estimation"
85 #define CORR_WIDTH      31              // Number of samples to correlate over.
86 #define CORR_MAX        16              // Maximum correlation offset
87 #define CORR_MAX_BUF    63
88 #define CORR_DEV        4
89 #define CORR_MAX_LEVEL  20
90 #define CORR_MAX_LOW    4
91 #define CORR_BUF_LEN    (CORR_MAX << 1) + 1
92 // Note that CORR_WIDTH + 2*CORR_MAX <= MAX_BUF_LEN
93 
94 #define ONE_Q14         (1 << 14)
95 
96 // NLP defines
97 #define NLP_COMP_LOW    3277            // 0.2 in Q14
98 #define NLP_COMP_HIGH   ONE_Q14         // 1 in Q14
99 
100 extern const WebRtc_Word16 WebRtcAecm_kSqrtHanning[];
101 
102 typedef struct {
103     WebRtc_Word16 real;
104     WebRtc_Word16 imag;
105 } complex16_t;
106 
107 typedef struct
108 {
109     int farBufWritePos;
110     int farBufReadPos;
111     int knownDelay;
112     int lastKnownDelay;
113     int firstVAD; // Parameter to control poorly initialized channels
114 
115     void *farFrameBuf;
116     void *nearNoisyFrameBuf;
117     void *nearCleanFrameBuf;
118     void *outFrameBuf;
119 
120     WebRtc_Word16 farBuf[FAR_BUF_LEN];
121 
122     WebRtc_Word16 mult;
123     WebRtc_UWord32 seed;
124 
125     // Delay estimation variables
126     void* delay_estimator;
127     WebRtc_UWord16 currentDelay;
128     // Far end history variables
129     // TODO(bjornv): Replace |far_history| with ring_buffer.
130     uint16_t far_history[PART_LEN1 * MAX_DELAY];
131     int far_history_pos;
132     int far_q_domains[MAX_DELAY];
133 
134     WebRtc_Word16 nlpFlag;
135     WebRtc_Word16 fixedDelay;
136 
137     WebRtc_UWord32 totCount;
138 
139     WebRtc_Word16 dfaCleanQDomain;
140     WebRtc_Word16 dfaCleanQDomainOld;
141     WebRtc_Word16 dfaNoisyQDomain;
142     WebRtc_Word16 dfaNoisyQDomainOld;
143 
144     WebRtc_Word16 nearLogEnergy[MAX_BUF_LEN];
145     WebRtc_Word16 farLogEnergy;
146     WebRtc_Word16 echoAdaptLogEnergy[MAX_BUF_LEN];
147     WebRtc_Word16 echoStoredLogEnergy[MAX_BUF_LEN];
148 
149     // The extra 16 or 32 bytes in the following buffers are for alignment based Neon code.
150     // It's designed this way since the current GCC compiler can't align a buffer in 16 or 32
151     // byte boundaries properly.
152     WebRtc_Word16 channelStored_buf[PART_LEN1 + 8];
153     WebRtc_Word16 channelAdapt16_buf[PART_LEN1 + 8];
154     WebRtc_Word32 channelAdapt32_buf[PART_LEN1 + 8];
155     WebRtc_Word16 xBuf_buf[PART_LEN2 + 16]; // farend
156     WebRtc_Word16 dBufClean_buf[PART_LEN2 + 16]; // nearend
157     WebRtc_Word16 dBufNoisy_buf[PART_LEN2 + 16]; // nearend
158     WebRtc_Word16 outBuf_buf[PART_LEN + 8];
159 
160     // Pointers to the above buffers
161     WebRtc_Word16 *channelStored;
162     WebRtc_Word16 *channelAdapt16;
163     WebRtc_Word32 *channelAdapt32;
164     WebRtc_Word16 *xBuf;
165     WebRtc_Word16 *dBufClean;
166     WebRtc_Word16 *dBufNoisy;
167     WebRtc_Word16 *outBuf;
168 
169     WebRtc_Word32 echoFilt[PART_LEN1];
170     WebRtc_Word16 nearFilt[PART_LEN1];
171     WebRtc_Word32 noiseEst[PART_LEN1];
172     int           noiseEstTooLowCtr[PART_LEN1];
173     int           noiseEstTooHighCtr[PART_LEN1];
174     WebRtc_Word16 noiseEstCtr;
175     WebRtc_Word16 cngMode;
176 
177     WebRtc_Word32 mseAdaptOld;
178     WebRtc_Word32 mseStoredOld;
179     WebRtc_Word32 mseThreshold;
180 
181     WebRtc_Word16 farEnergyMin;
182     WebRtc_Word16 farEnergyMax;
183     WebRtc_Word16 farEnergyMaxMin;
184     WebRtc_Word16 farEnergyVAD;
185     WebRtc_Word16 farEnergyMSE;
186     int currentVADValue;
187     WebRtc_Word16 vadUpdateCount;
188 
189     WebRtc_Word16 startupState;
190     WebRtc_Word16 mseChannelCount;
191     WebRtc_Word16 supGain;
192     WebRtc_Word16 supGainOld;
193 
194     WebRtc_Word16 supGainErrParamA;
195     WebRtc_Word16 supGainErrParamD;
196     WebRtc_Word16 supGainErrParamDiffAB;
197     WebRtc_Word16 supGainErrParamDiffBD;
198 
199 #ifdef AEC_DEBUG
200     FILE *farFile;
201     FILE *nearFile;
202     FILE *outFile;
203 #endif
204 } AecmCore_t;
205 
206 ///////////////////////////////////////////////////////////////////////////////////////////////
207 // WebRtcAecm_CreateCore(...)
208 //
209 // Allocates the memory needed by the AECM. The memory needs to be
210 // initialized separately using the WebRtcAecm_InitCore() function.
211 //
212 // Input:
213 //      - aecm          : Instance that should be created
214 //
215 // Output:
216 //      - aecm          : Created instance
217 //
218 // Return value         :  0 - Ok
219 //                        -1 - Error
220 //
221 int WebRtcAecm_CreateCore(AecmCore_t **aecm);
222 
223 ///////////////////////////////////////////////////////////////////////////////////////////////
224 // WebRtcAecm_InitCore(...)
225 //
226 // This function initializes the AECM instant created with WebRtcAecm_CreateCore(...)
227 // Input:
228 //      - aecm          : Pointer to the AECM instance
229 //      - samplingFreq  : Sampling Frequency
230 //
231 // Output:
232 //      - aecm          : Initialized instance
233 //
234 // Return value         :  0 - Ok
235 //                        -1 - Error
236 //
237 int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq);
238 
239 ///////////////////////////////////////////////////////////////////////////////////////////////
240 // WebRtcAecm_FreeCore(...)
241 //
242 // This function releases the memory allocated by WebRtcAecm_CreateCore()
243 // Input:
244 //      - aecm          : Pointer to the AECM instance
245 //
246 // Return value         :  0 - Ok
247 //                        -1 - Error
248 //           11001-11016: Error
249 //
250 int WebRtcAecm_FreeCore(AecmCore_t *aecm);
251 
252 int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag);
253 
254 ///////////////////////////////////////////////////////////////////////////////////////////////
255 // WebRtcAecm_InitEchoPathCore(...)
256 //
257 // This function resets the echo channel adaptation with the specified channel.
258 // Input:
259 //      - aecm          : Pointer to the AECM instance
260 //      - echo_path     : Pointer to the data that should initialize the echo path
261 //
262 // Output:
263 //      - aecm          : Initialized instance
264 //
265 void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, const WebRtc_Word16* echo_path);
266 
267 ///////////////////////////////////////////////////////////////////////////////////////////////
268 // WebRtcAecm_ProcessFrame(...)
269 //
270 // This function processes frames and sends blocks to WebRtcAecm_ProcessBlock(...)
271 //
272 // Inputs:
273 //      - aecm          : Pointer to the AECM instance
274 //      - farend        : In buffer containing one frame of echo signal
275 //      - nearendNoisy  : In buffer containing one frame of nearend+echo signal without NS
276 //      - nearendClean  : In buffer containing one frame of nearend+echo signal with NS
277 //
278 // Output:
279 //      - out           : Out buffer, one frame of nearend signal          :
280 //
281 //
282 int WebRtcAecm_ProcessFrame(AecmCore_t * aecm, const WebRtc_Word16 * farend,
283                             const WebRtc_Word16 * nearendNoisy,
284                             const WebRtc_Word16 * nearendClean,
285                             WebRtc_Word16 * out);
286 
287 ///////////////////////////////////////////////////////////////////////////////////////////////
288 // WebRtcAecm_ProcessBlock(...)
289 //
290 // This function is called for every block within one frame
291 // This function is called by WebRtcAecm_ProcessFrame(...)
292 //
293 // Inputs:
294 //      - aecm          : Pointer to the AECM instance
295 //      - farend        : In buffer containing one block of echo signal
296 //      - nearendNoisy  : In buffer containing one frame of nearend+echo signal without NS
297 //      - nearendClean  : In buffer containing one frame of nearend+echo signal with NS
298 //
299 // Output:
300 //      - out           : Out buffer, one block of nearend signal          :
301 //
302 //
303 int WebRtcAecm_ProcessBlock(AecmCore_t * aecm, const WebRtc_Word16 * farend,
304                             const WebRtc_Word16 * nearendNoisy,
305                             const WebRtc_Word16 * noisyClean,
306                             WebRtc_Word16 * out);
307 
308 ///////////////////////////////////////////////////////////////////////////////////////////////
309 // WebRtcAecm_BufferFarFrame()
310 //
311 // Inserts a frame of data into farend buffer.
312 //
313 // Inputs:
314 //      - aecm          : Pointer to the AECM instance
315 //      - farend        : In buffer containing one frame of farend signal
316 //      - farLen        : Length of frame
317 //
318 void WebRtcAecm_BufferFarFrame(AecmCore_t * const aecm, const WebRtc_Word16 * const farend,
319                                const int farLen);
320 
321 ///////////////////////////////////////////////////////////////////////////////////////////////
322 // WebRtcAecm_FetchFarFrame()
323 //
324 // Read the farend buffer to account for known delay
325 //
326 // Inputs:
327 //      - aecm          : Pointer to the AECM instance
328 //      - farend        : In buffer containing one frame of farend signal
329 //      - farLen        : Length of frame
330 //      - knownDelay    : known delay
331 //
332 void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm, WebRtc_Word16 * const farend,
333                               const int farLen, const int knownDelay);
334 
335 ///////////////////////////////////////////////////////////////////////////////
336 // Some function pointers, for internal functions shared by ARM NEON and
337 // generic C code.
338 //
339 typedef void (*CalcLinearEnergies)(
340     AecmCore_t* aecm,
341     const WebRtc_UWord16* far_spectrum,
342     WebRtc_Word32* echoEst,
343     WebRtc_UWord32* far_energy,
344     WebRtc_UWord32* echo_energy_adapt,
345     WebRtc_UWord32* echo_energy_stored);
346 extern CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
347 
348 typedef void (*StoreAdaptiveChannel)(
349     AecmCore_t* aecm,
350     const WebRtc_UWord16* far_spectrum,
351     WebRtc_Word32* echo_est);
352 extern StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
353 
354 typedef void (*ResetAdaptiveChannel)(AecmCore_t* aecm);
355 extern ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
356 
357 typedef void (*WindowAndFFT)(
358     WebRtc_Word16* fft,
359     const WebRtc_Word16* time_signal,
360     complex16_t* freq_signal,
361     int time_signal_scaling);
362 extern WindowAndFFT WebRtcAecm_WindowAndFFT;
363 
364 typedef void (*InverseFFTAndWindow)(
365     AecmCore_t* aecm,
366     WebRtc_Word16* fft, complex16_t* efw,
367     WebRtc_Word16* output,
368     const WebRtc_Word16* nearendClean);
369 extern InverseFFTAndWindow WebRtcAecm_InverseFFTAndWindow;
370 
371 // Initialization of the above function pointers for ARM Neon.
372 void WebRtcAecm_InitNeon(void);
373 
374 
375 #endif
376