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 |