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
100extern const WebRtc_Word16 WebRtcAecm_kSqrtHanning[];
101
102typedef struct {
103    WebRtc_Word16 real;
104    WebRtc_Word16 imag;
105} complex16_t;
106
107typedef 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//
221int 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//
237int 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//
250int WebRtcAecm_FreeCore(AecmCore_t *aecm);
251
252int 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//
265void 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//
282int 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//
303int 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//
318void 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//
332void 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//
339typedef 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);
346extern CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
347
348typedef void (*StoreAdaptiveChannel)(
349    AecmCore_t* aecm,
350    const WebRtc_UWord16* far_spectrum,
351    WebRtc_Word32* echo_est);
352extern StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
353
354typedef void (*ResetAdaptiveChannel)(AecmCore_t* aecm);
355extern ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
356
357typedef void (*WindowAndFFT)(
358    WebRtc_Word16* fft,
359    const WebRtc_Word16* time_signal,
360    complex16_t* freq_signal,
361    int time_signal_scaling);
362extern WindowAndFFT WebRtcAecm_WindowAndFFT;
363
364typedef void (*InverseFFTAndWindow)(
365    AecmCore_t* aecm,
366    WebRtc_Word16* fft, complex16_t* efw,
367    WebRtc_Word16* output,
368    const WebRtc_Word16* nearendClean);
369extern InverseFFTAndWindow WebRtcAecm_InverseFFTAndWindow;
370
371// Initialization of the above function pointers for ARM Neon.
372void WebRtcAecm_InitNeon(void);
373
374
375#endif
376