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

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

Issue 1963493003: Moved the AEC echo suppression gain computation code to a separate method (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Rebase Created 4 years, 7 months 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 968 matching lines...) Expand 10 before | Expand all | Expand 10 after
979 memcpy(e_extended + PART_LEN, e, sizeof(float) * PART_LEN); 979 memcpy(e_extended + PART_LEN, e, sizeof(float) * PART_LEN);
980 Fft(e_extended, e_fft); 980 Fft(e_extended, e_fft);
981 981
982 // Scale error signal inversely with far power. 982 // Scale error signal inversely with far power.
983 WebRtcAec_ScaleErrorSignal(filter_step_size, error_threshold, x_pow, e_fft); 983 WebRtcAec_ScaleErrorSignal(filter_step_size, error_threshold, x_pow, e_fft);
984 WebRtcAec_FilterAdaptation(num_partitions, *x_fft_buf_block_pos, x_fft_buf, 984 WebRtcAec_FilterAdaptation(num_partitions, *x_fft_buf_block_pos, x_fft_buf,
985 e_fft, h_fft_buf); 985 e_fft, h_fft_buf);
986 memcpy(echo_subtractor_output, e, sizeof(float) * PART_LEN); 986 memcpy(echo_subtractor_output, e, sizeof(float) * PART_LEN);
987 } 987 }
988 988
989 static void EchoSuppression(AecCore* aec, 989 static void FormSuppressionGain(AecCore* aec,
990 float farend[PART_LEN2], 990 float cohde[PART_LEN1],
991 float* echo_subtractor_output, 991 float cohxd[PART_LEN1],
992 float* output, 992 float hNl[PART_LEN1]) {
993 float* const* outputH) {
994 float efw[2][PART_LEN1];
995 float xfw[2][PART_LEN1];
996 float dfw[2][PART_LEN1];
997 float comfortNoiseHband[2][PART_LEN1];
998 float fft[PART_LEN2];
999 float nlpGainHband;
1000 int i;
1001 size_t j;
1002
1003 // Coherence and non-linear filter
1004 float cohde[PART_LEN1], cohxd[PART_LEN1];
1005 float hNlDeAvg, hNlXdAvg; 993 float hNlDeAvg, hNlXdAvg;
1006 float hNl[PART_LEN1];
1007 float hNlPref[kPrefBandSize]; 994 float hNlPref[kPrefBandSize];
1008 float hNlFb = 0, hNlFbLow = 0; 995 float hNlFb = 0, hNlFbLow = 0;
996 const int prefBandSize = kPrefBandSize / aec->mult;
1009 const float prefBandQuant = 0.75f, prefBandQuantLow = 0.5f; 997 const float prefBandQuant = 0.75f, prefBandQuantLow = 0.5f;
1010 const int prefBandSize = kPrefBandSize / aec->mult;
1011 const int minPrefBand = 4 / aec->mult; 998 const int minPrefBand = 4 / aec->mult;
1012 // Power estimate smoothing coefficients. 999 // Power estimate smoothing coefficients.
1013 const float* min_overdrive = aec->extended_filter_enabled 1000 const float* min_overdrive = aec->extended_filter_enabled
1014 ? kExtendedMinOverDrive 1001 ? kExtendedMinOverDrive
1015 : kNormalMinOverDrive; 1002 : kNormalMinOverDrive;
1016 1003
1017 // Filter energy
1018 const int delayEstInterval = 10 * aec->mult;
1019
1020 float* xfw_ptr = NULL;
1021
1022 // Update eBuf with echo subtractor output.
1023 memcpy(aec->eBuf + PART_LEN, echo_subtractor_output,
1024 sizeof(float) * PART_LEN);
1025
1026 // Analysis filter banks for the echo suppressor.
1027 // Windowed near-end ffts.
1028 WindowData(fft, aec->dBuf);
1029 aec_rdft_forward_128(fft);
1030 StoreAsComplex(fft, dfw);
1031
1032 // Windowed echo suppressor output ffts.
1033 WindowData(fft, aec->eBuf);
1034 aec_rdft_forward_128(fft);
1035 StoreAsComplex(fft, efw);
1036
1037 // NLP
1038
1039 // Convert far-end partition to the frequency domain with windowing.
1040 WindowData(fft, farend);
1041 Fft(fft, xfw);
1042 xfw_ptr = &xfw[0][0];
1043
1044 // Buffer far.
1045 memcpy(aec->xfwBuf, xfw_ptr, sizeof(float) * 2 * PART_LEN1);
1046
1047 aec->delayEstCtr++;
1048 if (aec->delayEstCtr == delayEstInterval) {
1049 aec->delayEstCtr = 0;
1050 aec->delayIdx = WebRtcAec_PartitionDelay(aec->num_partitions, aec->wfBuf);
1051 }
1052
1053 // Use delayed far.
1054 memcpy(xfw, aec->xfwBuf + aec->delayIdx * PART_LEN1,
1055 sizeof(xfw[0][0]) * 2 * PART_LEN1);
1056
1057 WebRtcAec_UpdateCoherenceSpectra(aec->mult, aec->extended_filter_enabled == 1,
1058 efw, dfw, xfw, &aec->coherence_state,
1059 &aec->divergeState,
1060 &aec->extreme_filter_divergence);
1061
1062 WebRtcAec_ComputeCoherence(&aec->coherence_state, cohde, cohxd);
1063
1064 // Select the microphone signal as output if the filter is deemed to have
1065 // diverged.
1066 if (aec->divergeState) {
1067 memcpy(efw, dfw, sizeof(efw[0][0]) * 2 * PART_LEN1);
1068 }
1069
1070 hNlXdAvg = 0; 1004 hNlXdAvg = 0;
1071 for (i = minPrefBand; i < prefBandSize + minPrefBand; i++) { 1005 for (int i = minPrefBand; i < prefBandSize + minPrefBand; ++i) {
1072 hNlXdAvg += cohxd[i]; 1006 hNlXdAvg += cohxd[i];
1073 } 1007 }
1074 hNlXdAvg /= prefBandSize; 1008 hNlXdAvg /= prefBandSize;
1075 hNlXdAvg = 1 - hNlXdAvg; 1009 hNlXdAvg = 1 - hNlXdAvg;
1076 1010
1077 hNlDeAvg = 0; 1011 hNlDeAvg = 0;
1078 for (i = minPrefBand; i < prefBandSize + minPrefBand; i++) { 1012 for (int i = minPrefBand; i < prefBandSize + minPrefBand; ++i) {
1079 hNlDeAvg += cohde[i]; 1013 hNlDeAvg += cohde[i];
1080 } 1014 }
1081 hNlDeAvg /= prefBandSize; 1015 hNlDeAvg /= prefBandSize;
1082 1016
1083 if (hNlXdAvg < 0.75f && hNlXdAvg < aec->hNlXdAvgMin) { 1017 if (hNlXdAvg < 0.75f && hNlXdAvg < aec->hNlXdAvgMin) {
1084 aec->hNlXdAvgMin = hNlXdAvg; 1018 aec->hNlXdAvgMin = hNlXdAvg;
1085 } 1019 }
1086 1020
1087 if (hNlDeAvg > 0.98f && hNlXdAvg > 0.9f) { 1021 if (hNlDeAvg > 0.98f && hNlXdAvg > 0.9f) {
1088 aec->stNearState = 1; 1022 aec->stNearState = 1;
1089 } else if (hNlDeAvg < 0.95f || hNlXdAvg < 0.8f) { 1023 } else if (hNlDeAvg < 0.95f || hNlXdAvg < 0.8f) {
1090 aec->stNearState = 0; 1024 aec->stNearState = 0;
1091 } 1025 }
1092 1026
1093 if (aec->hNlXdAvgMin == 1) { 1027 if (aec->hNlXdAvgMin == 1) {
1094 aec->echoState = 0; 1028 aec->echoState = 0;
1095 aec->overDrive = min_overdrive[aec->nlp_mode]; 1029 aec->overDrive = min_overdrive[aec->nlp_mode];
1096 1030
1097 if (aec->stNearState == 1) { 1031 if (aec->stNearState == 1) {
1098 memcpy(hNl, cohde, sizeof(hNl)); 1032 memcpy(hNl, cohde, sizeof(hNl[0]) * PART_LEN1);
1099 hNlFb = hNlDeAvg; 1033 hNlFb = hNlDeAvg;
1100 hNlFbLow = hNlDeAvg; 1034 hNlFbLow = hNlDeAvg;
1101 } else { 1035 } else {
1102 for (i = 0; i < PART_LEN1; i++) { 1036 for (int i = 0; i < PART_LEN1; ++i) {
1103 hNl[i] = 1 - cohxd[i]; 1037 hNl[i] = 1 - cohxd[i];
1104 } 1038 }
1105 hNlFb = hNlXdAvg; 1039 hNlFb = hNlXdAvg;
1106 hNlFbLow = hNlXdAvg; 1040 hNlFbLow = hNlXdAvg;
1107 } 1041 }
1108 } else { 1042 } else {
1109 if (aec->stNearState == 1) { 1043 if (aec->stNearState == 1) {
1110 aec->echoState = 0; 1044 aec->echoState = 0;
1111 memcpy(hNl, cohde, sizeof(hNl)); 1045 memcpy(hNl, cohde, sizeof(hNl[0]) * PART_LEN1);
1112 hNlFb = hNlDeAvg; 1046 hNlFb = hNlDeAvg;
1113 hNlFbLow = hNlDeAvg; 1047 hNlFbLow = hNlDeAvg;
1114 } else { 1048 } else {
1115 aec->echoState = 1; 1049 aec->echoState = 1;
1116 for (i = 0; i < PART_LEN1; i++) { 1050 for (int i = 0; i < PART_LEN1; ++i) {
1117 hNl[i] = WEBRTC_SPL_MIN(cohde[i], 1 - cohxd[i]); 1051 hNl[i] = WEBRTC_SPL_MIN(cohde[i], 1 - cohxd[i]);
1118 } 1052 }
1119 1053
1120 // Select an order statistic from the preferred bands. 1054 // Select an order statistic from the preferred bands.
1121 // TODO(peah): Using quicksort now, but a selection algorithm may be 1055 // TODO(peah): Using quicksort now, but a selection algorithm may be
1122 // preferred. 1056 // preferred.
1123 memcpy(hNlPref, &hNl[minPrefBand], sizeof(float) * prefBandSize); 1057 memcpy(hNlPref, &hNl[minPrefBand], sizeof(float) * prefBandSize);
1124 qsort(hNlPref, prefBandSize, sizeof(float), CmpFloat); 1058 qsort(hNlPref, prefBandSize, sizeof(float), CmpFloat);
1125 hNlFb = hNlPref[static_cast<int>(floor(prefBandQuant * 1059 hNlFb = hNlPref[static_cast<int>(floor(prefBandQuant *
1126 (prefBandSize - 1)))]; 1060 (prefBandSize - 1)))];
(...skipping 27 matching lines...) Expand all
1154 1088
1155 // Smooth the overdrive. 1089 // Smooth the overdrive.
1156 if (aec->overDrive < aec->overdrive_scaling) { 1090 if (aec->overDrive < aec->overdrive_scaling) {
1157 aec->overdrive_scaling = 1091 aec->overdrive_scaling =
1158 0.99f * aec->overdrive_scaling + 0.01f * aec->overDrive; 1092 0.99f * aec->overdrive_scaling + 0.01f * aec->overDrive;
1159 } else { 1093 } else {
1160 aec->overdrive_scaling = 1094 aec->overdrive_scaling =
1161 0.9f * aec->overdrive_scaling + 0.1f * aec->overDrive; 1095 0.9f * aec->overdrive_scaling + 0.1f * aec->overDrive;
1162 } 1096 }
1163 1097
1098 // Apply the overdrive.
1164 WebRtcAec_Overdrive(aec->overdrive_scaling, hNlFb, hNl); 1099 WebRtcAec_Overdrive(aec->overdrive_scaling, hNlFb, hNl);
1100 }
1101
1102 static void EchoSuppression(AecCore* aec,
1103 float farend[PART_LEN2],
1104 float* echo_subtractor_output,
1105 float* output,
1106 float* const* outputH) {
1107 float efw[2][PART_LEN1];
1108 float xfw[2][PART_LEN1];
1109 float dfw[2][PART_LEN1];
1110 float comfortNoiseHband[2][PART_LEN1];
1111 float fft[PART_LEN2];
1112 float nlpGainHband;
1113 int i;
1114 size_t j;
1115
1116 // Coherence and non-linear filter
1117 float cohde[PART_LEN1], cohxd[PART_LEN1];
1118 float hNl[PART_LEN1];
1119
1120 // Filter energy
1121 const int delayEstInterval = 10 * aec->mult;
1122
1123 float* xfw_ptr = NULL;
1124
1125 // Update eBuf with echo subtractor output.
1126 memcpy(aec->eBuf + PART_LEN, echo_subtractor_output,
1127 sizeof(float) * PART_LEN);
1128
1129 // Analysis filter banks for the echo suppressor.
1130 // Windowed near-end ffts.
1131 WindowData(fft, aec->dBuf);
1132 aec_rdft_forward_128(fft);
1133 StoreAsComplex(fft, dfw);
1134
1135 // Windowed echo suppressor output ffts.
1136 WindowData(fft, aec->eBuf);
1137 aec_rdft_forward_128(fft);
1138 StoreAsComplex(fft, efw);
1139
1140 // NLP
1141
1142 // Convert far-end partition to the frequency domain with windowing.
1143 WindowData(fft, farend);
1144 Fft(fft, xfw);
1145 xfw_ptr = &xfw[0][0];
1146
1147 // Buffer far.
1148 memcpy(aec->xfwBuf, xfw_ptr, sizeof(float) * 2 * PART_LEN1);
1149
1150 aec->delayEstCtr++;
1151 if (aec->delayEstCtr == delayEstInterval) {
1152 aec->delayEstCtr = 0;
1153 aec->delayIdx = WebRtcAec_PartitionDelay(aec->num_partitions, aec->wfBuf);
1154 }
1155
1156 // Use delayed far.
1157 memcpy(xfw, aec->xfwBuf + aec->delayIdx * PART_LEN1,
1158 sizeof(xfw[0][0]) * 2 * PART_LEN1);
1159
1160 WebRtcAec_UpdateCoherenceSpectra(aec->mult, aec->extended_filter_enabled == 1,
1161 efw, dfw, xfw, &aec->coherence_state,
1162 &aec->divergeState,
1163 &aec->extreme_filter_divergence);
1164
1165 WebRtcAec_ComputeCoherence(&aec->coherence_state, cohde, cohxd);
1166
1167 // Select the microphone signal as output if the filter is deemed to have
1168 // diverged.
1169 if (aec->divergeState) {
1170 memcpy(efw, dfw, sizeof(efw[0][0]) * 2 * PART_LEN1);
1171 }
1172
1173 FormSuppressionGain(aec, cohde, cohxd, hNl);
1174
1165 WebRtcAec_Suppress(hNl, efw); 1175 WebRtcAec_Suppress(hNl, efw);
1166 1176
1167 // Add comfort noise. 1177 // Add comfort noise.
1168 ComfortNoise(aec, efw, comfortNoiseHband, aec->noisePow, hNl); 1178 ComfortNoise(aec, efw, comfortNoiseHband, aec->noisePow, hNl);
1169 1179
1170 // Inverse error fft. 1180 // Inverse error fft.
1171 ScaledInverseFft(efw, fft, 2.0f, 1); 1181 ScaledInverseFft(efw, fft, 2.0f, 1);
1172 1182
1173 // Overlap and add to obtain output. 1183 // Overlap and add to obtain output.
1174 for (i = 0; i < PART_LEN; i++) { 1184 for (i = 0; i < PART_LEN; i++) {
(...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after
1957 1967
1958 int WebRtcAec_system_delay(AecCore* self) { 1968 int WebRtcAec_system_delay(AecCore* self) {
1959 return self->system_delay; 1969 return self->system_delay;
1960 } 1970 }
1961 1971
1962 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { 1972 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) {
1963 assert(delay >= 0); 1973 assert(delay >= 0);
1964 self->system_delay = delay; 1974 self->system_delay = delay;
1965 } 1975 }
1966 } // namespace webrtc 1976 } // namespace webrtc
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698