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/signal_processing/include/signal_processing_library.h"
17#include "webrtc/modules/audio_processing/aecm/aecm_defines.h"
18#include "webrtc/modules/audio_processing/utility/ring_buffer.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} complex16_t;
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_t;
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_t **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_t * 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_t *aecm);
182
183int WebRtcAecm_Control(AecmCore_t *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_t* aecm,
198                                 const int16_t* echo_path);
199
200////////////////////////////////////////////////////////////////////////////////
201// WebRtcAecm_ProcessFrame(...)
202//
203// This function processes frames and sends blocks to
204// WebRtcAecm_ProcessBlock(...)
205//
206// Inputs:
207//      - aecm          : Pointer to the AECM instance
208//      - farend        : In buffer containing one frame of echo signal
209//      - nearendNoisy  : In buffer containing one frame of nearend+echo signal
210//                        without NS
211//      - nearendClean  : In buffer containing one frame of nearend+echo signal
212//                        with NS
213//
214// Output:
215//      - out           : Out buffer, one frame of nearend signal          :
216//
217//
218int WebRtcAecm_ProcessFrame(AecmCore_t * aecm, 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_t * aecm, const int16_t * farend,
242                            const int16_t * nearendNoisy,
243                            const int16_t * noisyClean,
244                            int16_t * out);
245
246////////////////////////////////////////////////////////////////////////////////
247// WebRtcAecm_BufferFarFrame()
248//
249// Inserts a frame of data into farend buffer.
250//
251// Inputs:
252//      - aecm          : Pointer to the AECM instance
253//      - farend        : In buffer containing one frame of farend signal
254//      - farLen        : Length of frame
255//
256void WebRtcAecm_BufferFarFrame(AecmCore_t * const aecm,
257                               const int16_t * const farend,
258                               const int farLen);
259
260////////////////////////////////////////////////////////////////////////////////
261// WebRtcAecm_FetchFarFrame()
262//
263// Read the farend buffer to account for known delay
264//
265// Inputs:
266//      - aecm          : Pointer to the AECM instance
267//      - farend        : In buffer containing one frame of farend signal
268//      - farLen        : Length of frame
269//      - knownDelay    : known delay
270//
271void WebRtcAecm_FetchFarFrame(AecmCore_t * const aecm,
272                              int16_t * const farend,
273                              const int farLen, const int knownDelay);
274
275
276// All the functions below are intended to be private
277
278////////////////////////////////////////////////////////////////////////////////
279// WebRtcAecm_UpdateFarHistory()
280//
281// Moves the pointer to the next entry and inserts |far_spectrum| and
282// corresponding Q-domain in its buffer.
283//
284// Inputs:
285//      - self          : Pointer to the delay estimation instance
286//      - far_spectrum  : Pointer to the far end spectrum
287//      - far_q         : Q-domain of far end spectrum
288//
289void WebRtcAecm_UpdateFarHistory(AecmCore_t* self,
290                                 uint16_t* far_spectrum,
291                                 int far_q);
292
293////////////////////////////////////////////////////////////////////////////////
294// WebRtcAecm_AlignedFarend()
295//
296// Returns a pointer to the far end spectrum aligned to current near end
297// spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been
298// called before AlignedFarend(...). Otherwise, you get the pointer to the
299// previous frame. The memory is only valid until the next call of
300// WebRtc_DelayEstimatorProcessFix(...).
301//
302// Inputs:
303//      - self              : Pointer to the AECM instance.
304//      - delay             : Current delay estimate.
305//
306// Output:
307//      - far_q             : The Q-domain of the aligned far end spectrum
308//
309// Return value:
310//      - far_spectrum      : Pointer to the aligned far end spectrum
311//                            NULL - Error
312//
313const uint16_t* WebRtcAecm_AlignedFarend(AecmCore_t* self,
314                                         int* far_q,
315                                         int delay);
316
317///////////////////////////////////////////////////////////////////////////////
318// WebRtcAecm_CalcSuppressionGain()
319//
320// This function calculates the suppression gain that is used in the
321// Wiener filter.
322//
323// Inputs:
324//      - aecm              : Pointer to the AECM instance.
325//
326// Return value:
327//      - supGain           : Suppression gain with which to scale the noise
328//                            level (Q14).
329//
330int16_t WebRtcAecm_CalcSuppressionGain(AecmCore_t * const aecm);
331
332///////////////////////////////////////////////////////////////////////////////
333// WebRtcAecm_CalcEnergies()
334//
335// This function calculates the log of energies for nearend, farend and
336// estimated echoes. There is also an update of energy decision levels,
337// i.e. internal VAD.
338//
339// Inputs:
340//      - aecm              : Pointer to the AECM instance.
341//      - far_spectrum      : Pointer to farend spectrum.
342//      - far_q             : Q-domain of farend spectrum.
343//      - nearEner          : Near end energy for current block in
344//                            Q(aecm->dfaQDomain).
345//
346// Output:
347//     - echoEst            : Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16).
348//
349void WebRtcAecm_CalcEnergies(AecmCore_t * aecm,
350                             const uint16_t* far_spectrum,
351                             const int16_t far_q,
352                             const uint32_t nearEner,
353                             int32_t * echoEst);
354
355///////////////////////////////////////////////////////////////////////////////
356// WebRtcAecm_CalcStepSize()
357//
358// This function calculates the step size used in channel estimation
359//
360// Inputs:
361//      - aecm              : Pointer to the AECM instance.
362//
363// Return value:
364//      - mu                : Stepsize in log2(), i.e. number of shifts.
365//
366int16_t WebRtcAecm_CalcStepSize(AecmCore_t * const aecm);
367
368///////////////////////////////////////////////////////////////////////////////
369// WebRtcAecm_UpdateChannel(...)
370//
371// This function performs channel estimation.
372// NLMS and decision on channel storage.
373//
374// Inputs:
375//      - aecm              : Pointer to the AECM instance.
376//      - far_spectrum      : Absolute value of the farend signal in Q(far_q)
377//      - far_q             : Q-domain of the farend signal
378//      - dfa               : Absolute value of the nearend signal
379//                            (Q[aecm->dfaQDomain])
380//      - mu                : NLMS step size.
381// Input/Output:
382//      - echoEst           : Estimated echo in Q(far_q+RESOLUTION_CHANNEL16).
383//
384void WebRtcAecm_UpdateChannel(AecmCore_t * aecm,
385                              const uint16_t* far_spectrum,
386                              const int16_t far_q,
387                              const uint16_t * const dfa,
388                              const int16_t mu,
389                              int32_t * echoEst);
390
391extern const int16_t WebRtcAecm_kCosTable[];
392extern const int16_t WebRtcAecm_kSinTable[];
393
394///////////////////////////////////////////////////////////////////////////////
395// Some function pointers, for internal functions shared by ARM NEON and
396// generic C code.
397//
398typedef void (*CalcLinearEnergies)(
399    AecmCore_t* aecm,
400    const uint16_t* far_spectrum,
401    int32_t* echoEst,
402    uint32_t* far_energy,
403    uint32_t* echo_energy_adapt,
404    uint32_t* echo_energy_stored);
405extern CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
406
407typedef void (*StoreAdaptiveChannel)(
408    AecmCore_t* aecm,
409    const uint16_t* far_spectrum,
410    int32_t* echo_est);
411extern StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
412
413typedef void (*ResetAdaptiveChannel)(AecmCore_t* aecm);
414extern ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
415
416// For the above function pointers, functions for generic platforms are declared
417// and defined as static in file aecm_core.c, while those for ARM Neon platforms
418// are declared below and defined in file aecm_core_neon.s.
419#if (defined WEBRTC_DETECT_ARM_NEON) || defined (WEBRTC_ARCH_ARM_NEON)
420void WebRtcAecm_CalcLinearEnergiesNeon(AecmCore_t* aecm,
421                                       const uint16_t* far_spectrum,
422                                       int32_t* echo_est,
423                                       uint32_t* far_energy,
424                                       uint32_t* echo_energy_adapt,
425                                       uint32_t* echo_energy_stored);
426
427void WebRtcAecm_StoreAdaptiveChannelNeon(AecmCore_t* aecm,
428                                         const uint16_t* far_spectrum,
429                                         int32_t* echo_est);
430
431void WebRtcAecm_ResetAdaptiveChannelNeon(AecmCore_t* aecm);
432#endif
433
434#if defined(MIPS32_LE)
435void WebRtcAecm_CalcLinearEnergies_mips(AecmCore_t* aecm,
436                                        const uint16_t* far_spectrum,
437                                        int32_t* echo_est,
438                                        uint32_t* far_energy,
439                                        uint32_t* echo_energy_adapt,
440                                        uint32_t* echo_energy_stored);
441#if defined(MIPS_DSP_R1_LE)
442void WebRtcAecm_StoreAdaptiveChannel_mips(AecmCore_t* aecm,
443                                          const uint16_t* far_spectrum,
444                                          int32_t* echo_est);
445
446void WebRtcAecm_ResetAdaptiveChannel_mips(AecmCore_t* aecm);
447#endif
448#endif
449
450#endif
451