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

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

Issue 1455163006: Ducking fix #1:Initial refactoring preparing for further AEC work (changes are bitexact). (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: 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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 aec->wfBuf[0][pos + j], 168 aec->wfBuf[0][pos + j],
169 aec->wfBuf[1][pos + j]); 169 aec->wfBuf[1][pos + j]);
170 yf[1][j] += MulIm(aec->xfBuf[0][xPos + j], 170 yf[1][j] += MulIm(aec->xfBuf[0][xPos + j],
171 aec->xfBuf[1][xPos + j], 171 aec->xfBuf[1][xPos + j],
172 aec->wfBuf[0][pos + j], 172 aec->wfBuf[0][pos + j],
173 aec->wfBuf[1][pos + j]); 173 aec->wfBuf[1][pos + j]);
174 } 174 }
175 } 175 }
176 } 176 }
177 177
178 static void ScaleErrorSignal(AecCore* aec, float ef[2][PART_LEN1]) { 178 static void ScaleErrorSignal(int extended_filter_enabled,
179 const float mu = aec->extended_filter_enabled ? kExtendedMu : aec->normal_mu; 179 float normal_mu,
180 const float error_threshold = aec->extended_filter_enabled 180 float normal_error_threshold,
181 float *xPow,
hlundin-webrtc 2015/11/20 10:55:40 Rename xPow -> x_pow while you are at it.
ivoc 2015/11/20 10:58:13 I know the style guide doesn't cover C-code, but d
peah-webrtc 2015/11/23 21:39:07 Done.
peah-webrtc 2015/11/23 21:39:07 I got the advice from kwiberg (I think) not to add
182 float ef[2][PART_LEN1]) {
183 const float mu = extended_filter_enabled ? kExtendedMu : normal_mu;
184 const float error_threshold = extended_filter_enabled
181 ? kExtendedErrorThreshold 185 ? kExtendedErrorThreshold
182 : aec->normal_error_threshold; 186 : normal_error_threshold;
183 int i; 187 int i;
184 float abs_ef; 188 float abs_ef;
185 for (i = 0; i < (PART_LEN1); i++) { 189 for (i = 0; i < (PART_LEN1); i++) {
186 ef[0][i] /= (aec->xPow[i] + 1e-10f); 190 ef[0][i] /= (xPow[i] + 1e-10f);
187 ef[1][i] /= (aec->xPow[i] + 1e-10f); 191 ef[1][i] /= (xPow[i] + 1e-10f);
188 abs_ef = sqrtf(ef[0][i] * ef[0][i] + ef[1][i] * ef[1][i]); 192 abs_ef = sqrtf(ef[0][i] * ef[0][i] + ef[1][i] * ef[1][i]);
189 193
190 if (abs_ef > error_threshold) { 194 if (abs_ef > error_threshold) {
191 abs_ef = error_threshold / (abs_ef + 1e-10f); 195 abs_ef = error_threshold / (abs_ef + 1e-10f);
192 ef[0][i] *= abs_ef; 196 ef[0][i] *= abs_ef;
193 ef[1][i] *= abs_ef; 197 ef[1][i] *= abs_ef;
194 } 198 }
195 199
196 // Stepsize factor 200 // Stepsize factor
197 ef[0][i] *= mu; 201 ef[0][i] *= mu;
(...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 self->num_delay_values; 834 self->num_delay_values;
831 } 835 }
832 836
833 // Reset histogram. 837 // Reset histogram.
834 memset(self->delay_histogram, 0, sizeof(self->delay_histogram)); 838 memset(self->delay_histogram, 0, sizeof(self->delay_histogram));
835 self->num_delay_values = 0; 839 self->num_delay_values = 0;
836 840
837 return; 841 return;
838 } 842 }
839 843
844 static void FrequencyToTime(float freq_data[2][PART_LEN1],
845 float time_data[PART_LEN2]) {
846 time_data[0] = freq_data[0][0];
847 time_data[1] = freq_data[0][PART_LEN];
ivoc 2015/11/20 10:58:13 Is it me, or are freq_data[1][0] and freq_data[1][
peah-webrtc 2015/11/23 21:39:07 You are correct, and I think that that format is u
848 for (int i = 1; i < PART_LEN; i++) {
849 time_data[2 * i] = freq_data[0][i];
850 time_data[2 * i + 1] = freq_data[1][i];
851 }
852 aec_rdft_inverse_128(time_data);
853 }
854
855
840 static void TimeToFrequency(float time_data[PART_LEN2], 856 static void TimeToFrequency(float time_data[PART_LEN2],
841 float freq_data[2][PART_LEN1], 857 float freq_data[2][PART_LEN1],
842 int window) { 858 int window) {
843 int i = 0; 859 int i = 0;
844 860
845 // TODO(bjornv): Should we have a different function/wrapper for windowed FFT? 861 // TODO(bjornv): Should we have a different function/wrapper for windowed FFT?
846 if (window) { 862 if (window) {
847 for (i = 0; i < PART_LEN; i++) { 863 for (i = 0; i < PART_LEN; i++) {
848 time_data[i] *= WebRtcAec_sqrtHanning[i]; 864 time_data[i] *= WebRtcAec_sqrtHanning[i];
849 time_data[PART_LEN + i] *= WebRtcAec_sqrtHanning[PART_LEN - i]; 865 time_data[PART_LEN + i] *= WebRtcAec_sqrtHanning[PART_LEN - i];
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 float delay_quality = WebRtc_last_delay_quality(self->delay_estimator); 951 float delay_quality = WebRtc_last_delay_quality(self->delay_estimator);
936 delay_quality = (delay_quality > kDelayQualityThresholdMax ? 952 delay_quality = (delay_quality > kDelayQualityThresholdMax ?
937 kDelayQualityThresholdMax : delay_quality); 953 kDelayQualityThresholdMax : delay_quality);
938 self->delay_quality_threshold = 954 self->delay_quality_threshold =
939 (delay_quality > self->delay_quality_threshold ? delay_quality : 955 (delay_quality > self->delay_quality_threshold ? delay_quality :
940 self->delay_quality_threshold); 956 self->delay_quality_threshold);
941 } 957 }
942 return delay_correction; 958 return delay_correction;
943 } 959 }
944 960
945 static void NonLinearProcessing(AecCore* aec, 961 static void EchoSubtraction(AecCore* aec,
946 float* output, 962 float* nearend_ptr) {
947 float* const* outputH) { 963 float yf[2][PART_LEN1];
964 float fft[PART_LEN2];
965 float y[PART_LEN];
966 float e[PART_LEN];
967 float ef[2][PART_LEN1];
968 float scale;
969 int i;
970 memset(yf, 0, sizeof(yf));
971
972 // Produce echo estimate.
hlundin-webrtc 2015/11/20 10:55:40 ... in frequency domain.
peah-webrtc 2015/11/23 21:39:06 Done.
973 WebRtcAec_FilterFar(aec, yf);
974
975 // Inverse fft to obtain echo estimate and error.
976 FrequencyToTime(yf, fft);
977
978 // Extract the output signal and compute the time-domain error
hlundin-webrtc 2015/11/20 10:55:40 .
peah-webrtc 2015/11/23 21:39:07 Done.
979 scale = 2.0f / PART_LEN2;
980 for (i = 0; i < PART_LEN; i++) {
981 y[i] = fft[PART_LEN + i] * scale; // fft scaling
ivoc 2015/11/20 10:58:13 Would it make sense to integrate this into the Fre
peah-webrtc 2015/11/23 21:39:07 I don't think we should, as that loses the symmetr
982 }
983
984 for (i = 0; i < PART_LEN; i++) {
985 e[i] = nearend_ptr[i] - y[i];
ivoc 2015/11/20 10:58:13 Could be integrated with the previous loop, for ef
peah-webrtc 2015/11/23 21:39:07 Agree, will do. Done.
986 }
987
988
ivoc 2015/11/20 10:58:14 2 empty lines is a bit much here (in my opinion).
peah-webrtc 2015/11/23 21:39:07 Done.
989 // Error fft
990 memcpy(aec->eBuf + PART_LEN, e, sizeof(float) * PART_LEN);
991 memset(fft, 0, sizeof(float) * PART_LEN);
992 memcpy(fft + PART_LEN, e, sizeof(float) * PART_LEN);
993 TimeToFrequency(fft, ef, 0);
994
995 RTC_AEC_DEBUG_RAW_WRITE(aec->e_fft_file,
996 &ef[0][0],
997 sizeof(ef[0][0]) * PART_LEN1 * 2);
998
999 if (aec->metricsMode == 1) {
1000 // Note that the first PART_LEN samples in fft (before transformation) are
1001 // zero. Hence, the scaling by two in UpdateLevel() should not be
1002 // performed. That scaling is taken care of in UpdateMetrics() instead.
1003 UpdateLevel(&aec->linoutlevel, ef);
1004 }
1005
1006 // Scale error signal inversely with far power.
1007 WebRtcAec_ScaleErrorSignal(aec->extended_filter_enabled,
1008 aec->normal_mu,
1009 aec->normal_error_threshold,
1010 aec->xPow,
1011 ef);
1012 WebRtcAec_FilterAdaptation(aec, fft, ef);
1013
1014
ivoc 2015/11/20 10:58:13 2 empty lines is a bit much here (in my opinion).
peah-webrtc 2015/11/23 21:39:07 Done.
1015 RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, e, PART_LEN);
1016 }
1017
1018
1019 static void EchoSuppression(AecCore* aec,
1020 float* output,
1021 float* const* outputH) {
948 float efw[2][PART_LEN1], xfw[2][PART_LEN1]; 1022 float efw[2][PART_LEN1], xfw[2][PART_LEN1];
949 complex_t comfortNoiseHband[PART_LEN1]; 1023 complex_t comfortNoiseHband[PART_LEN1];
950 float fft[PART_LEN2]; 1024 float fft[PART_LEN2];
951 float scale, dtmp; 1025 float scale, dtmp;
952 float nlpGainHband; 1026 float nlpGainHband;
953 int i; 1027 int i;
954 size_t j; 1028 size_t j;
955 1029
956 // Coherence and non-linear filter 1030 // Coherence and non-linear filter
957 float cohde[PART_LEN1], cohxd[PART_LEN1]; 1031 float cohde[PART_LEN1], cohxd[PART_LEN1];
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
1170 memcpy(aec->dBufH[j], aec->dBufH[j] + PART_LEN, sizeof(float) * PART_LEN); 1244 memcpy(aec->dBufH[j], aec->dBufH[j] + PART_LEN, sizeof(float) * PART_LEN);
1171 } 1245 }
1172 1246
1173 memmove(aec->xfwBuf + PART_LEN1, 1247 memmove(aec->xfwBuf + PART_LEN1,
1174 aec->xfwBuf, 1248 aec->xfwBuf,
1175 sizeof(aec->xfwBuf) - sizeof(complex_t) * PART_LEN1); 1249 sizeof(aec->xfwBuf) - sizeof(complex_t) * PART_LEN1);
1176 } 1250 }
1177 1251
1178 static void ProcessBlock(AecCore* aec) { 1252 static void ProcessBlock(AecCore* aec) {
1179 size_t i; 1253 size_t i;
1180 float y[PART_LEN], e[PART_LEN];
1181 float scale;
1182 1254
1183 float fft[PART_LEN2]; 1255 float fft[PART_LEN2];
1184 float xf[2][PART_LEN1], yf[2][PART_LEN1], ef[2][PART_LEN1]; 1256 float xf[2][PART_LEN1];
1185 float df[2][PART_LEN1]; 1257 float df[2][PART_LEN1];
1186 float far_spectrum = 0.0f; 1258 float far_spectrum = 0.0f;
1187 float near_spectrum = 0.0f; 1259 float near_spectrum = 0.0f;
1188 float abs_far_spectrum[PART_LEN1]; 1260 float abs_far_spectrum[PART_LEN1];
1189 float abs_near_spectrum[PART_LEN1]; 1261 float abs_near_spectrum[PART_LEN1];
1190 1262
1191 const float gPow[2] = {0.9f, 0.1f}; 1263 const float gPow[2] = {0.9f, 0.1f};
1192 1264
1193 // Noise estimate constants. 1265 // Noise estimate constants.
1194 const int noiseInitBlocks = 500 * aec->mult; 1266 const int noiseInitBlocks = 500 * aec->mult;
1195 const float step = 0.1f; 1267 const float step = 0.1f;
1196 const float ramp = 1.0002f; 1268 const float ramp = 1.0002f;
1197 const float gInitNoise[2] = {0.999f, 0.001f}; 1269 const float gInitNoise[2] = {0.999f, 0.001f};
1198 1270
1199 float nearend[PART_LEN]; 1271 float nearend[PART_LEN];
1200 float* nearend_ptr = NULL; 1272 float* nearend_ptr = NULL;
1201 float output[PART_LEN]; 1273 float output[PART_LEN];
1202 float outputH[NUM_HIGH_BANDS_MAX][PART_LEN]; 1274 float outputH[NUM_HIGH_BANDS_MAX][PART_LEN];
1203 float* outputH_ptr[NUM_HIGH_BANDS_MAX]; 1275 float* outputH_ptr[NUM_HIGH_BANDS_MAX];
1276 float* xf_ptr = NULL;
1277
1204 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { 1278 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) {
1205 outputH_ptr[i] = outputH[i]; 1279 outputH_ptr[i] = outputH[i];
1206 } 1280 }
1207 1281
1208 float* xf_ptr = NULL;
1209
1210 // Concatenate old and new nearend blocks. 1282 // Concatenate old and new nearend blocks.
1211 for (i = 0; i < aec->num_bands - 1; ++i) { 1283 for (i = 0; i < aec->num_bands - 1; ++i) {
1212 WebRtc_ReadBuffer(aec->nearFrBufH[i], 1284 WebRtc_ReadBuffer(aec->nearFrBufH[i],
1213 (void**)&nearend_ptr, 1285 (void**)&nearend_ptr,
1214 nearend, 1286 nearend,
1215 PART_LEN); 1287 PART_LEN);
1216 memcpy(aec->dBufH[i] + PART_LEN, nearend_ptr, sizeof(nearend)); 1288 memcpy(aec->dBufH[i] + PART_LEN, nearend_ptr, sizeof(nearend));
1217 } 1289 }
1218 WebRtc_ReadBuffer(aec->nearFrBuf, (void**)&nearend_ptr, nearend, PART_LEN); 1290 WebRtc_ReadBuffer(aec->nearFrBuf, (void**)&nearend_ptr, nearend, PART_LEN);
1219 memcpy(aec->dBuf + PART_LEN, nearend_ptr, sizeof(nearend)); 1291 memcpy(aec->dBuf + PART_LEN, nearend_ptr, sizeof(nearend));
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1307 } 1379 }
1308 1380
1309 // Buffer xf 1381 // Buffer xf
1310 memcpy(aec->xfBuf[0] + aec->xfBufBlockPos * PART_LEN1, 1382 memcpy(aec->xfBuf[0] + aec->xfBufBlockPos * PART_LEN1,
1311 xf_ptr, 1383 xf_ptr,
1312 sizeof(float) * PART_LEN1); 1384 sizeof(float) * PART_LEN1);
1313 memcpy(aec->xfBuf[1] + aec->xfBufBlockPos * PART_LEN1, 1385 memcpy(aec->xfBuf[1] + aec->xfBufBlockPos * PART_LEN1,
1314 &xf_ptr[PART_LEN1], 1386 &xf_ptr[PART_LEN1],
1315 sizeof(float) * PART_LEN1); 1387 sizeof(float) * PART_LEN1);
1316 1388
1317 memset(yf, 0, sizeof(yf)); 1389 // Perform echo subtraction.
1390 EchoSubtraction(aec, nearend_ptr);
1318 1391
1319 // Filter far 1392 // Perform echo suppression.
1320 WebRtcAec_FilterFar(aec, yf); 1393 EchoSuppression(aec, output, outputH_ptr);
1321
1322 // Inverse fft to obtain echo estimate and error.
1323 fft[0] = yf[0][0];
1324 fft[1] = yf[0][PART_LEN];
1325 for (i = 1; i < PART_LEN; i++) {
1326 fft[2 * i] = yf[0][i];
1327 fft[2 * i + 1] = yf[1][i];
1328 }
1329 aec_rdft_inverse_128(fft);
1330
1331 scale = 2.0f / PART_LEN2;
1332 for (i = 0; i < PART_LEN; i++) {
1333 y[i] = fft[PART_LEN + i] * scale; // fft scaling
1334 }
1335
1336 for (i = 0; i < PART_LEN; i++) {
1337 e[i] = nearend_ptr[i] - y[i];
1338 }
1339
1340 // Error fft
1341 memcpy(aec->eBuf + PART_LEN, e, sizeof(float) * PART_LEN);
1342 memset(fft, 0, sizeof(float) * PART_LEN);
1343 memcpy(fft + PART_LEN, e, sizeof(float) * PART_LEN);
1344 // TODO(bjornv): Change to use TimeToFrequency().
1345 aec_rdft_forward_128(fft);
1346
1347 ef[1][0] = 0;
1348 ef[1][PART_LEN] = 0;
1349 ef[0][0] = fft[0];
1350 ef[0][PART_LEN] = fft[1];
1351 for (i = 1; i < PART_LEN; i++) {
1352 ef[0][i] = fft[2 * i];
1353 ef[1][i] = fft[2 * i + 1];
1354 }
1355
1356 RTC_AEC_DEBUG_RAW_WRITE(aec->e_fft_file,
1357 &ef[0][0],
1358 sizeof(ef[0][0]) * PART_LEN1 * 2);
1359
1360 if (aec->metricsMode == 1) {
1361 // Note that the first PART_LEN samples in fft (before transformation) are
1362 // zero. Hence, the scaling by two in UpdateLevel() should not be
1363 // performed. That scaling is taken care of in UpdateMetrics() instead.
1364 UpdateLevel(&aec->linoutlevel, ef);
1365 }
1366
1367 // Scale error signal inversely with far power.
1368 WebRtcAec_ScaleErrorSignal(aec, ef);
1369 WebRtcAec_FilterAdaptation(aec, fft, ef);
1370 NonLinearProcessing(aec, output, outputH_ptr);
1371 1394
1372 if (aec->metricsMode == 1) { 1395 if (aec->metricsMode == 1) {
1373 // Update power levels and echo metrics 1396 // Update power levels and echo metrics
1374 UpdateLevel(&aec->farlevel, (float(*)[PART_LEN1])xf_ptr); 1397 UpdateLevel(&aec->farlevel, (float(*)[PART_LEN1])xf_ptr);
1375 UpdateLevel(&aec->nearlevel, df); 1398 UpdateLevel(&aec->nearlevel, df);
1376 UpdateMetrics(aec); 1399 UpdateMetrics(aec);
1377 } 1400 }
1378 1401
1379 // Store the output block. 1402 // Store the output block.
1380 WebRtc_WriteBuffer(aec->outFrBuf, output, PART_LEN); 1403 WebRtc_WriteBuffer(aec->outFrBuf, output, PART_LEN);
1381 // For high bands 1404 // For high bands
1382 for (i = 0; i < aec->num_bands - 1; ++i) { 1405 for (i = 0; i < aec->num_bands - 1; ++i) {
1383 WebRtc_WriteBuffer(aec->outFrBufH[i], outputH[i], PART_LEN); 1406 WebRtc_WriteBuffer(aec->outFrBufH[i], outputH[i], PART_LEN);
1384 } 1407 }
1385 1408
1386 RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, e, PART_LEN);
1387 RTC_AEC_DEBUG_WAV_WRITE(aec->outFile, output, PART_LEN); 1409 RTC_AEC_DEBUG_WAV_WRITE(aec->outFile, output, PART_LEN);
1388 } 1410 }
1389 1411
1390 AecCore* WebRtcAec_CreateAec() { 1412 AecCore* WebRtcAec_CreateAec() {
1391 int i; 1413 int i;
1392 AecCore* aec = malloc(sizeof(AecCore)); 1414 AecCore* aec = malloc(sizeof(AecCore));
1393 if (!aec) { 1415 if (!aec) {
1394 return NULL; 1416 return NULL;
1395 } 1417 }
1396 1418
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
1920 int WebRtcAec_extended_filter_enabled(AecCore* self) { 1942 int WebRtcAec_extended_filter_enabled(AecCore* self) {
1921 return self->extended_filter_enabled; 1943 return self->extended_filter_enabled;
1922 } 1944 }
1923 1945
1924 int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; } 1946 int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; }
1925 1947
1926 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { 1948 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) {
1927 assert(delay >= 0); 1949 assert(delay >= 0);
1928 self->system_delay = delay; 1950 self->system_delay = delay;
1929 } 1951 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698