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