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