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 10 matching lines...) Expand all Loading... | |
21 #include <string.h> | 21 #include <string.h> |
22 | 22 |
23 #include "webrtc/base/checks.h" | 23 #include "webrtc/base/checks.h" |
24 extern "C" { | 24 extern "C" { |
25 #include "webrtc/common_audio/ring_buffer.h" | 25 #include "webrtc/common_audio/ring_buffer.h" |
26 } | 26 } |
27 #include "webrtc/base/checks.h" | 27 #include "webrtc/base/checks.h" |
28 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar y.h" | 28 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar y.h" |
29 #include "webrtc/modules/audio_processing/aec/aec_common.h" | 29 #include "webrtc/modules/audio_processing/aec/aec_common.h" |
30 #include "webrtc/modules/audio_processing/aec/aec_core_optimized_methods.h" | 30 #include "webrtc/modules/audio_processing/aec/aec_core_optimized_methods.h" |
31 #include "webrtc/modules/audio_processing/aec/aec_rdft.h" | |
32 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" | 31 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" |
33 #include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" | 32 #include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" |
33 #include "webrtc/modules/audio_processing/utility/ooura_fft.h" | |
hlundin-webrtc
2016/10/05 12:54:53
No need to include here, when you already included
peah-webrtc
2016/10/06 06:23:39
Done.
| |
34 #include "webrtc/system_wrappers/include/cpu_features_wrapper.h" | 34 #include "webrtc/system_wrappers/include/cpu_features_wrapper.h" |
35 #include "webrtc/system_wrappers/include/metrics.h" | 35 #include "webrtc/system_wrappers/include/metrics.h" |
36 #include "webrtc/typedefs.h" | 36 #include "webrtc/typedefs.h" |
37 | 37 |
38 namespace webrtc { | 38 namespace webrtc { |
39 namespace { | 39 namespace { |
40 enum class DelaySource { | 40 enum class DelaySource { |
41 kSystemDelay, // The delay values come from the OS. | 41 kSystemDelay, // The delay values come from the OS. |
42 kDelayAgnostic, // The delay values come from the DA-AEC. | 42 kDelayAgnostic, // The delay values come from the DA-AEC. |
43 }; | 43 }; |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
330 ef[1][i] *= abs_ef; | 330 ef[1][i] *= abs_ef; |
331 } | 331 } |
332 | 332 |
333 // Stepsize factor | 333 // Stepsize factor |
334 ef[0][i] *= mu; | 334 ef[0][i] *= mu; |
335 ef[1][i] *= mu; | 335 ef[1][i] *= mu; |
336 } | 336 } |
337 } | 337 } |
338 | 338 |
339 static void FilterAdaptation( | 339 static void FilterAdaptation( |
340 const OouraFft* ooura_fft, | |
hlundin-webrtc
2016/10/05 12:54:53
Why not a const ref? (This is C++ now, right?) Her
peah-webrtc
2016/10/06 06:23:39
Good point!
Done.
| |
340 int num_partitions, | 341 int num_partitions, |
341 int x_fft_buf_block_pos, | 342 int x_fft_buf_block_pos, |
342 float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1], | 343 float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1], |
343 float e_fft[2][PART_LEN1], | 344 float e_fft[2][PART_LEN1], |
344 float h_fft_buf[2][kExtendedNumPartitions * PART_LEN1]) { | 345 float h_fft_buf[2][kExtendedNumPartitions * PART_LEN1]) { |
345 int i, j; | 346 int i, j; |
346 float fft[PART_LEN2]; | 347 float fft[PART_LEN2]; |
347 for (i = 0; i < num_partitions; i++) { | 348 for (i = 0; i < num_partitions; i++) { |
348 int xPos = (i + x_fft_buf_block_pos) * (PART_LEN1); | 349 int xPos = (i + x_fft_buf_block_pos) * (PART_LEN1); |
349 int pos; | 350 int pos; |
350 // Check for wrap | 351 // Check for wrap |
351 if (i + x_fft_buf_block_pos >= num_partitions) { | 352 if (i + x_fft_buf_block_pos >= num_partitions) { |
352 xPos -= num_partitions * PART_LEN1; | 353 xPos -= num_partitions * PART_LEN1; |
353 } | 354 } |
354 | 355 |
355 pos = i * PART_LEN1; | 356 pos = i * PART_LEN1; |
356 | 357 |
357 for (j = 0; j < PART_LEN; j++) { | 358 for (j = 0; j < PART_LEN; j++) { |
358 fft[2 * j] = MulRe(x_fft_buf[0][xPos + j], -x_fft_buf[1][xPos + j], | 359 fft[2 * j] = MulRe(x_fft_buf[0][xPos + j], -x_fft_buf[1][xPos + j], |
359 e_fft[0][j], e_fft[1][j]); | 360 e_fft[0][j], e_fft[1][j]); |
360 fft[2 * j + 1] = MulIm(x_fft_buf[0][xPos + j], -x_fft_buf[1][xPos + j], | 361 fft[2 * j + 1] = MulIm(x_fft_buf[0][xPos + j], -x_fft_buf[1][xPos + j], |
361 e_fft[0][j], e_fft[1][j]); | 362 e_fft[0][j], e_fft[1][j]); |
362 } | 363 } |
363 fft[1] = | 364 fft[1] = |
364 MulRe(x_fft_buf[0][xPos + PART_LEN], -x_fft_buf[1][xPos + PART_LEN], | 365 MulRe(x_fft_buf[0][xPos + PART_LEN], -x_fft_buf[1][xPos + PART_LEN], |
365 e_fft[0][PART_LEN], e_fft[1][PART_LEN]); | 366 e_fft[0][PART_LEN], e_fft[1][PART_LEN]); |
366 | 367 |
367 aec_rdft_inverse_128(fft); | 368 ooura_fft->InverseFft(fft); |
368 memset(fft + PART_LEN, 0, sizeof(float) * PART_LEN); | 369 memset(fft + PART_LEN, 0, sizeof(float) * PART_LEN); |
369 | 370 |
370 // fft scaling | 371 // fft scaling |
371 { | 372 { |
372 float scale = 2.0f / PART_LEN2; | 373 float scale = 2.0f / PART_LEN2; |
373 for (j = 0; j < PART_LEN; j++) { | 374 for (j = 0; j < PART_LEN; j++) { |
374 fft[j] *= scale; | 375 fft[j] *= scale; |
375 } | 376 } |
376 } | 377 } |
377 aec_rdft_forward_128(fft); | 378 ooura_fft->Fft(fft); |
378 | 379 |
379 h_fft_buf[0][pos] += fft[0]; | 380 h_fft_buf[0][pos] += fft[0]; |
380 h_fft_buf[0][pos + PART_LEN] += fft[1]; | 381 h_fft_buf[0][pos + PART_LEN] += fft[1]; |
381 | 382 |
382 for (j = 1; j < PART_LEN; j++) { | 383 for (j = 1; j < PART_LEN; j++) { |
383 h_fft_buf[0][pos + j] += fft[2 * j]; | 384 h_fft_buf[0][pos + j] += fft[2 * j]; |
384 h_fft_buf[1][pos + j] += fft[2 * j + 1]; | 385 h_fft_buf[1][pos + j] += fft[2 * j + 1]; |
385 } | 386 } |
386 } | 387 } |
387 } | 388 } |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
828 static_cast<float>(num_delays_out_of_bounds) / self->num_delay_values; | 829 static_cast<float>(num_delays_out_of_bounds) / self->num_delay_values; |
829 } | 830 } |
830 | 831 |
831 // Reset histogram. | 832 // Reset histogram. |
832 memset(self->delay_histogram, 0, sizeof(self->delay_histogram)); | 833 memset(self->delay_histogram, 0, sizeof(self->delay_histogram)); |
833 self->num_delay_values = 0; | 834 self->num_delay_values = 0; |
834 | 835 |
835 return; | 836 return; |
836 } | 837 } |
837 | 838 |
838 static void ScaledInverseFft(float freq_data[2][PART_LEN1], | 839 static void ScaledInverseFft(const OouraFft* ooura_fft, |
840 float freq_data[2][PART_LEN1], | |
839 float time_data[PART_LEN2], | 841 float time_data[PART_LEN2], |
840 float scale, | 842 float scale, |
841 int conjugate) { | 843 int conjugate) { |
842 int i; | 844 int i; |
843 const float normalization = scale / static_cast<float>(PART_LEN2); | 845 const float normalization = scale / static_cast<float>(PART_LEN2); |
844 const float sign = (conjugate ? -1 : 1); | 846 const float sign = (conjugate ? -1 : 1); |
845 time_data[0] = freq_data[0][0] * normalization; | 847 time_data[0] = freq_data[0][0] * normalization; |
846 time_data[1] = freq_data[0][PART_LEN] * normalization; | 848 time_data[1] = freq_data[0][PART_LEN] * normalization; |
847 for (i = 1; i < PART_LEN; i++) { | 849 for (i = 1; i < PART_LEN; i++) { |
848 time_data[2 * i] = freq_data[0][i] * normalization; | 850 time_data[2 * i] = freq_data[0][i] * normalization; |
849 time_data[2 * i + 1] = sign * freq_data[1][i] * normalization; | 851 time_data[2 * i + 1] = sign * freq_data[1][i] * normalization; |
850 } | 852 } |
851 aec_rdft_inverse_128(time_data); | 853 ooura_fft->InverseFft(time_data); |
852 } | 854 } |
853 | 855 |
854 static void Fft(float time_data[PART_LEN2], float freq_data[2][PART_LEN1]) { | 856 static void Fft(const OouraFft* ooura_fft, |
857 float time_data[PART_LEN2], | |
858 float freq_data[2][PART_LEN1]) { | |
855 int i; | 859 int i; |
856 aec_rdft_forward_128(time_data); | 860 ooura_fft->Fft(time_data); |
857 | 861 |
858 // Reorder fft output data. | 862 // Reorder fft output data. |
859 freq_data[1][0] = 0; | 863 freq_data[1][0] = 0; |
860 freq_data[1][PART_LEN] = 0; | 864 freq_data[1][PART_LEN] = 0; |
861 freq_data[0][0] = time_data[0]; | 865 freq_data[0][0] = time_data[0]; |
862 freq_data[0][PART_LEN] = time_data[1]; | 866 freq_data[0][PART_LEN] = time_data[1]; |
863 for (i = 1; i < PART_LEN; i++) { | 867 for (i = 1; i < PART_LEN; i++) { |
864 freq_data[0][i] = time_data[2 * i]; | 868 freq_data[0][i] = time_data[2 * i]; |
865 freq_data[1][i] = time_data[2 * i + 1]; | 869 freq_data[1][i] = time_data[2 * i + 1]; |
866 } | 870 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
963 | 967 |
964 ++partition; | 968 ++partition; |
965 if (partition == num_partitions) { | 969 if (partition == num_partitions) { |
966 partition = 0; | 970 partition = 0; |
967 RTC_DCHECK_EQ(num_partitions * PART_LEN1, x_fft_buf_position); | 971 RTC_DCHECK_EQ(num_partitions * PART_LEN1, x_fft_buf_position); |
968 x_fft_buf_position = 0; | 972 x_fft_buf_position = 0; |
969 } | 973 } |
970 } | 974 } |
971 } | 975 } |
972 | 976 |
973 static void EchoSubtraction(int num_partitions, | 977 static void EchoSubtraction(const OouraFft* ooura_fft, |
978 int num_partitions, | |
974 int extended_filter_enabled, | 979 int extended_filter_enabled, |
975 int* extreme_filter_divergence, | 980 int* extreme_filter_divergence, |
976 float filter_step_size, | 981 float filter_step_size, |
977 float error_threshold, | 982 float error_threshold, |
978 float* x_fft, | 983 float* x_fft, |
979 int* x_fft_buf_block_pos, | 984 int* x_fft_buf_block_pos, |
980 float x_fft_buf[2] | 985 float x_fft_buf[2] |
981 [kExtendedNumPartitions * PART_LEN1], | 986 [kExtendedNumPartitions * PART_LEN1], |
982 float* const y, | 987 float* const y, |
983 float x_pow[PART_LEN1], | 988 float x_pow[PART_LEN1], |
(...skipping 28 matching lines...) Expand all Loading... | |
1012 memset(h_fft_buf, 0, | 1017 memset(h_fft_buf, 0, |
1013 2 * kExtendedNumPartitions * PART_LEN1 * sizeof(h_fft_buf[0][0])); | 1018 2 * kExtendedNumPartitions * PART_LEN1 * sizeof(h_fft_buf[0][0])); |
1014 *extreme_filter_divergence = 0; | 1019 *extreme_filter_divergence = 0; |
1015 } | 1020 } |
1016 | 1021 |
1017 // Produce echo estimate s_fft. | 1022 // Produce echo estimate s_fft. |
1018 WebRtcAec_FilterFar(num_partitions, *x_fft_buf_block_pos, x_fft_buf, | 1023 WebRtcAec_FilterFar(num_partitions, *x_fft_buf_block_pos, x_fft_buf, |
1019 h_fft_buf, s_fft); | 1024 h_fft_buf, s_fft); |
1020 | 1025 |
1021 // Compute the time-domain echo estimate s. | 1026 // Compute the time-domain echo estimate s. |
1022 ScaledInverseFft(s_fft, s_extended, 2.0f, 0); | 1027 ScaledInverseFft(ooura_fft, s_fft, s_extended, 2.0f, 0); |
1023 s = &s_extended[PART_LEN]; | 1028 s = &s_extended[PART_LEN]; |
1024 | 1029 |
1025 // Compute the time-domain echo prediction error. | 1030 // Compute the time-domain echo prediction error. |
1026 for (i = 0; i < PART_LEN; ++i) { | 1031 for (i = 0; i < PART_LEN; ++i) { |
1027 e[i] = y[i] - s[i]; | 1032 e[i] = y[i] - s[i]; |
1028 } | 1033 } |
1029 | 1034 |
1030 // Compute the frequency domain echo prediction error. | 1035 // Compute the frequency domain echo prediction error. |
1031 memset(e_extended, 0, sizeof(float) * PART_LEN); | 1036 memset(e_extended, 0, sizeof(float) * PART_LEN); |
1032 memcpy(e_extended + PART_LEN, e, sizeof(float) * PART_LEN); | 1037 memcpy(e_extended + PART_LEN, e, sizeof(float) * PART_LEN); |
1033 Fft(e_extended, e_fft); | 1038 Fft(ooura_fft, e_extended, e_fft); |
1034 | 1039 |
1035 // Scale error signal inversely with far power. | 1040 // Scale error signal inversely with far power. |
1036 WebRtcAec_ScaleErrorSignal(filter_step_size, error_threshold, x_pow, e_fft); | 1041 WebRtcAec_ScaleErrorSignal(filter_step_size, error_threshold, x_pow, e_fft); |
1037 WebRtcAec_FilterAdaptation(num_partitions, *x_fft_buf_block_pos, x_fft_buf, | 1042 WebRtcAec_FilterAdaptation(ooura_fft, num_partitions, *x_fft_buf_block_pos, |
1038 e_fft, h_fft_buf); | 1043 x_fft_buf, e_fft, h_fft_buf); |
1039 memcpy(echo_subtractor_output, e, sizeof(float) * PART_LEN); | 1044 memcpy(echo_subtractor_output, e, sizeof(float) * PART_LEN); |
1040 } | 1045 } |
1041 | 1046 |
1042 static void FormSuppressionGain(AecCore* aec, | 1047 static void FormSuppressionGain(AecCore* aec, |
1043 float cohde[PART_LEN1], | 1048 float cohde[PART_LEN1], |
1044 float cohxd[PART_LEN1], | 1049 float cohxd[PART_LEN1], |
1045 float hNl[PART_LEN1]) { | 1050 float hNl[PART_LEN1]) { |
1046 float hNlDeAvg, hNlXdAvg; | 1051 float hNlDeAvg, hNlXdAvg; |
1047 float hNlPref[kPrefBandSize]; | 1052 float hNlPref[kPrefBandSize]; |
1048 float hNlFb = 0, hNlFbLow = 0; | 1053 float hNlFb = 0, hNlFbLow = 0; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1145 0.99f * aec->overdrive_scaling + 0.01f * aec->overDrive; | 1150 0.99f * aec->overdrive_scaling + 0.01f * aec->overDrive; |
1146 } else { | 1151 } else { |
1147 aec->overdrive_scaling = | 1152 aec->overdrive_scaling = |
1148 0.9f * aec->overdrive_scaling + 0.1f * aec->overDrive; | 1153 0.9f * aec->overdrive_scaling + 0.1f * aec->overDrive; |
1149 } | 1154 } |
1150 | 1155 |
1151 // Apply the overdrive. | 1156 // Apply the overdrive. |
1152 WebRtcAec_Overdrive(aec->overdrive_scaling, hNlFb, hNl); | 1157 WebRtcAec_Overdrive(aec->overdrive_scaling, hNlFb, hNl); |
1153 } | 1158 } |
1154 | 1159 |
1155 static void EchoSuppression(AecCore* aec, | 1160 static void EchoSuppression(const OouraFft* ooura_fft, |
1161 AecCore* aec, | |
1156 float* nearend_extended_block_lowest_band, | 1162 float* nearend_extended_block_lowest_band, |
1157 float farend_extended_block[PART_LEN2], | 1163 float farend_extended_block[PART_LEN2], |
1158 float* echo_subtractor_output, | 1164 float* echo_subtractor_output, |
1159 float output[NUM_HIGH_BANDS_MAX + 1][PART_LEN]) { | 1165 float output[NUM_HIGH_BANDS_MAX + 1][PART_LEN]) { |
1160 float efw[2][PART_LEN1]; | 1166 float efw[2][PART_LEN1]; |
1161 float xfw[2][PART_LEN1]; | 1167 float xfw[2][PART_LEN1]; |
1162 float dfw[2][PART_LEN1]; | 1168 float dfw[2][PART_LEN1]; |
1163 float comfortNoiseHband[2][PART_LEN1]; | 1169 float comfortNoiseHband[2][PART_LEN1]; |
1164 float fft[PART_LEN2]; | 1170 float fft[PART_LEN2]; |
1165 float nlpGainHband; | 1171 float nlpGainHband; |
1166 int i; | 1172 int i; |
1167 size_t j; | 1173 size_t j; |
1168 | 1174 |
1169 // Coherence and non-linear filter | 1175 // Coherence and non-linear filter |
1170 float cohde[PART_LEN1], cohxd[PART_LEN1]; | 1176 float cohde[PART_LEN1], cohxd[PART_LEN1]; |
1171 float hNl[PART_LEN1]; | 1177 float hNl[PART_LEN1]; |
1172 | 1178 |
1173 // Filter energy | 1179 // Filter energy |
1174 const int delayEstInterval = 10 * aec->mult; | 1180 const int delayEstInterval = 10 * aec->mult; |
1175 | 1181 |
1176 float* xfw_ptr = NULL; | 1182 float* xfw_ptr = NULL; |
1177 | 1183 |
1178 // Update eBuf with echo subtractor output. | 1184 // Update eBuf with echo subtractor output. |
1179 memcpy(aec->eBuf + PART_LEN, echo_subtractor_output, | 1185 memcpy(aec->eBuf + PART_LEN, echo_subtractor_output, |
1180 sizeof(float) * PART_LEN); | 1186 sizeof(float) * PART_LEN); |
1181 | 1187 |
1182 // Analysis filter banks for the echo suppressor. | 1188 // Analysis filter banks for the echo suppressor. |
1183 // Windowed near-end ffts. | 1189 // Windowed near-end ffts. |
1184 WindowData(fft, nearend_extended_block_lowest_band); | 1190 WindowData(fft, nearend_extended_block_lowest_band); |
1185 aec_rdft_forward_128(fft); | 1191 ooura_fft->Fft(fft); |
1186 StoreAsComplex(fft, dfw); | 1192 StoreAsComplex(fft, dfw); |
1187 | 1193 |
1188 // Windowed echo suppressor output ffts. | 1194 // Windowed echo suppressor output ffts. |
1189 WindowData(fft, aec->eBuf); | 1195 WindowData(fft, aec->eBuf); |
1190 aec_rdft_forward_128(fft); | 1196 ooura_fft->Fft(fft); |
1191 StoreAsComplex(fft, efw); | 1197 StoreAsComplex(fft, efw); |
1192 | 1198 |
1193 // NLP | 1199 // NLP |
1194 | 1200 |
1195 // Convert far-end partition to the frequency domain with windowing. | 1201 // Convert far-end partition to the frequency domain with windowing. |
1196 WindowData(fft, farend_extended_block); | 1202 WindowData(fft, farend_extended_block); |
1197 Fft(fft, xfw); | 1203 Fft(ooura_fft, fft, xfw); |
1198 xfw_ptr = &xfw[0][0]; | 1204 xfw_ptr = &xfw[0][0]; |
1199 | 1205 |
1200 // Buffer far. | 1206 // Buffer far. |
1201 memcpy(aec->xfwBuf, xfw_ptr, sizeof(float) * 2 * PART_LEN1); | 1207 memcpy(aec->xfwBuf, xfw_ptr, sizeof(float) * 2 * PART_LEN1); |
1202 | 1208 |
1203 aec->delayEstCtr++; | 1209 aec->delayEstCtr++; |
1204 if (aec->delayEstCtr == delayEstInterval) { | 1210 if (aec->delayEstCtr == delayEstInterval) { |
1205 aec->delayEstCtr = 0; | 1211 aec->delayEstCtr = 0; |
1206 aec->delayIdx = WebRtcAec_PartitionDelay(aec->num_partitions, aec->wfBuf); | 1212 aec->delayIdx = WebRtcAec_PartitionDelay(aec->num_partitions, aec->wfBuf); |
1207 } | 1213 } |
(...skipping 21 matching lines...) Expand all Loading... | |
1229 | 1235 |
1230 aec->data_dumper->DumpRaw("aec_nlp_gain", PART_LEN1, hNl); | 1236 aec->data_dumper->DumpRaw("aec_nlp_gain", PART_LEN1, hNl); |
1231 | 1237 |
1232 WebRtcAec_Suppress(hNl, efw); | 1238 WebRtcAec_Suppress(hNl, efw); |
1233 | 1239 |
1234 // Add comfort noise. | 1240 // Add comfort noise. |
1235 ComfortNoise(aec->num_bands > 1, &aec->seed, efw, comfortNoiseHband, | 1241 ComfortNoise(aec->num_bands > 1, &aec->seed, efw, comfortNoiseHband, |
1236 aec->noisePow, hNl); | 1242 aec->noisePow, hNl); |
1237 | 1243 |
1238 // Inverse error fft. | 1244 // Inverse error fft. |
1239 ScaledInverseFft(efw, fft, 2.0f, 1); | 1245 ScaledInverseFft(ooura_fft, efw, fft, 2.0f, 1); |
1240 | 1246 |
1241 // Overlap and add to obtain output. | 1247 // Overlap and add to obtain output. |
1242 for (i = 0; i < PART_LEN; i++) { | 1248 for (i = 0; i < PART_LEN; i++) { |
1243 output[0][i] = (fft[i] * WebRtcAec_sqrtHanning[i] + | 1249 output[0][i] = (fft[i] * WebRtcAec_sqrtHanning[i] + |
1244 aec->outBuf[i] * WebRtcAec_sqrtHanning[PART_LEN - i]); | 1250 aec->outBuf[i] * WebRtcAec_sqrtHanning[PART_LEN - i]); |
1245 | 1251 |
1246 // Saturate output to keep it in the allowed range. | 1252 // Saturate output to keep it in the allowed range. |
1247 output[0][i] = WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, output[0][i], | 1253 output[0][i] = WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, output[0][i], |
1248 WEBRTC_SPL_WORD16_MIN); | 1254 WEBRTC_SPL_WORD16_MIN); |
1249 } | 1255 } |
1250 memcpy(aec->outBuf, &fft[PART_LEN], PART_LEN * sizeof(aec->outBuf[0])); | 1256 memcpy(aec->outBuf, &fft[PART_LEN], PART_LEN * sizeof(aec->outBuf[0])); |
1251 | 1257 |
1252 // For H band | 1258 // For H band |
1253 if (aec->num_bands > 1) { | 1259 if (aec->num_bands > 1) { |
1254 // H band gain | 1260 // H band gain |
1255 // average nlp over low band: average over second half of freq spectrum | 1261 // average nlp over low band: average over second half of freq spectrum |
1256 // (4->8khz) | 1262 // (4->8khz) |
1257 GetHighbandGain(hNl, &nlpGainHband); | 1263 GetHighbandGain(hNl, &nlpGainHband); |
1258 | 1264 |
1259 // Inverse comfort_noise | 1265 // Inverse comfort_noise |
1260 ScaledInverseFft(comfortNoiseHband, fft, 2.0f, 0); | 1266 ScaledInverseFft(ooura_fft, comfortNoiseHband, fft, 2.0f, 0); |
1261 | 1267 |
1262 // compute gain factor | 1268 // compute gain factor |
1263 for (j = 1; j < aec->num_bands; ++j) { | 1269 for (j = 1; j < aec->num_bands; ++j) { |
1264 for (i = 0; i < PART_LEN; i++) { | 1270 for (i = 0; i < PART_LEN; i++) { |
1265 output[j][i] = aec->previous_nearend_block[j][i] * nlpGainHband; | 1271 output[j][i] = aec->previous_nearend_block[j][i] * nlpGainHband; |
1266 } | 1272 } |
1267 } | 1273 } |
1268 | 1274 |
1269 // Add some comfort noise where Hband is attenuated. | 1275 // Add some comfort noise where Hband is attenuated. |
1270 for (i = 0; i < PART_LEN; i++) { | 1276 for (i = 0; i < PART_LEN; i++) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1323 // Update power levels | 1329 // Update power levels |
1324 UpdateLevel( | 1330 UpdateLevel( |
1325 &aec->farlevel, | 1331 &aec->farlevel, |
1326 CalculatePower(&farend_extended_block_lowest_band[PART_LEN], PART_LEN)); | 1332 CalculatePower(&farend_extended_block_lowest_band[PART_LEN], PART_LEN)); |
1327 UpdateLevel(&aec->nearlevel, | 1333 UpdateLevel(&aec->nearlevel, |
1328 CalculatePower(&nearend_block[0][0], PART_LEN)); | 1334 CalculatePower(&nearend_block[0][0], PART_LEN)); |
1329 } | 1335 } |
1330 | 1336 |
1331 // Convert far-end signal to the frequency domain. | 1337 // Convert far-end signal to the frequency domain. |
1332 memcpy(fft, farend_extended_block_lowest_band, sizeof(float) * PART_LEN2); | 1338 memcpy(fft, farend_extended_block_lowest_band, sizeof(float) * PART_LEN2); |
1333 Fft(fft, farend_fft); | 1339 Fft(&aec->ooura_fft, fft, farend_fft); |
1334 | 1340 |
1335 // Form extended nearend frame. | 1341 // Form extended nearend frame. |
1336 memcpy(&nearend_extended_block_lowest_band[0], | 1342 memcpy(&nearend_extended_block_lowest_band[0], |
1337 &aec->previous_nearend_block[0][0], sizeof(float) * PART_LEN); | 1343 &aec->previous_nearend_block[0][0], sizeof(float) * PART_LEN); |
1338 memcpy(&nearend_extended_block_lowest_band[PART_LEN], &nearend_block[0][0], | 1344 memcpy(&nearend_extended_block_lowest_band[PART_LEN], &nearend_block[0][0], |
1339 sizeof(float) * PART_LEN); | 1345 sizeof(float) * PART_LEN); |
1340 | 1346 |
1341 // Convert near-end signal to the frequency domain. | 1347 // Convert near-end signal to the frequency domain. |
1342 memcpy(fft, nearend_extended_block_lowest_band, sizeof(float) * PART_LEN2); | 1348 memcpy(fft, nearend_extended_block_lowest_band, sizeof(float) * PART_LEN2); |
1343 Fft(fft, nearend_fft); | 1349 Fft(&aec->ooura_fft, fft, nearend_fft); |
1344 | 1350 |
1345 // Power smoothing. | 1351 // Power smoothing. |
1346 if (aec->refined_adaptive_filter_enabled) { | 1352 if (aec->refined_adaptive_filter_enabled) { |
1347 for (i = 0; i < PART_LEN1; ++i) { | 1353 for (i = 0; i < PART_LEN1; ++i) { |
1348 far_spectrum = farend_fft[0][i] * farend_fft[0][i] + | 1354 far_spectrum = farend_fft[0][i] * farend_fft[0][i] + |
1349 farend_fft[1][i] * farend_fft[1][i]; | 1355 farend_fft[1][i] * farend_fft[1][i]; |
1350 // Calculate the magnitude spectrum. | 1356 // Calculate the magnitude spectrum. |
1351 abs_far_spectrum[i] = sqrtf(far_spectrum); | 1357 abs_far_spectrum[i] = sqrtf(far_spectrum); |
1352 } | 1358 } |
1353 RegressorPower(aec->num_partitions, aec->xfBufBlockPos, aec->xfBuf, | 1359 RegressorPower(aec->num_partitions, aec->xfBufBlockPos, aec->xfBuf, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1412 aec->num_delay_values++; | 1418 aec->num_delay_values++; |
1413 } | 1419 } |
1414 if (aec->delay_metrics_delivered == 1 && | 1420 if (aec->delay_metrics_delivered == 1 && |
1415 aec->num_delay_values >= kDelayMetricsAggregationWindow) { | 1421 aec->num_delay_values >= kDelayMetricsAggregationWindow) { |
1416 UpdateDelayMetrics(aec); | 1422 UpdateDelayMetrics(aec); |
1417 } | 1423 } |
1418 } | 1424 } |
1419 } | 1425 } |
1420 | 1426 |
1421 // Perform echo subtraction. | 1427 // Perform echo subtraction. |
1422 EchoSubtraction(aec->num_partitions, aec->extended_filter_enabled, | 1428 EchoSubtraction( |
1423 &aec->extreme_filter_divergence, aec->filter_step_size, | 1429 &aec->ooura_fft, aec->num_partitions, aec->extended_filter_enabled, |
1424 aec->error_threshold, &farend_fft[0][0], &aec->xfBufBlockPos, | 1430 &aec->extreme_filter_divergence, aec->filter_step_size, |
1425 aec->xfBuf, &nearend_block[0][0], aec->xPow, aec->wfBuf, | 1431 aec->error_threshold, &farend_fft[0][0], &aec->xfBufBlockPos, aec->xfBuf, |
1426 echo_subtractor_output); | 1432 &nearend_block[0][0], aec->xPow, aec->wfBuf, echo_subtractor_output); |
1427 aec->data_dumper->DumpRaw("aec_h_fft", PART_LEN1 * aec->num_partitions, | 1433 aec->data_dumper->DumpRaw("aec_h_fft", PART_LEN1 * aec->num_partitions, |
1428 &aec->wfBuf[0][0]); | 1434 &aec->wfBuf[0][0]); |
1429 aec->data_dumper->DumpRaw("aec_h_fft", PART_LEN1 * aec->num_partitions, | 1435 aec->data_dumper->DumpRaw("aec_h_fft", PART_LEN1 * aec->num_partitions, |
1430 &aec->wfBuf[1][0]); | 1436 &aec->wfBuf[1][0]); |
1431 | 1437 |
1432 aec->data_dumper->DumpWav("aec_out_linear", PART_LEN, echo_subtractor_output, | 1438 aec->data_dumper->DumpWav("aec_out_linear", PART_LEN, echo_subtractor_output, |
1433 std::min(aec->sampFreq, 16000), 1); | 1439 std::min(aec->sampFreq, 16000), 1); |
1434 | 1440 |
1435 if (aec->metricsMode == 1) { | 1441 if (aec->metricsMode == 1) { |
1436 UpdateLevel(&aec->linoutlevel, | 1442 UpdateLevel(&aec->linoutlevel, |
1437 CalculatePower(echo_subtractor_output, PART_LEN)); | 1443 CalculatePower(echo_subtractor_output, PART_LEN)); |
1438 } | 1444 } |
1439 | 1445 |
1440 // Perform echo suppression. | 1446 // Perform echo suppression. |
1441 EchoSuppression(aec, nearend_extended_block_lowest_band, | 1447 EchoSuppression(&aec->ooura_fft, aec, nearend_extended_block_lowest_band, |
1442 farend_extended_block_lowest_band, echo_subtractor_output, | 1448 farend_extended_block_lowest_band, echo_subtractor_output, |
1443 output_block); | 1449 output_block); |
1444 | 1450 |
1445 if (aec->metricsMode == 1) { | 1451 if (aec->metricsMode == 1) { |
1446 UpdateLevel(&aec->nlpoutlevel, | 1452 UpdateLevel(&aec->nlpoutlevel, |
1447 CalculatePower(&output_block[0][0], PART_LEN)); | 1453 CalculatePower(&output_block[0][0], PART_LEN)); |
1448 UpdateMetrics(aec); | 1454 UpdateMetrics(aec); |
1449 } | 1455 } |
1450 | 1456 |
1451 // Store the nearend signal until the next frame. | 1457 // Store the nearend signal until the next frame. |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1517 #endif | 1523 #endif |
1518 | 1524 |
1519 #if defined(MIPS_FPU_LE) | 1525 #if defined(MIPS_FPU_LE) |
1520 WebRtcAec_InitAec_mips(); | 1526 WebRtcAec_InitAec_mips(); |
1521 #endif | 1527 #endif |
1522 | 1528 |
1523 #if defined(WEBRTC_HAS_NEON) | 1529 #if defined(WEBRTC_HAS_NEON) |
1524 WebRtcAec_InitAec_neon(); | 1530 WebRtcAec_InitAec_neon(); |
1525 #endif | 1531 #endif |
1526 | 1532 |
1527 aec_rdft_init(); | |
1528 | |
1529 return aec; | 1533 return aec; |
1530 } | 1534 } |
1531 | 1535 |
1532 void WebRtcAec_FreeAec(AecCore* aec) { | 1536 void WebRtcAec_FreeAec(AecCore* aec) { |
1533 if (aec == NULL) { | 1537 if (aec == NULL) { |
1534 return; | 1538 return; |
1535 } | 1539 } |
1536 | 1540 |
1537 WebRtc_FreeDelayEstimator(aec->delay_estimator); | 1541 WebRtc_FreeDelayEstimator(aec->delay_estimator); |
1538 WebRtc_FreeDelayEstimatorFarend(aec->delay_estimator_farend); | 1542 WebRtc_FreeDelayEstimatorFarend(aec->delay_estimator_farend); |
(...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2048 | 2052 |
2049 int WebRtcAec_system_delay(AecCore* self) { | 2053 int WebRtcAec_system_delay(AecCore* self) { |
2050 return self->system_delay; | 2054 return self->system_delay; |
2051 } | 2055 } |
2052 | 2056 |
2053 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { | 2057 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { |
2054 RTC_DCHECK_GE(delay, 0); | 2058 RTC_DCHECK_GE(delay, 0); |
2055 self->system_delay = delay; | 2059 self->system_delay = delay; |
2056 } | 2060 } |
2057 } // namespace webrtc | 2061 } // namespace webrtc |
OLD | NEW |