Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 return aRe * bIm + aIm * bRe; | 144 return aRe * bIm + aIm * bRe; |
| 145 } | 145 } |
| 146 | 146 |
| 147 static int CmpFloat(const void* a, const void* b) { | 147 static int CmpFloat(const void* a, const void* b) { |
| 148 const float* da = (const float*)a; | 148 const float* da = (const float*)a; |
| 149 const float* db = (const float*)b; | 149 const float* db = (const float*)b; |
| 150 | 150 |
| 151 return (*da > *db) - (*da < *db); | 151 return (*da > *db) - (*da < *db); |
| 152 } | 152 } |
| 153 | 153 |
| 154 static void FilterFar(int num_partitions, | 154 static void FilterFar( |
| 155 int xfBufBlockPos, | 155 int num_partitions, |
| 156 float xfBuf[2][kExtendedNumPartitions * PART_LEN1], | 156 int x_fft_buf_block_pos, |
| 157 float wfBuf[2][kExtendedNumPartitions * PART_LEN1], | 157 const float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1], |
| 158 float yf[2][PART_LEN1]) { | 158 const float h_fft_buf[2][kExtendedNumPartitions * PART_LEN1], |
| 159 float y_fft[2][PART_LEN1]) { | |
| 159 int i; | 160 int i; |
| 160 for (i = 0; i < num_partitions; i++) { | 161 for (i = 0; i < num_partitions; i++) { |
| 161 int j; | 162 int j; |
| 162 int xPos = (i + xfBufBlockPos) * PART_LEN1; | 163 int xPos = (i + x_fft_buf_block_pos) * PART_LEN1; |
| 163 int pos = i * PART_LEN1; | 164 int pos = i * PART_LEN1; |
| 164 // Check for wrap | 165 // Check for wrap |
| 165 if (i + xfBufBlockPos >= num_partitions) { | 166 if (i + x_fft_buf_block_pos >= num_partitions) { |
| 166 xPos -= num_partitions * (PART_LEN1); | 167 xPos -= num_partitions * (PART_LEN1); |
| 167 } | 168 } |
| 168 | 169 |
| 169 for (j = 0; j < PART_LEN1; j++) { | 170 for (j = 0; j < PART_LEN1; j++) { |
| 170 yf[0][j] += MulRe(xfBuf[0][xPos + j], | 171 y_fft[0][j] += MulRe(x_fft_buf[0][xPos + j], |
| 171 xfBuf[1][xPos + j], | 172 x_fft_buf[1][xPos + j], |
| 172 wfBuf[0][pos + j], | 173 h_fft_buf[0][pos + j], |
| 173 wfBuf[1][pos + j]); | 174 h_fft_buf[1][pos + j]); |
| 174 yf[1][j] += MulIm(xfBuf[0][xPos + j], | 175 y_fft[1][j] += MulIm(x_fft_buf[0][xPos + j], |
| 175 xfBuf[1][xPos + j], | 176 x_fft_buf[1][xPos + j], |
| 176 wfBuf[0][pos + j], | 177 h_fft_buf[0][pos + j], |
| 177 wfBuf[1][pos + j]); | 178 h_fft_buf[1][pos + j]); |
| 178 } | 179 } |
| 179 } | 180 } |
| 180 } | 181 } |
| 181 | 182 |
| 182 static void ScaleErrorSignal(int extended_filter_enabled, | 183 static void ScaleErrorSignal(int extended_filter_enabled, |
| 183 float normal_mu, | 184 float normal_mu, |
| 184 float normal_error_threshold, | 185 float normal_error_threshold, |
| 185 float *xPow, | 186 const float xPow[PART_LEN1], |
| 186 float ef[2][PART_LEN1]) { | 187 float ef[2][PART_LEN1]) { |
| 187 const float mu = extended_filter_enabled ? kExtendedMu : normal_mu; | 188 const float mu = extended_filter_enabled ? kExtendedMu : normal_mu; |
| 188 const float error_threshold = extended_filter_enabled | 189 const float error_threshold = extended_filter_enabled |
| 189 ? kExtendedErrorThreshold | 190 ? kExtendedErrorThreshold |
| 190 : normal_error_threshold; | 191 : normal_error_threshold; |
| 191 int i; | 192 int i; |
| 192 float abs_ef; | 193 float abs_ef; |
| 193 for (i = 0; i < (PART_LEN1); i++) { | 194 for (i = 0; i < (PART_LEN1); i++) { |
| 194 ef[0][i] /= (xPow[i] + 1e-10f); | 195 ef[0][i] /= (xPow[i] + 1e-10f); |
| 195 ef[1][i] /= (xPow[i] + 1e-10f); | 196 ef[1][i] /= (xPow[i] + 1e-10f); |
| 196 abs_ef = sqrtf(ef[0][i] * ef[0][i] + ef[1][i] * ef[1][i]); | 197 abs_ef = sqrtf(ef[0][i] * ef[0][i] + ef[1][i] * ef[1][i]); |
| 197 | 198 |
| 198 if (abs_ef > error_threshold) { | 199 if (abs_ef > error_threshold) { |
| 199 abs_ef = error_threshold / (abs_ef + 1e-10f); | 200 abs_ef = error_threshold / (abs_ef + 1e-10f); |
| 200 ef[0][i] *= abs_ef; | 201 ef[0][i] *= abs_ef; |
| 201 ef[1][i] *= abs_ef; | 202 ef[1][i] *= abs_ef; |
| 202 } | 203 } |
| 203 | 204 |
| 204 // Stepsize factor | 205 // Stepsize factor |
| 205 ef[0][i] *= mu; | 206 ef[0][i] *= mu; |
| 206 ef[1][i] *= mu; | 207 ef[1][i] *= mu; |
| 207 } | 208 } |
| 208 } | 209 } |
| 209 | 210 |
| 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 | 211 |
| 236 static void FilterAdaptation(AecCore* aec, float* fft, float ef[2][PART_LEN1]) { | 212 static void FilterAdaptation( |
| 213 int num_partitions, | |
| 214 int x_fft_buf_block_pos, | |
| 215 const float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1], | |
| 216 const float e_fft[2][PART_LEN1], | |
| 217 float h_fft_buf[2][kExtendedNumPartitions * PART_LEN1]) { | |
| 237 int i, j; | 218 int i, j; |
| 238 for (i = 0; i < aec->num_partitions; i++) { | 219 float fft[PART_LEN2]; |
| 239 int xPos = (i + aec->xfBufBlockPos) * (PART_LEN1); | 220 for (i = 0; i < num_partitions; i++) { |
| 221 int xPos = (i + x_fft_buf_block_pos) * (PART_LEN1); | |
| 240 int pos; | 222 int pos; |
| 241 // Check for wrap | 223 // Check for wrap |
| 242 if (i + aec->xfBufBlockPos >= aec->num_partitions) { | 224 if (i + x_fft_buf_block_pos >= num_partitions) { |
| 243 xPos -= aec->num_partitions * PART_LEN1; | 225 xPos -= num_partitions * PART_LEN1; |
| 244 } | 226 } |
| 245 | 227 |
| 246 pos = i * PART_LEN1; | 228 pos = i * PART_LEN1; |
| 247 | 229 |
| 248 for (j = 0; j < PART_LEN; j++) { | 230 for (j = 0; j < PART_LEN; j++) { |
| 249 | 231 |
| 250 fft[2 * j] = MulRe(aec->xfBuf[0][xPos + j], | 232 fft[2 * j] = MulRe(x_fft_buf[0][xPos + j], |
| 251 -aec->xfBuf[1][xPos + j], | 233 -x_fft_buf[1][xPos + j], |
| 252 ef[0][j], | 234 e_fft[0][j], |
| 253 ef[1][j]); | 235 e_fft[1][j]); |
| 254 fft[2 * j + 1] = MulIm(aec->xfBuf[0][xPos + j], | 236 fft[2 * j + 1] = MulIm(x_fft_buf[0][xPos + j], |
| 255 -aec->xfBuf[1][xPos + j], | 237 -x_fft_buf[1][xPos + j], |
| 256 ef[0][j], | 238 e_fft[0][j], |
| 257 ef[1][j]); | 239 e_fft[1][j]); |
| 258 } | 240 } |
| 259 fft[1] = MulRe(aec->xfBuf[0][xPos + PART_LEN], | 241 fft[1] = MulRe(x_fft_buf[0][xPos + PART_LEN], |
| 260 -aec->xfBuf[1][xPos + PART_LEN], | 242 -x_fft_buf[1][xPos + PART_LEN], |
| 261 ef[0][PART_LEN], | 243 e_fft[0][PART_LEN], |
| 262 ef[1][PART_LEN]); | 244 e_fft[1][PART_LEN]); |
| 263 | 245 |
| 264 aec_rdft_inverse_128(fft); | 246 aec_rdft_inverse_128(fft); |
| 265 memset(fft + PART_LEN, 0, sizeof(float) * PART_LEN); | 247 memset(fft + PART_LEN, 0, sizeof(float) * PART_LEN); |
| 266 | 248 |
| 267 // fft scaling | 249 // fft scaling |
| 268 { | 250 { |
| 269 float scale = 2.0f / PART_LEN2; | 251 float scale = 2.0f / PART_LEN2; |
| 270 for (j = 0; j < PART_LEN; j++) { | 252 for (j = 0; j < PART_LEN; j++) { |
| 271 fft[j] *= scale; | 253 fft[j] *= scale; |
| 272 } | 254 } |
| 273 } | 255 } |
| 274 aec_rdft_forward_128(fft); | 256 aec_rdft_forward_128(fft); |
| 275 | 257 |
| 276 aec->wfBuf[0][pos] += fft[0]; | 258 h_fft_buf[0][pos] += fft[0]; |
| 277 aec->wfBuf[0][pos + PART_LEN] += fft[1]; | 259 h_fft_buf[0][pos + PART_LEN] += fft[1]; |
| 278 | 260 |
| 279 for (j = 1; j < PART_LEN; j++) { | 261 for (j = 1; j < PART_LEN; j++) { |
| 280 aec->wfBuf[0][pos + j] += fft[2 * j]; | 262 h_fft_buf[0][pos + j] += fft[2 * j]; |
| 281 aec->wfBuf[1][pos + j] += fft[2 * j + 1]; | 263 h_fft_buf[1][pos + j] += fft[2 * j + 1]; |
| 282 } | 264 } |
| 283 } | 265 } |
| 284 } | 266 } |
| 285 | 267 |
| 286 static void OverdriveAndSuppress(AecCore* aec, | 268 static void OverdriveAndSuppress(AecCore* aec, |
| 287 float hNl[PART_LEN1], | 269 float hNl[PART_LEN1], |
| 288 const float hNlFb, | 270 const float hNlFb, |
| 289 float efw[2][PART_LEN1]) { | 271 float efw[2][PART_LEN1]) { |
| 290 int i; | 272 int i; |
| 291 for (i = 0; i < PART_LEN1; i++) { | 273 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; | 820 self->num_delay_values; |
| 839 } | 821 } |
| 840 | 822 |
| 841 // Reset histogram. | 823 // Reset histogram. |
| 842 memset(self->delay_histogram, 0, sizeof(self->delay_histogram)); | 824 memset(self->delay_histogram, 0, sizeof(self->delay_histogram)); |
| 843 self->num_delay_values = 0; | 825 self->num_delay_values = 0; |
| 844 | 826 |
| 845 return; | 827 return; |
| 846 } | 828 } |
| 847 | 829 |
| 848 static void FrequencyToTime(float freq_data[2][PART_LEN1], | 830 static void InverseFft(const float freq_data[2][PART_LEN1], |
| 849 float time_data[PART_LEN2]) { | 831 float time_data[PART_LEN2]) { |
| 832 const float scale = 1.0f / PART_LEN2; | |
| 850 time_data[0] = freq_data[0][0]; | 833 time_data[0] = freq_data[0][0]; |
| 851 time_data[1] = freq_data[0][PART_LEN]; | 834 time_data[1] = freq_data[0][PART_LEN]; |
| 852 for (int i = 1; i < PART_LEN; i++) { | 835 for (int i = 1; i < PART_LEN; i++) { |
| 853 time_data[2 * i] = freq_data[0][i]; | 836 time_data[2 * i] = freq_data[0][i]; |
| 854 time_data[2 * i + 1] = freq_data[1][i]; | 837 time_data[2 * i + 1] = freq_data[1][i]; |
| 855 } | 838 } |
| 856 aec_rdft_inverse_128(time_data); | 839 aec_rdft_inverse_128(time_data); |
| 840 | |
| 841 for (int i = 0; i < PART_LEN2; i++) { | |
| 842 time_data[i] *= scale; | |
|
ivoc
2015/11/26 12:46:44
I think it is more efficient to merge this loop wi
peah-webrtc
2015/11/27 04:58:36
I'll do that. Before I did not to that for fear of
| |
| 843 } | |
| 857 } | 844 } |
| 858 | 845 |
| 859 | 846 |
| 860 static void TimeToFrequency(float time_data[PART_LEN2], | 847 static void Fft(float time_data[PART_LEN2], |
| 861 float freq_data[2][PART_LEN1], | 848 float freq_data[2][PART_LEN1]) { |
| 862 int window) { | 849 // Make local copy of the time_data to avoid changing it. |
| 863 int i = 0; | 850 float time_data_copy[PART_LEN2]; |
| 864 | 851 memcpy(time_data_copy, time_data, sizeof(float) * PART_LEN2); |
|
hlundin-webrtc
2015/11/24 13:51:44
I'm not sure I like yet another memcpy of all audi
peah-webrtc
2015/11/26 05:55:17
I'll remote it.
Done.
hlundin-webrtc
2015/11/26 08:41:44
Great. Btw: did you even use it?
peah-webrtc
2015/11/27 04:58:36
No. So safe removal it is! :-)
| |
| 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 | 852 |
| 873 aec_rdft_forward_128(time_data); | 853 aec_rdft_forward_128(time_data); |
| 874 // Reorder. | 854 |
| 855 // Reorder fft output data. | |
| 875 freq_data[1][0] = 0; | 856 freq_data[1][0] = 0; |
| 876 freq_data[1][PART_LEN] = 0; | 857 freq_data[1][PART_LEN] = 0; |
| 877 freq_data[0][0] = time_data[0]; | 858 freq_data[0][0] = time_data[0]; |
| 878 freq_data[0][PART_LEN] = time_data[1]; | 859 freq_data[0][PART_LEN] = time_data[1]; |
| 879 for (i = 1; i < PART_LEN; i++) { | 860 for (int i = 1; i < PART_LEN; i++) { |
| 880 freq_data[0][i] = time_data[2 * i]; | 861 freq_data[0][i] = time_data[2 * i]; |
| 881 freq_data[1][i] = time_data[2 * i + 1]; | 862 freq_data[1][i] = time_data[2 * i + 1]; |
| 882 } | 863 } |
| 883 } | 864 } |
| 884 | 865 |
| 885 static int MoveFarReadPtrWithoutSystemDelayUpdate(AecCore* self, int elements) { | 866 static int MoveFarReadPtrWithoutSystemDelayUpdate(AecCore* self, int elements) { |
| 886 WebRtc_MoveReadPtr(self->far_buf_windowed, elements); | 867 WebRtc_MoveReadPtr(self->far_buf_windowed, elements); |
| 887 #ifdef WEBRTC_AEC_DEBUG_DUMP | 868 #ifdef WEBRTC_AEC_DEBUG_DUMP |
| 888 WebRtc_MoveReadPtr(self->far_time_buf, elements); | 869 WebRtc_MoveReadPtr(self->far_time_buf, elements); |
| 889 #endif | 870 #endif |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 955 float delay_quality = WebRtc_last_delay_quality(self->delay_estimator); | 936 float delay_quality = WebRtc_last_delay_quality(self->delay_estimator); |
| 956 delay_quality = (delay_quality > kDelayQualityThresholdMax ? | 937 delay_quality = (delay_quality > kDelayQualityThresholdMax ? |
| 957 kDelayQualityThresholdMax : delay_quality); | 938 kDelayQualityThresholdMax : delay_quality); |
| 958 self->delay_quality_threshold = | 939 self->delay_quality_threshold = |
| 959 (delay_quality > self->delay_quality_threshold ? delay_quality : | 940 (delay_quality > self->delay_quality_threshold ? delay_quality : |
| 960 self->delay_quality_threshold); | 941 self->delay_quality_threshold); |
| 961 } | 942 } |
| 962 return delay_correction; | 943 return delay_correction; |
| 963 } | 944 } |
| 964 | 945 |
| 965 static void EchoSubtraction(AecCore* aec, | 946 static void EchoSubtraction( |
| 966 float* nearend_ptr) { | 947 AecCore* aec, |
| 967 float yf[2][PART_LEN1]; | 948 int num_partitions, |
| 968 float fft[PART_LEN2]; | 949 int x_fft_buf_block_pos, |
| 969 float y[PART_LEN]; | 950 int metrics_mode, |
| 951 int extended_filter_enabled, | |
| 952 float normal_mu, | |
| 953 float normal_error_threshold, | |
| 954 const float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1], | |
| 955 const float* const y, | |
| 956 const float x_pow[PART_LEN1], | |
| 957 float h_fft_buf[2][kExtendedNumPartitions * PART_LEN1], | |
| 958 PowerLevel* linout_level, | |
| 959 float echo_subtractor_output[PART_LEN]) { | |
| 960 float s_fft[2][PART_LEN1]; | |
| 961 float e_extended[PART_LEN2]; | |
| 962 float s_extended[PART_LEN2]; | |
| 963 float *s; | |
| 970 float e[PART_LEN]; | 964 float e[PART_LEN]; |
| 971 float ef[2][PART_LEN1]; | 965 float e_fft[2][PART_LEN1]; |
| 972 float scale; | |
| 973 int i; | 966 int i; |
| 974 memset(yf, 0, sizeof(yf)); | 967 memset(s_fft, 0, sizeof(s_fft)); |
| 975 | 968 |
| 976 // Produce echo estimate. | 969 // Produce echo estimate s_fft. |
| 977 WebRtcAec_FilterFar(aec->num_partitions, | 970 WebRtcAec_FilterFar(num_partitions, |
| 978 aec->xfBufBlockPos, | 971 x_fft_buf_block_pos, |
| 979 aec->xfBuf, | 972 x_fft_buf, |
| 980 aec->wfBuf, | 973 h_fft_buf, |
| 981 yf); | 974 s_fft); |
| 982 | 975 |
| 983 // Inverse fft to obtain echo estimate and error. | 976 // Compute the time-domain echo estimate s. |
| 984 FrequencyToTime(yf, fft); | 977 InverseFft(s_fft, s_extended); |
| 985 | 978 s = &s_extended[PART_LEN]; |
| 986 // Extract the output signal and compute the time-domain error | 979 for (i = 0; i < PART_LEN; ++i) { |
| 987 scale = 2.0f / PART_LEN2; | 980 s[i] *= 2.0f; |
| 988 for (i = 0; i < PART_LEN; i++) { | |
| 989 y[i] = fft[PART_LEN + i] * scale; // fft scaling | |
| 990 } | 981 } |
| 991 | 982 |
| 992 for (i = 0; i < PART_LEN; i++) { | 983 // Compute the time-domain echo prediction error. |
| 993 e[i] = nearend_ptr[i] - y[i]; | 984 for (i = 0; i < PART_LEN; ++i) { |
| 985 e[i] = y[i] - s[i]; | |
| 994 } | 986 } |
| 995 | 987 |
| 988 // Compute the frequency domain echo prediction error. | |
| 989 memset(e_extended, 0, sizeof(float) * PART_LEN); | |
| 990 memcpy(e_extended + PART_LEN, e, sizeof(float) * PART_LEN); | |
| 991 Fft(e_extended, e_fft); | |
| 996 | 992 |
| 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 | 993 |
| 1003 RTC_AEC_DEBUG_RAW_WRITE(aec->e_fft_file, | 994 RTC_AEC_DEBUG_RAW_WRITE(aec->e_fft_file, |
| 1004 &ef[0][0], | 995 &e_fft[0][0], |
| 1005 sizeof(ef[0][0]) * PART_LEN1 * 2); | 996 sizeof(e_fft[0][0]) * PART_LEN1 * 2); |
| 1006 | 997 |
| 1007 if (aec->metricsMode == 1) { | 998 if (metrics_mode == 1) { |
| 1008 // Note that the first PART_LEN samples in fft (before transformation) are | 999 // Note that the first PART_LEN samples in fft (before transformation) are |
| 1009 // zero. Hence, the scaling by two in UpdateLevel() should not be | 1000 // zero. Hence, the scaling by two in UpdateLevel() should not be |
| 1010 // performed. That scaling is taken care of in UpdateMetrics() instead. | 1001 // performed. That scaling is taken care of in UpdateMetrics() instead. |
| 1011 UpdateLevel(&aec->linoutlevel, ef); | 1002 UpdateLevel(linout_level, e_fft); |
| 1012 } | 1003 } |
| 1013 | 1004 |
| 1014 // Scale error signal inversely with far power. | 1005 // Scale error signal inversely with far power. |
| 1015 WebRtcAec_ScaleErrorSignal(aec->extended_filter_enabled, | 1006 WebRtcAec_ScaleErrorSignal(extended_filter_enabled, |
| 1016 aec->normal_mu, | 1007 normal_mu, |
| 1017 aec->normal_error_threshold, | 1008 normal_error_threshold, |
| 1018 aec->xPow, | 1009 x_pow, |
| 1019 ef); | 1010 e_fft); |
| 1020 WebRtcAec_FilterAdaptation(aec, fft, ef); | 1011 WebRtcAec_FilterAdaptation(num_partitions, |
| 1021 | 1012 x_fft_buf_block_pos, |
| 1022 | 1013 x_fft_buf, |
| 1023 RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, e, PART_LEN); | 1014 e_fft, |
| 1015 h_fft_buf); | |
| 1016 memcpy(echo_subtractor_output, e, sizeof(float) * PART_LEN); | |
| 1024 } | 1017 } |
| 1025 | 1018 |
| 1026 | 1019 |
| 1027 static void EchoSuppression(AecCore* aec, | 1020 static void EchoSuppression(AecCore* aec, |
| 1028 float* output, | 1021 float* output, |
| 1029 float* const* outputH) { | 1022 float* const* outputH) { |
| 1030 float efw[2][PART_LEN1], xfw[2][PART_LEN1]; | 1023 float efw[2][PART_LEN1], xfw[2][PART_LEN1]; |
| 1031 complex_t comfortNoiseHband[PART_LEN1]; | 1024 complex_t comfortNoiseHband[PART_LEN1]; |
| 1032 float fft[PART_LEN2]; | 1025 float fft[PART_LEN2]; |
| 1033 float scale, dtmp; | 1026 float scale, dtmp; |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1270 | 1263 |
| 1271 const float gPow[2] = {0.9f, 0.1f}; | 1264 const float gPow[2] = {0.9f, 0.1f}; |
| 1272 | 1265 |
| 1273 // Noise estimate constants. | 1266 // Noise estimate constants. |
| 1274 const int noiseInitBlocks = 500 * aec->mult; | 1267 const int noiseInitBlocks = 500 * aec->mult; |
| 1275 const float step = 0.1f; | 1268 const float step = 0.1f; |
| 1276 const float ramp = 1.0002f; | 1269 const float ramp = 1.0002f; |
| 1277 const float gInitNoise[2] = {0.999f, 0.001f}; | 1270 const float gInitNoise[2] = {0.999f, 0.001f}; |
| 1278 | 1271 |
| 1279 float nearend[PART_LEN]; | 1272 float nearend[PART_LEN]; |
| 1273 float echo_subtractor_output[PART_LEN]; | |
| 1280 float* nearend_ptr = NULL; | 1274 float* nearend_ptr = NULL; |
| 1281 float output[PART_LEN]; | 1275 float output[PART_LEN]; |
| 1282 float outputH[NUM_HIGH_BANDS_MAX][PART_LEN]; | 1276 float outputH[NUM_HIGH_BANDS_MAX][PART_LEN]; |
| 1283 float* outputH_ptr[NUM_HIGH_BANDS_MAX]; | 1277 float* outputH_ptr[NUM_HIGH_BANDS_MAX]; |
| 1284 float* xf_ptr = NULL; | 1278 float* xf_ptr = NULL; |
| 1285 | 1279 |
| 1286 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { | 1280 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { |
| 1287 outputH_ptr[i] = outputH[i]; | 1281 outputH_ptr[i] = outputH[i]; |
| 1288 } | 1282 } |
| 1289 | 1283 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1309 RTC_AEC_DEBUG_WAV_WRITE(aec->nearFile, nearend_ptr, PART_LEN); | 1303 RTC_AEC_DEBUG_WAV_WRITE(aec->nearFile, nearend_ptr, PART_LEN); |
| 1310 } | 1304 } |
| 1311 #endif | 1305 #endif |
| 1312 | 1306 |
| 1313 // We should always have at least one element stored in |far_buf|. | 1307 // We should always have at least one element stored in |far_buf|. |
| 1314 assert(WebRtc_available_read(aec->far_buf) > 0); | 1308 assert(WebRtc_available_read(aec->far_buf) > 0); |
| 1315 WebRtc_ReadBuffer(aec->far_buf, (void**)&xf_ptr, &xf[0][0], 1); | 1309 WebRtc_ReadBuffer(aec->far_buf, (void**)&xf_ptr, &xf[0][0], 1); |
| 1316 | 1310 |
| 1317 // Near fft | 1311 // Near fft |
| 1318 memcpy(fft, aec->dBuf, sizeof(float) * PART_LEN2); | 1312 memcpy(fft, aec->dBuf, sizeof(float) * PART_LEN2); |
| 1319 TimeToFrequency(fft, df, 0); | 1313 Fft(fft, df); |
| 1320 | 1314 |
| 1321 // Power smoothing | 1315 // Power smoothing |
| 1322 for (i = 0; i < PART_LEN1; i++) { | 1316 for (i = 0; i < PART_LEN1; i++) { |
| 1323 far_spectrum = (xf_ptr[i] * xf_ptr[i]) + | 1317 far_spectrum = (xf_ptr[i] * xf_ptr[i]) + |
| 1324 (xf_ptr[PART_LEN1 + i] * xf_ptr[PART_LEN1 + i]); | 1318 (xf_ptr[PART_LEN1 + i] * xf_ptr[PART_LEN1 + i]); |
| 1325 aec->xPow[i] = | 1319 aec->xPow[i] = |
| 1326 gPow[0] * aec->xPow[i] + gPow[1] * aec->num_partitions * far_spectrum; | 1320 gPow[0] * aec->xPow[i] + gPow[1] * aec->num_partitions * far_spectrum; |
| 1327 // Calculate absolute spectra | 1321 // Calculate absolute spectra |
| 1328 abs_far_spectrum[i] = sqrtf(far_spectrum); | 1322 abs_far_spectrum[i] = sqrtf(far_spectrum); |
| 1329 | 1323 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1388 | 1382 |
| 1389 // Buffer xf | 1383 // Buffer xf |
| 1390 memcpy(aec->xfBuf[0] + aec->xfBufBlockPos * PART_LEN1, | 1384 memcpy(aec->xfBuf[0] + aec->xfBufBlockPos * PART_LEN1, |
| 1391 xf_ptr, | 1385 xf_ptr, |
| 1392 sizeof(float) * PART_LEN1); | 1386 sizeof(float) * PART_LEN1); |
| 1393 memcpy(aec->xfBuf[1] + aec->xfBufBlockPos * PART_LEN1, | 1387 memcpy(aec->xfBuf[1] + aec->xfBufBlockPos * PART_LEN1, |
| 1394 &xf_ptr[PART_LEN1], | 1388 &xf_ptr[PART_LEN1], |
| 1395 sizeof(float) * PART_LEN1); | 1389 sizeof(float) * PART_LEN1); |
| 1396 | 1390 |
| 1397 // Perform echo subtraction. | 1391 // Perform echo subtraction. |
| 1398 EchoSubtraction(aec, nearend_ptr); | 1392 EchoSubtraction(aec, |
| 1393 aec->num_partitions, | |
| 1394 aec->xfBufBlockPos, | |
| 1395 aec->metricsMode, | |
| 1396 aec->extended_filter_enabled, | |
| 1397 aec->normal_mu, | |
| 1398 aec->normal_error_threshold, | |
| 1399 aec->xfBuf, | |
| 1400 nearend_ptr, | |
| 1401 aec->xPow, | |
| 1402 aec->wfBuf, | |
| 1403 &aec->linoutlevel, | |
| 1404 echo_subtractor_output); | |
| 1405 | |
| 1406 RTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, echo_subtractor_output, PART_LEN); | |
| 1399 | 1407 |
| 1400 // Perform echo suppression. | 1408 // Perform echo suppression. |
| 1409 memcpy(aec->eBuf + PART_LEN, | |
| 1410 echo_subtractor_output, | |
| 1411 sizeof(float) * PART_LEN); | |
| 1401 EchoSuppression(aec, output, outputH_ptr); | 1412 EchoSuppression(aec, output, outputH_ptr); |
| 1402 | 1413 |
| 1403 if (aec->metricsMode == 1) { | 1414 if (aec->metricsMode == 1) { |
| 1404 // Update power levels and echo metrics | 1415 // Update power levels and echo metrics |
| 1405 UpdateLevel(&aec->farlevel, (float(*)[PART_LEN1])xf_ptr); | 1416 UpdateLevel(&aec->farlevel, (float(*)[PART_LEN1])xf_ptr); |
| 1406 UpdateLevel(&aec->nearlevel, df); | 1417 UpdateLevel(&aec->nearlevel, df); |
| 1407 UpdateMetrics(aec); | 1418 UpdateMetrics(aec); |
| 1408 } | 1419 } |
| 1409 | 1420 |
| 1410 // Store the output block. | 1421 // 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) { | 1744 void WebRtcAec_BufferFarendPartition(AecCore* aec, const float* farend) { |
| 1734 float fft[PART_LEN2]; | 1745 float fft[PART_LEN2]; |
| 1735 float xf[2][PART_LEN1]; | 1746 float xf[2][PART_LEN1]; |
| 1736 | 1747 |
| 1737 // Check if the buffer is full, and in that case flush the oldest data. | 1748 // Check if the buffer is full, and in that case flush the oldest data. |
| 1738 if (WebRtc_available_write(aec->far_buf) < 1) { | 1749 if (WebRtc_available_write(aec->far_buf) < 1) { |
| 1739 WebRtcAec_MoveFarReadPtr(aec, 1); | 1750 WebRtcAec_MoveFarReadPtr(aec, 1); |
| 1740 } | 1751 } |
| 1741 // Convert far-end partition to the frequency domain without windowing. | 1752 // Convert far-end partition to the frequency domain without windowing. |
| 1742 memcpy(fft, farend, sizeof(float) * PART_LEN2); | 1753 memcpy(fft, farend, sizeof(float) * PART_LEN2); |
| 1743 TimeToFrequency(fft, xf, 0); | 1754 Fft(fft, xf); |
| 1744 WebRtc_WriteBuffer(aec->far_buf, &xf[0][0], 1); | 1755 WebRtc_WriteBuffer(aec->far_buf, &xf[0][0], 1); |
| 1745 | 1756 |
| 1746 // Convert far-end partition to the frequency domain with windowing. | 1757 // Convert far-end partition to the frequency domain with windowing. |
| 1747 memcpy(fft, farend, sizeof(float) * PART_LEN2); | 1758 WindowData(fft, farend); |
| 1748 TimeToFrequency(fft, xf, 1); | 1759 Fft(fft, xf); |
| 1749 WebRtc_WriteBuffer(aec->far_buf_windowed, &xf[0][0], 1); | 1760 WebRtc_WriteBuffer(aec->far_buf_windowed, &xf[0][0], 1); |
| 1750 } | 1761 } |
| 1751 | 1762 |
| 1752 int WebRtcAec_MoveFarReadPtr(AecCore* aec, int elements) { | 1763 int WebRtcAec_MoveFarReadPtr(AecCore* aec, int elements) { |
| 1753 int elements_moved = MoveFarReadPtrWithoutSystemDelayUpdate(aec, elements); | 1764 int elements_moved = MoveFarReadPtrWithoutSystemDelayUpdate(aec, elements); |
| 1754 aec->system_delay -= elements_moved * PART_LEN; | 1765 aec->system_delay -= elements_moved * PART_LEN; |
| 1755 return elements_moved; | 1766 return elements_moved; |
| 1756 } | 1767 } |
| 1757 | 1768 |
| 1758 void WebRtcAec_ProcessFrames(AecCore* aec, | 1769 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) { | 1961 int WebRtcAec_extended_filter_enabled(AecCore* self) { |
| 1951 return self->extended_filter_enabled; | 1962 return self->extended_filter_enabled; |
| 1952 } | 1963 } |
| 1953 | 1964 |
| 1954 int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; } | 1965 int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; } |
| 1955 | 1966 |
| 1956 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { | 1967 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { |
| 1957 assert(delay >= 0); | 1968 assert(delay >= 0); |
| 1958 self->system_delay = delay; | 1969 self->system_delay = delay; |
| 1959 } | 1970 } |
| OLD | NEW |