aecm_core.h revision 6b6301588ef2d7b5f5d442aa95bef442a43ead53
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// Performs echo control (suppression) with fft routines in fixed-point.
12
13#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AECM_AECM_CORE_H_
14#define WEBRTC_MODULES_AUDIO_PROCESSING_AECM_AECM_CORE_H_
15
16#include "webrtc/common_audio/ring_buffer.h"
17#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
18#include "webrtc/modules/audio_processing/aecm/aecm_defines.h"
19#include "webrtc/typedefs.h"
20
21#ifdef _MSC_VER  // visual c++
22#define ALIGN8_BEG __declspec(align(8))
23#define ALIGN8_END
24#else  // gcc or icc
25#define ALIGN8_BEG
26#define ALIGN8_END __attribute__((aligned(8)))
27#endif
28
29typedef struct {
30    int16_t real;
31    int16_t imag;
32} ComplexInt16;
33
34typedef struct {
35    int farBufWritePos;
36    int farBufReadPos;
37    int knownDelay;
38    int lastKnownDelay;
39    int firstVAD;  // Parameter to control poorly initialized channels
40
41    RingBuffer* farFrameBuf;
42    RingBuffer* nearNoisyFrameBuf;
43    RingBuffer* nearCleanFrameBuf;
44    RingBuffer* outFrameBuf;
45
46    int16_t farBuf[FAR_BUF_LEN];
47
48    int16_t mult;
49    uint32_t seed;
50
51    // Delay estimation variables
52    void* delay_estimator_farend;
53    void* delay_estimator;
54    uint16_t currentDelay;
55    // Far end history variables
56    // TODO(bjornv): Replace |far_history| with ring_buffer.
57    uint16_t far_history[PART_LEN1 * MAX_DELAY];
58    int far_history_pos;
59    int far_q_domains[MAX_DELAY];
60
61    int16_t nlpFlag;
62    int16_t fixedDelay;
63
64    uint32_t totCount;
65
66    int16_t dfaCleanQDomain;
67    int16_t dfaCleanQDomainOld;
68    int16_t dfaNoisyQDomain;
69    int16_t dfaNoisyQDomainOld;
70
71    int16_t nearLogEnergy[MAX_BUF_LEN];
72    int16_t farLogEnergy;
73    int16_t echoAdaptLogEnergy[MAX_BUF_LEN];
74    int16_t echoStoredLogEnergy[MAX_BUF_LEN];
75
76    // The extra 16 or 32 bytes in the following buffers are for alignment based
77    // Neon code.
78    // It's designed this way since the current GCC compiler can't align a
79    // buffer in 16 or 32 byte boundaries properly.
80    int16_t channelStored_buf[PART_LEN1 + 8];
81    int16_t channelAdapt16_buf[PART_LEN1 + 8];
82    int32_t channelAdapt32_buf[PART_LEN1 + 8];
83    int16_t xBuf_buf[PART_LEN2 + 16];  // farend
84    int16_t dBufClean_buf[PART_LEN2 + 16];  // nearend
85    int16_t dBufNoisy_buf[PART_LEN2 + 16];  // nearend
86    int16_t outBuf_buf[PART_LEN + 8];
87
88    // Pointers to the above buffers
89    int16_t *channelStored;
90    int16_t *channelAdapt16;
91    int32_t *channelAdapt32;
92    int16_t *xBuf;
93    int16_t *dBufClean;
94    int16_t *dBufNoisy;
95    int16_t *outBuf;
96
97    int32_t echoFilt[PART_LEN1];
98    int16_t nearFilt[PART_LEN1];
99    int32_t noiseEst[PART_LEN1];
100    int           noiseEstTooLowCtr[PART_LEN1];
101    int           noiseEstTooHighCtr[PART_LEN1];
102    int16_t noiseEstCtr;
103    int16_t cngMode;
104
105    int32_t mseAdaptOld;
106    int32_t mseStoredOld;
107    int32_t mseThreshold;
108
109    int16_t farEnergyMin;
110    int16_t farEnergyMax;
111    int16_t farEnergyMaxMin;
112    int16_t farEnergyVAD;
113    int16_t farEnergyMSE;
114    int currentVADValue;
115    int16_t vadUpdateCount;
116
117    int16_t startupState;
118    int16_t mseChannelCount;
119    int16_t supGain;
120    int16_t supGainOld;
121
122    int16_t supGainErrParamA;
123    int16_t supGainErrParamD;
124    int16_t supGainErrParamDiffAB;
125    int16_t supGainErrParamDiffBD;
126
127    struct RealFFT* real_fft;
128
129#ifdef AEC_DEBUG
130    FILE *farFile;
131    FILE *nearFile;
132    FILE *outFile;
133#endif
134} AecmCore;
135
136////////////////////////////////////////////////////////////////////////////////
137// WebRtcAecm_CreateCore(...)
138//
139// Allocates the memory needed by the AECM. The memory needs to be
140// initialized separately using the WebRtcAecm_InitCore() function.
141//
142// Input:
143//      - aecm          : Instance that should be created
144//
145// Output:
146//      - aecm          : Created instance
147//
148// Return value         :  0 - Ok
149//                        -1 - Error
150//
151int WebRtcAecm_CreateCore(AecmCore** aecm);
152
153////////////////////////////////////////////////////////////////////////////////
154// WebRtcAecm_InitCore(...)
155//
156// This function initializes the AECM instant created with
157// WebRtcAecm_CreateCore(...)
158// Input:
159//      - aecm          : Pointer to the AECM instance
160//      - samplingFreq  : Sampling Frequency
161//
162// Output:
163//      - aecm          : Initialized instance
164//
165// Return value         :  0 - Ok
166//                        -1 - Error
167//
168int WebRtcAecm_InitCore(AecmCore* const aecm, int samplingFreq);
169
170////////////////////////////////////////////////////////////////////////////////
171// WebRtcAecm_FreeCore(...)
172//
173// This function releases the memory allocated by WebRtcAecm_CreateCore()
174// Input:
175//      - aecm          : Pointer to the AECM instance
176//
177// Return value         :  0 - Ok
178//                        -1 - Error
179//           11001-11016: Error
180//
181int WebRtcAecm_FreeCore(AecmCore* aecm);
182
183int WebRtcAecm_Control(AecmCore* aecm, int delay, int nlpFlag);
184
185////////////////////////////////////////////////////////////////////////////////
186// WebRtcAecm_InitEchoPathCore(...)
187//
188// This function resets the echo channel adaptation with the specified channel.
189// Input:
190//      - aecm          : Pointer to the AECM instance
191//      - echo_path     : Pointer to the data that should initialize the echo
192//                        path
193//
194// Output:
195//      - aecm          : Initialized instance
196//
197void WebRtcAecm_InitEchoPathCore(AecmCore* aecm, const int16_t* echo_path);
198
199////////////////////////////////////////////////////////////////////////////////
200// WebRtcAecm_ProcessFrame(...)
201//
202// This function processes frames and sends blocks to
203// WebRtcAecm_ProcessBlock(...)
204//
205// Inputs:
206//      - aecm          : Pointer to the AECM instance
207//      - farend        : In buffer containing one frame of echo signal
208//      - nearendNoisy  : In buffer containing one frame of nearend+echo signal
209//                        without NS
210//      - nearendClean  : In buffer containing one frame of nearend+echo signal
211//                        with NS
212//
213// Output:
214//      - out           : Out buffer, one frame of nearend signal          :
215//
216//
217int WebRtcAecm_ProcessFrame(AecmCore* aecm,
218                            const int16_t* farend,
219                            const int16_t* nearendNoisy,
220                            const int16_t* nearendClean,
221                            int16_t* out);
222
223////////////////////////////////////////////////////////////////////////////////
224// WebRtcAecm_ProcessBlock(...)
225//
226// This function is called for every block within one frame
227// This function is called by WebRtcAecm_ProcessFrame(...)
228//
229// Inputs:
230//      - aecm          : Pointer to the AECM instance
231//      - farend        : In buffer containing one block of echo signal
232//      - nearendNoisy  : In buffer containing one frame of nearend+echo signal
233//                        without NS
234//      - nearendClean  : In buffer containing one frame of nearend+echo signal
235//                        with NS
236//
237// Output:
238//      - out           : Out buffer, one block of nearend signal          :
239//
240//
241int WebRtcAecm_ProcessBlock(AecmCore* aecm,
242                            const int16_t* farend,
243                            const int16_t* nearendNoisy,
244                            const int16_t* noisyClean,
245                            int16_t* out);
246
247////////////////////////////////////////////////////////////////////////////////
248// WebRtcAecm_BufferFarFrame()
249//
250// Inserts a frame of data into farend buffer.
251//
252// Inputs:
253//      - aecm          : Pointer to the AECM instance
254//      - farend        : In buffer containing one frame of farend signal
255//      - farLen        : Length of frame
256//
257void WebRtcAecm_BufferFarFrame(AecmCore* const aecm,
258                               const int16_t* const farend,
259                               const int farLen);
260
261////////////////////////////////////////////////////////////////////////////////
262// WebRtcAecm_FetchFarFrame()
263//
264// Read the farend buffer to account for known delay
265//
266// Inputs:
267//      - aecm          : Pointer to the AECM instance
268//      - farend        : In buffer containing one frame of farend signal
269//      - farLen        : Length of frame
270//      - knownDelay    : known delay
271//
272void WebRtcAecm_FetchFarFrame(AecmCore* const aecm,
273                              int16_t* const farend,
274                              const int farLen,
275                              const int knownDelay);
276
277// All the functions below are intended to be private
278
279////////////////////////////////////////////////////////////////////////////////
280// WebRtcAecm_UpdateFarHistory()
281//
282// Moves the pointer to the next entry and inserts |far_spectrum| and
283// corresponding Q-domain in its buffer.
284//
285// Inputs:
286//      - self          : Pointer to the delay estimation instance
287//      - far_spectrum  : Pointer to the far end spectrum
288//      - far_q         : Q-domain of far end spectrum
289//
290void WebRtcAecm_UpdateFarHistory(AecmCore* self,
291                                 uint16_t* far_spectrum,
292                                 int far_q);
293
294////////////////////////////////////////////////////////////////////////////////
295// WebRtcAecm_AlignedFarend()
296//
297// Returns a pointer to the far end spectrum aligned to current near end
298// spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been
299// called before AlignedFarend(...). Otherwise, you get the pointer to the
300// previous frame. The memory is only valid until the next call of
301// WebRtc_DelayEstimatorProcessFix(...).
302//
303// Inputs:
304//      - self              : Pointer to the AECM instance.
305//      - delay             : Current delay estimate.
306//
307// Output:
308//      - far_q             : The Q-domain of the aligned far end spectrum
309//
310// Return value:
311//      - far_spectrum      : Pointer to the aligned far end spectrum
312//                            NULL - Error
313//
314const uint16_t* WebRtcAecm_AlignedFarend(AecmCore* self, int* far_q, int delay);
315
316///////////////////////////////////////////////////////////////////////////////
317// WebRtcAecm_CalcSuppressionGain()
318//
319// This function calculates the suppression gain that is used in the
320// Wiener filter.
321//
322// Inputs:
323//      - aecm              : Pointer to the AECM instance.
324//
325// Return value:
326//      - supGain           : Suppression gain with which to scale the noise
327//                            level (Q14).
328//
329int16_t WebRtcAecm_CalcSuppressionGain(AecmCore* const aecm);
330
331///////////////////////////////////////////////////////////////////////////////
332// WebRtcAecm_CalcEnergies()
333//
334// This function calculates the log of energies for nearend, farend and
335// estimated echoes. There is also an update of energy decision levels,
336// i.e. internal VAD.
337//
338// Inputs:
339//      - aecm              : Pointer to the AECM instance.
340//      - far_spectrum      : Pointer to farend spectrum.
341//      - far_q             : Q-domain of farend spectrum.
342//      - nearEner          : Near end energy for current block in
343//                            Q(aecm->dfaQDomain).
344//
345// Output:
346//     - echoEst            : Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16).
347//
348void WebRtcAecm_CalcEnergies(AecmCore* aecm,
349                             const uint16_t* far_spectrum,
350                             const int16_t far_q,
351                             const uint32_t nearEner,
352                             int32_t* echoEst);
353
354///////////////////////////////////////////////////////////////////////////////
355// WebRtcAecm_CalcStepSize()
356//
357// This function calculates the step size used in channel estimation
358//
359// Inputs:
360//      - aecm              : Pointer to the AECM instance.
361//
362// Return value:
363//      - mu                : Stepsize in log2(), i.e. number of shifts.
364//
365int16_t WebRtcAecm_CalcStepSize(AecmCore* const aecm);
366
367///////////////////////////////////////////////////////////////////////////////
368// WebRtcAecm_UpdateChannel(...)
369//
370// This function performs channel estimation.
371// NLMS and decision on channel storage.
372//
373// Inputs:
374//      - aecm              : Pointer to the AECM instance.
375//      - far_spectrum      : Absolute value of the farend signal in Q(far_q)
376//      - far_q             : Q-domain of the farend signal
377//      - dfa               : Absolute value of the nearend signal
378//                            (Q[aecm->dfaQDomain])
379//      - mu                : NLMS step size.
380// Input/Output:
381//      - echoEst           : Estimated echo in Q(far_q+RESOLUTION_CHANNEL16).
382//
383void WebRtcAecm_UpdateChannel(AecmCore* aecm,
384                              const uint16_t* far_spectrum,
385                              const int16_t far_q,
386                              const uint16_t* const dfa,
387                              const int16_t mu,
388                              int32_t* echoEst);
389
390extern const int16_t WebRtcAecm_kCosTable[];
391extern const int16_t WebRtcAecm_kSinTable[];
392
393///////////////////////////////////////////////////////////////////////////////
394// Some function pointers, for internal functions shared by ARM NEON and
395// generic C code.
396//
397typedef void (*CalcLinearEnergies)(AecmCore* aecm,
398                                   const uint16_t* far_spectrum,
399                                   int32_t* echoEst,
400                                   uint32_t* far_energy,
401                                   uint32_t* echo_energy_adapt,
402                                   uint32_t* echo_energy_stored);
403extern CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
404
405typedef void (*StoreAdaptiveChannel)(AecmCore* aecm,
406                                     const uint16_t* far_spectrum,
407                                     int32_t* echo_est);
408extern StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
409
410typedef void (*ResetAdaptiveChannel)(AecmCore* aecm);
411extern ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
412
413// For the above function pointers, functions for generic platforms are declared
414// and defined as static in file aecm_core.c, while those for ARM Neon platforms
415// are declared below and defined in file aecm_core_neon.c.
416#if (defined WEBRTC_DETECT_ARM_NEON) || defined (WEBRTC_ARCH_ARM_NEON) || \
417     defined (WEBRTC_ARCH_ARM64_NEON)
418void WebRtcAecm_CalcLinearEnergiesNeon(AecmCore* aecm,
419                                       const uint16_t* far_spectrum,
420                                       int32_t* echo_est,
421                                       uint32_t* far_energy,
422                                       uint32_t* echo_energy_adapt,
423                                       uint32_t* echo_energy_stored);
424
425void WebRtcAecm_StoreAdaptiveChannelNeon(AecmCore* aecm,
426                                         const uint16_t* far_spectrum,
427                                         int32_t* echo_est);
428
429void WebRtcAecm_ResetAdaptiveChannelNeon(AecmCore* aecm);
430#endif
431
432#if defined(MIPS32_LE)
433void WebRtcAecm_CalcLinearEnergies_mips(AecmCore* aecm,
434                                        const uint16_t* far_spectrum,
435                                        int32_t* echo_est,
436                                        uint32_t* far_energy,
437                                        uint32_t* echo_energy_adapt,
438                                        uint32_t* echo_energy_stored);
439#if defined(MIPS_DSP_R1_LE)
440void WebRtcAecm_StoreAdaptiveChannel_mips(AecmCore* aecm,
441                                          const uint16_t* far_spectrum,
442                                          int32_t* echo_est);
443
444void WebRtcAecm_ResetAdaptiveChannel_mips(AecmCore* aecm);
445#endif
446#endif
447
448#endif
449