Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 128 #ifdef WEBRTC_AEC_DEBUG_DUMP | 128 #ifdef WEBRTC_AEC_DEBUG_DUMP |
| 129 extern int webrtc_aec_instance_count; | 129 extern int webrtc_aec_instance_count; |
| 130 #endif | 130 #endif |
| 131 | 131 |
| 132 WebRtcAecFilterFar WebRtcAec_FilterFar; | 132 WebRtcAecFilterFar WebRtcAec_FilterFar; |
| 133 WebRtcAecScaleErrorSignal WebRtcAec_ScaleErrorSignal; | 133 WebRtcAecScaleErrorSignal WebRtcAec_ScaleErrorSignal; |
| 134 WebRtcAecFilterAdaptation WebRtcAec_FilterAdaptation; | 134 WebRtcAecFilterAdaptation WebRtcAec_FilterAdaptation; |
| 135 WebRtcAecOverdriveAndSuppress WebRtcAec_OverdriveAndSuppress; | 135 WebRtcAecOverdriveAndSuppress WebRtcAec_OverdriveAndSuppress; |
| 136 WebRtcAecComfortNoise WebRtcAec_ComfortNoise; | 136 WebRtcAecComfortNoise WebRtcAec_ComfortNoise; |
| 137 WebRtcAecSubBandCoherence WebRtcAec_SubbandCoherence; | 137 WebRtcAecSubBandCoherence WebRtcAec_SubbandCoherence; |
| 138 WebRtcAecStoreAsComplex WebRtcAec_StoreAsComplex; | |
| 139 WebRtcAecPartitionDelay WebRtcAec_PartitionDelay; | |
| 140 WebRtcAecWindowData WebRtcAec_WindowData; | |
| 138 | 141 |
| 139 __inline static float MulRe(float aRe, float aIm, float bRe, float bIm) { | 142 __inline static float MulRe(float aRe, float aIm, float bRe, float bIm) { |
| 140 return aRe * bRe - aIm * bIm; | 143 return aRe * bRe - aIm * bIm; |
| 141 } | 144 } |
| 142 | 145 |
| 143 __inline static float MulIm(float aRe, float aIm, float bRe, float bIm) { | 146 __inline static float MulIm(float aRe, float aIm, float bRe, float bIm) { |
| 144 return aRe * bIm + aIm * bRe; | 147 return aRe * bIm + aIm * bRe; |
| 145 } | 148 } |
| 146 | 149 |
| 147 static int CmpFloat(const void* a, const void* b) { | 150 static int CmpFloat(const void* a, const void* b) { |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 400 for (i = 1; i < PART_LEN; i++) { | 403 for (i = 1; i < PART_LEN; i++) { |
| 401 data_complex[0][i] = data[2 * i]; | 404 data_complex[0][i] = data[2 * i]; |
| 402 data_complex[1][i] = data[2 * i + 1]; | 405 data_complex[1][i] = data[2 * i + 1]; |
| 403 } | 406 } |
| 404 data_complex[0][PART_LEN] = data[1]; | 407 data_complex[0][PART_LEN] = data[1]; |
| 405 data_complex[1][PART_LEN] = 0; | 408 data_complex[1][PART_LEN] = 0; |
| 406 } | 409 } |
| 407 | 410 |
| 408 static void SubbandCoherence(AecCore* aec, | 411 static void SubbandCoherence(AecCore* aec, |
| 409 float efw[2][PART_LEN1], | 412 float efw[2][PART_LEN1], |
| 413 float dfw[2][PART_LEN1], | |
| 410 float xfw[2][PART_LEN1], | 414 float xfw[2][PART_LEN1], |
| 411 float* fft, | 415 float* fft, |
| 412 float* cohde, | 416 float* cohde, |
| 413 float* cohxd) { | 417 float* cohxd) { |
| 414 float dfw[2][PART_LEN1]; | |
| 415 int i; | 418 int i; |
| 416 | 419 |
| 417 if (aec->delayEstCtr == 0) | |
| 418 aec->delayIdx = PartitionDelay(aec); | |
| 419 | |
| 420 // Use delayed far. | |
| 421 memcpy(xfw, | |
| 422 aec->xfwBuf + aec->delayIdx * PART_LEN1, | |
| 423 sizeof(xfw[0][0]) * 2 * PART_LEN1); | |
| 424 | |
| 425 // Windowed near fft | |
| 426 WindowData(fft, aec->dBuf); | |
| 427 aec_rdft_forward_128(fft); | |
| 428 StoreAsComplex(fft, dfw); | |
| 429 | |
| 430 // Windowed error fft | |
| 431 WindowData(fft, aec->eBuf); | |
| 432 aec_rdft_forward_128(fft); | |
| 433 StoreAsComplex(fft, efw); | |
| 434 | |
| 435 SmoothedPSD(aec, efw, dfw, xfw); | 420 SmoothedPSD(aec, efw, dfw, xfw); |
| 436 | 421 |
| 437 // Subband coherence | 422 // Subband coherence |
| 438 for (i = 0; i < PART_LEN1; i++) { | 423 for (i = 0; i < PART_LEN1; i++) { |
| 439 cohde[i] = | 424 cohde[i] = |
| 440 (aec->sde[i][0] * aec->sde[i][0] + aec->sde[i][1] * aec->sde[i][1]) / | 425 (aec->sde[i][0] * aec->sde[i][0] + aec->sde[i][1] * aec->sde[i][1]) / |
| 441 (aec->sd[i] * aec->se[i] + 1e-10f); | 426 (aec->sd[i] * aec->se[i] + 1e-10f); |
| 442 cohxd[i] = | 427 cohxd[i] = |
| 443 (aec->sxd[i][0] * aec->sxd[i][0] + aec->sxd[i][1] * aec->sxd[i][1]) / | 428 (aec->sxd[i][0] * aec->sxd[i][0] + aec->sxd[i][1] * aec->sxd[i][1]) / |
| 444 (aec->sx[i] * aec->sd[i] + 1e-10f); | 429 (aec->sx[i] * aec->sd[i] + 1e-10f); |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1004 WebRtcAec_FilterAdaptation(num_partitions, | 989 WebRtcAec_FilterAdaptation(num_partitions, |
| 1005 x_fft_buf_block_pos, | 990 x_fft_buf_block_pos, |
| 1006 x_fft_buf, | 991 x_fft_buf, |
| 1007 e_fft, | 992 e_fft, |
| 1008 h_fft_buf); | 993 h_fft_buf); |
| 1009 memcpy(echo_subtractor_output, e, sizeof(float) * PART_LEN); | 994 memcpy(echo_subtractor_output, e, sizeof(float) * PART_LEN); |
| 1010 } | 995 } |
| 1011 | 996 |
| 1012 | 997 |
| 1013 static void EchoSuppression(AecCore* aec, | 998 static void EchoSuppression(AecCore* aec, |
| 999 float* echo_subtractor_output, | |
| 1014 float* output, | 1000 float* output, |
| 1015 float* const* outputH) { | 1001 float* const* outputH) { |
| 1016 float efw[2][PART_LEN1], xfw[2][PART_LEN1]; | 1002 float efw[2][PART_LEN1]; |
| 1003 float xfw[2][PART_LEN1]; | |
| 1004 float dfw[2][PART_LEN1]; | |
| 1017 complex_t comfortNoiseHband[PART_LEN1]; | 1005 complex_t comfortNoiseHband[PART_LEN1]; |
| 1018 float fft[PART_LEN2]; | 1006 float fft[PART_LEN2]; |
| 1019 float scale, dtmp; | 1007 float scale, dtmp; |
| 1020 float nlpGainHband; | 1008 float nlpGainHband; |
| 1021 int i; | 1009 int i; |
| 1022 size_t j; | 1010 size_t j; |
| 1023 | 1011 |
| 1024 // Coherence and non-linear filter | 1012 // Coherence and non-linear filter |
| 1025 float cohde[PART_LEN1], cohxd[PART_LEN1]; | 1013 float cohde[PART_LEN1], cohxd[PART_LEN1]; |
| 1026 float hNlDeAvg, hNlXdAvg; | 1014 float hNlDeAvg, hNlXdAvg; |
| 1027 float hNl[PART_LEN1]; | 1015 float hNl[PART_LEN1]; |
| 1028 float hNlPref[kPrefBandSize]; | 1016 float hNlPref[kPrefBandSize]; |
| 1029 float hNlFb = 0, hNlFbLow = 0; | 1017 float hNlFb = 0, hNlFbLow = 0; |
| 1030 const float prefBandQuant = 0.75f, prefBandQuantLow = 0.5f; | 1018 const float prefBandQuant = 0.75f, prefBandQuantLow = 0.5f; |
| 1031 const int prefBandSize = kPrefBandSize / aec->mult; | 1019 const int prefBandSize = kPrefBandSize / aec->mult; |
| 1032 const int minPrefBand = 4 / aec->mult; | 1020 const int minPrefBand = 4 / aec->mult; |
| 1033 // Power estimate smoothing coefficients. | 1021 // Power estimate smoothing coefficients. |
| 1034 const float* min_overdrive = aec->extended_filter_enabled | 1022 const float* min_overdrive = aec->extended_filter_enabled |
| 1035 ? kExtendedMinOverDrive | 1023 ? kExtendedMinOverDrive |
| 1036 : kNormalMinOverDrive; | 1024 : kNormalMinOverDrive; |
| 1037 | 1025 |
| 1038 // Filter energy | 1026 // Filter energy |
| 1039 const int delayEstInterval = 10 * aec->mult; | 1027 const int delayEstInterval = 10 * aec->mult; |
| 1040 | 1028 |
| 1041 float* xfw_ptr = NULL; | 1029 float* xfw_ptr = NULL; |
| 1042 | 1030 |
| 1031 // Update eBuf with echo subtractor output. | |
|
hlundin-webrtc
2015/12/04 09:56:58
Is there any reason you moved this block earlier t
peah-webrtc
2015/12/04 14:14:49
I'm a bit confused, afaics it has been moved later
hlundin-webrtc
2015/12/04 15:04:04
What I meant was this: What used to be one block o
peah-webrtc
2015/12/04 22:37:52
Ah, then I see :-) Sorry.
Firstly, note that the
hlundin-webrtc
2015/12/08 11:48:52
That makes sense. Thanks!
| |
| 1032 memcpy(aec->eBuf + PART_LEN, | |
| 1033 echo_subtractor_output, | |
| 1034 sizeof(float) * PART_LEN); | |
| 1035 | |
| 1036 // Analysis filter banks for the echo suppressor. | |
| 1037 // Windowed near-end ffts. | |
| 1038 WindowData(fft, aec->dBuf); | |
| 1039 aec_rdft_forward_128(fft); | |
| 1040 WebRtcAec_StoreAsComplex(fft, dfw); | |
|
hlundin-webrtc
2015/12/04 09:56:58
Why did this function change to WebRtcAec_*, but n
peah-webrtc
2015/12/04 14:14:49
Good find! Initially neither had the WebRtcAec_ pr
hlundin-webrtc
2015/12/04 15:04:04
Acknowledged.
| |
| 1041 | |
| 1042 // Windowed echo suppressor output ffts. | |
| 1043 WindowData(fft, aec->eBuf); | |
| 1044 aec_rdft_forward_128(fft); | |
| 1045 StoreAsComplex(fft, efw); | |
| 1046 | |
| 1043 aec->delayEstCtr++; | 1047 aec->delayEstCtr++; |
| 1044 if (aec->delayEstCtr == delayEstInterval) { | 1048 if (aec->delayEstCtr == delayEstInterval) { |
| 1045 aec->delayEstCtr = 0; | 1049 aec->delayEstCtr = 0; |
| 1046 } | 1050 } |
| 1047 | 1051 |
| 1048 // initialize comfort noise for H band | 1052 // initialize comfort noise for H band |
| 1049 memset(comfortNoiseHband, 0, sizeof(comfortNoiseHband)); | 1053 memset(comfortNoiseHband, 0, sizeof(comfortNoiseHband)); |
| 1050 nlpGainHband = (float)0.0; | 1054 nlpGainHband = (float)0.0; |
| 1051 dtmp = (float)0.0; | 1055 dtmp = (float)0.0; |
| 1052 | 1056 |
| 1053 // We should always have at least one element stored in |far_buf|. | 1057 // We should always have at least one element stored in |far_buf|. |
| 1054 assert(WebRtc_available_read(aec->far_buf_windowed) > 0); | 1058 assert(WebRtc_available_read(aec->far_buf_windowed) > 0); |
| 1055 // NLP | 1059 // NLP |
| 1056 WebRtc_ReadBuffer(aec->far_buf_windowed, (void**)&xfw_ptr, &xfw[0][0], 1); | 1060 WebRtc_ReadBuffer(aec->far_buf_windowed, (void**)&xfw_ptr, &xfw[0][0], 1); |
| 1057 | 1061 |
| 1058 // TODO(bjornv): Investigate if we can reuse |far_buf_windowed| instead of | 1062 // TODO(bjornv): Investigate if we can reuse |far_buf_windowed| instead of |
| 1059 // |xfwBuf|. | 1063 // |xfwBuf|. |
| 1060 // Buffer far. | 1064 // Buffer far. |
| 1061 memcpy(aec->xfwBuf, xfw_ptr, sizeof(float) * 2 * PART_LEN1); | 1065 memcpy(aec->xfwBuf, xfw_ptr, sizeof(float) * 2 * PART_LEN1); |
| 1062 | 1066 |
| 1063 WebRtcAec_SubbandCoherence(aec, efw, xfw, fft, cohde, cohxd); | 1067 if (aec->delayEstCtr == 0) |
| 1068 aec->delayIdx = WebRtcAec_PartitionDelay(aec); | |
| 1069 | |
| 1070 // Use delayed far. | |
| 1071 memcpy(xfw, | |
| 1072 aec->xfwBuf + aec->delayIdx * PART_LEN1, | |
| 1073 sizeof(xfw[0][0]) * 2 * PART_LEN1); | |
| 1074 | |
| 1075 WebRtcAec_SubbandCoherence(aec, efw, dfw, xfw, fft, cohde, cohxd); | |
| 1064 | 1076 |
| 1065 hNlXdAvg = 0; | 1077 hNlXdAvg = 0; |
| 1066 for (i = minPrefBand; i < prefBandSize + minPrefBand; i++) { | 1078 for (i = minPrefBand; i < prefBandSize + minPrefBand; i++) { |
| 1067 hNlXdAvg += cohxd[i]; | 1079 hNlXdAvg += cohxd[i]; |
| 1068 } | 1080 } |
| 1069 hNlXdAvg /= prefBandSize; | 1081 hNlXdAvg /= prefBandSize; |
| 1070 hNlXdAvg = 1 - hNlXdAvg; | 1082 hNlXdAvg = 1 - hNlXdAvg; |
| 1071 | 1083 |
| 1072 hNlDeAvg = 0; | 1084 hNlDeAvg = 0; |
| 1073 for (i = minPrefBand; i < prefBandSize + minPrefBand; i++) { | 1085 for (i = minPrefBand; i < prefBandSize + minPrefBand; i++) { |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1392 aec->xfBuf, | 1404 aec->xfBuf, |
| 1393 nearend_ptr, | 1405 nearend_ptr, |
| 1394 aec->xPow, | 1406 aec->xPow, |
| 1395 aec->wfBuf, | 1407 aec->wfBuf, |
| 1396 &aec->linoutlevel, | 1408 &aec->linoutlevel, |
| 1397 echo_subtractor_output); | 1409 echo_subtractor_output); |
| 1398 | 1410 |
| 1399 RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, echo_subtractor_output, PART_LEN); | 1411 RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, echo_subtractor_output, PART_LEN); |
| 1400 | 1412 |
| 1401 // Perform echo suppression. | 1413 // Perform echo suppression. |
| 1402 memcpy(aec->eBuf + PART_LEN, | 1414 EchoSuppression(aec, echo_subtractor_output, output, outputH_ptr); |
|
minyue-webrtc
2015/12/03 12:42:51
This is ok, but it makes the treatment of eBuf dif
peah-webrtc
2015/12/03 15:00:36
I guess that what you are saying is that all opera
| |
| 1403 echo_subtractor_output, | |
| 1404 sizeof(float) * PART_LEN); | |
| 1405 EchoSuppression(aec, output, outputH_ptr); | |
| 1406 | 1415 |
| 1407 if (aec->metricsMode == 1) { | 1416 if (aec->metricsMode == 1) { |
| 1408 // Update power levels and echo metrics | 1417 // Update power levels and echo metrics |
| 1409 UpdateLevel(&aec->farlevel, (float(*)[PART_LEN1])xf_ptr); | 1418 UpdateLevel(&aec->farlevel, (float(*)[PART_LEN1])xf_ptr); |
| 1410 UpdateLevel(&aec->nearlevel, df); | 1419 UpdateLevel(&aec->nearlevel, df); |
| 1411 UpdateMetrics(aec); | 1420 UpdateMetrics(aec); |
| 1412 } | 1421 } |
| 1413 | 1422 |
| 1414 // Store the output block. | 1423 // Store the output block. |
| 1415 WebRtc_WriteBuffer(aec->outFrBuf, output, PART_LEN); | 1424 WebRtc_WriteBuffer(aec->outFrBuf, output, PART_LEN); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1504 #endif | 1513 #endif |
| 1505 aec->extended_filter_enabled = 0; | 1514 aec->extended_filter_enabled = 0; |
| 1506 | 1515 |
| 1507 // Assembly optimization | 1516 // Assembly optimization |
| 1508 WebRtcAec_FilterFar = FilterFar; | 1517 WebRtcAec_FilterFar = FilterFar; |
| 1509 WebRtcAec_ScaleErrorSignal = ScaleErrorSignal; | 1518 WebRtcAec_ScaleErrorSignal = ScaleErrorSignal; |
| 1510 WebRtcAec_FilterAdaptation = FilterAdaptation; | 1519 WebRtcAec_FilterAdaptation = FilterAdaptation; |
| 1511 WebRtcAec_OverdriveAndSuppress = OverdriveAndSuppress; | 1520 WebRtcAec_OverdriveAndSuppress = OverdriveAndSuppress; |
| 1512 WebRtcAec_ComfortNoise = ComfortNoise; | 1521 WebRtcAec_ComfortNoise = ComfortNoise; |
| 1513 WebRtcAec_SubbandCoherence = SubbandCoherence; | 1522 WebRtcAec_SubbandCoherence = SubbandCoherence; |
| 1523 WebRtcAec_StoreAsComplex = StoreAsComplex; | |
| 1524 WebRtcAec_PartitionDelay = PartitionDelay; | |
| 1525 WebRtcAec_WindowData = WindowData; | |
| 1526 | |
| 1514 | 1527 |
| 1515 #if defined(WEBRTC_ARCH_X86_FAMILY) | 1528 #if defined(WEBRTC_ARCH_X86_FAMILY) |
| 1516 if (WebRtc_GetCPUInfo(kSSE2)) { | 1529 if (WebRtc_GetCPUInfo(kSSE2)) { |
| 1517 WebRtcAec_InitAec_SSE2(); | 1530 WebRtcAec_InitAec_SSE2(); |
| 1518 } | 1531 } |
| 1519 #endif | 1532 #endif |
| 1520 | 1533 |
| 1521 #if defined(MIPS_FPU_LE) | 1534 #if defined(MIPS_FPU_LE) |
| 1522 WebRtcAec_InitAec_mips(); | 1535 WebRtcAec_InitAec_mips(); |
| 1523 #endif | 1536 #endif |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1954 int WebRtcAec_extended_filter_enabled(AecCore* self) { | 1967 int WebRtcAec_extended_filter_enabled(AecCore* self) { |
| 1955 return self->extended_filter_enabled; | 1968 return self->extended_filter_enabled; |
| 1956 } | 1969 } |
| 1957 | 1970 |
| 1958 int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; } | 1971 int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; } |
| 1959 | 1972 |
| 1960 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { | 1973 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { |
| 1961 assert(delay >= 0); | 1974 assert(delay >= 0); |
| 1962 self->system_delay = delay; | 1975 self->system_delay = delay; |
| 1963 } | 1976 } |
| OLD | NEW |