1e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org/* 2e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org * 4e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org */ 10e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 11e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#include "webrtc/modules/audio_processing/aecm/aecm_core.h" 12e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 13e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#include <assert.h> 14e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#include <stddef.h> 15e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#include <stdlib.h> 16e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 176b6301588ef2d7b5f5d442aa95bef442a43ead53andrew@webrtc.org#include "webrtc/common_audio/ring_buffer.h" 18e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#include "webrtc/common_audio/signal_processing/include/real_fft.h" 199b72af94cd61782ada88f777b07854daf9657bb2Henrik Kjellander#include "webrtc/modules/audio_processing/aecm/echo_control_mobile.h" 20e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" 2198f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/compile_assert_c.h" 2298f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/cpu_features_wrapper.h" 23e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#include "webrtc/typedefs.h" 24e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 25e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// Square root of Hanning window in Q14. 26cb7f8ce2df7564546936d3041a96ccc86a90f988Andrew MacDonald#if defined(WEBRTC_DETECT_NEON) || defined(WEBRTC_HAS_NEON) 27e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// Table is defined in an ARM assembly file. 28e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.orgextern const ALIGN8_BEG int16_t WebRtcAecm_kSqrtHanning[] ALIGN8_END; 29e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#else 30e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.orgstatic const ALIGN8_BEG int16_t WebRtcAecm_kSqrtHanning[] ALIGN8_END = { 31e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 0, 399, 798, 1196, 1594, 1990, 2386, 2780, 3172, 32e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 3562, 3951, 4337, 4720, 5101, 5478, 5853, 6224, 33e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 6591, 6954, 7313, 7668, 8019, 8364, 8705, 9040, 34e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 9370, 9695, 10013, 10326, 10633, 10933, 11227, 11514, 35e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 11795, 12068, 12335, 12594, 12845, 13089, 13325, 13553, 36e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 13773, 13985, 14189, 14384, 14571, 14749, 14918, 15079, 37e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 15231, 15373, 15506, 15631, 15746, 15851, 15947, 16034, 38e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 16111, 16179, 16237, 16286, 16325, 16354, 16373, 16384 39e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org}; 40e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#endif 41e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 42e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#ifdef AECM_WITH_ABS_APPROX 43e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org//Q15 alpha = 0.99439986968132 const Factor for magnitude approximation 44e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.orgstatic const uint16_t kAlpha1 = 32584; 45e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org//Q15 beta = 0.12967166976970 const Factor for magnitude approximation 46e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.orgstatic const uint16_t kBeta1 = 4249; 47e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org//Q15 alpha = 0.94234827210087 const Factor for magnitude approximation 48e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.orgstatic const uint16_t kAlpha2 = 30879; 49e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org//Q15 beta = 0.33787806009150 const Factor for magnitude approximation 50e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.orgstatic const uint16_t kBeta2 = 11072; 51e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org//Q15 alpha = 0.82247698684306 const Factor for magnitude approximation 52e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.orgstatic const uint16_t kAlpha3 = 26951; 53e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org//Q15 beta = 0.57762063060713 const Factor for magnitude approximation 54e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.orgstatic const uint16_t kBeta3 = 18927; 55e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#endif 56e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 57e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.orgstatic const int16_t kNoiseEstQDomain = 15; 58e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.orgstatic const int16_t kNoiseEstIncCount = 5; 59e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 60e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.orgstatic void ComfortNoise(AecmCore* aecm, 61e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org const uint16_t* dfa, 62e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org ComplexInt16* out, 63e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org const int16_t* lambda); 64e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 65e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.orgstatic void WindowAndFFT(AecmCore* aecm, 66e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org int16_t* fft, 67e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org const int16_t* time_signal, 68e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org ComplexInt16* freq_signal, 69e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org int time_signal_scaling) { 70e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int i = 0; 71e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 72e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // FFT of signal 73e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 0; i < PART_LEN; i++) { 74e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Window time domain signal and insert into real part of 75e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // transformation array |fft| 76b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org int16_t scaled_time_signal = time_signal[i] << time_signal_scaling; 77b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org fft[i] = (int16_t)((scaled_time_signal * WebRtcAecm_kSqrtHanning[i]) >> 14); 78b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org scaled_time_signal = time_signal[i + PART_LEN] << time_signal_scaling; 79b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org fft[PART_LEN + i] = (int16_t)(( 80b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org scaled_time_signal * WebRtcAecm_kSqrtHanning[PART_LEN - i]) >> 14); 81e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 82e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 83e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Do forward FFT, then take only the first PART_LEN complex samples, 84e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // and change signs of the imaginary parts. 85e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org WebRtcSpl_RealForwardFFT(aecm->real_fft, fft, (int16_t*)freq_signal); 86e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 0; i < PART_LEN; i++) { 87e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org freq_signal[i].imag = -freq_signal[i].imag; 88e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 89e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org} 90e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 91e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.orgstatic void InverseFFTAndWindow(AecmCore* aecm, 92e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t* fft, 93e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org ComplexInt16* efw, 94e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t* output, 95e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org const int16_t* nearendClean) { 96e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int i, j, outCFFT; 97e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int32_t tmp32no1; 98e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Reuse |efw| for the inverse FFT output after transferring 99e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // the contents to |fft|. 100e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t* ifft_out = (int16_t*)efw; 101e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 102e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Synthesis 103e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 1, j = 2; i < PART_LEN; i += 1, j += 2) { 104e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org fft[j] = efw[i].real; 105e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org fft[j + 1] = -efw[i].imag; 106e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 107e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org fft[0] = efw[0].real; 108e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org fft[1] = -efw[0].imag; 109e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 110e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org fft[PART_LEN2] = efw[PART_LEN].real; 111e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org fft[PART_LEN2 + 1] = -efw[PART_LEN].imag; 112e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 113e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Inverse FFT. Keep outCFFT to scale the samples in the next block. 114e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org outCFFT = WebRtcSpl_RealInverseFFT(aecm->real_fft, fft, ifft_out); 115e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 0; i < PART_LEN; i++) { 116e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org ifft_out[i] = (int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND( 117e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org ifft_out[i], WebRtcAecm_kSqrtHanning[i], 14); 118e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp32no1 = WEBRTC_SPL_SHIFT_W32((int32_t)ifft_out[i], 119e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org outCFFT - aecm->dfaCleanQDomain); 120e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org output[i] = (int16_t)WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, 121e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp32no1 + aecm->outBuf[i], 122e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org WEBRTC_SPL_WORD16_MIN); 123e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 124b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org tmp32no1 = (ifft_out[PART_LEN + i] * 125b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org WebRtcAecm_kSqrtHanning[PART_LEN - i]) >> 14; 126e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp32no1 = WEBRTC_SPL_SHIFT_W32(tmp32no1, 127e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org outCFFT - aecm->dfaCleanQDomain); 128e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->outBuf[i] = (int16_t)WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, 129e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp32no1, 130e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org WEBRTC_SPL_WORD16_MIN); 131e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 132e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 133e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Copy the current block to the old position 134e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // (aecm->outBuf is shifted elsewhere) 135e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org memcpy(aecm->xBuf, aecm->xBuf + PART_LEN, sizeof(int16_t) * PART_LEN); 136e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org memcpy(aecm->dBufNoisy, 137e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->dBufNoisy + PART_LEN, 138e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org sizeof(int16_t) * PART_LEN); 139e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (nearendClean != NULL) 140e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 141e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org memcpy(aecm->dBufClean, 142e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->dBufClean + PART_LEN, 143e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org sizeof(int16_t) * PART_LEN); 144e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 145e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org} 146e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 147e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// Transforms a time domain signal into the frequency domain, outputting the 148e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// complex valued signal, absolute value and sum of absolute values. 149e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// 150e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// time_signal [in] Pointer to time domain signal 151e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// freq_signal_real [out] Pointer to real part of frequency domain array 152e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// freq_signal_imag [out] Pointer to imaginary part of frequency domain 153e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// array 154e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// freq_signal_abs [out] Pointer to absolute value of frequency domain 155e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// array 156e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// freq_signal_sum_abs [out] Pointer to the sum of all absolute values in 157e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// the frequency domain array 158e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// return value The Q-domain of current frequency values 159e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org// 160e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.orgstatic int TimeToFrequencyDomain(AecmCore* aecm, 161e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org const int16_t* time_signal, 162e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org ComplexInt16* freq_signal, 163e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uint16_t* freq_signal_abs, 164e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org uint32_t* freq_signal_sum_abs) { 165e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int i = 0; 166e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int time_signal_scaling = 0; 167e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 168e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int32_t tmp32no1 = 0; 169e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int32_t tmp32no2 = 0; 170e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 171e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // In fft_buf, +16 for 32-byte alignment. 172e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t fft_buf[PART_LEN4 + 16]; 173e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t *fft = (int16_t *) (((uintptr_t) fft_buf + 31) & ~31); 174e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 175e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t tmp16no1; 176e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#ifndef WEBRTC_ARCH_ARM_V7 177e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t tmp16no2; 178e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#endif 179e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#ifdef AECM_WITH_ABS_APPROX 180e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t max_value = 0; 181e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t min_value = 0; 182e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uint16_t alpha = 0; 183e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uint16_t beta = 0; 184e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#endif 185e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 186e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#ifdef AECM_DYNAMIC_Q 187e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp16no1 = WebRtcSpl_MaxAbsValueW16(time_signal, PART_LEN2); 188e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org time_signal_scaling = WebRtcSpl_NormW16(tmp16no1); 189e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#endif 190e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 191e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org WindowAndFFT(aecm, fft, time_signal, freq_signal, time_signal_scaling); 192e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 193e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Extract imaginary and real part, calculate the magnitude for 194e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // all frequency bins 195e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org freq_signal[0].imag = 0; 196e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org freq_signal[PART_LEN].imag = 0; 197e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org freq_signal_abs[0] = (uint16_t)WEBRTC_SPL_ABS_W16(freq_signal[0].real); 198e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org freq_signal_abs[PART_LEN] = (uint16_t)WEBRTC_SPL_ABS_W16( 199e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org freq_signal[PART_LEN].real); 200e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org (*freq_signal_sum_abs) = (uint32_t)(freq_signal_abs[0]) + 201e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org (uint32_t)(freq_signal_abs[PART_LEN]); 202e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 203e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 1; i < PART_LEN; i++) 204e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 205e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (freq_signal[i].real == 0) 206e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 207e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org freq_signal_abs[i] = (uint16_t)WEBRTC_SPL_ABS_W16(freq_signal[i].imag); 208e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 209e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org else if (freq_signal[i].imag == 0) 210e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 211e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org freq_signal_abs[i] = (uint16_t)WEBRTC_SPL_ABS_W16(freq_signal[i].real); 212e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 213e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org else 214e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 215e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Approximation for magnitude of complex fft output 216e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // magn = sqrt(real^2 + imag^2) 217e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // magn ~= alpha * max(|imag|,|real|) + beta * min(|imag|,|real|) 218e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // 219e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // The parameters alpha and beta are stored in Q15 220e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 221e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#ifdef AECM_WITH_ABS_APPROX 222e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp16no1 = WEBRTC_SPL_ABS_W16(freq_signal[i].real); 223e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp16no2 = WEBRTC_SPL_ABS_W16(freq_signal[i].imag); 224e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 225e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if(tmp16no1 > tmp16no2) 226e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 227e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org max_value = tmp16no1; 228e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org min_value = tmp16no2; 229e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else 230e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 231e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org max_value = tmp16no2; 232e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org min_value = tmp16no1; 233e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 234e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 235e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Magnitude in Q(-6) 236e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if ((max_value >> 2) > min_value) 237e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 238e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org alpha = kAlpha1; 239e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org beta = kBeta1; 240e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else if ((max_value >> 1) > min_value) 241e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 242e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org alpha = kAlpha2; 243e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org beta = kBeta2; 244e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else 245e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 246e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org alpha = kAlpha3; 247e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org beta = kBeta3; 248e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 249b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org tmp16no1 = (int16_t)((max_value * alpha) >> 15); 250b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org tmp16no2 = (int16_t)((min_value * beta) >> 15); 251e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org freq_signal_abs[i] = (uint16_t)tmp16no1 + (uint16_t)tmp16no2; 252e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#else 253e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#ifdef WEBRTC_ARCH_ARM_V7 254e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org __asm __volatile( 255e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org "smulbb %[tmp32no1], %[real], %[real]\n\t" 256e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org "smlabb %[tmp32no2], %[imag], %[imag], %[tmp32no1]\n\t" 257aafd7a88c50b21ab2ac56e9a53ba3f04c199f625bjornv@webrtc.org :[tmp32no1]"+&r"(tmp32no1), 258e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org [tmp32no2]"=r"(tmp32no2) 259e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org :[real]"r"(freq_signal[i].real), 260e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org [imag]"r"(freq_signal[i].imag) 261e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org ); 262e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#else 263e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp16no1 = WEBRTC_SPL_ABS_W16(freq_signal[i].real); 264e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp16no2 = WEBRTC_SPL_ABS_W16(freq_signal[i].imag); 265758d6d431ef527130ab95cd20f0e42bb543d6da8bjornv@webrtc.org tmp32no1 = tmp16no1 * tmp16no1; 266758d6d431ef527130ab95cd20f0e42bb543d6da8bjornv@webrtc.org tmp32no2 = tmp16no2 * tmp16no2; 2676e71d17bc98d3b179f55fd4fd42dc5c53b7787dcbjornv@webrtc.org tmp32no2 = WebRtcSpl_AddSatW32(tmp32no1, tmp32no2); 268e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#endif // WEBRTC_ARCH_ARM_V7 269e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp32no1 = WebRtcSpl_SqrtFloor(tmp32no2); 270e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 271e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org freq_signal_abs[i] = (uint16_t)tmp32no1; 272e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org#endif // AECM_WITH_ABS_APPROX 273e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 274e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org (*freq_signal_sum_abs) += (uint32_t)freq_signal_abs[i]; 275e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 276e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 277e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org return time_signal_scaling; 278e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org} 279e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 280e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.orgint WebRtcAecm_ProcessBlock(AecmCore* aecm, 281e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org const int16_t* farend, 282e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org const int16_t* nearendNoisy, 283e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org const int16_t* nearendClean, 284e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org int16_t* output) { 285e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int i; 286e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 287e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uint32_t xfaSum; 288e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uint32_t dfaNoisySum; 289e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uint32_t dfaCleanSum; 290e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uint32_t echoEst32Gained; 291e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uint32_t tmpU32; 292e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 293e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int32_t tmp32no1; 294e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 295e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uint16_t xfa[PART_LEN1]; 296e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uint16_t dfaNoisy[PART_LEN1]; 297e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uint16_t dfaClean[PART_LEN1]; 298e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uint16_t* ptrDfaClean = dfaClean; 299e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org const uint16_t* far_spectrum_ptr = NULL; 300e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 301e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // 32 byte aligned buffers (with +8 or +16). 302e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org // TODO(kma): define fft with ComplexInt16. 303e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t fft_buf[PART_LEN4 + 2 + 16]; // +2 to make a loop safe. 304e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int32_t echoEst32_buf[PART_LEN1 + 8]; 305e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int32_t dfw_buf[PART_LEN2 + 8]; 306e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int32_t efw_buf[PART_LEN2 + 8]; 307e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 308e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t* fft = (int16_t*) (((uintptr_t) fft_buf + 31) & ~ 31); 309e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int32_t* echoEst32 = (int32_t*) (((uintptr_t) echoEst32_buf + 31) & ~ 31); 310e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org ComplexInt16* dfw = (ComplexInt16*)(((uintptr_t)dfw_buf + 31) & ~31); 311e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org ComplexInt16* efw = (ComplexInt16*)(((uintptr_t)efw_buf + 31) & ~31); 312e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 313e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t hnl[PART_LEN1]; 314e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t numPosCoef = 0; 315e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t nlpGain = ONE_Q14; 316e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int delay; 317e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t tmp16no1; 318e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t tmp16no2; 319e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t mu; 320e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t supGain; 321e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t zeros32, zeros16; 322e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t zerosDBufNoisy, zerosDBufClean, zerosXBuf; 323e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int far_q; 324c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org int16_t resolutionDiff, qDomainDiff, dfa_clean_q_domain_diff; 325e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 326e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org const int kMinPrefBand = 4; 327e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org const int kMaxPrefBand = 24; 328e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int32_t avgHnl32 = 0; 329e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 330e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Determine startup state. There are three states: 331e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // (0) the first CONV_LEN blocks 332e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // (1) another CONV_LEN blocks 333e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // (2) the rest 334e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 335e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (aecm->startupState < 2) 336e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 337e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->startupState = (aecm->totCount >= CONV_LEN) + 338e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org (aecm->totCount >= CONV_LEN2); 339e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 340e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // END: Determine startup state 341e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 342e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Buffer near and far end signals 343e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org memcpy(aecm->xBuf + PART_LEN, farend, sizeof(int16_t) * PART_LEN); 344e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org memcpy(aecm->dBufNoisy + PART_LEN, nearendNoisy, sizeof(int16_t) * PART_LEN); 345e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (nearendClean != NULL) 346e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 347e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org memcpy(aecm->dBufClean + PART_LEN, 348e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org nearendClean, 349e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org sizeof(int16_t) * PART_LEN); 350e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 351e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 352e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Transform far end signal from time domain to frequency domain. 353e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org far_q = TimeToFrequencyDomain(aecm, 354e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->xBuf, 355e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org dfw, 356e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org xfa, 357e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org &xfaSum); 358e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 359e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Transform noisy near end signal from time domain to frequency domain. 360e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org zerosDBufNoisy = TimeToFrequencyDomain(aecm, 361e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->dBufNoisy, 362e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org dfw, 363e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org dfaNoisy, 364e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org &dfaNoisySum); 365e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->dfaNoisyQDomainOld = aecm->dfaNoisyQDomain; 366e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->dfaNoisyQDomain = (int16_t)zerosDBufNoisy; 367e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 368e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 369e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (nearendClean == NULL) 370e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 371e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org ptrDfaClean = dfaNoisy; 372e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->dfaCleanQDomainOld = aecm->dfaNoisyQDomainOld; 373e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->dfaCleanQDomain = aecm->dfaNoisyQDomain; 374e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org dfaCleanSum = dfaNoisySum; 375e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else 376e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 377e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Transform clean near end signal from time domain to frequency domain. 378e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org zerosDBufClean = TimeToFrequencyDomain(aecm, 379e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->dBufClean, 380e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org dfw, 381e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org dfaClean, 382e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org &dfaCleanSum); 383e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->dfaCleanQDomainOld = aecm->dfaCleanQDomain; 384e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->dfaCleanQDomain = (int16_t)zerosDBufClean; 385e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 386e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 387e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Get the delay 388e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Save far-end history and estimate delay 389e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org WebRtcAecm_UpdateFarHistory(aecm, xfa, far_q); 390e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (WebRtc_AddFarSpectrumFix(aecm->delay_estimator_farend, 391e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org xfa, 392e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org PART_LEN1, 393e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org far_q) == -1) { 394e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org return -1; 395e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 396e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org delay = WebRtc_DelayEstimatorProcessFix(aecm->delay_estimator, 397e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org dfaNoisy, 398e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org PART_LEN1, 399e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org zerosDBufNoisy); 400e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (delay == -1) 401e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 402e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org return -1; 403e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 404e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org else if (delay == -2) 405e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 406e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // If the delay is unknown, we assume zero. 407e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // NOTE: this will have to be adjusted if we ever add lookahead. 408e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org delay = 0; 409e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 410e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 411e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (aecm->fixedDelay >= 0) 412e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 413e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Use fixed delay 414e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org delay = aecm->fixedDelay; 415e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 416e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 417e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Get aligned far end spectrum 418e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org far_spectrum_ptr = WebRtcAecm_AlignedFarend(aecm, &far_q, delay); 419e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org zerosXBuf = (int16_t) far_q; 420e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (far_spectrum_ptr == NULL) 421e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 422e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org return -1; 423e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 424e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 425e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Calculate log(energy) and update energy threshold levels 426e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org WebRtcAecm_CalcEnergies(aecm, 427e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org far_spectrum_ptr, 428e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org zerosXBuf, 429e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org dfaNoisySum, 430e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org echoEst32); 431e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 432e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Calculate stepsize 433e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org mu = WebRtcAecm_CalcStepSize(aecm); 434e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 435e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Update counters 436e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->totCount++; 437e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 438e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // This is the channel estimation algorithm. 439e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // It is base on NLMS but has a variable step length, 440e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // which was calculated above. 441e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org WebRtcAecm_UpdateChannel(aecm, 442e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org far_spectrum_ptr, 443e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org zerosXBuf, 444e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org dfaNoisy, 445e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org mu, 446e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org echoEst32); 447e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org supGain = WebRtcAecm_CalcSuppressionGain(aecm); 448e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 449e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 450e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Calculate Wiener filter hnl[] 451e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 0; i < PART_LEN1; i++) 452e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 453e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Far end signal through channel estimate in Q8 454e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // How much can we shift right to preserve resolution 455e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp32no1 = echoEst32[i] - aecm->echoFilt[i]; 456926707b167e9bfb876c7c903dcefc41c84e5fedbbjornv@webrtc.org aecm->echoFilt[i] += (tmp32no1 * 50) >> 8; 457e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 458e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org zeros32 = WebRtcSpl_NormW32(aecm->echoFilt[i]) + 1; 459e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org zeros16 = WebRtcSpl_NormW16(supGain) + 1; 460e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (zeros32 + zeros16 > 16) 461e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 462e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Multiplication is safe 463e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Result in 464e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Q(RESOLUTION_CHANNEL+RESOLUTION_SUPGAIN+ 465e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // aecm->xfaQDomainBuf[diff]) 466e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org echoEst32Gained = WEBRTC_SPL_UMUL_32_16((uint32_t)aecm->echoFilt[i], 467e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org (uint16_t)supGain); 468e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org resolutionDiff = 14 - RESOLUTION_CHANNEL16 - RESOLUTION_SUPGAIN; 469e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org resolutionDiff += (aecm->dfaCleanQDomain - zerosXBuf); 470e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else 471e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 472e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp16no1 = 17 - zeros32 - zeros16; 473e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org resolutionDiff = 14 + tmp16no1 - RESOLUTION_CHANNEL16 - 474e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org RESOLUTION_SUPGAIN; 475e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org resolutionDiff += (aecm->dfaCleanQDomain - zerosXBuf); 476e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (zeros32 > tmp16no1) 477e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 478e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org echoEst32Gained = WEBRTC_SPL_UMUL_32_16((uint32_t)aecm->echoFilt[i], 479d4fe8248621223b12fd2e3907c7c19e0f6837a26bjornv@webrtc.org supGain >> tmp16no1); 480e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else 481e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 482e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Result in Q-(RESOLUTION_CHANNEL+RESOLUTION_SUPGAIN-16) 483f87c0aff7f222174916091da8071d0c57cbe5125bjornv@webrtc.org echoEst32Gained = (aecm->echoFilt[i] >> tmp16no1) * supGain; 484e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 485e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 486e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 487e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org zeros16 = WebRtcSpl_NormW16(aecm->nearFilt[i]); 488c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org assert(zeros16 >= 0); // |zeros16| is a norm, hence non-negative. 489c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org dfa_clean_q_domain_diff = aecm->dfaCleanQDomain - aecm->dfaCleanQDomainOld; 490c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org if (zeros16 < dfa_clean_q_domain_diff && aecm->nearFilt[i]) { 491c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org tmp16no1 = aecm->nearFilt[i] << zeros16; 492c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org qDomainDiff = zeros16 - dfa_clean_q_domain_diff; 493c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org tmp16no2 = ptrDfaClean[i] >> -qDomainDiff; 494c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org } else { 495c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org tmp16no1 = dfa_clean_q_domain_diff < 0 496c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org ? aecm->nearFilt[i] >> -dfa_clean_q_domain_diff 497c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org : aecm->nearFilt[i] << dfa_clean_q_domain_diff; 498e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org qDomainDiff = 0; 499c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org tmp16no2 = ptrDfaClean[i]; 500e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 501e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp32no1 = (int32_t)(tmp16no2 - tmp16no1); 502f87c0aff7f222174916091da8071d0c57cbe5125bjornv@webrtc.org tmp16no2 = (int16_t)(tmp32no1 >> 4); 503e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp16no2 += tmp16no1; 504e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org zeros16 = WebRtcSpl_NormW16(tmp16no2); 505c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org if ((tmp16no2) & (-qDomainDiff > zeros16)) { 506e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->nearFilt[i] = WEBRTC_SPL_WORD16_MAX; 507c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org } else { 508c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org aecm->nearFilt[i] = qDomainDiff < 0 ? tmp16no2 << -qDomainDiff 509c0ba4392f18f083839673c97f3f63015a72a8bb5bjornv@webrtc.org : tmp16no2 >> qDomainDiff; 510e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 511e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 512e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Wiener filter coefficients, resulting hnl in Q14 513e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (echoEst32Gained == 0) 514e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 515e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i] = ONE_Q14; 516e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else if (aecm->nearFilt[i] == 0) 517e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 518e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i] = 0; 519e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else 520e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 521e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Multiply the suppression gain 522e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Rounding 523e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org echoEst32Gained += (uint32_t)(aecm->nearFilt[i] >> 1); 524e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmpU32 = WebRtcSpl_DivU32U16(echoEst32Gained, 525e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org (uint16_t)aecm->nearFilt[i]); 526e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 527e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Current resolution is 528e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Q-(RESOLUTION_CHANNEL+RESOLUTION_SUPGAIN- max(0,17-zeros16- zeros32)) 529e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Make sure we are in Q14 530e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp32no1 = (int32_t)WEBRTC_SPL_SHIFT_W32(tmpU32, resolutionDiff); 531e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (tmp32no1 > ONE_Q14) 532e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 533e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i] = 0; 534e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else if (tmp32no1 < 0) 535e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 536e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i] = ONE_Q14; 537e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else 538e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 539e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // 1-echoEst/dfa 540e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i] = ONE_Q14 - (int16_t)tmp32no1; 541e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (hnl[i] < 0) 542e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 543e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i] = 0; 544e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 545e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 546e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 547e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (hnl[i]) 548e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 549e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org numPosCoef++; 550e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 551e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 552e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Only in wideband. Prevent the gain in upper band from being larger than 553e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // in lower band. 554e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (aecm->mult == 2) 555e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 556e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // TODO(bjornv): Investigate if the scaling of hnl[i] below can cause 557e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // speech distortion in double-talk. 558e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 0; i < PART_LEN1; i++) 559e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 560b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org hnl[i] = (int16_t)((hnl[i] * hnl[i]) >> 14); 561e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 562e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 563e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = kMinPrefBand; i <= kMaxPrefBand; i++) 564e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 565e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org avgHnl32 += (int32_t)hnl[i]; 566e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 567e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org assert(kMaxPrefBand - kMinPrefBand + 1 > 0); 568e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org avgHnl32 /= (kMaxPrefBand - kMinPrefBand + 1); 569e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 570e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = kMaxPrefBand; i < PART_LEN1; i++) 571e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 572e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (hnl[i] > (int16_t)avgHnl32) 573e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 574e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i] = (int16_t)avgHnl32; 575e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 576e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 577e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 578e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 579e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Calculate NLP gain, result is in Q14 580e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (aecm->nlpFlag) 581e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 582e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 0; i < PART_LEN1; i++) 583e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 584e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Truncate values close to zero and one. 585e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (hnl[i] > NLP_COMP_HIGH) 586e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 587e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i] = ONE_Q14; 588e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else if (hnl[i] < NLP_COMP_LOW) 589e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 590e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i] = 0; 591e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 592e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 593e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Remove outliers 594e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (numPosCoef < 3) 595e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 596e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org nlpGain = 0; 597e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else 598e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 599e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org nlpGain = ONE_Q14; 600e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 601e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 602e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // NLP 603e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if ((hnl[i] == ONE_Q14) && (nlpGain == ONE_Q14)) 604e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 605e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i] = ONE_Q14; 606e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else 607e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 608b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org hnl[i] = (int16_t)((hnl[i] * nlpGain) >> 14); 609e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 610e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 611e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // multiply with Wiener coefficients 612e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org efw[i].real = (int16_t)(WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(dfw[i].real, 613e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i], 14)); 614e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org efw[i].imag = (int16_t)(WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(dfw[i].imag, 615e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i], 14)); 616e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 617e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 618e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org else 619e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 620e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // multiply with Wiener coefficients 621e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 0; i < PART_LEN1; i++) 622e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 623e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org efw[i].real = (int16_t)(WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(dfw[i].real, 624e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i], 14)); 625e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org efw[i].imag = (int16_t)(WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(dfw[i].imag, 626e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org hnl[i], 14)); 627e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 628e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 629e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 630e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (aecm->cngMode == AecmTrue) 631e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 632e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org ComfortNoise(aecm, ptrDfaClean, efw, hnl); 633e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 634e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 635e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org InverseFFTAndWindow(aecm, fft, efw, output, nearendClean); 636e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 637e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org return 0; 638e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org} 639e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 640e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.orgstatic void ComfortNoise(AecmCore* aecm, 641e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org const uint16_t* dfa, 642e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org ComplexInt16* out, 643e468bc9e604213054e5fc73431ee127ebe0211a8pbos@webrtc.org const int16_t* lambda) { 644e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t i; 645e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t tmp16; 646e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int32_t tmp32; 647e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 648e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t randW16[PART_LEN]; 649e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t uReal[PART_LEN1]; 650e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t uImag[PART_LEN1]; 651e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int32_t outLShift32; 652e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t noiseRShift16[PART_LEN1]; 653e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 654e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t shiftFromNearToNoise = kNoiseEstQDomain - aecm->dfaCleanQDomain; 655e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org int16_t minTrackShift; 656e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 657e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org assert(shiftFromNearToNoise >= 0); 658e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org assert(shiftFromNearToNoise < 16); 659e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 660e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (aecm->noiseEstCtr < 100) 661e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 662e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Track the minimum more quickly initially. 663e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEstCtr++; 664e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org minTrackShift = 6; 665e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else 666e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 667e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org minTrackShift = 9; 668e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 669e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 670e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Estimate noise power. 671e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 0; i < PART_LEN1; i++) 672e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 673e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Shift to the noise domain. 674e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp32 = (int32_t)dfa[i]; 675750423c7227be04acf65472af0ee57ce47376fcbbjornv@webrtc.org outLShift32 = tmp32 << shiftFromNearToNoise; 676e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 677e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (outLShift32 < aecm->noiseEst[i]) 678e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 679e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Reset "too low" counter 680e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEstTooLowCtr[i] = 0; 681e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Track the minimum. 682e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (aecm->noiseEst[i] < (1 << minTrackShift)) 683e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 684e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // For small values, decrease noiseEst[i] every 685e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // |kNoiseEstIncCount| block. The regular approach below can not 686e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // go further down due to truncation. 687e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEstTooHighCtr[i]++; 688e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (aecm->noiseEstTooHighCtr[i] >= kNoiseEstIncCount) 689e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 690e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEst[i]--; 691e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEstTooHighCtr[i] = 0; // Reset the counter 692e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 693e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 694e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org else 695e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 696e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEst[i] -= ((aecm->noiseEst[i] - outLShift32) 697e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org >> minTrackShift); 698e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 699e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } else 700e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 701e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Reset "too high" counter 702e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEstTooHighCtr[i] = 0; 703e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Ramp slowly upwards until we hit the minimum again. 704e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if ((aecm->noiseEst[i] >> 19) > 0) 705e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 706e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Avoid overflow. 707e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Multiplication with 2049 will cause wrap around. Scale 708e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // down first and then multiply 709e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEst[i] >>= 11; 710e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEst[i] *= 2049; 711e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 712e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org else if ((aecm->noiseEst[i] >> 11) > 0) 713e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 714e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Large enough for relative increase 715e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEst[i] *= 2049; 716e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEst[i] >>= 11; 717e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 718e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org else 719e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 720e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Make incremental increases based on size every 721e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // |kNoiseEstIncCount| block 722e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEstTooLowCtr[i]++; 723e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (aecm->noiseEstTooLowCtr[i] >= kNoiseEstIncCount) 724e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 725e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEst[i] += (aecm->noiseEst[i] >> 9) + 1; 726e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org aecm->noiseEstTooLowCtr[i] = 0; // Reset counter 727e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 728e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 729e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 730e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 731e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 732e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 0; i < PART_LEN1; i++) 733e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 734f87c0aff7f222174916091da8071d0c57cbe5125bjornv@webrtc.org tmp32 = aecm->noiseEst[i] >> shiftFromNearToNoise; 735e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org if (tmp32 > 32767) 736e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 737e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp32 = 32767; 738750423c7227be04acf65472af0ee57ce47376fcbbjornv@webrtc.org aecm->noiseEst[i] = tmp32 << shiftFromNearToNoise; 739e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 740e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org noiseRShift16[i] = (int16_t)tmp32; 741e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 742e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org tmp16 = ONE_Q14 - lambda[i]; 743b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org noiseRShift16[i] = (int16_t)((tmp16 * noiseRShift16[i]) >> 14); 744e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 745e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 746e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Generate a uniform random array on [0 2^15-1]. 747e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org WebRtcSpl_RandUArray(randW16, PART_LEN, &aecm->seed); 748e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 749e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Generate noise according to estimated energy. 750e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uReal[0] = 0; // Reject LF noise. 751e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uImag[0] = 0; 752e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 1; i < PART_LEN1; i++) 753e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 754e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Get a random index for the cos and sin tables over [0 359]. 755b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org tmp16 = (int16_t)((359 * randW16[i - 1]) >> 15); 756e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 757e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org // Tables are in Q13. 758b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org uReal[i] = (int16_t)((noiseRShift16[i] * WebRtcAecm_kCosTable[tmp16]) >> 759b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org 13); 760b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org uImag[i] = (int16_t)((-noiseRShift16[i] * WebRtcAecm_kSinTable[tmp16]) >> 761b38b009d216bc6fc45934d8dafa9e7489ec8e91abjornv@webrtc.org 13); 762e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 763e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org uImag[PART_LEN] = 0; 764e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 765e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org for (i = 0; i < PART_LEN1; i++) 766e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org { 7676e71d17bc98d3b179f55fd4fd42dc5c53b7787dcbjornv@webrtc.org out[i].real = WebRtcSpl_AddSatW16(out[i].real, uReal[i]); 7686e71d17bc98d3b179f55fd4fd42dc5c53b7787dcbjornv@webrtc.org out[i].imag = WebRtcSpl_AddSatW16(out[i].imag, uImag[i]); 769e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org } 770e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org} 771e03cafaebc767b2deb4d6350158e82afb6c6d3c4andrew@webrtc.org 772