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