Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(840)

Side by Side Diff: webrtc/modules/audio_processing/aec/aec_core.c

Issue 1456123003: Ducking fix #3: Removed the state as an input to the FilterAdaptation function (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@Aec_Code_Cleanup2_CL
Patch Set: Changes in response to reviewer comments Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698