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