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