1e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/*
2e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *
4e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  Use of this source code is governed by a BSD-style license
5e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  that can be found in the LICENSE file in the root of the source
6e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  tree. An additional intellectual property rights grant can be found
7e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  in the file PATENTS.  All contributing project authors may
8e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  be found in the AUTHORS file in the root of the source tree.
9e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */
10e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
11e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/*
12e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * The core AEC algorithm, which is presented with time-aligned signals.
13e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */
14e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
15c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "aec_core.h"
16c55a96383497a772a307b346368133960b02ad03Eric Laurent
17c55a96383497a772a307b346368133960b02ad03Eric Laurent#include <assert.h>
18e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <math.h>
19c55a96383497a772a307b346368133960b02ad03Eric Laurent#include <stddef.h>  // size_t
20e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <stdlib.h>
21e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <string.h>
22e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
23e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "aec_rdft.h"
24c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "delay_estimator_wrapper.h"
25e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "ring_buffer.h"
26e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "system_wrappers/interface/cpu_features_wrapper.h"
27c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "typedefs.h"
28c55a96383497a772a307b346368133960b02ad03Eric Laurent
29c55a96383497a772a307b346368133960b02ad03Eric Laurent// Buffer size (samples)
30c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic const size_t kBufSizePartitions = 250;  // 1 second of audio in 16 kHz.
31e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
32e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// Noise suppression
33e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const int converged = 250;
34e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
35e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// Metrics
36e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const int subCountLen = 4;
37e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const int countLen = 50;
38e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
39e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// Quantities to control H band scaling for SWB input
40e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const int flagHbandCn = 1; // flag for adding comfort noise in H band
41e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const float cnScaleHband = (float)0.4; // scale for comfort noise in H band
42e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// Initial bin for averaging nlp gain in low band
43e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const int freqAvgIc = PART_LEN / 2;
44e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
45c55a96383497a772a307b346368133960b02ad03Eric Laurent// Matlab code to produce table:
46c55a96383497a772a307b346368133960b02ad03Eric Laurent// win = sqrt(hanning(63)); win = [0 ; win(1:32)];
47c55a96383497a772a307b346368133960b02ad03Eric Laurent// fprintf(1, '\t%.14f, %.14f, %.14f,\n', win);
48e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic const float sqrtHanning[65] = {
49e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.00000000000000f, 0.02454122852291f, 0.04906767432742f,
50e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.07356456359967f, 0.09801714032956f, 0.12241067519922f,
51e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.14673047445536f, 0.17096188876030f, 0.19509032201613f,
52e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.21910124015687f, 0.24298017990326f, 0.26671275747490f,
53e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.29028467725446f, 0.31368174039889f, 0.33688985339222f,
54e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.35989503653499f, 0.38268343236509f, 0.40524131400499f,
55e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.42755509343028f, 0.44961132965461f, 0.47139673682600f,
56e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.49289819222978f, 0.51410274419322f, 0.53499761988710f,
57e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.55557023301960f, 0.57580819141785f, 0.59569930449243f,
58e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.61523159058063f, 0.63439328416365f, 0.65317284295378f,
59e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.67155895484702f, 0.68954054473707f, 0.70710678118655f,
60e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.72424708295147f, 0.74095112535496f, 0.75720884650648f,
61e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.77301045336274f, 0.78834642762661f, 0.80320753148064f,
62e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.81758481315158f, 0.83146961230255f, 0.84485356524971f,
63e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.85772861000027f, 0.87008699110871f, 0.88192126434835f,
64e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.89322430119552f, 0.90398929312344f, 0.91420975570353f,
65e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.92387953251129f, 0.93299279883474f, 0.94154406518302f,
66e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.94952818059304f, 0.95694033573221f, 0.96377606579544f,
67e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.97003125319454f, 0.97570213003853f, 0.98078528040323f,
68e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.98527764238894f, 0.98917650996478f, 0.99247953459871f,
69e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.99518472667220f, 0.99729045667869f, 0.99879545620517f,
70e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.99969881869620f, 1.00000000000000f
71e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent};
72e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
73c55a96383497a772a307b346368133960b02ad03Eric Laurent// Matlab code to produce table:
74c55a96383497a772a307b346368133960b02ad03Eric Laurent// weightCurve = [0 ; 0.3 * sqrt(linspace(0,1,64))' + 0.1];
75c55a96383497a772a307b346368133960b02ad03Eric Laurent// fprintf(1, '\t%.4f, %.4f, %.4f, %.4f, %.4f, %.4f,\n', weightCurve);
76e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentconst float WebRtcAec_weightCurve[65] = {
77e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.0000f, 0.1000f, 0.1378f, 0.1535f, 0.1655f, 0.1756f,
78e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.1845f, 0.1926f, 0.2000f, 0.2069f, 0.2134f, 0.2195f,
79e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.2254f, 0.2309f, 0.2363f, 0.2414f, 0.2464f, 0.2512f,
80e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.2558f, 0.2604f, 0.2648f, 0.2690f, 0.2732f, 0.2773f,
81e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.2813f, 0.2852f, 0.2890f, 0.2927f, 0.2964f, 0.3000f,
82e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.3035f, 0.3070f, 0.3104f, 0.3138f, 0.3171f, 0.3204f,
83e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.3236f, 0.3268f, 0.3299f, 0.3330f, 0.3360f, 0.3390f,
84e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.3420f, 0.3449f, 0.3478f, 0.3507f, 0.3535f, 0.3563f,
85e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.3591f, 0.3619f, 0.3646f, 0.3673f, 0.3699f, 0.3726f,
86e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.3752f, 0.3777f, 0.3803f, 0.3828f, 0.3854f, 0.3878f,
87e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    0.3903f, 0.3928f, 0.3952f, 0.3976f, 0.4000f
88e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent};
89e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
90c55a96383497a772a307b346368133960b02ad03Eric Laurent// Matlab code to produce table:
91c55a96383497a772a307b346368133960b02ad03Eric Laurent// overDriveCurve = [sqrt(linspace(0,1,65))' + 1];
92c55a96383497a772a307b346368133960b02ad03Eric Laurent// fprintf(1, '\t%.4f, %.4f, %.4f, %.4f, %.4f, %.4f,\n', overDriveCurve);
93e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentconst float WebRtcAec_overDriveCurve[65] = {
94e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    1.0000f, 1.1250f, 1.1768f, 1.2165f, 1.2500f, 1.2795f,
95e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    1.3062f, 1.3307f, 1.3536f, 1.3750f, 1.3953f, 1.4146f,
96e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    1.4330f, 1.4507f, 1.4677f, 1.4841f, 1.5000f, 1.5154f,
97e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    1.5303f, 1.5449f, 1.5590f, 1.5728f, 1.5863f, 1.5995f,
98e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    1.6124f, 1.6250f, 1.6374f, 1.6495f, 1.6614f, 1.6731f,
99e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    1.6847f, 1.6960f, 1.7071f, 1.7181f, 1.7289f, 1.7395f,
100e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    1.7500f, 1.7603f, 1.7706f, 1.7806f, 1.7906f, 1.8004f,
101e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    1.8101f, 1.8197f, 1.8292f, 1.8385f, 1.8478f, 1.8570f,
102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    1.8660f, 1.8750f, 1.8839f, 1.8927f, 1.9014f, 1.9100f,
103e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    1.9186f, 1.9270f, 1.9354f, 1.9437f, 1.9520f, 1.9601f,
104e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    1.9682f, 1.9763f, 1.9843f, 1.9922f, 2.0000f
105e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent};
106e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
107e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// "Private" function prototypes.
108c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic void ProcessBlock(aec_t* aec);
109e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
110e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void NonLinearProcessing(aec_t *aec, short *output, short *outputH);
111e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
112e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void GetHighbandGain(const float *lambda, float *nlpGainHband);
113e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
114e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// Comfort_noise also computes noise for H band returned in comfortNoiseHband
115e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void ComfortNoise(aec_t *aec, float efw[2][PART_LEN1],
116e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                  complex_t *comfortNoiseHband,
117e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                  const float *noisePow, const float *lambda);
118e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
119e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void WebRtcAec_InitLevel(power_level_t *level);
120e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void WebRtcAec_InitStats(stats_t *stats);
121c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic void UpdateLevel(power_level_t* level, float in[2][PART_LEN1]);
122e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void UpdateMetrics(aec_t *aec);
123c55a96383497a772a307b346368133960b02ad03Eric Laurent// Convert from time domain to frequency domain. Note that |time_data| are
124c55a96383497a772a307b346368133960b02ad03Eric Laurent// overwritten.
125c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic void TimeToFrequency(float time_data[PART_LEN2],
126c55a96383497a772a307b346368133960b02ad03Eric Laurent                            float freq_data[2][PART_LEN1],
127c55a96383497a772a307b346368133960b02ad03Eric Laurent                            int window);
128e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
129e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent__inline static float MulRe(float aRe, float aIm, float bRe, float bIm)
130e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
131e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return aRe * bRe - aIm * bIm;
132e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
133e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
134e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent__inline static float MulIm(float aRe, float aIm, float bRe, float bIm)
135e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
136e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return aRe * bIm + aIm * bRe;
137e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
138e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
139e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic int CmpFloat(const void *a, const void *b)
140e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
141e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float *da = (const float *)a;
142e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float *db = (const float *)b;
143e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
144e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return (*da > *db) - (*da < *db);
145e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
146e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
147e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAec_CreateAec(aec_t **aecInst)
148e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
149e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec_t *aec = malloc(sizeof(aec_t));
150e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    *aecInst = aec;
151e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec == NULL) {
152e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return -1;
153e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
154e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
155c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_CreateBuffer(&aec->nearFrBuf,
156c55a96383497a772a307b346368133960b02ad03Eric Laurent                            FRAME_LEN + PART_LEN,
157c55a96383497a772a307b346368133960b02ad03Eric Laurent                            sizeof(int16_t)) == -1) {
158e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        WebRtcAec_FreeAec(aec);
159e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec = NULL;
160e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return -1;
161e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
162e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
163c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_CreateBuffer(&aec->outFrBuf,
164c55a96383497a772a307b346368133960b02ad03Eric Laurent                            FRAME_LEN + PART_LEN,
165c55a96383497a772a307b346368133960b02ad03Eric Laurent                            sizeof(int16_t)) == -1) {
166e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        WebRtcAec_FreeAec(aec);
167e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec = NULL;
168e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return -1;
169e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
170e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
171c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_CreateBuffer(&aec->nearFrBufH,
172c55a96383497a772a307b346368133960b02ad03Eric Laurent                            FRAME_LEN + PART_LEN,
173c55a96383497a772a307b346368133960b02ad03Eric Laurent                            sizeof(int16_t)) == -1) {
174e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        WebRtcAec_FreeAec(aec);
175e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec = NULL;
176e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return -1;
177e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
178e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
179c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_CreateBuffer(&aec->outFrBufH,
180c55a96383497a772a307b346368133960b02ad03Eric Laurent                            FRAME_LEN + PART_LEN,
181c55a96383497a772a307b346368133960b02ad03Eric Laurent                            sizeof(int16_t)) == -1) {
182e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        WebRtcAec_FreeAec(aec);
183e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec = NULL;
184e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return -1;
185e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
186e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
187c55a96383497a772a307b346368133960b02ad03Eric Laurent    // Create far-end buffers.
188c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_CreateBuffer(&aec->far_buf, kBufSizePartitions,
189c55a96383497a772a307b346368133960b02ad03Eric Laurent                            sizeof(float) * 2 * PART_LEN1) == -1) {
190c55a96383497a772a307b346368133960b02ad03Eric Laurent        WebRtcAec_FreeAec(aec);
191c55a96383497a772a307b346368133960b02ad03Eric Laurent        aec = NULL;
192c55a96383497a772a307b346368133960b02ad03Eric Laurent        return -1;
193c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
194c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_CreateBuffer(&aec->far_buf_windowed, kBufSizePartitions,
195c55a96383497a772a307b346368133960b02ad03Eric Laurent                            sizeof(float) * 2 * PART_LEN1) == -1) {
196c55a96383497a772a307b346368133960b02ad03Eric Laurent        WebRtcAec_FreeAec(aec);
197c55a96383497a772a307b346368133960b02ad03Eric Laurent        aec = NULL;
198c55a96383497a772a307b346368133960b02ad03Eric Laurent        return -1;
199c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
200c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AEC_DEBUG_DUMP
201c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_CreateBuffer(&aec->far_time_buf, kBufSizePartitions,
202c55a96383497a772a307b346368133960b02ad03Eric Laurent                            sizeof(int16_t) * PART_LEN) == -1) {
203e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        WebRtcAec_FreeAec(aec);
204e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec = NULL;
205e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return -1;
206e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
207c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
208c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_CreateDelayEstimator(&aec->delay_estimator,
209c55a96383497a772a307b346368133960b02ad03Eric Laurent                                    PART_LEN1,
210c55a96383497a772a307b346368133960b02ad03Eric Laurent                                    kMaxDelayBlocks,
211c55a96383497a772a307b346368133960b02ad03Eric Laurent                                    kLookaheadBlocks) == -1) {
212c55a96383497a772a307b346368133960b02ad03Eric Laurent      WebRtcAec_FreeAec(aec);
213c55a96383497a772a307b346368133960b02ad03Eric Laurent      aec = NULL;
214c55a96383497a772a307b346368133960b02ad03Eric Laurent      return -1;
215c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
216e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
217e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return 0;
218e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
219e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
220e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAec_FreeAec(aec_t *aec)
221e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
222e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec == NULL) {
223e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return -1;
224e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
225e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
226c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_FreeBuffer(aec->nearFrBuf);
227c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_FreeBuffer(aec->outFrBuf);
228e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
229c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_FreeBuffer(aec->nearFrBufH);
230c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_FreeBuffer(aec->outFrBufH);
231c55a96383497a772a307b346368133960b02ad03Eric Laurent
232c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_FreeBuffer(aec->far_buf);
233c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_FreeBuffer(aec->far_buf_windowed);
234c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AEC_DEBUG_DUMP
235c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_FreeBuffer(aec->far_time_buf);
236c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
237c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_FreeDelayEstimator(aec->delay_estimator);
238e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
239e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    free(aec);
240e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return 0;
241e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
242e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
243e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void FilterFar(aec_t *aec, float yf[2][PART_LEN1])
244e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
245e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  int i;
246e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  for (i = 0; i < NR_PART; i++) {
247e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int j;
248e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int xPos = (i + aec->xfBufBlockPos) * PART_LEN1;
249e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int pos = i * PART_LEN1;
250e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Check for wrap
251e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (i + aec->xfBufBlockPos >= NR_PART) {
252e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      xPos -= NR_PART*(PART_LEN1);
253e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
254e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
255e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (j = 0; j < PART_LEN1; j++) {
256e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      yf[0][j] += MulRe(aec->xfBuf[0][xPos + j], aec->xfBuf[1][xPos + j],
257e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                        aec->wfBuf[0][ pos + j], aec->wfBuf[1][ pos + j]);
258e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      yf[1][j] += MulIm(aec->xfBuf[0][xPos + j], aec->xfBuf[1][xPos + j],
259e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                        aec->wfBuf[0][ pos + j], aec->wfBuf[1][ pos + j]);
260e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
261e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
262e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
263e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
264e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void ScaleErrorSignal(aec_t *aec, float ef[2][PART_LEN1])
265e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
266e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  int i;
267e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  float absEf;
268e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  for (i = 0; i < (PART_LEN1); i++) {
269e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    ef[0][i] /= (aec->xPow[i] + 1e-10f);
270e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    ef[1][i] /= (aec->xPow[i] + 1e-10f);
271e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    absEf = sqrtf(ef[0][i] * ef[0][i] + ef[1][i] * ef[1][i]);
272e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
273e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (absEf > aec->errThresh) {
274e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      absEf = aec->errThresh / (absEf + 1e-10f);
275e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      ef[0][i] *= absEf;
276e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      ef[1][i] *= absEf;
277e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
278e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
279e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Stepsize factor
280e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    ef[0][i] *= aec->mu;
281e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    ef[1][i] *= aec->mu;
282e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
283e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
284e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
285c55a96383497a772a307b346368133960b02ad03Eric Laurent// Time-unconstrined filter adaptation.
286c55a96383497a772a307b346368133960b02ad03Eric Laurent// TODO(andrew): consider for a low-complexity mode.
287c55a96383497a772a307b346368133960b02ad03Eric Laurent//static void FilterAdaptationUnconstrained(aec_t *aec, float *fft,
288c55a96383497a772a307b346368133960b02ad03Eric Laurent//                                          float ef[2][PART_LEN1]) {
289c55a96383497a772a307b346368133960b02ad03Eric Laurent//  int i, j;
290c55a96383497a772a307b346368133960b02ad03Eric Laurent//  for (i = 0; i < NR_PART; i++) {
291c55a96383497a772a307b346368133960b02ad03Eric Laurent//    int xPos = (i + aec->xfBufBlockPos)*(PART_LEN1);
292c55a96383497a772a307b346368133960b02ad03Eric Laurent//    int pos;
293c55a96383497a772a307b346368133960b02ad03Eric Laurent//    // Check for wrap
294c55a96383497a772a307b346368133960b02ad03Eric Laurent//    if (i + aec->xfBufBlockPos >= NR_PART) {
295c55a96383497a772a307b346368133960b02ad03Eric Laurent//      xPos -= NR_PART * PART_LEN1;
296c55a96383497a772a307b346368133960b02ad03Eric Laurent//    }
297c55a96383497a772a307b346368133960b02ad03Eric Laurent//
298c55a96383497a772a307b346368133960b02ad03Eric Laurent//    pos = i * PART_LEN1;
299c55a96383497a772a307b346368133960b02ad03Eric Laurent//
300c55a96383497a772a307b346368133960b02ad03Eric Laurent//    for (j = 0; j < PART_LEN1; j++) {
301c55a96383497a772a307b346368133960b02ad03Eric Laurent//      aec->wfBuf[pos + j][0] += MulRe(aec->xfBuf[xPos + j][0],
302c55a96383497a772a307b346368133960b02ad03Eric Laurent//                                      -aec->xfBuf[xPos + j][1],
303c55a96383497a772a307b346368133960b02ad03Eric Laurent//                                      ef[j][0], ef[j][1]);
304c55a96383497a772a307b346368133960b02ad03Eric Laurent//      aec->wfBuf[pos + j][1] += MulIm(aec->xfBuf[xPos + j][0],
305c55a96383497a772a307b346368133960b02ad03Eric Laurent//                                      -aec->xfBuf[xPos + j][1],
306c55a96383497a772a307b346368133960b02ad03Eric Laurent//                                      ef[j][0], ef[j][1]);
307c55a96383497a772a307b346368133960b02ad03Eric Laurent//    }
308c55a96383497a772a307b346368133960b02ad03Eric Laurent//  }
309c55a96383497a772a307b346368133960b02ad03Eric Laurent//}
310c55a96383497a772a307b346368133960b02ad03Eric Laurent
311e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void FilterAdaptation(aec_t *aec, float *fft, float ef[2][PART_LEN1]) {
312e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  int i, j;
313e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  for (i = 0; i < NR_PART; i++) {
314e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int xPos = (i + aec->xfBufBlockPos)*(PART_LEN1);
315e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int pos;
316e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Check for wrap
317e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (i + aec->xfBufBlockPos >= NR_PART) {
318e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      xPos -= NR_PART * PART_LEN1;
319e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
320e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
321e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    pos = i * PART_LEN1;
322e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
323e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (j = 0; j < PART_LEN; j++) {
324e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
325e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      fft[2 * j] = MulRe(aec->xfBuf[0][xPos + j],
326e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                         -aec->xfBuf[1][xPos + j],
327e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                         ef[0][j], ef[1][j]);
328e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      fft[2 * j + 1] = MulIm(aec->xfBuf[0][xPos + j],
329e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                             -aec->xfBuf[1][xPos + j],
330e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                             ef[0][j], ef[1][j]);
331e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
332e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    fft[1] = MulRe(aec->xfBuf[0][xPos + PART_LEN],
333e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                   -aec->xfBuf[1][xPos + PART_LEN],
334e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                   ef[0][PART_LEN], ef[1][PART_LEN]);
335e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
336e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec_rdft_inverse_128(fft);
337e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(fft + PART_LEN, 0, sizeof(float) * PART_LEN);
338e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
339e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // fft scaling
340e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    {
341e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      float scale = 2.0f / PART_LEN2;
342e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      for (j = 0; j < PART_LEN; j++) {
343e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        fft[j] *= scale;
344e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      }
345e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
346e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec_rdft_forward_128(fft);
347e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
348e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->wfBuf[0][pos] += fft[0];
349e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->wfBuf[0][pos + PART_LEN] += fft[1];
350e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
351e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (j = 1; j < PART_LEN; j++) {
352e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      aec->wfBuf[0][pos + j] += fft[2 * j];
353e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      aec->wfBuf[1][pos + j] += fft[2 * j + 1];
354e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
355e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
356e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
357e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
358e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void OverdriveAndSuppress(aec_t *aec, float hNl[PART_LEN1],
359e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                 const float hNlFb,
360e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                 float efw[2][PART_LEN1]) {
361e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  int i;
362e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  for (i = 0; i < PART_LEN1; i++) {
363e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Weight subbands
364e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (hNl[i] > hNlFb) {
365e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      hNl[i] = WebRtcAec_weightCurve[i] * hNlFb +
366e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          (1 - WebRtcAec_weightCurve[i]) * hNl[i];
367e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
368e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    hNl[i] = powf(hNl[i], aec->overDriveSm * WebRtcAec_overDriveCurve[i]);
369e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
370e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Suppress error signal
371e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    efw[0][i] *= hNl[i];
372e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    efw[1][i] *= hNl[i];
373e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
374e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Ooura fft returns incorrect sign on imaginary component. It matters here
375e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // because we are making an additive change with comfort noise.
376e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    efw[1][i] *= -1;
377e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
378e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
379e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
380e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebRtcAec_FilterFar_t WebRtcAec_FilterFar;
381e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebRtcAec_ScaleErrorSignal_t WebRtcAec_ScaleErrorSignal;
382e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebRtcAec_FilterAdaptation_t WebRtcAec_FilterAdaptation;
383e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebRtcAec_OverdriveAndSuppress_t WebRtcAec_OverdriveAndSuppress;
384e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
385e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint WebRtcAec_InitAec(aec_t *aec, int sampFreq)
386e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
387e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int i;
388e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
389e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->sampFreq = sampFreq;
390e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
391e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (sampFreq == 8000) {
392e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->mu = 0.6f;
393e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->errThresh = 2e-6f;
394e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
395e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    else {
396e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->mu = 0.5f;
397e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->errThresh = 1.5e-6f;
398e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
399e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
400c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_InitBuffer(aec->nearFrBuf) == -1) {
401e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return -1;
402e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
403e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
404c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_InitBuffer(aec->outFrBuf) == -1) {
405e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return -1;
406e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
407e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
408c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_InitBuffer(aec->nearFrBufH) == -1) {
409e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return -1;
410e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
411e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
412c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_InitBuffer(aec->outFrBufH) == -1) {
413e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return -1;
414e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
415e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
416c55a96383497a772a307b346368133960b02ad03Eric Laurent    // Initialize far-end buffers.
417c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_InitBuffer(aec->far_buf) == -1) {
418c55a96383497a772a307b346368133960b02ad03Eric Laurent        return -1;
419c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
420c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_InitBuffer(aec->far_buf_windowed) == -1) {
421c55a96383497a772a307b346368133960b02ad03Eric Laurent        return -1;
422c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
423c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AEC_DEBUG_DUMP
424c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_InitBuffer(aec->far_time_buf) == -1) {
425e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return -1;
426e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
427c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
428c55a96383497a772a307b346368133960b02ad03Eric Laurent    aec->system_delay = 0;
429c55a96383497a772a307b346368133960b02ad03Eric Laurent
430c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (WebRtc_InitDelayEstimator(aec->delay_estimator) != 0) {
431c55a96383497a772a307b346368133960b02ad03Eric Laurent      return -1;
432c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
433c55a96383497a772a307b346368133960b02ad03Eric Laurent    aec->delay_logging_enabled = 0;
434c55a96383497a772a307b346368133960b02ad03Eric Laurent    memset(aec->delay_histogram, 0, sizeof(aec->delay_histogram));
435e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
436e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Default target suppression level
437e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->targetSupp = -11.5;
438e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->minOverDrive = 2.0;
439e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
440e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Sampling frequency multiplier
441e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // SWB is processed as 160 frame size
442e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->sampFreq == 32000) {
443e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      aec->mult = (short)aec->sampFreq / 16000;
444e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
445e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    else {
446e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->mult = (short)aec->sampFreq / 8000;
447e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
448e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
449e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->farBufWritePos = 0;
450e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->farBufReadPos = 0;
451e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
452e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->inSamples = 0;
453e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->outSamples = 0;
454e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->knownDelay = 0;
455e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
456e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Initialize buffers
457e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->dBuf, 0, sizeof(aec->dBuf));
458e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->eBuf, 0, sizeof(aec->eBuf));
459e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // For H band
460e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->dBufH, 0, sizeof(aec->dBufH));
461e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
462e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->xPow, 0, sizeof(aec->xPow));
463e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->dPow, 0, sizeof(aec->dPow));
464e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->dInitMinPow, 0, sizeof(aec->dInitMinPow));
465e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->noisePow = aec->dInitMinPow;
466e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->noiseEstCtr = 0;
467e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
468e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Initial comfort noise power
469e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN1; i++) {
470e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->dMinPow[i] = 1.0e6f;
471e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
472e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
473e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Holds the last block written to
474e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->xfBufBlockPos = 0;
475e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // TODO: Investigate need for these initializations. Deleting them doesn't
476e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    //       change the output at all and yields 0.4% overall speedup.
477e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->xfBuf, 0, sizeof(complex_t) * NR_PART * PART_LEN1);
478e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->wfBuf, 0, sizeof(complex_t) * NR_PART * PART_LEN1);
479e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->sde, 0, sizeof(complex_t) * PART_LEN1);
480e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->sxd, 0, sizeof(complex_t) * PART_LEN1);
481e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->xfwBuf, 0, sizeof(complex_t) * NR_PART * PART_LEN1);
482e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->se, 0, sizeof(float) * PART_LEN1);
483e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
484e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // To prevent numerical instability in the first block.
485e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN1; i++) {
486e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->sd[i] = 1;
487e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
488e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN1; i++) {
489e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->sx[i] = 1;
490e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
491e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
492e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->hNs, 0, sizeof(aec->hNs));
493e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(aec->outBuf, 0, sizeof(float) * PART_LEN);
494e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
495e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->hNlFbMin = 1;
496e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->hNlFbLocalMin = 1;
497e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->hNlXdAvgMin = 1;
498e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->hNlNewMin = 0;
499e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->hNlMinCtr = 0;
500e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->overDrive = 2;
501e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->overDriveSm = 2;
502e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->delayIdx = 0;
503e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->stNearState = 0;
504e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->echoState = 0;
505e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->divergeState = 0;
506e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
507e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->seed = 777;
508e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->delayEstCtr = 0;
509e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
510e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Metrics disabled by default
511e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->metricsMode = 0;
512e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_InitMetrics(aec);
513e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
514e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Assembly optimization
515e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_FilterFar = FilterFar;
516e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_ScaleErrorSignal = ScaleErrorSignal;
517e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_FilterAdaptation = FilterAdaptation;
518e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_OverdriveAndSuppress = OverdriveAndSuppress;
519e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (WebRtc_GetCPUInfo(kSSE2)) {
520c55a96383497a772a307b346368133960b02ad03Eric Laurent#if defined(WEBRTC_USE_SSE2)
521e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      WebRtcAec_InitAec_SSE2();
522e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif
523e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
524e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec_rdft_init();
525e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
526e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return 0;
527e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
528e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
529e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid WebRtcAec_InitMetrics(aec_t *aec)
530e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
531e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->stateCounter = 0;
532e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_InitLevel(&aec->farlevel);
533e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_InitLevel(&aec->nearlevel);
534e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_InitLevel(&aec->linoutlevel);
535e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_InitLevel(&aec->nlpoutlevel);
536e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
537e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_InitStats(&aec->erl);
538e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_InitStats(&aec->erle);
539e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_InitStats(&aec->aNlp);
540e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_InitStats(&aec->rerl);
541e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
542e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
543e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
544c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid WebRtcAec_BufferFarendPartition(aec_t *aec, const float* farend) {
545c55a96383497a772a307b346368133960b02ad03Eric Laurent  float fft[PART_LEN2];
546c55a96383497a772a307b346368133960b02ad03Eric Laurent  float xf[2][PART_LEN1];
547e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
548c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Check if the buffer is full, and in that case flush the oldest data.
549c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (WebRtc_available_write(aec->far_buf) < 1) {
550c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_MoveReadPtr(aec->far_buf, 1);
551c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_MoveReadPtr(aec->far_buf_windowed, 1);
552c55a96383497a772a307b346368133960b02ad03Eric Laurent    aec->system_delay -= PART_LEN;
553c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AEC_DEBUG_DUMP
554c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_MoveReadPtr(aec->far_time_buf, 1);
555c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
556c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
557c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Convert far-end partition to the frequency domain without windowing.
558c55a96383497a772a307b346368133960b02ad03Eric Laurent  memcpy(fft, farend, sizeof(float) * PART_LEN2);
559c55a96383497a772a307b346368133960b02ad03Eric Laurent  TimeToFrequency(fft, xf, 0);
560c55a96383497a772a307b346368133960b02ad03Eric Laurent  WebRtc_WriteBuffer(aec->far_buf, &xf[0][0], 1);
561c55a96383497a772a307b346368133960b02ad03Eric Laurent
562c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Convert far-end partition to the frequency domain with windowing.
563c55a96383497a772a307b346368133960b02ad03Eric Laurent  memcpy(fft, farend, sizeof(float) * PART_LEN2);
564c55a96383497a772a307b346368133960b02ad03Eric Laurent  TimeToFrequency(fft, xf, 1);
565c55a96383497a772a307b346368133960b02ad03Eric Laurent  WebRtc_WriteBuffer(aec->far_buf_windowed, &xf[0][0], 1);
566c55a96383497a772a307b346368133960b02ad03Eric Laurent}
567e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
568c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid WebRtcAec_ProcessFrame(aec_t *aec,
569c55a96383497a772a307b346368133960b02ad03Eric Laurent                            const short *nearend,
570c55a96383497a772a307b346368133960b02ad03Eric Laurent                            const short *nearendH,
571c55a96383497a772a307b346368133960b02ad03Eric Laurent                            int knownDelay)
572c55a96383497a772a307b346368133960b02ad03Eric Laurent{
573c55a96383497a772a307b346368133960b02ad03Eric Laurent    // For each frame the process is as follows:
574c55a96383497a772a307b346368133960b02ad03Eric Laurent    // 1) If the system_delay indicates on being too small for processing a
575c55a96383497a772a307b346368133960b02ad03Eric Laurent    //    frame we stuff the buffer with enough data for 10 ms.
576c55a96383497a772a307b346368133960b02ad03Eric Laurent    // 2) Adjust the buffer to the system delay, by moving the read pointer.
577c55a96383497a772a307b346368133960b02ad03Eric Laurent    // 3) If we can't move read pointer due to buffer size limitations we
578c55a96383497a772a307b346368133960b02ad03Eric Laurent    //    flush/stuff the buffer.
579c55a96383497a772a307b346368133960b02ad03Eric Laurent    // 4) Process as many partitions as possible.
580c55a96383497a772a307b346368133960b02ad03Eric Laurent    // 5) Update the |system_delay| with respect to a full frame of FRAME_LEN
581c55a96383497a772a307b346368133960b02ad03Eric Laurent    //    samples. Even though we will have data left to process (we work with
582c55a96383497a772a307b346368133960b02ad03Eric Laurent    //    partitions) we consider updating a whole frame, since that's the
583c55a96383497a772a307b346368133960b02ad03Eric Laurent    //    amount of data we input and output in audio_processing.
584c55a96383497a772a307b346368133960b02ad03Eric Laurent
585c55a96383497a772a307b346368133960b02ad03Eric Laurent    // TODO(bjornv): Investigate how we should round the delay difference; right
586c55a96383497a772a307b346368133960b02ad03Eric Laurent    // now we know that incoming |knownDelay| is underestimated when it's less
587c55a96383497a772a307b346368133960b02ad03Eric Laurent    // than |aec->knownDelay|. We therefore, round (-32) in that direction. In
588c55a96383497a772a307b346368133960b02ad03Eric Laurent    // the other direction, we don't have this situation, but might flush one
589c55a96383497a772a307b346368133960b02ad03Eric Laurent    // partition too little. This can cause non-causality, which should be
590c55a96383497a772a307b346368133960b02ad03Eric Laurent    // investigated. Maybe, allow for a non-symmetric rounding, like -16.
591c55a96383497a772a307b346368133960b02ad03Eric Laurent    int move_elements = (aec->knownDelay - knownDelay - 32) / PART_LEN;
592c55a96383497a772a307b346368133960b02ad03Eric Laurent    int moved_elements = 0;
593c55a96383497a772a307b346368133960b02ad03Eric Laurent
594c55a96383497a772a307b346368133960b02ad03Eric Laurent    // TODO(bjornv): Change the near-end buffer handling to be the same as for
595c55a96383497a772a307b346368133960b02ad03Eric Laurent    // far-end, that is, with a near_pre_buf.
596c55a96383497a772a307b346368133960b02ad03Eric Laurent    // Buffer the near-end frame.
597c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_WriteBuffer(aec->nearFrBuf, nearend, FRAME_LEN);
598e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // For H band
599e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->sampFreq == 32000) {
600c55a96383497a772a307b346368133960b02ad03Eric Laurent        WebRtc_WriteBuffer(aec->nearFrBufH, nearendH, FRAME_LEN);
601c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
602c55a96383497a772a307b346368133960b02ad03Eric Laurent
603c55a96383497a772a307b346368133960b02ad03Eric Laurent    // 1) At most we process |aec->mult|+1 partitions in 10 ms. Make sure we
604c55a96383497a772a307b346368133960b02ad03Eric Laurent    // have enough far-end data for that by stuffing the buffer if the
605c55a96383497a772a307b346368133960b02ad03Eric Laurent    // |system_delay| indicates others.
606c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (aec->system_delay < FRAME_LEN) {
607c55a96383497a772a307b346368133960b02ad03Eric Laurent      // We don't have enough data so we rewind 10 ms.
608c55a96383497a772a307b346368133960b02ad03Eric Laurent      WebRtc_MoveReadPtr(aec->far_buf_windowed, -(aec->mult + 1));
609c55a96383497a772a307b346368133960b02ad03Eric Laurent      aec->system_delay -= WebRtc_MoveReadPtr(aec->far_buf, -(aec->mult + 1)) *
610c55a96383497a772a307b346368133960b02ad03Eric Laurent          PART_LEN;
611c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AEC_DEBUG_DUMP
612c55a96383497a772a307b346368133960b02ad03Eric Laurent      WebRtc_MoveReadPtr(aec->far_time_buf, -(aec->mult + 1));
613c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
614e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
615e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
616c55a96383497a772a307b346368133960b02ad03Eric Laurent    // 2) Compensate for a possible change in the system delay.
617e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
618c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_MoveReadPtr(aec->far_buf_windowed, move_elements);
619c55a96383497a772a307b346368133960b02ad03Eric Laurent    moved_elements = WebRtc_MoveReadPtr(aec->far_buf, move_elements);
620c55a96383497a772a307b346368133960b02ad03Eric Laurent    aec->knownDelay -= moved_elements * PART_LEN;
621c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AEC_DEBUG_DUMP
622c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_MoveReadPtr(aec->far_time_buf, move_elements);
623c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
624e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
625c55a96383497a772a307b346368133960b02ad03Eric Laurent    // 4) Process as many blocks as possible.
626c55a96383497a772a307b346368133960b02ad03Eric Laurent    while (WebRtc_available_read(aec->nearFrBuf) >= PART_LEN) {
627c55a96383497a772a307b346368133960b02ad03Eric Laurent        ProcessBlock(aec);
628e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
629e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
630c55a96383497a772a307b346368133960b02ad03Eric Laurent    // 5) Update system delay with respect to the entire frame.
631c55a96383497a772a307b346368133960b02ad03Eric Laurent    aec->system_delay -= FRAME_LEN;
632e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
633e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
634c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic void ProcessBlock(aec_t* aec) {
635e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int i;
636e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float d[PART_LEN], y[PART_LEN], e[PART_LEN], dH[PART_LEN];
637e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float scale;
638e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
639e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float fft[PART_LEN2];
640e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float xf[2][PART_LEN1], yf[2][PART_LEN1], ef[2][PART_LEN1];
641c55a96383497a772a307b346368133960b02ad03Eric Laurent    float df[2][PART_LEN1];
642c55a96383497a772a307b346368133960b02ad03Eric Laurent    float far_spectrum = 0.0f;
643c55a96383497a772a307b346368133960b02ad03Eric Laurent    float near_spectrum = 0.0f;
644c55a96383497a772a307b346368133960b02ad03Eric Laurent    float abs_far_spectrum[PART_LEN1];
645c55a96383497a772a307b346368133960b02ad03Eric Laurent    float abs_near_spectrum[PART_LEN1];
646e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
647e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float gPow[2] = {0.9f, 0.1f};
648e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
649e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Noise estimate constants.
650e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const int noiseInitBlocks = 500 * aec->mult;
651e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float step = 0.1f;
652e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float ramp = 1.0002f;
653e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float gInitNoise[2] = {0.999f, 0.001f};
654e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
655c55a96383497a772a307b346368133960b02ad03Eric Laurent    int16_t nearend[PART_LEN];
656c55a96383497a772a307b346368133960b02ad03Eric Laurent    int16_t* nearend_ptr = NULL;
657c55a96383497a772a307b346368133960b02ad03Eric Laurent    int16_t output[PART_LEN];
658c55a96383497a772a307b346368133960b02ad03Eric Laurent    int16_t outputH[PART_LEN];
659c55a96383497a772a307b346368133960b02ad03Eric Laurent
660c55a96383497a772a307b346368133960b02ad03Eric Laurent    float* xf_ptr = NULL;
661e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
662e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(dH, 0, sizeof(dH));
663c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (aec->sampFreq == 32000) {
664c55a96383497a772a307b346368133960b02ad03Eric Laurent      // Get the upper band first so we can reuse |nearend|.
665c55a96383497a772a307b346368133960b02ad03Eric Laurent      WebRtc_ReadBuffer(aec->nearFrBufH,
666c55a96383497a772a307b346368133960b02ad03Eric Laurent                        (void**) &nearend_ptr,
667c55a96383497a772a307b346368133960b02ad03Eric Laurent                        nearend,
668c55a96383497a772a307b346368133960b02ad03Eric Laurent                        PART_LEN);
669c55a96383497a772a307b346368133960b02ad03Eric Laurent      for (i = 0; i < PART_LEN; i++) {
670c55a96383497a772a307b346368133960b02ad03Eric Laurent          dH[i] = (float) (nearend_ptr[i]);
671c55a96383497a772a307b346368133960b02ad03Eric Laurent      }
672c55a96383497a772a307b346368133960b02ad03Eric Laurent      memcpy(aec->dBufH + PART_LEN, dH, sizeof(float) * PART_LEN);
673c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
674c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_ReadBuffer(aec->nearFrBuf, (void**) &nearend_ptr, nearend, PART_LEN);
675e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
676e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // ---------- Ooura fft ----------
677c55a96383497a772a307b346368133960b02ad03Eric Laurent    // Concatenate old and new nearend blocks.
678e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN; i++) {
679c55a96383497a772a307b346368133960b02ad03Eric Laurent        d[i] = (float) (nearend_ptr[i]);
680e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
681e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memcpy(aec->dBuf + PART_LEN, d, sizeof(float) * PART_LEN);
682e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
683c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AEC_DEBUG_DUMP
684c55a96383497a772a307b346368133960b02ad03Eric Laurent    {
685c55a96383497a772a307b346368133960b02ad03Eric Laurent        int16_t farend[PART_LEN];
686c55a96383497a772a307b346368133960b02ad03Eric Laurent        int16_t* farend_ptr = NULL;
687c55a96383497a772a307b346368133960b02ad03Eric Laurent        WebRtc_ReadBuffer(aec->far_time_buf, (void**) &farend_ptr, farend, 1);
688c55a96383497a772a307b346368133960b02ad03Eric Laurent        fwrite(farend_ptr, sizeof(int16_t), PART_LEN, aec->farFile);
689c55a96383497a772a307b346368133960b02ad03Eric Laurent        fwrite(nearend_ptr, sizeof(int16_t), PART_LEN, aec->nearFile);
690e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
691c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif
692c55a96383497a772a307b346368133960b02ad03Eric Laurent
693c55a96383497a772a307b346368133960b02ad03Eric Laurent    // We should always have at least one element stored in |far_buf|.
694c55a96383497a772a307b346368133960b02ad03Eric Laurent    assert(WebRtc_available_read(aec->far_buf) > 0);
695c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_ReadBuffer(aec->far_buf, (void**) &xf_ptr, &xf[0][0], 1);
696e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
697e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Near fft
698e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memcpy(fft, aec->dBuf, sizeof(float) * PART_LEN2);
699c55a96383497a772a307b346368133960b02ad03Eric Laurent    TimeToFrequency(fft, df, 0);
700e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
701e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Power smoothing
702e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN1; i++) {
703c55a96383497a772a307b346368133960b02ad03Eric Laurent      far_spectrum = (xf_ptr[i] * xf_ptr[i]) +
704c55a96383497a772a307b346368133960b02ad03Eric Laurent          (xf_ptr[PART_LEN1 + i] * xf_ptr[PART_LEN1 + i]);
705c55a96383497a772a307b346368133960b02ad03Eric Laurent      aec->xPow[i] = gPow[0] * aec->xPow[i] + gPow[1] * NR_PART * far_spectrum;
706c55a96383497a772a307b346368133960b02ad03Eric Laurent      // Calculate absolute spectra
707c55a96383497a772a307b346368133960b02ad03Eric Laurent      abs_far_spectrum[i] = sqrtf(far_spectrum);
708c55a96383497a772a307b346368133960b02ad03Eric Laurent
709c55a96383497a772a307b346368133960b02ad03Eric Laurent      near_spectrum = df[0][i] * df[0][i] + df[1][i] * df[1][i];
710c55a96383497a772a307b346368133960b02ad03Eric Laurent      aec->dPow[i] = gPow[0] * aec->dPow[i] + gPow[1] * near_spectrum;
711c55a96383497a772a307b346368133960b02ad03Eric Laurent      // Calculate absolute spectra
712c55a96383497a772a307b346368133960b02ad03Eric Laurent      abs_near_spectrum[i] = sqrtf(near_spectrum);
713e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
714e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
715e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Estimate noise power. Wait until dPow is more stable.
716e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->noiseEstCtr > 50) {
717e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        for (i = 0; i < PART_LEN1; i++) {
718e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (aec->dPow[i] < aec->dMinPow[i]) {
719e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->dMinPow[i] = (aec->dPow[i] + step * (aec->dMinPow[i] -
720e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                    aec->dPow[i])) * ramp;
721e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
722e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            else {
723e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->dMinPow[i] *= ramp;
724e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
725e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
726e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
727e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
728e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Smooth increasing noise power from zero at the start,
729e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // to avoid a sudden burst of comfort noise.
730e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->noiseEstCtr < noiseInitBlocks) {
731e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->noiseEstCtr++;
732e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        for (i = 0; i < PART_LEN1; i++) {
733e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (aec->dMinPow[i] > aec->dInitMinPow[i]) {
734e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->dInitMinPow[i] = gInitNoise[0] * aec->dInitMinPow[i] +
735e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                    gInitNoise[1] * aec->dMinPow[i];
736e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
737e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            else {
738e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->dInitMinPow[i] = aec->dMinPow[i];
739e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
740e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
741e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->noisePow = aec->dInitMinPow;
742e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
743e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    else {
744e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->noisePow = aec->dMinPow;
745e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
746e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
747c55a96383497a772a307b346368133960b02ad03Eric Laurent    // Block wise delay estimation used for logging
748c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (aec->delay_logging_enabled) {
749c55a96383497a772a307b346368133960b02ad03Eric Laurent      int delay_estimate = 0;
750c55a96383497a772a307b346368133960b02ad03Eric Laurent      // Estimate the delay
751c55a96383497a772a307b346368133960b02ad03Eric Laurent      delay_estimate = WebRtc_DelayEstimatorProcessFloat(aec->delay_estimator,
752c55a96383497a772a307b346368133960b02ad03Eric Laurent                                                         abs_far_spectrum,
753c55a96383497a772a307b346368133960b02ad03Eric Laurent                                                         abs_near_spectrum,
754c55a96383497a772a307b346368133960b02ad03Eric Laurent                                                         PART_LEN1);
755c55a96383497a772a307b346368133960b02ad03Eric Laurent      if (delay_estimate >= 0) {
756c55a96383497a772a307b346368133960b02ad03Eric Laurent        // Update delay estimate buffer.
757c55a96383497a772a307b346368133960b02ad03Eric Laurent        aec->delay_histogram[delay_estimate]++;
758c55a96383497a772a307b346368133960b02ad03Eric Laurent      }
759c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
760e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
761e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Update the xfBuf block position.
762e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->xfBufBlockPos--;
763e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->xfBufBlockPos == -1) {
764e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->xfBufBlockPos = NR_PART - 1;
765e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
766e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
767e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Buffer xf
768c55a96383497a772a307b346368133960b02ad03Eric Laurent    memcpy(aec->xfBuf[0] + aec->xfBufBlockPos * PART_LEN1, xf_ptr,
769e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent           sizeof(float) * PART_LEN1);
770c55a96383497a772a307b346368133960b02ad03Eric Laurent    memcpy(aec->xfBuf[1] + aec->xfBufBlockPos * PART_LEN1, &xf_ptr[PART_LEN1],
771e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent           sizeof(float) * PART_LEN1);
772e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
773e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(yf[0], 0, sizeof(float) * (PART_LEN1 * 2));
774e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
775e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Filter far
776e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_FilterFar(aec, yf);
777e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
778e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Inverse fft to obtain echo estimate and error.
779e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    fft[0] = yf[0][0];
780e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    fft[1] = yf[0][PART_LEN];
781e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 1; i < PART_LEN; i++) {
782e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        fft[2 * i] = yf[0][i];
783e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        fft[2 * i + 1] = yf[1][i];
784e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
785e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec_rdft_inverse_128(fft);
786e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
787e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    scale = 2.0f / PART_LEN2;
788e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN; i++) {
789e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        y[i] = fft[PART_LEN + i] * scale; // fft scaling
790e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
791e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
792e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN; i++) {
793e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        e[i] = d[i] - y[i];
794e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
795e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
796e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Error fft
797e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memcpy(aec->eBuf + PART_LEN, e, sizeof(float) * PART_LEN);
798e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(fft, 0, sizeof(float) * PART_LEN);
799e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memcpy(fft + PART_LEN, e, sizeof(float) * PART_LEN);
800c55a96383497a772a307b346368133960b02ad03Eric Laurent    // TODO(bjornv): Change to use TimeToFrequency().
801e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec_rdft_forward_128(fft);
802e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
803e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    ef[1][0] = 0;
804e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    ef[1][PART_LEN] = 0;
805e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    ef[0][0] = fft[0];
806e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    ef[0][PART_LEN] = fft[1];
807e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 1; i < PART_LEN; i++) {
808e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        ef[0][i] = fft[2 * i];
809e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        ef[1][i] = fft[2 * i + 1];
810e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
811e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
812c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (aec->metricsMode == 1) {
813c55a96383497a772a307b346368133960b02ad03Eric Laurent      // Note that the first PART_LEN samples in fft (before transformation) are
814c55a96383497a772a307b346368133960b02ad03Eric Laurent      // zero. Hence, the scaling by two in UpdateLevel() should not be
815c55a96383497a772a307b346368133960b02ad03Eric Laurent      // performed. That scaling is taken care of in UpdateMetrics() instead.
816c55a96383497a772a307b346368133960b02ad03Eric Laurent      UpdateLevel(&aec->linoutlevel, ef);
817e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
818e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
819c55a96383497a772a307b346368133960b02ad03Eric Laurent    // Scale error signal inversely with far power.
820c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtcAec_ScaleErrorSignal(aec, ef);
821c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtcAec_FilterAdaptation(aec, fft, ef);
822e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    NonLinearProcessing(aec, output, outputH);
823e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
824c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (aec->metricsMode == 1) {
825c55a96383497a772a307b346368133960b02ad03Eric Laurent        // Update power levels and echo metrics
826c55a96383497a772a307b346368133960b02ad03Eric Laurent        UpdateLevel(&aec->farlevel, (float (*)[PART_LEN1]) xf_ptr);
827c55a96383497a772a307b346368133960b02ad03Eric Laurent        UpdateLevel(&aec->nearlevel, df);
828c55a96383497a772a307b346368133960b02ad03Eric Laurent        UpdateMetrics(aec);
829e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
830c55a96383497a772a307b346368133960b02ad03Eric Laurent
831c55a96383497a772a307b346368133960b02ad03Eric Laurent    // Store the output block.
832c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_WriteBuffer(aec->outFrBuf, output, PART_LEN);
833c55a96383497a772a307b346368133960b02ad03Eric Laurent    // For H band
834c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (aec->sampFreq == 32000) {
835c55a96383497a772a307b346368133960b02ad03Eric Laurent        WebRtc_WriteBuffer(aec->outFrBufH, outputH, PART_LEN);
836e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
837e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
838c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_AEC_DEBUG_DUMP
839c55a96383497a772a307b346368133960b02ad03Eric Laurent    {
840c55a96383497a772a307b346368133960b02ad03Eric Laurent        int16_t eInt16[PART_LEN];
841e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        for (i = 0; i < PART_LEN; i++) {
842c55a96383497a772a307b346368133960b02ad03Eric Laurent            eInt16[i] = (int16_t)WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, e[i],
843e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                WEBRTC_SPL_WORD16_MIN);
844e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
845e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
846c55a96383497a772a307b346368133960b02ad03Eric Laurent        fwrite(eInt16, sizeof(int16_t), PART_LEN, aec->outLinearFile);
847c55a96383497a772a307b346368133960b02ad03Eric Laurent        fwrite(output, sizeof(int16_t), PART_LEN, aec->outFile);
848e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
849e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#endif
850e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
851e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
852e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void NonLinearProcessing(aec_t *aec, short *output, short *outputH)
853e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
854c55a96383497a772a307b346368133960b02ad03Eric Laurent    float efw[2][PART_LEN1], dfw[2][PART_LEN1], xfw[2][PART_LEN1];
855e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    complex_t comfortNoiseHband[PART_LEN1];
856e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float fft[PART_LEN2];
857e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float scale, dtmp;
858e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float nlpGainHband;
859e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int i, j, pos;
860e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
861e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Coherence and non-linear filter
862e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float cohde[PART_LEN1], cohxd[PART_LEN1];
863e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float hNlDeAvg, hNlXdAvg;
864e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float hNl[PART_LEN1];
865e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float hNlPref[PREF_BAND_SIZE];
866e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float hNlFb = 0, hNlFbLow = 0;
867e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float prefBandQuant = 0.75f, prefBandQuantLow = 0.5f;
868e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const int prefBandSize = PREF_BAND_SIZE / aec->mult;
869e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const int minPrefBand = 4 / aec->mult;
870e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
871e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Near and error power sums
872e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float sdSum = 0, seSum = 0;
873e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
874e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Power estimate smoothing coefficients
875e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float gCoh[2][2] = {{0.9f, 0.1f}, {0.93f, 0.07f}};
876e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float *ptrGCoh = gCoh[aec->mult - 1];
877e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
878c55a96383497a772a307b346368133960b02ad03Eric Laurent    // Filter energy
879e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float wfEnMax = 0, wfEn = 0;
880e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const int delayEstInterval = 10 * aec->mult;
881e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
882c55a96383497a772a307b346368133960b02ad03Eric Laurent    float* xfw_ptr = NULL;
883c55a96383497a772a307b346368133960b02ad03Eric Laurent
884e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->delayEstCtr++;
885e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->delayEstCtr == delayEstInterval) {
886e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->delayEstCtr = 0;
887e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
888e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
889e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // initialize comfort noise for H band
890e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memset(comfortNoiseHband, 0, sizeof(comfortNoiseHband));
891e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    nlpGainHband = (float)0.0;
892e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    dtmp = (float)0.0;
893e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
894e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Measure energy in each filter partition to determine delay.
895e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // TODO: Spread by computing one partition per block?
896e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->delayEstCtr == 0) {
897e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        wfEnMax = 0;
898e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->delayIdx = 0;
899e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        for (i = 0; i < NR_PART; i++) {
900e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            pos = i * PART_LEN1;
901e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            wfEn = 0;
902e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            for (j = 0; j < PART_LEN1; j++) {
903e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                wfEn += aec->wfBuf[0][pos + j] * aec->wfBuf[0][pos + j] +
904e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                    aec->wfBuf[1][pos + j] * aec->wfBuf[1][pos + j];
905e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
906e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
907e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (wfEn > wfEnMax) {
908e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                wfEnMax = wfEn;
909e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->delayIdx = i;
910e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
911e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
912e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
913e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
914c55a96383497a772a307b346368133960b02ad03Eric Laurent    // We should always have at least one element stored in |far_buf|.
915c55a96383497a772a307b346368133960b02ad03Eric Laurent    assert(WebRtc_available_read(aec->far_buf_windowed) > 0);
916e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // NLP
917c55a96383497a772a307b346368133960b02ad03Eric Laurent    WebRtc_ReadBuffer(aec->far_buf_windowed, (void**) &xfw_ptr, &xfw[0][0], 1);
918e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
919c55a96383497a772a307b346368133960b02ad03Eric Laurent    // TODO(bjornv): Investigate if we can reuse |far_buf_windowed| instead of
920c55a96383497a772a307b346368133960b02ad03Eric Laurent    // |xfwBuf|.
921e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Buffer far.
922c55a96383497a772a307b346368133960b02ad03Eric Laurent    memcpy(aec->xfwBuf, xfw_ptr, sizeof(float) * 2 * PART_LEN1);
923e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
924e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Use delayed far.
925e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memcpy(xfw, aec->xfwBuf + aec->delayIdx * PART_LEN1, sizeof(xfw));
926e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
927e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Windowed near fft
928e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN; i++) {
929e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        fft[i] = aec->dBuf[i] * sqrtHanning[i];
930e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        fft[PART_LEN + i] = aec->dBuf[PART_LEN + i] * sqrtHanning[PART_LEN - i];
931e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
932e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec_rdft_forward_128(fft);
933e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
934e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    dfw[1][0] = 0;
935e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    dfw[1][PART_LEN] = 0;
936e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    dfw[0][0] = fft[0];
937e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    dfw[0][PART_LEN] = fft[1];
938e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 1; i < PART_LEN; i++) {
939e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        dfw[0][i] = fft[2 * i];
940e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        dfw[1][i] = fft[2 * i + 1];
941e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
942e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
943e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Windowed error fft
944e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN; i++) {
945e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        fft[i] = aec->eBuf[i] * sqrtHanning[i];
946e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        fft[PART_LEN + i] = aec->eBuf[PART_LEN + i] * sqrtHanning[PART_LEN - i];
947e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
948e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec_rdft_forward_128(fft);
949e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    efw[1][0] = 0;
950e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    efw[1][PART_LEN] = 0;
951e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    efw[0][0] = fft[0];
952e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    efw[0][PART_LEN] = fft[1];
953e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 1; i < PART_LEN; i++) {
954e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        efw[0][i] = fft[2 * i];
955e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        efw[1][i] = fft[2 * i + 1];
956e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
957e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
958e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Smoothed PSD
959e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN1; i++) {
960e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->sd[i] = ptrGCoh[0] * aec->sd[i] + ptrGCoh[1] *
961e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            (dfw[0][i] * dfw[0][i] + dfw[1][i] * dfw[1][i]);
962e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->se[i] = ptrGCoh[0] * aec->se[i] + ptrGCoh[1] *
963e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            (efw[0][i] * efw[0][i] + efw[1][i] * efw[1][i]);
964e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // We threshold here to protect against the ill-effects of a zero farend.
965e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // The threshold is not arbitrarily chosen, but balances protection and
966e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // adverse interaction with the algorithm's tuning.
967e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // TODO: investigate further why this is so sensitive.
968e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->sx[i] = ptrGCoh[0] * aec->sx[i] + ptrGCoh[1] *
969c55a96383497a772a307b346368133960b02ad03Eric Laurent            WEBRTC_SPL_MAX(xfw[0][i] * xfw[0][i] + xfw[1][i] * xfw[1][i], 15);
970e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
971e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->sde[i][0] = ptrGCoh[0] * aec->sde[i][0] + ptrGCoh[1] *
972e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            (dfw[0][i] * efw[0][i] + dfw[1][i] * efw[1][i]);
973e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->sde[i][1] = ptrGCoh[0] * aec->sde[i][1] + ptrGCoh[1] *
974e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            (dfw[0][i] * efw[1][i] - dfw[1][i] * efw[0][i]);
975e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
976e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->sxd[i][0] = ptrGCoh[0] * aec->sxd[i][0] + ptrGCoh[1] *
977c55a96383497a772a307b346368133960b02ad03Eric Laurent            (dfw[0][i] * xfw[0][i] + dfw[1][i] * xfw[1][i]);
978e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->sxd[i][1] = ptrGCoh[0] * aec->sxd[i][1] + ptrGCoh[1] *
979c55a96383497a772a307b346368133960b02ad03Eric Laurent            (dfw[0][i] * xfw[1][i] - dfw[1][i] * xfw[0][i]);
980e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
981e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        sdSum += aec->sd[i];
982e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        seSum += aec->se[i];
983e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
984e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
985e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Divergent filter safeguard.
986e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->divergeState == 0) {
987e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        if (seSum > sdSum) {
988e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->divergeState = 1;
989e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
990e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
991e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    else {
992e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        if (seSum * 1.05f < sdSum) {
993e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->divergeState = 0;
994e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
995e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
996e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
997e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->divergeState == 1) {
998e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        memcpy(efw, dfw, sizeof(efw));
999e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1000e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1001e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Reset if error is significantly larger than nearend (13 dB).
1002e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (seSum > (19.95f * sdSum)) {
1003e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        memset(aec->wfBuf, 0, sizeof(aec->wfBuf));
1004e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1005e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1006e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Subband coherence
1007e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN1; i++) {
1008e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        cohde[i] = (aec->sde[i][0] * aec->sde[i][0] + aec->sde[i][1] * aec->sde[i][1]) /
1009e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            (aec->sd[i] * aec->se[i] + 1e-10f);
1010e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        cohxd[i] = (aec->sxd[i][0] * aec->sxd[i][0] + aec->sxd[i][1] * aec->sxd[i][1]) /
1011e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            (aec->sx[i] * aec->sd[i] + 1e-10f);
1012e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1013e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1014e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    hNlXdAvg = 0;
1015e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = minPrefBand; i < prefBandSize + minPrefBand; i++) {
1016e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        hNlXdAvg += cohxd[i];
1017e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1018e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    hNlXdAvg /= prefBandSize;
1019e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    hNlXdAvg = 1 - hNlXdAvg;
1020e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1021e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    hNlDeAvg = 0;
1022e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = minPrefBand; i < prefBandSize + minPrefBand; i++) {
1023e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        hNlDeAvg += cohde[i];
1024e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1025e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    hNlDeAvg /= prefBandSize;
1026e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1027e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (hNlXdAvg < 0.75f && hNlXdAvg < aec->hNlXdAvgMin) {
1028e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->hNlXdAvgMin = hNlXdAvg;
1029e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1030e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1031e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (hNlDeAvg > 0.98f && hNlXdAvg > 0.9f) {
1032e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->stNearState = 1;
1033e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1034e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    else if (hNlDeAvg < 0.95f || hNlXdAvg < 0.8f) {
1035e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->stNearState = 0;
1036e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1037e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1038e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->hNlXdAvgMin == 1) {
1039e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->echoState = 0;
1040e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->overDrive = aec->minOverDrive;
1041e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1042e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        if (aec->stNearState == 1) {
1043e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            memcpy(hNl, cohde, sizeof(hNl));
1044e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            hNlFb = hNlDeAvg;
1045e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            hNlFbLow = hNlDeAvg;
1046e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
1047e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        else {
1048e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            for (i = 0; i < PART_LEN1; i++) {
1049e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                hNl[i] = 1 - cohxd[i];
1050e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1051e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            hNlFb = hNlXdAvg;
1052e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            hNlFbLow = hNlXdAvg;
1053e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
1054e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1055e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    else {
1056e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1057e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        if (aec->stNearState == 1) {
1058e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->echoState = 0;
1059e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            memcpy(hNl, cohde, sizeof(hNl));
1060e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            hNlFb = hNlDeAvg;
1061e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            hNlFbLow = hNlDeAvg;
1062e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
1063e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        else {
1064e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->echoState = 1;
1065e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            for (i = 0; i < PART_LEN1; i++) {
1066e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                hNl[i] = WEBRTC_SPL_MIN(cohde[i], 1 - cohxd[i]);
1067e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1068e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1069e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // Select an order statistic from the preferred bands.
1070e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // TODO: Using quicksort now, but a selection algorithm may be preferred.
1071e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            memcpy(hNlPref, &hNl[minPrefBand], sizeof(float) * prefBandSize);
1072e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            qsort(hNlPref, prefBandSize, sizeof(float), CmpFloat);
1073e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            hNlFb = hNlPref[(int)floor(prefBandQuant * (prefBandSize - 1))];
1074e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            hNlFbLow = hNlPref[(int)floor(prefBandQuantLow * (prefBandSize - 1))];
1075e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
1076e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1077e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1078e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Track the local filter minimum to determine suppression overdrive.
1079e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (hNlFbLow < 0.6f && hNlFbLow < aec->hNlFbLocalMin) {
1080e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->hNlFbLocalMin = hNlFbLow;
1081e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->hNlFbMin = hNlFbLow;
1082e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->hNlNewMin = 1;
1083e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->hNlMinCtr = 0;
1084e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1085e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->hNlFbLocalMin = WEBRTC_SPL_MIN(aec->hNlFbLocalMin + 0.0008f / aec->mult, 1);
1086e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec->hNlXdAvgMin = WEBRTC_SPL_MIN(aec->hNlXdAvgMin + 0.0006f / aec->mult, 1);
1087e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1088e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->hNlNewMin == 1) {
1089e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->hNlMinCtr++;
1090e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1091e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->hNlMinCtr == 2) {
1092e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->hNlNewMin = 0;
1093e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->hNlMinCtr = 0;
1094e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->overDrive = WEBRTC_SPL_MAX(aec->targetSupp /
1095e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            ((float)log(aec->hNlFbMin + 1e-10f) + 1e-10f), aec->minOverDrive);
1096e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1097e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1098e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Smooth the overdrive.
1099e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->overDrive < aec->overDriveSm) {
1100e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      aec->overDriveSm = 0.99f * aec->overDriveSm + 0.01f * aec->overDrive;
1101e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    else {
1103e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      aec->overDriveSm = 0.9f * aec->overDriveSm + 0.1f * aec->overDrive;
1104e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1105e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1106e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcAec_OverdriveAndSuppress(aec, hNl, hNlFb, efw);
1107e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1108e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Add comfort noise.
1109e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    ComfortNoise(aec, efw, comfortNoiseHband, aec->noisePow, hNl);
1110e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1111c55a96383497a772a307b346368133960b02ad03Eric Laurent    // TODO(bjornv): Investigate how to take the windowing below into account if
1112c55a96383497a772a307b346368133960b02ad03Eric Laurent    // needed.
1113c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (aec->metricsMode == 1) {
1114c55a96383497a772a307b346368133960b02ad03Eric Laurent      // Note that we have a scaling by two in the time domain |eBuf|.
1115c55a96383497a772a307b346368133960b02ad03Eric Laurent      // In addition the time domain signal is windowed before transformation,
1116c55a96383497a772a307b346368133960b02ad03Eric Laurent      // losing half the energy on the average. We take care of the first
1117c55a96383497a772a307b346368133960b02ad03Eric Laurent      // scaling only in UpdateMetrics().
1118c55a96383497a772a307b346368133960b02ad03Eric Laurent      UpdateLevel(&aec->nlpoutlevel, efw);
1119c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
1120e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Inverse error fft.
1121e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    fft[0] = efw[0][0];
1122e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    fft[1] = efw[0][PART_LEN];
1123e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 1; i < PART_LEN; i++) {
1124e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        fft[2*i] = efw[0][i];
1125e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // Sign change required by Ooura fft.
1126e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        fft[2*i + 1] = -efw[1][i];
1127e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1128e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    aec_rdft_inverse_128(fft);
1129e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1130e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Overlap and add to obtain output.
1131e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    scale = 2.0f / PART_LEN2;
1132e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN; i++) {
1133e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        fft[i] *= scale; // fft scaling
1134e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        fft[i] = fft[i]*sqrtHanning[i] + aec->outBuf[i];
1135e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1136e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // Saturation protection
1137e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        output[i] = (short)WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, fft[i],
1138e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            WEBRTC_SPL_WORD16_MIN);
1139e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1140e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        fft[PART_LEN + i] *= scale; // fft scaling
1141e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->outBuf[i] = fft[PART_LEN + i] * sqrtHanning[PART_LEN - i];
1142e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1143e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1144e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // For H band
1145e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->sampFreq == 32000) {
1146e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1147e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // H band gain
1148e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // average nlp over low band: average over second half of freq spectrum
1149e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // (4->8khz)
1150e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        GetHighbandGain(hNl, &nlpGainHband);
1151e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1152e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // Inverse comfort_noise
1153e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        if (flagHbandCn == 1) {
1154e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            fft[0] = comfortNoiseHband[0][0];
1155e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            fft[1] = comfortNoiseHband[PART_LEN][0];
1156e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            for (i = 1; i < PART_LEN; i++) {
1157e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                fft[2*i] = comfortNoiseHband[i][0];
1158e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                fft[2*i + 1] = comfortNoiseHband[i][1];
1159e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1160e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec_rdft_inverse_128(fft);
1161e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            scale = 2.0f / PART_LEN2;
1162e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
1163e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1164e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // compute gain factor
1165e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        for (i = 0; i < PART_LEN; i++) {
1166e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            dtmp = (float)aec->dBufH[i];
1167e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            dtmp = (float)dtmp * nlpGainHband; // for variable gain
1168e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1169e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // add some comfort noise where Hband is attenuated
1170e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (flagHbandCn == 1) {
1171e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                fft[i] *= scale; // fft scaling
1172e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                dtmp += cnScaleHband * fft[i];
1173e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1174e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1175e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // Saturation protection
1176e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            outputH[i] = (short)WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, dtmp,
1177e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                WEBRTC_SPL_WORD16_MIN);
1178e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent         }
1179e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1180e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1181e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Copy the current block to the old position.
1182e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memcpy(aec->dBuf, aec->dBuf + PART_LEN, sizeof(float) * PART_LEN);
1183e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memcpy(aec->eBuf, aec->eBuf + PART_LEN, sizeof(float) * PART_LEN);
1184e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1185e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Copy the current block to the old position for H band
1186e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->sampFreq == 32000) {
1187e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        memcpy(aec->dBufH, aec->dBufH + PART_LEN, sizeof(float) * PART_LEN);
1188e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1189e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1190e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    memmove(aec->xfwBuf + PART_LEN1, aec->xfwBuf, sizeof(aec->xfwBuf) -
1191e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        sizeof(complex_t) * PART_LEN1);
1192e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
1193e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1194e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void GetHighbandGain(const float *lambda, float *nlpGainHband)
1195e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
1196e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int i;
1197e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1198e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    nlpGainHband[0] = (float)0.0;
1199e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = freqAvgIc; i < PART_LEN1 - 1; i++) {
1200e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        nlpGainHband[0] += lambda[i];
1201e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1202e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    nlpGainHband[0] /= (float)(PART_LEN1 - 1 - freqAvgIc);
1203e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
1204e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1205e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void ComfortNoise(aec_t *aec, float efw[2][PART_LEN1],
1206e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    complex_t *comfortNoiseHband, const float *noisePow, const float *lambda)
1207e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
1208e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int i, num;
1209e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float rand[PART_LEN];
1210e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float noise, noiseAvg, tmp, tmpAvg;
1211e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtc_Word16 randW16[PART_LEN];
1212e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    complex_t u[PART_LEN1];
1213e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1214e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float pi2 = 6.28318530717959f;
1215e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1216e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Generate a uniform random array on [0 1]
1217e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtcSpl_RandUArray(randW16, PART_LEN, &aec->seed);
1218e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN; i++) {
1219e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        rand[i] = ((float)randW16[i]) / 32768;
1220e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1221e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1222e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Reject LF noise
1223e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    u[0][0] = 0;
1224e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    u[0][1] = 0;
1225e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 1; i < PART_LEN1; i++) {
1226e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        tmp = pi2 * rand[i - 1];
1227e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1228e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        noise = sqrtf(noisePow[i]);
1229e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        u[i][0] = noise * (float)cos(tmp);
1230e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        u[i][1] = -noise * (float)sin(tmp);
1231e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1232e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    u[PART_LEN][1] = 0;
1233e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1234e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (i = 0; i < PART_LEN1; i++) {
1235e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // This is the proper weighting to match the background noise power
1236e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        tmp = sqrtf(WEBRTC_SPL_MAX(1 - lambda[i] * lambda[i], 0));
1237e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        //tmp = 1 - lambda[i];
1238e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        efw[0][i] += tmp * u[i][0];
1239e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        efw[1][i] += tmp * u[i][1];
1240e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1241e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1242e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // For H band comfort noise
1243e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // TODO: don't compute noise and "tmp" twice. Use the previous results.
1244e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    noiseAvg = 0.0;
1245e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    tmpAvg = 0.0;
1246e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    num = 0;
1247e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->sampFreq == 32000 && flagHbandCn == 1) {
1248e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1249e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // average noise scale
1250e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // average over second half of freq spectrum (i.e., 4->8khz)
1251e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // TODO: we shouldn't need num. We know how many elements we're summing.
1252e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        for (i = PART_LEN1 >> 1; i < PART_LEN1; i++) {
1253e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            num++;
1254e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            noiseAvg += sqrtf(noisePow[i]);
1255e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
1256e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        noiseAvg /= (float)num;
1257e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1258e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // average nlp scale
1259e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // average over second half of freq spectrum (i.e., 4->8khz)
1260e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // TODO: we shouldn't need num. We know how many elements we're summing.
1261e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        num = 0;
1262e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        for (i = PART_LEN1 >> 1; i < PART_LEN1; i++) {
1263e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            num++;
1264e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            tmpAvg += sqrtf(WEBRTC_SPL_MAX(1 - lambda[i] * lambda[i], 0));
1265e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
1266e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        tmpAvg /= (float)num;
1267e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1268e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // Use average noise for H band
1269e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // TODO: we should probably have a new random vector here.
1270e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        // Reject LF noise
1271e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        u[0][0] = 0;
1272e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        u[0][1] = 0;
1273e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        for (i = 1; i < PART_LEN1; i++) {
1274e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            tmp = pi2 * rand[i - 1];
1275e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1276e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // Use average noise for H band
1277e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            u[i][0] = noiseAvg * (float)cos(tmp);
1278e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            u[i][1] = -noiseAvg * (float)sin(tmp);
1279e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
1280e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        u[PART_LEN][1] = 0;
1281e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1282e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        for (i = 0; i < PART_LEN1; i++) {
1283e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // Use average NLP weight for H band
1284e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            comfortNoiseHband[i][0] = tmpAvg * u[i][0];
1285e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            comfortNoiseHband[i][1] = tmpAvg * u[i][1];
1286e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
1287e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1288e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
1289e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1290e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void WebRtcAec_InitLevel(power_level_t *level)
1291e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
1292e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float bigFloat = 1E17f;
1293e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1294e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    level->averagelevel = 0;
1295e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    level->framelevel = 0;
1296e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    level->minlevel = bigFloat;
1297e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    level->frsum = 0;
1298e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    level->sfrsum = 0;
1299e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    level->frcounter = 0;
1300e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    level->sfrcounter = 0;
1301e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
1302e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1303e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void WebRtcAec_InitStats(stats_t *stats)
1304e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
1305e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    stats->instant = offsetLevel;
1306e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    stats->average = offsetLevel;
1307e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    stats->max = offsetLevel;
1308e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    stats->min = offsetLevel * (-1);
1309e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    stats->sum = 0;
1310e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    stats->hisum = 0;
1311e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    stats->himean = offsetLevel;
1312e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    stats->counter = 0;
1313e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    stats->hicounter = 0;
1314e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
1315e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1316c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic void UpdateLevel(power_level_t* level, float in[2][PART_LEN1]) {
1317c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Do the energy calculation in the frequency domain. The FFT is performed on
1318c55a96383497a772a307b346368133960b02ad03Eric Laurent  // a segment of PART_LEN2 samples due to overlap, but we only want the energy
1319c55a96383497a772a307b346368133960b02ad03Eric Laurent  // of half that data (the last PART_LEN samples). Parseval's relation states
1320c55a96383497a772a307b346368133960b02ad03Eric Laurent  // that the energy is preserved according to
1321c55a96383497a772a307b346368133960b02ad03Eric Laurent  //
1322c55a96383497a772a307b346368133960b02ad03Eric Laurent  // \sum_{n=0}^{N-1} |x(n)|^2 = 1/N * \sum_{n=0}^{N-1} |X(n)|^2
1323c55a96383497a772a307b346368133960b02ad03Eric Laurent  //                           = ENERGY,
1324c55a96383497a772a307b346368133960b02ad03Eric Laurent  //
1325c55a96383497a772a307b346368133960b02ad03Eric Laurent  // where N = PART_LEN2. Since we are only interested in calculating the energy
1326c55a96383497a772a307b346368133960b02ad03Eric Laurent  // for the last PART_LEN samples we approximate by calculating ENERGY and
1327c55a96383497a772a307b346368133960b02ad03Eric Laurent  // divide by 2,
1328c55a96383497a772a307b346368133960b02ad03Eric Laurent  //
1329c55a96383497a772a307b346368133960b02ad03Eric Laurent  // \sum_{n=N/2}^{N-1} |x(n)|^2 ~= ENERGY / 2
1330c55a96383497a772a307b346368133960b02ad03Eric Laurent  //
1331c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Since we deal with real valued time domain signals we only store frequency
1332c55a96383497a772a307b346368133960b02ad03Eric Laurent  // bins [0, PART_LEN], which is what |in| consists of. To calculate ENERGY we
1333c55a96383497a772a307b346368133960b02ad03Eric Laurent  // need to add the contribution from the missing part in
1334c55a96383497a772a307b346368133960b02ad03Eric Laurent  // [PART_LEN+1, PART_LEN2-1]. These values are, up to a phase shift, identical
1335c55a96383497a772a307b346368133960b02ad03Eric Laurent  // with the values in [1, PART_LEN-1], hence multiply those values by 2. This
1336c55a96383497a772a307b346368133960b02ad03Eric Laurent  // is the values in the for loop below, but multiplication by 2 and division
1337c55a96383497a772a307b346368133960b02ad03Eric Laurent  // by 2 cancel.
1338c55a96383497a772a307b346368133960b02ad03Eric Laurent
1339c55a96383497a772a307b346368133960b02ad03Eric Laurent  // TODO(bjornv): Investigate reusing energy calculations performed at other
1340c55a96383497a772a307b346368133960b02ad03Eric Laurent  // places in the code.
1341c55a96383497a772a307b346368133960b02ad03Eric Laurent  int k = 1;
1342c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Imaginary parts are zero at end points and left out of the calculation.
1343c55a96383497a772a307b346368133960b02ad03Eric Laurent  float energy = (in[0][0] * in[0][0]) / 2;
1344c55a96383497a772a307b346368133960b02ad03Eric Laurent  energy += (in[0][PART_LEN] * in[0][PART_LEN]) / 2;
1345c55a96383497a772a307b346368133960b02ad03Eric Laurent
1346c55a96383497a772a307b346368133960b02ad03Eric Laurent  for (k = 1; k < PART_LEN; k++) {
1347c55a96383497a772a307b346368133960b02ad03Eric Laurent    energy += (in[0][k] * in[0][k] + in[1][k] * in[1][k]);
1348c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
1349c55a96383497a772a307b346368133960b02ad03Eric Laurent  energy /= PART_LEN2;
1350e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1351c55a96383497a772a307b346368133960b02ad03Eric Laurent  level->sfrsum += energy;
1352c55a96383497a772a307b346368133960b02ad03Eric Laurent  level->sfrcounter++;
1353e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1354c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (level->sfrcounter > subCountLen) {
1355c55a96383497a772a307b346368133960b02ad03Eric Laurent    level->framelevel = level->sfrsum / (subCountLen * PART_LEN);
1356c55a96383497a772a307b346368133960b02ad03Eric Laurent    level->sfrsum = 0;
1357c55a96383497a772a307b346368133960b02ad03Eric Laurent    level->sfrcounter = 0;
1358c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (level->framelevel > 0) {
1359c55a96383497a772a307b346368133960b02ad03Eric Laurent      if (level->framelevel < level->minlevel) {
1360c55a96383497a772a307b346368133960b02ad03Eric Laurent        level->minlevel = level->framelevel;  // New minimum.
1361c55a96383497a772a307b346368133960b02ad03Eric Laurent      } else {
1362c55a96383497a772a307b346368133960b02ad03Eric Laurent        level->minlevel *= (1 + 0.001f);  // Small increase.
1363c55a96383497a772a307b346368133960b02ad03Eric Laurent      }
1364e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1365c55a96383497a772a307b346368133960b02ad03Eric Laurent    level->frcounter++;
1366c55a96383497a772a307b346368133960b02ad03Eric Laurent    level->frsum += level->framelevel;
1367c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (level->frcounter > countLen) {
1368c55a96383497a772a307b346368133960b02ad03Eric Laurent      level->averagelevel = level->frsum / countLen;
1369c55a96383497a772a307b346368133960b02ad03Eric Laurent      level->frsum = 0;
1370c55a96383497a772a307b346368133960b02ad03Eric Laurent      level->frcounter = 0;
1371c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
1372c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
1373e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
1374e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1375e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentstatic void UpdateMetrics(aec_t *aec)
1376e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{
1377c55a96383497a772a307b346368133960b02ad03Eric Laurent    float dtmp, dtmp2;
1378e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1379e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float actThresholdNoisy = 8.0f;
1380e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float actThresholdClean = 40.0f;
1381e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float safety = 0.99995f;
1382e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    const float noisyPower = 300000.0f;
1383e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1384e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float actThreshold;
1385e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    float echo, suppressedEcho;
1386e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1387e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (aec->echoState) {   // Check if echo is likely present
1388e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->stateCounter++;
1389e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1390e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1391c55a96383497a772a307b346368133960b02ad03Eric Laurent    if (aec->farlevel.frcounter == 0) {
1392e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1393e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        if (aec->farlevel.minlevel < noisyPower) {
1394e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            actThreshold = actThresholdClean;
1395e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
1396e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        else {
1397e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            actThreshold = actThresholdNoisy;
1398e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
1399e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1400e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        if ((aec->stateCounter > (0.5f * countLen * subCountLen))
1401e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            && (aec->farlevel.sfrcounter == 0)
1402e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1403e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // Estimate in active far-end segments only
1404e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            && (aec->farlevel.averagelevel > (actThreshold * aec->farlevel.minlevel))
1405e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            ) {
1406e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1407e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // Subtract noise power
1408e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            echo = aec->nearlevel.averagelevel - safety * aec->nearlevel.minlevel;
1409e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1410e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // ERL
1411e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            dtmp = 10 * (float)log10(aec->farlevel.averagelevel /
1412e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->nearlevel.averagelevel + 1e-10f);
1413e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            dtmp2 = 10 * (float)log10(aec->farlevel.averagelevel / echo + 1e-10f);
1414e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1415e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->erl.instant = dtmp;
1416e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (dtmp > aec->erl.max) {
1417e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->erl.max = dtmp;
1418e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1419e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1420e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (dtmp < aec->erl.min) {
1421e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->erl.min = dtmp;
1422e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1423e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1424e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->erl.counter++;
1425e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->erl.sum += dtmp;
1426e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->erl.average = aec->erl.sum / aec->erl.counter;
1427e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1428e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // Upper mean
1429e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (dtmp > aec->erl.average) {
1430e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->erl.hicounter++;
1431e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->erl.hisum += dtmp;
1432e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->erl.himean = aec->erl.hisum / aec->erl.hicounter;
1433e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1434e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1435e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // A_NLP
1436e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            dtmp = 10 * (float)log10(aec->nearlevel.averagelevel /
1437c55a96383497a772a307b346368133960b02ad03Eric Laurent                (2 * aec->linoutlevel.averagelevel) + 1e-10f);
1438e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1439e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // subtract noise power
1440c55a96383497a772a307b346368133960b02ad03Eric Laurent            suppressedEcho = 2 * (aec->linoutlevel.averagelevel -
1441c55a96383497a772a307b346368133960b02ad03Eric Laurent                safety * aec->linoutlevel.minlevel);
1442e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1443e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            dtmp2 = 10 * (float)log10(echo / suppressedEcho + 1e-10f);
1444e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1445e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->aNlp.instant = dtmp2;
1446e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (dtmp > aec->aNlp.max) {
1447e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->aNlp.max = dtmp;
1448e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1449e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1450e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (dtmp < aec->aNlp.min) {
1451e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->aNlp.min = dtmp;
1452e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1453e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1454e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->aNlp.counter++;
1455e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->aNlp.sum += dtmp;
1456e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->aNlp.average = aec->aNlp.sum / aec->aNlp.counter;
1457e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1458e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // Upper mean
1459e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (dtmp > aec->aNlp.average) {
1460e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->aNlp.hicounter++;
1461e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->aNlp.hisum += dtmp;
1462e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->aNlp.himean = aec->aNlp.hisum / aec->aNlp.hicounter;
1463e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1464e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1465e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // ERLE
1466e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1467e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // subtract noise power
1468c55a96383497a772a307b346368133960b02ad03Eric Laurent            suppressedEcho = 2 * (aec->nlpoutlevel.averagelevel -
1469c55a96383497a772a307b346368133960b02ad03Eric Laurent                safety * aec->nlpoutlevel.minlevel);
1470e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1471e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            dtmp = 10 * (float)log10(aec->nearlevel.averagelevel /
1472c55a96383497a772a307b346368133960b02ad03Eric Laurent                (2 * aec->nlpoutlevel.averagelevel) + 1e-10f);
1473e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            dtmp2 = 10 * (float)log10(echo / suppressedEcho + 1e-10f);
1474e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1475e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            dtmp = dtmp2;
1476e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->erle.instant = dtmp;
1477e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (dtmp > aec->erle.max) {
1478e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->erle.max = dtmp;
1479e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1480e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1481e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (dtmp < aec->erle.min) {
1482e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->erle.min = dtmp;
1483e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1484e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1485e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->erle.counter++;
1486e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->erle.sum += dtmp;
1487e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            aec->erle.average = aec->erle.sum / aec->erle.counter;
1488e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1489e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            // Upper mean
1490e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            if (dtmp > aec->erle.average) {
1491e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->erle.hicounter++;
1492e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->erle.hisum += dtmp;
1493e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                aec->erle.himean = aec->erle.hisum / aec->erle.hicounter;
1494e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent            }
1495e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        }
1496e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1497e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        aec->stateCounter = 0;
1498e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
1499e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
1500e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
1501c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic void TimeToFrequency(float time_data[PART_LEN2],
1502c55a96383497a772a307b346368133960b02ad03Eric Laurent                            float freq_data[2][PART_LEN1],
1503c55a96383497a772a307b346368133960b02ad03Eric Laurent                            int window) {
1504c55a96383497a772a307b346368133960b02ad03Eric Laurent  int i = 0;
1505c55a96383497a772a307b346368133960b02ad03Eric Laurent
1506c55a96383497a772a307b346368133960b02ad03Eric Laurent  // TODO(bjornv): Should we have a different function/wrapper for windowed FFT?
1507c55a96383497a772a307b346368133960b02ad03Eric Laurent  if (window) {
1508c55a96383497a772a307b346368133960b02ad03Eric Laurent    for (i = 0; i < PART_LEN; i++) {
1509c55a96383497a772a307b346368133960b02ad03Eric Laurent      time_data[i] *= sqrtHanning[i];
1510c55a96383497a772a307b346368133960b02ad03Eric Laurent      time_data[PART_LEN + i] *= sqrtHanning[PART_LEN - i];
1511c55a96383497a772a307b346368133960b02ad03Eric Laurent    }
1512c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
1513c55a96383497a772a307b346368133960b02ad03Eric Laurent
1514c55a96383497a772a307b346368133960b02ad03Eric Laurent  aec_rdft_forward_128(time_data);
1515c55a96383497a772a307b346368133960b02ad03Eric Laurent  // Reorder.
1516c55a96383497a772a307b346368133960b02ad03Eric Laurent  freq_data[1][0] = 0;
1517c55a96383497a772a307b346368133960b02ad03Eric Laurent  freq_data[1][PART_LEN] = 0;
1518c55a96383497a772a307b346368133960b02ad03Eric Laurent  freq_data[0][0] = time_data[0];
1519c55a96383497a772a307b346368133960b02ad03Eric Laurent  freq_data[0][PART_LEN] = time_data[1];
1520c55a96383497a772a307b346368133960b02ad03Eric Laurent  for (i = 1; i < PART_LEN; i++) {
1521c55a96383497a772a307b346368133960b02ad03Eric Laurent    freq_data[0][i] = time_data[2 * i];
1522c55a96383497a772a307b346368133960b02ad03Eric Laurent    freq_data[1][i] = time_data[2 * i + 1];
1523c55a96383497a772a307b346368133960b02ad03Eric Laurent  }
1524c55a96383497a772a307b346368133960b02ad03Eric Laurent}
1525