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