• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
29 typedef struct {
30     int16_t real;
31     int16_t imag;
32 } ComplexInt16;
33 
34 typedef 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 // Returns a pointer to the instance and a nullptr at failure.
142 AecmCore* WebRtcAecm_CreateCore();
143 
144 ////////////////////////////////////////////////////////////////////////////////
145 // WebRtcAecm_InitCore(...)
146 //
147 // This function initializes the AECM instant created with
148 // WebRtcAecm_CreateCore()
149 // Input:
150 //      - aecm          : Pointer to the AECM instance
151 //      - samplingFreq  : Sampling Frequency
152 //
153 // Output:
154 //      - aecm          : Initialized instance
155 //
156 // Return value         :  0 - Ok
157 //                        -1 - Error
158 //
159 int WebRtcAecm_InitCore(AecmCore* const aecm, int samplingFreq);
160 
161 ////////////////////////////////////////////////////////////////////////////////
162 // WebRtcAecm_FreeCore(...)
163 //
164 // This function releases the memory allocated by WebRtcAecm_CreateCore()
165 // Input:
166 //      - aecm          : Pointer to the AECM instance
167 //
168 void WebRtcAecm_FreeCore(AecmCore* aecm);
169 
170 int WebRtcAecm_Control(AecmCore* aecm, int delay, int nlpFlag);
171 
172 ////////////////////////////////////////////////////////////////////////////////
173 // WebRtcAecm_InitEchoPathCore(...)
174 //
175 // This function resets the echo channel adaptation with the specified channel.
176 // Input:
177 //      - aecm          : Pointer to the AECM instance
178 //      - echo_path     : Pointer to the data that should initialize the echo
179 //                        path
180 //
181 // Output:
182 //      - aecm          : Initialized instance
183 //
184 void WebRtcAecm_InitEchoPathCore(AecmCore* aecm, const int16_t* echo_path);
185 
186 ////////////////////////////////////////////////////////////////////////////////
187 // WebRtcAecm_ProcessFrame(...)
188 //
189 // This function processes frames and sends blocks to
190 // WebRtcAecm_ProcessBlock(...)
191 //
192 // Inputs:
193 //      - aecm          : Pointer to the AECM instance
194 //      - farend        : In buffer containing one frame of echo signal
195 //      - nearendNoisy  : In buffer containing one frame of nearend+echo signal
196 //                        without NS
197 //      - nearendClean  : In buffer containing one frame of nearend+echo signal
198 //                        with NS
199 //
200 // Output:
201 //      - out           : Out buffer, one frame of nearend signal          :
202 //
203 //
204 int WebRtcAecm_ProcessFrame(AecmCore* aecm,
205                             const int16_t* farend,
206                             const int16_t* nearendNoisy,
207                             const int16_t* nearendClean,
208                             int16_t* out);
209 
210 ////////////////////////////////////////////////////////////////////////////////
211 // WebRtcAecm_ProcessBlock(...)
212 //
213 // This function is called for every block within one frame
214 // This function is called by WebRtcAecm_ProcessFrame(...)
215 //
216 // Inputs:
217 //      - aecm          : Pointer to the AECM instance
218 //      - farend        : In buffer containing one block of echo signal
219 //      - nearendNoisy  : In buffer containing one frame of nearend+echo signal
220 //                        without NS
221 //      - nearendClean  : In buffer containing one frame of nearend+echo signal
222 //                        with NS
223 //
224 // Output:
225 //      - out           : Out buffer, one block of nearend signal          :
226 //
227 //
228 int WebRtcAecm_ProcessBlock(AecmCore* aecm,
229                             const int16_t* farend,
230                             const int16_t* nearendNoisy,
231                             const int16_t* noisyClean,
232                             int16_t* out);
233 
234 ////////////////////////////////////////////////////////////////////////////////
235 // WebRtcAecm_BufferFarFrame()
236 //
237 // Inserts a frame of data into farend buffer.
238 //
239 // Inputs:
240 //      - aecm          : Pointer to the AECM instance
241 //      - farend        : In buffer containing one frame of farend signal
242 //      - farLen        : Length of frame
243 //
244 void WebRtcAecm_BufferFarFrame(AecmCore* const aecm,
245                                const int16_t* const farend,
246                                const int farLen);
247 
248 ////////////////////////////////////////////////////////////////////////////////
249 // WebRtcAecm_FetchFarFrame()
250 //
251 // Read the farend buffer to account for known delay
252 //
253 // Inputs:
254 //      - aecm          : Pointer to the AECM instance
255 //      - farend        : In buffer containing one frame of farend signal
256 //      - farLen        : Length of frame
257 //      - knownDelay    : known delay
258 //
259 void WebRtcAecm_FetchFarFrame(AecmCore* const aecm,
260                               int16_t* const farend,
261                               const int farLen,
262                               const int knownDelay);
263 
264 // All the functions below are intended to be private
265 
266 ////////////////////////////////////////////////////////////////////////////////
267 // WebRtcAecm_UpdateFarHistory()
268 //
269 // Moves the pointer to the next entry and inserts |far_spectrum| and
270 // corresponding Q-domain in its buffer.
271 //
272 // Inputs:
273 //      - self          : Pointer to the delay estimation instance
274 //      - far_spectrum  : Pointer to the far end spectrum
275 //      - far_q         : Q-domain of far end spectrum
276 //
277 void WebRtcAecm_UpdateFarHistory(AecmCore* self,
278                                  uint16_t* far_spectrum,
279                                  int far_q);
280 
281 ////////////////////////////////////////////////////////////////////////////////
282 // WebRtcAecm_AlignedFarend()
283 //
284 // Returns a pointer to the far end spectrum aligned to current near end
285 // spectrum. The function WebRtc_DelayEstimatorProcessFix(...) should have been
286 // called before AlignedFarend(...). Otherwise, you get the pointer to the
287 // previous frame. The memory is only valid until the next call of
288 // WebRtc_DelayEstimatorProcessFix(...).
289 //
290 // Inputs:
291 //      - self              : Pointer to the AECM instance.
292 //      - delay             : Current delay estimate.
293 //
294 // Output:
295 //      - far_q             : The Q-domain of the aligned far end spectrum
296 //
297 // Return value:
298 //      - far_spectrum      : Pointer to the aligned far end spectrum
299 //                            NULL - Error
300 //
301 const uint16_t* WebRtcAecm_AlignedFarend(AecmCore* self, int* far_q, int delay);
302 
303 ///////////////////////////////////////////////////////////////////////////////
304 // WebRtcAecm_CalcSuppressionGain()
305 //
306 // This function calculates the suppression gain that is used in the
307 // Wiener filter.
308 //
309 // Inputs:
310 //      - aecm              : Pointer to the AECM instance.
311 //
312 // Return value:
313 //      - supGain           : Suppression gain with which to scale the noise
314 //                            level (Q14).
315 //
316 int16_t WebRtcAecm_CalcSuppressionGain(AecmCore* const aecm);
317 
318 ///////////////////////////////////////////////////////////////////////////////
319 // WebRtcAecm_CalcEnergies()
320 //
321 // This function calculates the log of energies for nearend, farend and
322 // estimated echoes. There is also an update of energy decision levels,
323 // i.e. internal VAD.
324 //
325 // Inputs:
326 //      - aecm              : Pointer to the AECM instance.
327 //      - far_spectrum      : Pointer to farend spectrum.
328 //      - far_q             : Q-domain of farend spectrum.
329 //      - nearEner          : Near end energy for current block in
330 //                            Q(aecm->dfaQDomain).
331 //
332 // Output:
333 //     - echoEst            : Estimated echo in Q(xfa_q+RESOLUTION_CHANNEL16).
334 //
335 void WebRtcAecm_CalcEnergies(AecmCore* aecm,
336                              const uint16_t* far_spectrum,
337                              const int16_t far_q,
338                              const uint32_t nearEner,
339                              int32_t* echoEst);
340 
341 ///////////////////////////////////////////////////////////////////////////////
342 // WebRtcAecm_CalcStepSize()
343 //
344 // This function calculates the step size used in channel estimation
345 //
346 // Inputs:
347 //      - aecm              : Pointer to the AECM instance.
348 //
349 // Return value:
350 //      - mu                : Stepsize in log2(), i.e. number of shifts.
351 //
352 int16_t WebRtcAecm_CalcStepSize(AecmCore* const aecm);
353 
354 ///////////////////////////////////////////////////////////////////////////////
355 // WebRtcAecm_UpdateChannel(...)
356 //
357 // This function performs channel estimation.
358 // NLMS and decision on channel storage.
359 //
360 // Inputs:
361 //      - aecm              : Pointer to the AECM instance.
362 //      - far_spectrum      : Absolute value of the farend signal in Q(far_q)
363 //      - far_q             : Q-domain of the farend signal
364 //      - dfa               : Absolute value of the nearend signal
365 //                            (Q[aecm->dfaQDomain])
366 //      - mu                : NLMS step size.
367 // Input/Output:
368 //      - echoEst           : Estimated echo in Q(far_q+RESOLUTION_CHANNEL16).
369 //
370 void WebRtcAecm_UpdateChannel(AecmCore* aecm,
371                               const uint16_t* far_spectrum,
372                               const int16_t far_q,
373                               const uint16_t* const dfa,
374                               const int16_t mu,
375                               int32_t* echoEst);
376 
377 extern const int16_t WebRtcAecm_kCosTable[];
378 extern const int16_t WebRtcAecm_kSinTable[];
379 
380 ///////////////////////////////////////////////////////////////////////////////
381 // Some function pointers, for internal functions shared by ARM NEON and
382 // generic C code.
383 //
384 typedef void (*CalcLinearEnergies)(AecmCore* aecm,
385                                    const uint16_t* far_spectrum,
386                                    int32_t* echoEst,
387                                    uint32_t* far_energy,
388                                    uint32_t* echo_energy_adapt,
389                                    uint32_t* echo_energy_stored);
390 extern CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
391 
392 typedef void (*StoreAdaptiveChannel)(AecmCore* aecm,
393                                      const uint16_t* far_spectrum,
394                                      int32_t* echo_est);
395 extern StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
396 
397 typedef void (*ResetAdaptiveChannel)(AecmCore* aecm);
398 extern ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
399 
400 // For the above function pointers, functions for generic platforms are declared
401 // and defined as static in file aecm_core.c, while those for ARM Neon platforms
402 // are declared below and defined in file aecm_core_neon.c.
403 #if defined(WEBRTC_DETECT_NEON) || defined(WEBRTC_HAS_NEON)
404 void WebRtcAecm_CalcLinearEnergiesNeon(AecmCore* aecm,
405                                        const uint16_t* far_spectrum,
406                                        int32_t* echo_est,
407                                        uint32_t* far_energy,
408                                        uint32_t* echo_energy_adapt,
409                                        uint32_t* echo_energy_stored);
410 
411 void WebRtcAecm_StoreAdaptiveChannelNeon(AecmCore* aecm,
412                                          const uint16_t* far_spectrum,
413                                          int32_t* echo_est);
414 
415 void WebRtcAecm_ResetAdaptiveChannelNeon(AecmCore* aecm);
416 #endif
417 
418 #if defined(MIPS32_LE)
419 void WebRtcAecm_CalcLinearEnergies_mips(AecmCore* aecm,
420                                         const uint16_t* far_spectrum,
421                                         int32_t* echo_est,
422                                         uint32_t* far_energy,
423                                         uint32_t* echo_energy_adapt,
424                                         uint32_t* echo_energy_stored);
425 #if defined(MIPS_DSP_R1_LE)
426 void WebRtcAecm_StoreAdaptiveChannel_mips(AecmCore* aecm,
427                                           const uint16_t* far_spectrum,
428                                           int32_t* echo_est);
429 
430 void WebRtcAecm_ResetAdaptiveChannel_mips(AecmCore* aecm);
431 #endif
432 #endif
433 
434 #endif
435