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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 xfBuf[1][xPos + j], | 175 xfBuf[1][xPos + j], |
176 wfBuf[0][pos + j], | 176 wfBuf[0][pos + j], |
177 wfBuf[1][pos + j]); | 177 wfBuf[1][pos + j]); |
178 } | 178 } |
179 } | 179 } |
180 } | 180 } |
181 | 181 |
182 static void ScaleErrorSignal(int extended_filter_enabled, | 182 static void ScaleErrorSignal(int extended_filter_enabled, |
183 float normal_mu, | 183 float normal_mu, |
184 float normal_error_threshold, | 184 float normal_error_threshold, |
185 float *xPow, | 185 float xPow[PART_LEN1], |
186 float ef[2][PART_LEN1]) { | 186 float ef[2][PART_LEN1]) { |
187 const float mu = extended_filter_enabled ? kExtendedMu : normal_mu; | 187 const float mu = extended_filter_enabled ? kExtendedMu : normal_mu; |
188 const float error_threshold = extended_filter_enabled | 188 const float error_threshold = extended_filter_enabled |
189 ? kExtendedErrorThreshold | 189 ? kExtendedErrorThreshold |
190 : normal_error_threshold; | 190 : normal_error_threshold; |
191 int i; | 191 int i; |
192 float abs_ef; | 192 float abs_ef; |
193 for (i = 0; i < (PART_LEN1); i++) { | 193 for (i = 0; i < (PART_LEN1); i++) { |
194 ef[0][i] /= (xPow[i] + 1e-10f); | 194 ef[0][i] /= (xPow[i] + 1e-10f); |
195 ef[1][i] /= (xPow[i] + 1e-10f); | 195 ef[1][i] /= (xPow[i] + 1e-10f); |
196 abs_ef = sqrtf(ef[0][i] * ef[0][i] + ef[1][i] * ef[1][i]); | 196 abs_ef = sqrtf(ef[0][i] * ef[0][i] + ef[1][i] * ef[1][i]); |
197 | 197 |
198 if (abs_ef > error_threshold) { | 198 if (abs_ef > error_threshold) { |
199 abs_ef = error_threshold / (abs_ef + 1e-10f); | 199 abs_ef = error_threshold / (abs_ef + 1e-10f); |
200 ef[0][i] *= abs_ef; | 200 ef[0][i] *= abs_ef; |
201 ef[1][i] *= abs_ef; | 201 ef[1][i] *= abs_ef; |
202 } | 202 } |
203 | 203 |
204 // Stepsize factor | 204 // Stepsize factor |
205 ef[0][i] *= mu; | 205 ef[0][i] *= mu; |
206 ef[1][i] *= mu; | 206 ef[1][i] *= mu; |
207 } | 207 } |
208 } | 208 } |
209 | 209 |
210 // Time-unconstrined filter adaptation. | |
211 // TODO(andrew): consider for a low-complexity mode. | |
212 // static void FilterAdaptationUnconstrained(AecCore* aec, float *fft, | |
213 // float ef[2][PART_LEN1]) { | |
214 // int i, j; | |
215 // for (i = 0; i < aec->num_partitions; i++) { | |
216 // int xPos = (i + aec->xfBufBlockPos)*(PART_LEN1); | |
217 // int pos; | |
218 // // Check for wrap | |
219 // if (i + aec->xfBufBlockPos >= aec->num_partitions) { | |
220 // xPos -= aec->num_partitions * PART_LEN1; | |
221 // } | |
222 // | |
223 // pos = i * PART_LEN1; | |
224 // | |
225 // for (j = 0; j < PART_LEN1; j++) { | |
226 // aec->wfBuf[0][pos + j] += MulRe(aec->xfBuf[0][xPos + j], | |
227 // -aec->xfBuf[1][xPos + j], | |
228 // ef[0][j], ef[1][j]); | |
229 // aec->wfBuf[1][pos + j] += MulIm(aec->xfBuf[0][xPos + j], | |
230 // -aec->xfBuf[1][xPos + j], | |
231 // ef[0][j], ef[1][j]); | |
232 // } | |
233 // } | |
234 //} | |
235 | 210 |
236 static void FilterAdaptation(AecCore* aec, float* fft, float ef[2][PART_LEN1]) { | 211 static void FilterAdaptation( |
212 int num_partitions, | |
213 int xfBufBlockPos, | |
hlundin-webrtc
2015/11/20 11:55:20
Rename parameters.
peah-webrtc
2015/11/24 13:03:01
Done.
| |
214 float xfBuf[2][kExtendedNumPartitions * PART_LEN1], | |
hlundin-webrtc
2015/11/20 11:55:20
Any of the array input that can be made const?
peah-webrtc
2015/11/24 13:03:01
I checked with kwiberg@ and he said it should be f
| |
215 float ef[2][PART_LEN1], | |
216 float wfBuf[2][kExtendedNumPartitions * PART_LEN1]) { | |
237 int i, j; | 217 int i, j; |
238 for (i = 0; i < aec->num_partitions; i++) { | 218 float fft[PART_LEN2]; |
239 int xPos = (i + aec->xfBufBlockPos) * (PART_LEN1); | 219 for (i = 0; i < num_partitions; i++) { |
220 int xPos = (i + xfBufBlockPos) * (PART_LEN1); | |
240 int pos; | 221 int pos; |
241 // Check for wrap | 222 // Check for wrap |
242 if (i + aec->xfBufBlockPos >= aec->num_partitions) { | 223 if (i + xfBufBlockPos >= num_partitions) { |
243 xPos -= aec->num_partitions * PART_LEN1; | 224 xPos -= num_partitions * PART_LEN1; |
244 } | 225 } |
245 | 226 |
246 pos = i * PART_LEN1; | 227 pos = i * PART_LEN1; |
247 | 228 |
248 for (j = 0; j < PART_LEN; j++) { | 229 for (j = 0; j < PART_LEN; j++) { |
249 | 230 |
250 fft[2 * j] = MulRe(aec->xfBuf[0][xPos + j], | 231 fft[2 * j] = MulRe(xfBuf[0][xPos + j], |
251 -aec->xfBuf[1][xPos + j], | 232 -xfBuf[1][xPos + j], |
252 ef[0][j], | 233 ef[0][j], |
253 ef[1][j]); | 234 ef[1][j]); |
254 fft[2 * j + 1] = MulIm(aec->xfBuf[0][xPos + j], | 235 fft[2 * j + 1] = MulIm(xfBuf[0][xPos + j], |
255 -aec->xfBuf[1][xPos + j], | 236 -xfBuf[1][xPos + j], |
256 ef[0][j], | 237 ef[0][j], |
257 ef[1][j]); | 238 ef[1][j]); |
258 } | 239 } |
259 fft[1] = MulRe(aec->xfBuf[0][xPos + PART_LEN], | 240 fft[1] = MulRe(xfBuf[0][xPos + PART_LEN], |
260 -aec->xfBuf[1][xPos + PART_LEN], | 241 -xfBuf[1][xPos + PART_LEN], |
261 ef[0][PART_LEN], | 242 ef[0][PART_LEN], |
262 ef[1][PART_LEN]); | 243 ef[1][PART_LEN]); |
263 | 244 |
264 aec_rdft_inverse_128(fft); | 245 aec_rdft_inverse_128(fft); |
265 memset(fft + PART_LEN, 0, sizeof(float) * PART_LEN); | 246 memset(fft + PART_LEN, 0, sizeof(float) * PART_LEN); |
266 | 247 |
267 // fft scaling | 248 // fft scaling |
268 { | 249 { |
269 float scale = 2.0f / PART_LEN2; | 250 float scale = 2.0f / PART_LEN2; |
270 for (j = 0; j < PART_LEN; j++) { | 251 for (j = 0; j < PART_LEN; j++) { |
271 fft[j] *= scale; | 252 fft[j] *= scale; |
272 } | 253 } |
273 } | 254 } |
274 aec_rdft_forward_128(fft); | 255 aec_rdft_forward_128(fft); |
275 | 256 |
276 aec->wfBuf[0][pos] += fft[0]; | 257 wfBuf[0][pos] += fft[0]; |
277 aec->wfBuf[0][pos + PART_LEN] += fft[1]; | 258 wfBuf[0][pos + PART_LEN] += fft[1]; |
278 | 259 |
279 for (j = 1; j < PART_LEN; j++) { | 260 for (j = 1; j < PART_LEN; j++) { |
280 aec->wfBuf[0][pos + j] += fft[2 * j]; | 261 wfBuf[0][pos + j] += fft[2 * j]; |
281 aec->wfBuf[1][pos + j] += fft[2 * j + 1]; | 262 wfBuf[1][pos + j] += fft[2 * j + 1]; |
282 } | 263 } |
283 } | 264 } |
284 } | 265 } |
285 | 266 |
286 static void OverdriveAndSuppress(AecCore* aec, | 267 static void OverdriveAndSuppress(AecCore* aec, |
287 float hNl[PART_LEN1], | 268 float hNl[PART_LEN1], |
288 const float hNlFb, | 269 const float hNlFb, |
289 float efw[2][PART_LEN1]) { | 270 float efw[2][PART_LEN1]) { |
290 int i; | 271 int i; |
291 for (i = 0; i < PART_LEN1; i++) { | 272 for (i = 0; i < PART_LEN1; i++) { |
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
838 self->num_delay_values; | 819 self->num_delay_values; |
839 } | 820 } |
840 | 821 |
841 // Reset histogram. | 822 // Reset histogram. |
842 memset(self->delay_histogram, 0, sizeof(self->delay_histogram)); | 823 memset(self->delay_histogram, 0, sizeof(self->delay_histogram)); |
843 self->num_delay_values = 0; | 824 self->num_delay_values = 0; |
844 | 825 |
845 return; | 826 return; |
846 } | 827 } |
847 | 828 |
848 static void FrequencyToTime(float freq_data[2][PART_LEN1], | 829 static void InverseFft(float freq_data[2][PART_LEN1], |
hlundin-webrtc
2015/11/20 11:55:20
Make freq_data const.
peah-webrtc
2015/11/24 13:03:01
Done.
| |
849 float time_data[PART_LEN2]) { | 830 float time_data[PART_LEN2]) { |
850 time_data[0] = freq_data[0][0]; | 831 time_data[0] = freq_data[0][0]; |
851 time_data[1] = freq_data[0][PART_LEN]; | 832 time_data[1] = freq_data[0][PART_LEN]; |
852 for (int i = 1; i < PART_LEN; i++) { | 833 for (int i = 1; i < PART_LEN; i++) { |
853 time_data[2 * i] = freq_data[0][i]; | 834 time_data[2 * i] = freq_data[0][i]; |
854 time_data[2 * i + 1] = freq_data[1][i]; | 835 time_data[2 * i + 1] = freq_data[1][i]; |
855 } | 836 } |
856 aec_rdft_inverse_128(time_data); | 837 aec_rdft_inverse_128(time_data); |
857 } | 838 } |
858 | 839 |
859 | 840 |
860 static void TimeToFrequency(float time_data[PART_LEN2], | 841 static void Fft(float time_data[PART_LEN2], |
hlundin-webrtc
2015/11/20 11:55:20
Make time_data const.
ivoc
2015/11/20 12:58:02
I think the aec_rdft_forward_128 function writes t
peah-webrtc
2015/11/24 13:03:01
That is fully correct. And you have a great point!
peah-webrtc
2015/11/24 13:03:01
Done.
| |
861 float freq_data[2][PART_LEN1], | 842 float freq_data[2][PART_LEN1]) { |
862 int window) { | |
863 int i = 0; | |
864 | |
865 // TODO(bjornv): Should we have a different function/wrapper for windowed FFT? | |
866 if (window) { | |
867 for (i = 0; i < PART_LEN; i++) { | |
868 time_data[i] *= WebRtcAec_sqrtHanning[i]; | |
869 time_data[PART_LEN + i] *= WebRtcAec_sqrtHanning[PART_LEN - i]; | |
870 } | |
871 } | |
872 | |
873 aec_rdft_forward_128(time_data); | 843 aec_rdft_forward_128(time_data); |
874 // Reorder. | 844 // Reorder fft output data. |
875 freq_data[1][0] = 0; | 845 freq_data[1][0] = 0; |
876 freq_data[1][PART_LEN] = 0; | 846 freq_data[1][PART_LEN] = 0; |
877 freq_data[0][0] = time_data[0]; | 847 freq_data[0][0] = time_data[0]; |
878 freq_data[0][PART_LEN] = time_data[1]; | 848 freq_data[0][PART_LEN] = time_data[1]; |
879 for (i = 1; i < PART_LEN; i++) { | 849 for (int i = 1; i < PART_LEN; i++) { |
880 freq_data[0][i] = time_data[2 * i]; | 850 freq_data[0][i] = time_data[2 * i]; |
881 freq_data[1][i] = time_data[2 * i + 1]; | 851 freq_data[1][i] = time_data[2 * i + 1]; |
882 } | 852 } |
883 } | 853 } |
884 | 854 |
885 static int MoveFarReadPtrWithoutSystemDelayUpdate(AecCore* self, int elements) { | 855 static int MoveFarReadPtrWithoutSystemDelayUpdate(AecCore* self, int elements) { |
886 WebRtc_MoveReadPtr(self->far_buf_windowed, elements); | 856 WebRtc_MoveReadPtr(self->far_buf_windowed, elements); |
887 #ifdef WEBRTC_AEC_DEBUG_DUMP | 857 #ifdef WEBRTC_AEC_DEBUG_DUMP |
888 WebRtc_MoveReadPtr(self->far_time_buf, elements); | 858 WebRtc_MoveReadPtr(self->far_time_buf, elements); |
889 #endif | 859 #endif |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
956 delay_quality = (delay_quality > kDelayQualityThresholdMax ? | 926 delay_quality = (delay_quality > kDelayQualityThresholdMax ? |
957 kDelayQualityThresholdMax : delay_quality); | 927 kDelayQualityThresholdMax : delay_quality); |
958 self->delay_quality_threshold = | 928 self->delay_quality_threshold = |
959 (delay_quality > self->delay_quality_threshold ? delay_quality : | 929 (delay_quality > self->delay_quality_threshold ? delay_quality : |
960 self->delay_quality_threshold); | 930 self->delay_quality_threshold); |
961 } | 931 } |
962 return delay_correction; | 932 return delay_correction; |
963 } | 933 } |
964 | 934 |
965 static void EchoSubtraction(AecCore* aec, | 935 static void EchoSubtraction(AecCore* aec, |
966 float* nearend_ptr) { | 936 int num_partitions, |
967 float yf[2][PART_LEN1]; | 937 int xfBufBlockPos, |
hlundin-webrtc
2015/11/20 11:55:20
Change naming format of input parameters.
peah-webrtc
2015/11/24 13:03:01
Done.
| |
968 float fft[PART_LEN2]; | 938 int metricsMode, |
969 float y[PART_LEN]; | 939 int extended_filter_enabled, |
940 float normal_mu, | |
941 float normal_error_threshold, | |
942 float xfBuf[2][kExtendedNumPartitions * PART_LEN1], | |
943 const float* const y, | |
944 float xPow[PART_LEN1], | |
hlundin-webrtc
2015/11/20 11:55:20
Can you make any array parameters const?
peah-webrtc
2015/11/24 13:03:01
Yes, and I'll as a consequense also add const to t
| |
945 float wfBuf[2][kExtendedNumPartitions * PART_LEN1], | |
946 PowerLevel* linoutlevel, | |
947 float echo_subtractor_output[PART_LEN]) { | |
948 float s_fft[2][PART_LEN1]; | |
949 float e_extended[PART_LEN2]; | |
950 float s_extended[PART_LEN2]; | |
951 float *s; | |
970 float e[PART_LEN]; | 952 float e[PART_LEN]; |
971 float ef[2][PART_LEN1]; | 953 float e_fft[2][PART_LEN1]; |
972 float scale; | 954 float scale; |
973 int i; | 955 int i; |
974 memset(yf, 0, sizeof(yf)); | 956 memset(s_fft, 0, sizeof(s_fft)); |
975 | 957 |
976 // Produce echo estimate. | 958 // Produce echo estimate s_fft. |
977 WebRtcAec_FilterFar(aec->num_partitions, | 959 WebRtcAec_FilterFar(num_partitions, |
978 aec->xfBufBlockPos, | 960 xfBufBlockPos, |
979 aec->xfBuf, | 961 xfBuf, |
980 aec->wfBuf, | 962 wfBuf, |
981 yf); | 963 s_fft); |
982 | 964 |
983 // Inverse fft to obtain echo estimate and error. | 965 // Compute the time-domain echo estimate s. |
984 FrequencyToTime(yf, fft); | 966 InverseFft(s_fft, s_extended); |
985 | |
986 // Extract the output signal and compute the time-domain error | |
987 scale = 2.0f / PART_LEN2; | 967 scale = 2.0f / PART_LEN2; |
988 for (i = 0; i < PART_LEN; i++) { | 968 s = &s_extended[PART_LEN]; |
989 y[i] = fft[PART_LEN + i] * scale; // fft scaling | 969 for (i = 0; i < PART_LEN; ++i) { |
970 s[i] *= scale; | |
ivoc
2015/11/20 12:58:02
Should scaling be part of the InverseFft function?
peah-webrtc
2015/11/24 13:03:01
I think the division by PART_LEN could go there, b
| |
990 } | 971 } |
991 | 972 |
992 for (i = 0; i < PART_LEN; i++) { | 973 // Compute the time-domain echo prediction error. |
993 e[i] = nearend_ptr[i] - y[i]; | 974 for (i = 0; i < PART_LEN; ++i) { |
975 e[i] = y[i] - s[i]; | |
ivoc
2015/11/20 12:58:02
Loop can be merged with previous loop.
peah-webrtc
2015/11/24 13:03:01
Done in a previous CL.
Done.
| |
994 } | 976 } |
995 | 977 |
978 // Compute the frequency domain echo prediction error. | |
979 memset(e_extended, 0, sizeof(float) * PART_LEN); | |
980 memcpy(e_extended + PART_LEN, e, sizeof(float) * PART_LEN); | |
ivoc
2015/11/20 12:58:02
I think it makes more sense to skip the e signal,
peah-webrtc
2015/11/24 13:03:01
I agree, but it will be used in an upcoming CL, so
| |
981 Fft(e_extended, e_fft); | |
996 | 982 |
997 // Error fft | |
998 memcpy(aec->eBuf + PART_LEN, e, sizeof(float) * PART_LEN); | |
999 memset(fft, 0, sizeof(float) * PART_LEN); | |
1000 memcpy(fft + PART_LEN, e, sizeof(float) * PART_LEN); | |
1001 TimeToFrequency(fft, ef, 0); | |
1002 | 983 |
1003 RTC_AEC_DEBUG_RAW_WRITE(aec->e_fft_file, | 984 RTC_AEC_DEBUG_RAW_WRITE(aec->e_fft_file, |
1004 &ef[0][0], | 985 &e_fft[0][0], |
1005 sizeof(ef[0][0]) * PART_LEN1 * 2); | 986 sizeof(e_fft[0][0]) * PART_LEN1 * 2); |
1006 | 987 |
1007 if (aec->metricsMode == 1) { | 988 if (metricsMode == 1) { |
1008 // Note that the first PART_LEN samples in fft (before transformation) are | 989 // Note that the first PART_LEN samples in fft (before transformation) are |
1009 // zero. Hence, the scaling by two in UpdateLevel() should not be | 990 // zero. Hence, the scaling by two in UpdateLevel() should not be |
1010 // performed. That scaling is taken care of in UpdateMetrics() instead. | 991 // performed. That scaling is taken care of in UpdateMetrics() instead. |
1011 UpdateLevel(&aec->linoutlevel, ef); | 992 UpdateLevel(linoutlevel, e_fft); |
1012 } | 993 } |
1013 | 994 |
1014 // Scale error signal inversely with far power. | 995 // Scale error signal inversely with far power. |
1015 WebRtcAec_ScaleErrorSignal(aec->extended_filter_enabled, | 996 WebRtcAec_ScaleErrorSignal(extended_filter_enabled, |
1016 aec->normal_mu, | 997 normal_mu, |
1017 aec->normal_error_threshold, | 998 normal_error_threshold, |
1018 aec->xPow, | 999 xPow, |
1019 ef); | 1000 e_fft); |
1020 WebRtcAec_FilterAdaptation(aec, fft, ef); | 1001 WebRtcAec_FilterAdaptation(num_partitions, |
1021 | 1002 xfBufBlockPos, |
1022 | 1003 xfBuf, |
1023 RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, e, PART_LEN); | 1004 e_fft, |
1005 wfBuf); | |
1006 memcpy(echo_subtractor_output, e, sizeof(float) * PART_LEN); | |
1024 } | 1007 } |
1025 | 1008 |
1026 | 1009 |
1027 static void EchoSuppression(AecCore* aec, | 1010 static void EchoSuppression(AecCore* aec, |
1028 float* output, | 1011 float* output, |
1029 float* const* outputH) { | 1012 float* const* outputH) { |
1030 float efw[2][PART_LEN1], xfw[2][PART_LEN1]; | 1013 float efw[2][PART_LEN1], xfw[2][PART_LEN1]; |
1031 complex_t comfortNoiseHband[PART_LEN1]; | 1014 complex_t comfortNoiseHband[PART_LEN1]; |
1032 float fft[PART_LEN2]; | 1015 float fft[PART_LEN2]; |
1033 float scale, dtmp; | 1016 float scale, dtmp; |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1270 | 1253 |
1271 const float gPow[2] = {0.9f, 0.1f}; | 1254 const float gPow[2] = {0.9f, 0.1f}; |
1272 | 1255 |
1273 // Noise estimate constants. | 1256 // Noise estimate constants. |
1274 const int noiseInitBlocks = 500 * aec->mult; | 1257 const int noiseInitBlocks = 500 * aec->mult; |
1275 const float step = 0.1f; | 1258 const float step = 0.1f; |
1276 const float ramp = 1.0002f; | 1259 const float ramp = 1.0002f; |
1277 const float gInitNoise[2] = {0.999f, 0.001f}; | 1260 const float gInitNoise[2] = {0.999f, 0.001f}; |
1278 | 1261 |
1279 float nearend[PART_LEN]; | 1262 float nearend[PART_LEN]; |
1263 float echo_subtractor_output[PART_LEN]; | |
1280 float* nearend_ptr = NULL; | 1264 float* nearend_ptr = NULL; |
1281 float output[PART_LEN]; | 1265 float output[PART_LEN]; |
1282 float outputH[NUM_HIGH_BANDS_MAX][PART_LEN]; | 1266 float outputH[NUM_HIGH_BANDS_MAX][PART_LEN]; |
1283 float* outputH_ptr[NUM_HIGH_BANDS_MAX]; | 1267 float* outputH_ptr[NUM_HIGH_BANDS_MAX]; |
1284 float* xf_ptr = NULL; | 1268 float* xf_ptr = NULL; |
1285 | 1269 |
1286 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { | 1270 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { |
1287 outputH_ptr[i] = outputH[i]; | 1271 outputH_ptr[i] = outputH[i]; |
1288 } | 1272 } |
1289 | 1273 |
(...skipping 19 matching lines...) Expand all Loading... | |
1309 RTC_AEC_DEBUG_WAV_WRITE(aec->nearFile, nearend_ptr, PART_LEN); | 1293 RTC_AEC_DEBUG_WAV_WRITE(aec->nearFile, nearend_ptr, PART_LEN); |
1310 } | 1294 } |
1311 #endif | 1295 #endif |
1312 | 1296 |
1313 // We should always have at least one element stored in |far_buf|. | 1297 // We should always have at least one element stored in |far_buf|. |
1314 assert(WebRtc_available_read(aec->far_buf) > 0); | 1298 assert(WebRtc_available_read(aec->far_buf) > 0); |
1315 WebRtc_ReadBuffer(aec->far_buf, (void**)&xf_ptr, &xf[0][0], 1); | 1299 WebRtc_ReadBuffer(aec->far_buf, (void**)&xf_ptr, &xf[0][0], 1); |
1316 | 1300 |
1317 // Near fft | 1301 // Near fft |
1318 memcpy(fft, aec->dBuf, sizeof(float) * PART_LEN2); | 1302 memcpy(fft, aec->dBuf, sizeof(float) * PART_LEN2); |
1319 TimeToFrequency(fft, df, 0); | 1303 Fft(fft, df); |
1320 | 1304 |
1321 // Power smoothing | 1305 // Power smoothing |
1322 for (i = 0; i < PART_LEN1; i++) { | 1306 for (i = 0; i < PART_LEN1; i++) { |
1323 far_spectrum = (xf_ptr[i] * xf_ptr[i]) + | 1307 far_spectrum = (xf_ptr[i] * xf_ptr[i]) + |
1324 (xf_ptr[PART_LEN1 + i] * xf_ptr[PART_LEN1 + i]); | 1308 (xf_ptr[PART_LEN1 + i] * xf_ptr[PART_LEN1 + i]); |
1325 aec->xPow[i] = | 1309 aec->xPow[i] = |
1326 gPow[0] * aec->xPow[i] + gPow[1] * aec->num_partitions * far_spectrum; | 1310 gPow[0] * aec->xPow[i] + gPow[1] * aec->num_partitions * far_spectrum; |
1327 // Calculate absolute spectra | 1311 // Calculate absolute spectra |
1328 abs_far_spectrum[i] = sqrtf(far_spectrum); | 1312 abs_far_spectrum[i] = sqrtf(far_spectrum); |
1329 | 1313 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1388 | 1372 |
1389 // Buffer xf | 1373 // Buffer xf |
1390 memcpy(aec->xfBuf[0] + aec->xfBufBlockPos * PART_LEN1, | 1374 memcpy(aec->xfBuf[0] + aec->xfBufBlockPos * PART_LEN1, |
1391 xf_ptr, | 1375 xf_ptr, |
1392 sizeof(float) * PART_LEN1); | 1376 sizeof(float) * PART_LEN1); |
1393 memcpy(aec->xfBuf[1] + aec->xfBufBlockPos * PART_LEN1, | 1377 memcpy(aec->xfBuf[1] + aec->xfBufBlockPos * PART_LEN1, |
1394 &xf_ptr[PART_LEN1], | 1378 &xf_ptr[PART_LEN1], |
1395 sizeof(float) * PART_LEN1); | 1379 sizeof(float) * PART_LEN1); |
1396 | 1380 |
1397 // Perform echo subtraction. | 1381 // Perform echo subtraction. |
1398 EchoSubtraction(aec, nearend_ptr); | 1382 EchoSubtraction(aec, |
1383 aec->num_partitions, | |
1384 aec->xfBufBlockPos, | |
1385 aec->metricsMode, | |
1386 aec->extended_filter_enabled, | |
1387 aec->normal_mu, | |
1388 aec->normal_error_threshold, | |
1389 aec->xfBuf, | |
1390 nearend_ptr, | |
1391 aec->xPow, | |
1392 aec->wfBuf, | |
1393 &aec->linoutlevel, | |
1394 echo_subtractor_output); | |
1395 | |
1396 RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, echo_subtractor_output, PART_LEN); | |
1399 | 1397 |
1400 // Perform echo suppression. | 1398 // Perform echo suppression. |
1399 memcpy(aec->eBuf + PART_LEN, | |
1400 echo_subtractor_output, | |
1401 sizeof(float) * PART_LEN); | |
1401 EchoSuppression(aec, output, outputH_ptr); | 1402 EchoSuppression(aec, output, outputH_ptr); |
1402 | 1403 |
1403 if (aec->metricsMode == 1) { | 1404 if (aec->metricsMode == 1) { |
1404 // Update power levels and echo metrics | 1405 // Update power levels and echo metrics |
1405 UpdateLevel(&aec->farlevel, (float(*)[PART_LEN1])xf_ptr); | 1406 UpdateLevel(&aec->farlevel, (float(*)[PART_LEN1])xf_ptr); |
1406 UpdateLevel(&aec->nearlevel, df); | 1407 UpdateLevel(&aec->nearlevel, df); |
1407 UpdateMetrics(aec); | 1408 UpdateMetrics(aec); |
1408 } | 1409 } |
1409 | 1410 |
1410 // Store the output block. | 1411 // Store the output block. |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1733 void WebRtcAec_BufferFarendPartition(AecCore* aec, const float* farend) { | 1734 void WebRtcAec_BufferFarendPartition(AecCore* aec, const float* farend) { |
1734 float fft[PART_LEN2]; | 1735 float fft[PART_LEN2]; |
1735 float xf[2][PART_LEN1]; | 1736 float xf[2][PART_LEN1]; |
1736 | 1737 |
1737 // Check if the buffer is full, and in that case flush the oldest data. | 1738 // Check if the buffer is full, and in that case flush the oldest data. |
1738 if (WebRtc_available_write(aec->far_buf) < 1) { | 1739 if (WebRtc_available_write(aec->far_buf) < 1) { |
1739 WebRtcAec_MoveFarReadPtr(aec, 1); | 1740 WebRtcAec_MoveFarReadPtr(aec, 1); |
1740 } | 1741 } |
1741 // Convert far-end partition to the frequency domain without windowing. | 1742 // Convert far-end partition to the frequency domain without windowing. |
1742 memcpy(fft, farend, sizeof(float) * PART_LEN2); | 1743 memcpy(fft, farend, sizeof(float) * PART_LEN2); |
1743 TimeToFrequency(fft, xf, 0); | 1744 Fft(fft, xf); |
1744 WebRtc_WriteBuffer(aec->far_buf, &xf[0][0], 1); | 1745 WebRtc_WriteBuffer(aec->far_buf, &xf[0][0], 1); |
1745 | 1746 |
1746 // Convert far-end partition to the frequency domain with windowing. | 1747 // Convert far-end partition to the frequency domain with windowing. |
1747 memcpy(fft, farend, sizeof(float) * PART_LEN2); | 1748 WindowData(fft, farend); |
1748 TimeToFrequency(fft, xf, 1); | 1749 Fft(fft, xf); |
1749 WebRtc_WriteBuffer(aec->far_buf_windowed, &xf[0][0], 1); | 1750 WebRtc_WriteBuffer(aec->far_buf_windowed, &xf[0][0], 1); |
1750 } | 1751 } |
1751 | 1752 |
1752 int WebRtcAec_MoveFarReadPtr(AecCore* aec, int elements) { | 1753 int WebRtcAec_MoveFarReadPtr(AecCore* aec, int elements) { |
1753 int elements_moved = MoveFarReadPtrWithoutSystemDelayUpdate(aec, elements); | 1754 int elements_moved = MoveFarReadPtrWithoutSystemDelayUpdate(aec, elements); |
1754 aec->system_delay -= elements_moved * PART_LEN; | 1755 aec->system_delay -= elements_moved * PART_LEN; |
1755 return elements_moved; | 1756 return elements_moved; |
1756 } | 1757 } |
1757 | 1758 |
1758 void WebRtcAec_ProcessFrames(AecCore* aec, | 1759 void WebRtcAec_ProcessFrames(AecCore* aec, |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1950 int WebRtcAec_extended_filter_enabled(AecCore* self) { | 1951 int WebRtcAec_extended_filter_enabled(AecCore* self) { |
1951 return self->extended_filter_enabled; | 1952 return self->extended_filter_enabled; |
1952 } | 1953 } |
1953 | 1954 |
1954 int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; } | 1955 int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; } |
1955 | 1956 |
1956 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { | 1957 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { |
1957 assert(delay >= 0); | 1958 assert(delay >= 0); |
1958 self->system_delay = delay; | 1959 self->system_delay = delay; |
1959 } | 1960 } |
OLD | NEW |