Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2379)

Side by Side Diff: webrtc/modules/audio_processing/aec/aec_core.c

Issue 1456123003: Ducking fix #3: Removed the state as an input to the FilterAdaptation function (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@Aec_Code_Cleanup2_CL
Patch Set: Various refactoring, among other things simplification of the EchoSubtraction function Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 xfBuf[1][xPos + j], 175 xfBuf[1][xPos + j],
176 wfBuf[0][pos + j], 176 wfBuf[0][pos + j],
177 wfBuf[1][pos + j]); 177 wfBuf[1][pos + j]);
178 } 178 }
179 } 179 }
180 } 180 }
181 181
182 static void ScaleErrorSignal(int extended_filter_enabled, 182 static void ScaleErrorSignal(int extended_filter_enabled,
183 float normal_mu, 183 float normal_mu,
184 float normal_error_threshold, 184 float normal_error_threshold,
185 float *xPow, 185 float xPow[PART_LEN1],
186 float ef[2][PART_LEN1]) { 186 float ef[2][PART_LEN1]) {
187 const float mu = extended_filter_enabled ? kExtendedMu : normal_mu; 187 const float mu = extended_filter_enabled ? kExtendedMu : normal_mu;
188 const float error_threshold = extended_filter_enabled 188 const float error_threshold = extended_filter_enabled
189 ? kExtendedErrorThreshold 189 ? kExtendedErrorThreshold
190 : normal_error_threshold; 190 : normal_error_threshold;
191 int i; 191 int i;
192 float abs_ef; 192 float abs_ef;
193 for (i = 0; i < (PART_LEN1); i++) { 193 for (i = 0; i < (PART_LEN1); i++) {
194 ef[0][i] /= (xPow[i] + 1e-10f); 194 ef[0][i] /= (xPow[i] + 1e-10f);
195 ef[1][i] /= (xPow[i] + 1e-10f); 195 ef[1][i] /= (xPow[i] + 1e-10f);
196 abs_ef = sqrtf(ef[0][i] * ef[0][i] + ef[1][i] * ef[1][i]); 196 abs_ef = sqrtf(ef[0][i] * ef[0][i] + ef[1][i] * ef[1][i]);
197 197
198 if (abs_ef > error_threshold) { 198 if (abs_ef > error_threshold) {
199 abs_ef = error_threshold / (abs_ef + 1e-10f); 199 abs_ef = error_threshold / (abs_ef + 1e-10f);
200 ef[0][i] *= abs_ef; 200 ef[0][i] *= abs_ef;
201 ef[1][i] *= abs_ef; 201 ef[1][i] *= abs_ef;
202 } 202 }
203 203
204 // Stepsize factor 204 // Stepsize factor
205 ef[0][i] *= mu; 205 ef[0][i] *= mu;
206 ef[1][i] *= mu; 206 ef[1][i] *= mu;
207 } 207 }
208 } 208 }
209 209
210 // Time-unconstrined filter adaptation.
211 // TODO(andrew): consider for a low-complexity mode.
212 // static void FilterAdaptationUnconstrained(AecCore* aec, float *fft,
213 // float ef[2][PART_LEN1]) {
214 // int i, j;
215 // for (i = 0; i < aec->num_partitions; i++) {
216 // int xPos = (i + aec->xfBufBlockPos)*(PART_LEN1);
217 // int pos;
218 // // Check for wrap
219 // if (i + aec->xfBufBlockPos >= aec->num_partitions) {
220 // xPos -= aec->num_partitions * PART_LEN1;
221 // }
222 //
223 // pos = i * PART_LEN1;
224 //
225 // for (j = 0; j < PART_LEN1; j++) {
226 // aec->wfBuf[0][pos + j] += MulRe(aec->xfBuf[0][xPos + j],
227 // -aec->xfBuf[1][xPos + j],
228 // ef[0][j], ef[1][j]);
229 // aec->wfBuf[1][pos + j] += MulIm(aec->xfBuf[0][xPos + j],
230 // -aec->xfBuf[1][xPos + j],
231 // ef[0][j], ef[1][j]);
232 // }
233 // }
234 //}
235 210
236 static void FilterAdaptation(AecCore* aec, float* fft, float ef[2][PART_LEN1]) { 211 static void FilterAdaptation(
212 int num_partitions,
213 int xfBufBlockPos,
hlundin-webrtc 2015/11/20 11:55:20 Rename parameters.
peah-webrtc 2015/11/24 13:03:01 Done.
214 float xfBuf[2][kExtendedNumPartitions * PART_LEN1],
hlundin-webrtc 2015/11/20 11:55:20 Any of the array input that can be made const?
peah-webrtc 2015/11/24 13:03:01 I checked with kwiberg@ and he said it should be f
215 float ef[2][PART_LEN1],
216 float wfBuf[2][kExtendedNumPartitions * PART_LEN1]) {
237 int i, j; 217 int i, j;
238 for (i = 0; i < aec->num_partitions; i++) { 218 float fft[PART_LEN2];
239 int xPos = (i + aec->xfBufBlockPos) * (PART_LEN1); 219 for (i = 0; i < num_partitions; i++) {
220 int xPos = (i + xfBufBlockPos) * (PART_LEN1);
240 int pos; 221 int pos;
241 // Check for wrap 222 // Check for wrap
242 if (i + aec->xfBufBlockPos >= aec->num_partitions) { 223 if (i + xfBufBlockPos >= num_partitions) {
243 xPos -= aec->num_partitions * PART_LEN1; 224 xPos -= num_partitions * PART_LEN1;
244 } 225 }
245 226
246 pos = i * PART_LEN1; 227 pos = i * PART_LEN1;
247 228
248 for (j = 0; j < PART_LEN; j++) { 229 for (j = 0; j < PART_LEN; j++) {
249 230
250 fft[2 * j] = MulRe(aec->xfBuf[0][xPos + j], 231 fft[2 * j] = MulRe(xfBuf[0][xPos + j],
251 -aec->xfBuf[1][xPos + j], 232 -xfBuf[1][xPos + j],
252 ef[0][j], 233 ef[0][j],
253 ef[1][j]); 234 ef[1][j]);
254 fft[2 * j + 1] = MulIm(aec->xfBuf[0][xPos + j], 235 fft[2 * j + 1] = MulIm(xfBuf[0][xPos + j],
255 -aec->xfBuf[1][xPos + j], 236 -xfBuf[1][xPos + j],
256 ef[0][j], 237 ef[0][j],
257 ef[1][j]); 238 ef[1][j]);
258 } 239 }
259 fft[1] = MulRe(aec->xfBuf[0][xPos + PART_LEN], 240 fft[1] = MulRe(xfBuf[0][xPos + PART_LEN],
260 -aec->xfBuf[1][xPos + PART_LEN], 241 -xfBuf[1][xPos + PART_LEN],
261 ef[0][PART_LEN], 242 ef[0][PART_LEN],
262 ef[1][PART_LEN]); 243 ef[1][PART_LEN]);
263 244
264 aec_rdft_inverse_128(fft); 245 aec_rdft_inverse_128(fft);
265 memset(fft + PART_LEN, 0, sizeof(float) * PART_LEN); 246 memset(fft + PART_LEN, 0, sizeof(float) * PART_LEN);
266 247
267 // fft scaling 248 // fft scaling
268 { 249 {
269 float scale = 2.0f / PART_LEN2; 250 float scale = 2.0f / PART_LEN2;
270 for (j = 0; j < PART_LEN; j++) { 251 for (j = 0; j < PART_LEN; j++) {
271 fft[j] *= scale; 252 fft[j] *= scale;
272 } 253 }
273 } 254 }
274 aec_rdft_forward_128(fft); 255 aec_rdft_forward_128(fft);
275 256
276 aec->wfBuf[0][pos] += fft[0]; 257 wfBuf[0][pos] += fft[0];
277 aec->wfBuf[0][pos + PART_LEN] += fft[1]; 258 wfBuf[0][pos + PART_LEN] += fft[1];
278 259
279 for (j = 1; j < PART_LEN; j++) { 260 for (j = 1; j < PART_LEN; j++) {
280 aec->wfBuf[0][pos + j] += fft[2 * j]; 261 wfBuf[0][pos + j] += fft[2 * j];
281 aec->wfBuf[1][pos + j] += fft[2 * j + 1]; 262 wfBuf[1][pos + j] += fft[2 * j + 1];
282 } 263 }
283 } 264 }
284 } 265 }
285 266
286 static void OverdriveAndSuppress(AecCore* aec, 267 static void OverdriveAndSuppress(AecCore* aec,
287 float hNl[PART_LEN1], 268 float hNl[PART_LEN1],
288 const float hNlFb, 269 const float hNlFb,
289 float efw[2][PART_LEN1]) { 270 float efw[2][PART_LEN1]) {
290 int i; 271 int i;
291 for (i = 0; i < PART_LEN1; i++) { 272 for (i = 0; i < PART_LEN1; i++) {
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 self->num_delay_values; 819 self->num_delay_values;
839 } 820 }
840 821
841 // Reset histogram. 822 // Reset histogram.
842 memset(self->delay_histogram, 0, sizeof(self->delay_histogram)); 823 memset(self->delay_histogram, 0, sizeof(self->delay_histogram));
843 self->num_delay_values = 0; 824 self->num_delay_values = 0;
844 825
845 return; 826 return;
846 } 827 }
847 828
848 static void FrequencyToTime(float freq_data[2][PART_LEN1], 829 static void InverseFft(float freq_data[2][PART_LEN1],
hlundin-webrtc 2015/11/20 11:55:20 Make freq_data const.
peah-webrtc 2015/11/24 13:03:01 Done.
849 float time_data[PART_LEN2]) { 830 float time_data[PART_LEN2]) {
850 time_data[0] = freq_data[0][0]; 831 time_data[0] = freq_data[0][0];
851 time_data[1] = freq_data[0][PART_LEN]; 832 time_data[1] = freq_data[0][PART_LEN];
852 for (int i = 1; i < PART_LEN; i++) { 833 for (int i = 1; i < PART_LEN; i++) {
853 time_data[2 * i] = freq_data[0][i]; 834 time_data[2 * i] = freq_data[0][i];
854 time_data[2 * i + 1] = freq_data[1][i]; 835 time_data[2 * i + 1] = freq_data[1][i];
855 } 836 }
856 aec_rdft_inverse_128(time_data); 837 aec_rdft_inverse_128(time_data);
857 } 838 }
858 839
859 840
860 static void TimeToFrequency(float time_data[PART_LEN2], 841 static void Fft(float time_data[PART_LEN2],
hlundin-webrtc 2015/11/20 11:55:20 Make time_data const.
ivoc 2015/11/20 12:58:02 I think the aec_rdft_forward_128 function writes t
peah-webrtc 2015/11/24 13:03:01 That is fully correct. And you have a great point!
peah-webrtc 2015/11/24 13:03:01 Done.
861 float freq_data[2][PART_LEN1], 842 float freq_data[2][PART_LEN1]) {
862 int window) {
863 int i = 0;
864
865 // TODO(bjornv): Should we have a different function/wrapper for windowed FFT?
866 if (window) {
867 for (i = 0; i < PART_LEN; i++) {
868 time_data[i] *= WebRtcAec_sqrtHanning[i];
869 time_data[PART_LEN + i] *= WebRtcAec_sqrtHanning[PART_LEN - i];
870 }
871 }
872
873 aec_rdft_forward_128(time_data); 843 aec_rdft_forward_128(time_data);
874 // Reorder. 844 // Reorder fft output data.
875 freq_data[1][0] = 0; 845 freq_data[1][0] = 0;
876 freq_data[1][PART_LEN] = 0; 846 freq_data[1][PART_LEN] = 0;
877 freq_data[0][0] = time_data[0]; 847 freq_data[0][0] = time_data[0];
878 freq_data[0][PART_LEN] = time_data[1]; 848 freq_data[0][PART_LEN] = time_data[1];
879 for (i = 1; i < PART_LEN; i++) { 849 for (int i = 1; i < PART_LEN; i++) {
880 freq_data[0][i] = time_data[2 * i]; 850 freq_data[0][i] = time_data[2 * i];
881 freq_data[1][i] = time_data[2 * i + 1]; 851 freq_data[1][i] = time_data[2 * i + 1];
882 } 852 }
883 } 853 }
884 854
885 static int MoveFarReadPtrWithoutSystemDelayUpdate(AecCore* self, int elements) { 855 static int MoveFarReadPtrWithoutSystemDelayUpdate(AecCore* self, int elements) {
886 WebRtc_MoveReadPtr(self->far_buf_windowed, elements); 856 WebRtc_MoveReadPtr(self->far_buf_windowed, elements);
887 #ifdef WEBRTC_AEC_DEBUG_DUMP 857 #ifdef WEBRTC_AEC_DEBUG_DUMP
888 WebRtc_MoveReadPtr(self->far_time_buf, elements); 858 WebRtc_MoveReadPtr(self->far_time_buf, elements);
889 #endif 859 #endif
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
956 delay_quality = (delay_quality > kDelayQualityThresholdMax ? 926 delay_quality = (delay_quality > kDelayQualityThresholdMax ?
957 kDelayQualityThresholdMax : delay_quality); 927 kDelayQualityThresholdMax : delay_quality);
958 self->delay_quality_threshold = 928 self->delay_quality_threshold =
959 (delay_quality > self->delay_quality_threshold ? delay_quality : 929 (delay_quality > self->delay_quality_threshold ? delay_quality :
960 self->delay_quality_threshold); 930 self->delay_quality_threshold);
961 } 931 }
962 return delay_correction; 932 return delay_correction;
963 } 933 }
964 934
965 static void EchoSubtraction(AecCore* aec, 935 static void EchoSubtraction(AecCore* aec,
966 float* nearend_ptr) { 936 int num_partitions,
967 float yf[2][PART_LEN1]; 937 int xfBufBlockPos,
hlundin-webrtc 2015/11/20 11:55:20 Change naming format of input parameters.
peah-webrtc 2015/11/24 13:03:01 Done.
968 float fft[PART_LEN2]; 938 int metricsMode,
969 float y[PART_LEN]; 939 int extended_filter_enabled,
940 float normal_mu,
941 float normal_error_threshold,
942 float xfBuf[2][kExtendedNumPartitions * PART_LEN1],
943 const float* const y,
944 float xPow[PART_LEN1],
hlundin-webrtc 2015/11/20 11:55:20 Can you make any array parameters const?
peah-webrtc 2015/11/24 13:03:01 Yes, and I'll as a consequense also add const to t
945 float wfBuf[2][kExtendedNumPartitions * PART_LEN1],
946 PowerLevel* linoutlevel,
947 float echo_subtractor_output[PART_LEN]) {
948 float s_fft[2][PART_LEN1];
949 float e_extended[PART_LEN2];
950 float s_extended[PART_LEN2];
951 float *s;
970 float e[PART_LEN]; 952 float e[PART_LEN];
971 float ef[2][PART_LEN1]; 953 float e_fft[2][PART_LEN1];
972 float scale; 954 float scale;
973 int i; 955 int i;
974 memset(yf, 0, sizeof(yf)); 956 memset(s_fft, 0, sizeof(s_fft));
975 957
976 // Produce echo estimate. 958 // Produce echo estimate s_fft.
977 WebRtcAec_FilterFar(aec->num_partitions, 959 WebRtcAec_FilterFar(num_partitions,
978 aec->xfBufBlockPos, 960 xfBufBlockPos,
979 aec->xfBuf, 961 xfBuf,
980 aec->wfBuf, 962 wfBuf,
981 yf); 963 s_fft);
982 964
983 // Inverse fft to obtain echo estimate and error. 965 // Compute the time-domain echo estimate s.
984 FrequencyToTime(yf, fft); 966 InverseFft(s_fft, s_extended);
985
986 // Extract the output signal and compute the time-domain error
987 scale = 2.0f / PART_LEN2; 967 scale = 2.0f / PART_LEN2;
988 for (i = 0; i < PART_LEN; i++) { 968 s = &s_extended[PART_LEN];
989 y[i] = fft[PART_LEN + i] * scale; // fft scaling 969 for (i = 0; i < PART_LEN; ++i) {
970 s[i] *= scale;
ivoc 2015/11/20 12:58:02 Should scaling be part of the InverseFft function?
peah-webrtc 2015/11/24 13:03:01 I think the division by PART_LEN could go there, b
990 } 971 }
991 972
992 for (i = 0; i < PART_LEN; i++) { 973 // Compute the time-domain echo prediction error.
993 e[i] = nearend_ptr[i] - y[i]; 974 for (i = 0; i < PART_LEN; ++i) {
975 e[i] = y[i] - s[i];
ivoc 2015/11/20 12:58:02 Loop can be merged with previous loop.
peah-webrtc 2015/11/24 13:03:01 Done in a previous CL. Done.
994 } 976 }
995 977
978 // Compute the frequency domain echo prediction error.
979 memset(e_extended, 0, sizeof(float) * PART_LEN);
980 memcpy(e_extended + PART_LEN, e, sizeof(float) * PART_LEN);
ivoc 2015/11/20 12:58:02 I think it makes more sense to skip the e signal,
peah-webrtc 2015/11/24 13:03:01 I agree, but it will be used in an upcoming CL, so
981 Fft(e_extended, e_fft);
996 982
997 // Error fft
998 memcpy(aec->eBuf + PART_LEN, e, sizeof(float) * PART_LEN);
999 memset(fft, 0, sizeof(float) * PART_LEN);
1000 memcpy(fft + PART_LEN, e, sizeof(float) * PART_LEN);
1001 TimeToFrequency(fft, ef, 0);
1002 983
1003 RTC_AEC_DEBUG_RAW_WRITE(aec->e_fft_file, 984 RTC_AEC_DEBUG_RAW_WRITE(aec->e_fft_file,
1004 &ef[0][0], 985 &e_fft[0][0],
1005 sizeof(ef[0][0]) * PART_LEN1 * 2); 986 sizeof(e_fft[0][0]) * PART_LEN1 * 2);
1006 987
1007 if (aec->metricsMode == 1) { 988 if (metricsMode == 1) {
1008 // Note that the first PART_LEN samples in fft (before transformation) are 989 // Note that the first PART_LEN samples in fft (before transformation) are
1009 // zero. Hence, the scaling by two in UpdateLevel() should not be 990 // zero. Hence, the scaling by two in UpdateLevel() should not be
1010 // performed. That scaling is taken care of in UpdateMetrics() instead. 991 // performed. That scaling is taken care of in UpdateMetrics() instead.
1011 UpdateLevel(&aec->linoutlevel, ef); 992 UpdateLevel(linoutlevel, e_fft);
1012 } 993 }
1013 994
1014 // Scale error signal inversely with far power. 995 // Scale error signal inversely with far power.
1015 WebRtcAec_ScaleErrorSignal(aec->extended_filter_enabled, 996 WebRtcAec_ScaleErrorSignal(extended_filter_enabled,
1016 aec->normal_mu, 997 normal_mu,
1017 aec->normal_error_threshold, 998 normal_error_threshold,
1018 aec->xPow, 999 xPow,
1019 ef); 1000 e_fft);
1020 WebRtcAec_FilterAdaptation(aec, fft, ef); 1001 WebRtcAec_FilterAdaptation(num_partitions,
1021 1002 xfBufBlockPos,
1022 1003 xfBuf,
1023 RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, e, PART_LEN); 1004 e_fft,
1005 wfBuf);
1006 memcpy(echo_subtractor_output, e, sizeof(float) * PART_LEN);
1024 } 1007 }
1025 1008
1026 1009
1027 static void EchoSuppression(AecCore* aec, 1010 static void EchoSuppression(AecCore* aec,
1028 float* output, 1011 float* output,
1029 float* const* outputH) { 1012 float* const* outputH) {
1030 float efw[2][PART_LEN1], xfw[2][PART_LEN1]; 1013 float efw[2][PART_LEN1], xfw[2][PART_LEN1];
1031 complex_t comfortNoiseHband[PART_LEN1]; 1014 complex_t comfortNoiseHband[PART_LEN1];
1032 float fft[PART_LEN2]; 1015 float fft[PART_LEN2];
1033 float scale, dtmp; 1016 float scale, dtmp;
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
1270 1253
1271 const float gPow[2] = {0.9f, 0.1f}; 1254 const float gPow[2] = {0.9f, 0.1f};
1272 1255
1273 // Noise estimate constants. 1256 // Noise estimate constants.
1274 const int noiseInitBlocks = 500 * aec->mult; 1257 const int noiseInitBlocks = 500 * aec->mult;
1275 const float step = 0.1f; 1258 const float step = 0.1f;
1276 const float ramp = 1.0002f; 1259 const float ramp = 1.0002f;
1277 const float gInitNoise[2] = {0.999f, 0.001f}; 1260 const float gInitNoise[2] = {0.999f, 0.001f};
1278 1261
1279 float nearend[PART_LEN]; 1262 float nearend[PART_LEN];
1263 float echo_subtractor_output[PART_LEN];
1280 float* nearend_ptr = NULL; 1264 float* nearend_ptr = NULL;
1281 float output[PART_LEN]; 1265 float output[PART_LEN];
1282 float outputH[NUM_HIGH_BANDS_MAX][PART_LEN]; 1266 float outputH[NUM_HIGH_BANDS_MAX][PART_LEN];
1283 float* outputH_ptr[NUM_HIGH_BANDS_MAX]; 1267 float* outputH_ptr[NUM_HIGH_BANDS_MAX];
1284 float* xf_ptr = NULL; 1268 float* xf_ptr = NULL;
1285 1269
1286 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { 1270 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) {
1287 outputH_ptr[i] = outputH[i]; 1271 outputH_ptr[i] = outputH[i];
1288 } 1272 }
1289 1273
(...skipping 19 matching lines...) Expand all
1309 RTC_AEC_DEBUG_WAV_WRITE(aec->nearFile, nearend_ptr, PART_LEN); 1293 RTC_AEC_DEBUG_WAV_WRITE(aec->nearFile, nearend_ptr, PART_LEN);
1310 } 1294 }
1311 #endif 1295 #endif
1312 1296
1313 // We should always have at least one element stored in |far_buf|. 1297 // We should always have at least one element stored in |far_buf|.
1314 assert(WebRtc_available_read(aec->far_buf) > 0); 1298 assert(WebRtc_available_read(aec->far_buf) > 0);
1315 WebRtc_ReadBuffer(aec->far_buf, (void**)&xf_ptr, &xf[0][0], 1); 1299 WebRtc_ReadBuffer(aec->far_buf, (void**)&xf_ptr, &xf[0][0], 1);
1316 1300
1317 // Near fft 1301 // Near fft
1318 memcpy(fft, aec->dBuf, sizeof(float) * PART_LEN2); 1302 memcpy(fft, aec->dBuf, sizeof(float) * PART_LEN2);
1319 TimeToFrequency(fft, df, 0); 1303 Fft(fft, df);
1320 1304
1321 // Power smoothing 1305 // Power smoothing
1322 for (i = 0; i < PART_LEN1; i++) { 1306 for (i = 0; i < PART_LEN1; i++) {
1323 far_spectrum = (xf_ptr[i] * xf_ptr[i]) + 1307 far_spectrum = (xf_ptr[i] * xf_ptr[i]) +
1324 (xf_ptr[PART_LEN1 + i] * xf_ptr[PART_LEN1 + i]); 1308 (xf_ptr[PART_LEN1 + i] * xf_ptr[PART_LEN1 + i]);
1325 aec->xPow[i] = 1309 aec->xPow[i] =
1326 gPow[0] * aec->xPow[i] + gPow[1] * aec->num_partitions * far_spectrum; 1310 gPow[0] * aec->xPow[i] + gPow[1] * aec->num_partitions * far_spectrum;
1327 // Calculate absolute spectra 1311 // Calculate absolute spectra
1328 abs_far_spectrum[i] = sqrtf(far_spectrum); 1312 abs_far_spectrum[i] = sqrtf(far_spectrum);
1329 1313
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1388 1372
1389 // Buffer xf 1373 // Buffer xf
1390 memcpy(aec->xfBuf[0] + aec->xfBufBlockPos * PART_LEN1, 1374 memcpy(aec->xfBuf[0] + aec->xfBufBlockPos * PART_LEN1,
1391 xf_ptr, 1375 xf_ptr,
1392 sizeof(float) * PART_LEN1); 1376 sizeof(float) * PART_LEN1);
1393 memcpy(aec->xfBuf[1] + aec->xfBufBlockPos * PART_LEN1, 1377 memcpy(aec->xfBuf[1] + aec->xfBufBlockPos * PART_LEN1,
1394 &xf_ptr[PART_LEN1], 1378 &xf_ptr[PART_LEN1],
1395 sizeof(float) * PART_LEN1); 1379 sizeof(float) * PART_LEN1);
1396 1380
1397 // Perform echo subtraction. 1381 // Perform echo subtraction.
1398 EchoSubtraction(aec, nearend_ptr); 1382 EchoSubtraction(aec,
1383 aec->num_partitions,
1384 aec->xfBufBlockPos,
1385 aec->metricsMode,
1386 aec->extended_filter_enabled,
1387 aec->normal_mu,
1388 aec->normal_error_threshold,
1389 aec->xfBuf,
1390 nearend_ptr,
1391 aec->xPow,
1392 aec->wfBuf,
1393 &aec->linoutlevel,
1394 echo_subtractor_output);
1395
1396 RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, echo_subtractor_output, PART_LEN);
1399 1397
1400 // Perform echo suppression. 1398 // Perform echo suppression.
1399 memcpy(aec->eBuf + PART_LEN,
1400 echo_subtractor_output,
1401 sizeof(float) * PART_LEN);
1401 EchoSuppression(aec, output, outputH_ptr); 1402 EchoSuppression(aec, output, outputH_ptr);
1402 1403
1403 if (aec->metricsMode == 1) { 1404 if (aec->metricsMode == 1) {
1404 // Update power levels and echo metrics 1405 // Update power levels and echo metrics
1405 UpdateLevel(&aec->farlevel, (float(*)[PART_LEN1])xf_ptr); 1406 UpdateLevel(&aec->farlevel, (float(*)[PART_LEN1])xf_ptr);
1406 UpdateLevel(&aec->nearlevel, df); 1407 UpdateLevel(&aec->nearlevel, df);
1407 UpdateMetrics(aec); 1408 UpdateMetrics(aec);
1408 } 1409 }
1409 1410
1410 // Store the output block. 1411 // Store the output block.
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
1733 void WebRtcAec_BufferFarendPartition(AecCore* aec, const float* farend) { 1734 void WebRtcAec_BufferFarendPartition(AecCore* aec, const float* farend) {
1734 float fft[PART_LEN2]; 1735 float fft[PART_LEN2];
1735 float xf[2][PART_LEN1]; 1736 float xf[2][PART_LEN1];
1736 1737
1737 // Check if the buffer is full, and in that case flush the oldest data. 1738 // Check if the buffer is full, and in that case flush the oldest data.
1738 if (WebRtc_available_write(aec->far_buf) < 1) { 1739 if (WebRtc_available_write(aec->far_buf) < 1) {
1739 WebRtcAec_MoveFarReadPtr(aec, 1); 1740 WebRtcAec_MoveFarReadPtr(aec, 1);
1740 } 1741 }
1741 // Convert far-end partition to the frequency domain without windowing. 1742 // Convert far-end partition to the frequency domain without windowing.
1742 memcpy(fft, farend, sizeof(float) * PART_LEN2); 1743 memcpy(fft, farend, sizeof(float) * PART_LEN2);
1743 TimeToFrequency(fft, xf, 0); 1744 Fft(fft, xf);
1744 WebRtc_WriteBuffer(aec->far_buf, &xf[0][0], 1); 1745 WebRtc_WriteBuffer(aec->far_buf, &xf[0][0], 1);
1745 1746
1746 // Convert far-end partition to the frequency domain with windowing. 1747 // Convert far-end partition to the frequency domain with windowing.
1747 memcpy(fft, farend, sizeof(float) * PART_LEN2); 1748 WindowData(fft, farend);
1748 TimeToFrequency(fft, xf, 1); 1749 Fft(fft, xf);
1749 WebRtc_WriteBuffer(aec->far_buf_windowed, &xf[0][0], 1); 1750 WebRtc_WriteBuffer(aec->far_buf_windowed, &xf[0][0], 1);
1750 } 1751 }
1751 1752
1752 int WebRtcAec_MoveFarReadPtr(AecCore* aec, int elements) { 1753 int WebRtcAec_MoveFarReadPtr(AecCore* aec, int elements) {
1753 int elements_moved = MoveFarReadPtrWithoutSystemDelayUpdate(aec, elements); 1754 int elements_moved = MoveFarReadPtrWithoutSystemDelayUpdate(aec, elements);
1754 aec->system_delay -= elements_moved * PART_LEN; 1755 aec->system_delay -= elements_moved * PART_LEN;
1755 return elements_moved; 1756 return elements_moved;
1756 } 1757 }
1757 1758
1758 void WebRtcAec_ProcessFrames(AecCore* aec, 1759 void WebRtcAec_ProcessFrames(AecCore* aec,
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
1950 int WebRtcAec_extended_filter_enabled(AecCore* self) { 1951 int WebRtcAec_extended_filter_enabled(AecCore* self) {
1951 return self->extended_filter_enabled; 1952 return self->extended_filter_enabled;
1952 } 1953 }
1953 1954
1954 int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; } 1955 int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; }
1955 1956
1956 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { 1957 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) {
1957 assert(delay >= 0); 1958 assert(delay >= 0);
1958 self->system_delay = delay; 1959 self->system_delay = delay;
1959 } 1960 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698