| 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 14 matching lines...) Expand all Loading... |
| 25 #include <string.h> | 25 #include <string.h> |
| 26 | 26 |
| 27 #include "webrtc/common_audio/ring_buffer.h" | 27 #include "webrtc/common_audio/ring_buffer.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_internal.h" | 30 #include "webrtc/modules/audio_processing/aec/aec_core_internal.h" |
| 31 #include "webrtc/modules/audio_processing/aec/aec_rdft.h" | 31 #include "webrtc/modules/audio_processing/aec/aec_rdft.h" |
| 32 #include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" | 32 #include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" |
| 33 #include "webrtc/system_wrappers/interface/cpu_features_wrapper.h" | 33 #include "webrtc/system_wrappers/interface/cpu_features_wrapper.h" |
| 34 #include "webrtc/typedefs.h" | 34 #include "webrtc/typedefs.h" |
| 35 #include "webrtc/modules/audio_processing/logging/aec_logging.h" |
| 35 | 36 |
| 36 // Buffer size (samples) | 37 // Buffer size (samples) |
| 37 static const size_t kBufSizePartitions = 250; // 1 second of audio in 16 kHz. | 38 static const size_t kBufSizePartitions = 250; // 1 second of audio in 16 kHz. |
| 38 | 39 |
| 39 // Metrics | 40 // Metrics |
| 40 static const int subCountLen = 4; | 41 static const int subCountLen = 4; |
| 41 static const int countLen = 50; | 42 static const int countLen = 50; |
| 42 static const int kDelayMetricsAggregationWindow = 1250; // 5 seconds at 16 kHz. | 43 static const int kDelayMetricsAggregationWindow = 1250; // 5 seconds at 16 kHz. |
| 43 | 44 |
| 44 // Quantities to control H band scaling for SWB input | 45 // Quantities to control H band scaling for SWB input |
| (...skipping 1167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1212 WebRtc_ReadBuffer(aec->nearFrBuf, (void**)&nearend_ptr, nearend, PART_LEN); | 1213 WebRtc_ReadBuffer(aec->nearFrBuf, (void**)&nearend_ptr, nearend, PART_LEN); |
| 1213 memcpy(aec->dBuf + PART_LEN, nearend_ptr, sizeof(nearend)); | 1214 memcpy(aec->dBuf + PART_LEN, nearend_ptr, sizeof(nearend)); |
| 1214 | 1215 |
| 1215 // ---------- Ooura fft ---------- | 1216 // ---------- Ooura fft ---------- |
| 1216 | 1217 |
| 1217 #ifdef WEBRTC_AEC_DEBUG_DUMP | 1218 #ifdef WEBRTC_AEC_DEBUG_DUMP |
| 1218 { | 1219 { |
| 1219 float farend[PART_LEN]; | 1220 float farend[PART_LEN]; |
| 1220 float* farend_ptr = NULL; | 1221 float* farend_ptr = NULL; |
| 1221 WebRtc_ReadBuffer(aec->far_time_buf, (void**)&farend_ptr, farend, 1); | 1222 WebRtc_ReadBuffer(aec->far_time_buf, (void**)&farend_ptr, farend, 1); |
| 1222 rtc_WavWriteSamples(aec->farFile, farend_ptr, PART_LEN); | 1223 WEBRTC_AEC_DEBUG_WAV_WRITE(aec->farFile, farend_ptr, PART_LEN); |
| 1223 rtc_WavWriteSamples(aec->nearFile, nearend_ptr, PART_LEN); | 1224 WEBRTC_AEC_DEBUG_WAV_WRITE(aec->nearFile, nearend_ptr, PART_LEN); |
| 1224 } | 1225 } |
| 1225 #endif | 1226 #endif |
| 1226 | 1227 |
| 1227 // We should always have at least one element stored in |far_buf|. | 1228 // We should always have at least one element stored in |far_buf|. |
| 1228 assert(WebRtc_available_read(aec->far_buf) > 0); | 1229 assert(WebRtc_available_read(aec->far_buf) > 0); |
| 1229 WebRtc_ReadBuffer(aec->far_buf, (void**)&xf_ptr, &xf[0][0], 1); | 1230 WebRtc_ReadBuffer(aec->far_buf, (void**)&xf_ptr, &xf[0][0], 1); |
| 1230 | 1231 |
| 1231 // Near fft | 1232 // Near fft |
| 1232 memcpy(fft, aec->dBuf, sizeof(float) * PART_LEN2); | 1233 memcpy(fft, aec->dBuf, sizeof(float) * PART_LEN2); |
| 1233 TimeToFrequency(fft, df, 0); | 1234 TimeToFrequency(fft, df, 0); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1340 | 1341 |
| 1341 ef[1][0] = 0; | 1342 ef[1][0] = 0; |
| 1342 ef[1][PART_LEN] = 0; | 1343 ef[1][PART_LEN] = 0; |
| 1343 ef[0][0] = fft[0]; | 1344 ef[0][0] = fft[0]; |
| 1344 ef[0][PART_LEN] = fft[1]; | 1345 ef[0][PART_LEN] = fft[1]; |
| 1345 for (i = 1; i < PART_LEN; i++) { | 1346 for (i = 1; i < PART_LEN; i++) { |
| 1346 ef[0][i] = fft[2 * i]; | 1347 ef[0][i] = fft[2 * i]; |
| 1347 ef[1][i] = fft[2 * i + 1]; | 1348 ef[1][i] = fft[2 * i + 1]; |
| 1348 } | 1349 } |
| 1349 | 1350 |
| 1351 WEBRTC_AEC_DEBUG_RAW_WRITE(aec->e_fft_file, |
| 1352 &ef[0][0], |
| 1353 sizeof(ef[0][0]) * PART_LEN1 * 2); |
| 1354 |
| 1350 if (aec->metricsMode == 1) { | 1355 if (aec->metricsMode == 1) { |
| 1351 // Note that the first PART_LEN samples in fft (before transformation) are | 1356 // Note that the first PART_LEN samples in fft (before transformation) are |
| 1352 // zero. Hence, the scaling by two in UpdateLevel() should not be | 1357 // zero. Hence, the scaling by two in UpdateLevel() should not be |
| 1353 // performed. That scaling is taken care of in UpdateMetrics() instead. | 1358 // performed. That scaling is taken care of in UpdateMetrics() instead. |
| 1354 UpdateLevel(&aec->linoutlevel, ef); | 1359 UpdateLevel(&aec->linoutlevel, ef); |
| 1355 } | 1360 } |
| 1356 | 1361 |
| 1357 // Scale error signal inversely with far power. | 1362 // Scale error signal inversely with far power. |
| 1358 WebRtcAec_ScaleErrorSignal(aec, ef); | 1363 WebRtcAec_ScaleErrorSignal(aec, ef); |
| 1359 WebRtcAec_FilterAdaptation(aec, fft, ef); | 1364 WebRtcAec_FilterAdaptation(aec, fft, ef); |
| 1360 NonLinearProcessing(aec, output, outputH_ptr); | 1365 NonLinearProcessing(aec, output, outputH_ptr); |
| 1361 | 1366 |
| 1362 if (aec->metricsMode == 1) { | 1367 if (aec->metricsMode == 1) { |
| 1363 // Update power levels and echo metrics | 1368 // Update power levels and echo metrics |
| 1364 UpdateLevel(&aec->farlevel, (float(*)[PART_LEN1])xf_ptr); | 1369 UpdateLevel(&aec->farlevel, (float(*)[PART_LEN1])xf_ptr); |
| 1365 UpdateLevel(&aec->nearlevel, df); | 1370 UpdateLevel(&aec->nearlevel, df); |
| 1366 UpdateMetrics(aec); | 1371 UpdateMetrics(aec); |
| 1367 } | 1372 } |
| 1368 | 1373 |
| 1369 // Store the output block. | 1374 // Store the output block. |
| 1370 WebRtc_WriteBuffer(aec->outFrBuf, output, PART_LEN); | 1375 WebRtc_WriteBuffer(aec->outFrBuf, output, PART_LEN); |
| 1371 // For high bands | 1376 // For high bands |
| 1372 for (i = 0; i < aec->num_bands - 1; ++i) { | 1377 for (i = 0; i < aec->num_bands - 1; ++i) { |
| 1373 WebRtc_WriteBuffer(aec->outFrBufH[i], outputH[i], PART_LEN); | 1378 WebRtc_WriteBuffer(aec->outFrBufH[i], outputH[i], PART_LEN); |
| 1374 } | 1379 } |
| 1375 | 1380 |
| 1376 #ifdef WEBRTC_AEC_DEBUG_DUMP | 1381 WEBRTC_AEC_DEBUG_WAV_WRITE(aec->outLinearFile, e, PART_LEN); |
| 1377 rtc_WavWriteSamples(aec->outLinearFile, e, PART_LEN); | 1382 WEBRTC_AEC_DEBUG_WAV_WRITE(aec->outFile, output, PART_LEN); |
| 1378 rtc_WavWriteSamples(aec->outFile, output, PART_LEN); | |
| 1379 #endif | |
| 1380 } | 1383 } |
| 1381 | 1384 |
| 1382 AecCore* WebRtcAec_CreateAec() { | 1385 AecCore* WebRtcAec_CreateAec() { |
| 1383 int i; | 1386 int i; |
| 1384 AecCore* aec = malloc(sizeof(AecCore)); | 1387 AecCore* aec = malloc(sizeof(AecCore)); |
| 1385 if (!aec) { | 1388 if (!aec) { |
| 1386 return NULL; | 1389 return NULL; |
| 1387 } | 1390 } |
| 1388 | 1391 |
| 1389 aec->nearFrBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(float)); | 1392 aec->nearFrBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(float)); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1504 | 1507 |
| 1505 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { | 1508 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { |
| 1506 WebRtc_FreeBuffer(aec->nearFrBufH[i]); | 1509 WebRtc_FreeBuffer(aec->nearFrBufH[i]); |
| 1507 WebRtc_FreeBuffer(aec->outFrBufH[i]); | 1510 WebRtc_FreeBuffer(aec->outFrBufH[i]); |
| 1508 } | 1511 } |
| 1509 | 1512 |
| 1510 WebRtc_FreeBuffer(aec->far_buf); | 1513 WebRtc_FreeBuffer(aec->far_buf); |
| 1511 WebRtc_FreeBuffer(aec->far_buf_windowed); | 1514 WebRtc_FreeBuffer(aec->far_buf_windowed); |
| 1512 #ifdef WEBRTC_AEC_DEBUG_DUMP | 1515 #ifdef WEBRTC_AEC_DEBUG_DUMP |
| 1513 WebRtc_FreeBuffer(aec->far_time_buf); | 1516 WebRtc_FreeBuffer(aec->far_time_buf); |
| 1514 rtc_WavClose(aec->farFile); | |
| 1515 rtc_WavClose(aec->nearFile); | |
| 1516 rtc_WavClose(aec->outFile); | |
| 1517 rtc_WavClose(aec->outLinearFile); | |
| 1518 #endif | 1517 #endif |
| 1518 WEBRTC_AEC_DEBUG_WAV_CLOSE(aec->farFile); |
| 1519 WEBRTC_AEC_DEBUG_WAV_CLOSE(aec->nearFile); |
| 1520 WEBRTC_AEC_DEBUG_WAV_CLOSE(aec->outFile); |
| 1521 WEBRTC_AEC_DEBUG_WAV_CLOSE(aec->outLinearFile); |
| 1522 WEBRTC_AEC_DEBUG_RAW_CLOSE(aec->e_fft_file); |
| 1523 |
| 1519 WebRtc_FreeDelayEstimator(aec->delay_estimator); | 1524 WebRtc_FreeDelayEstimator(aec->delay_estimator); |
| 1520 WebRtc_FreeDelayEstimatorFarend(aec->delay_estimator_farend); | 1525 WebRtc_FreeDelayEstimatorFarend(aec->delay_estimator_farend); |
| 1521 | 1526 |
| 1522 free(aec); | 1527 free(aec); |
| 1523 } | 1528 } |
| 1524 | 1529 |
| 1525 #ifdef WEBRTC_AEC_DEBUG_DUMP | |
| 1526 // Open a new Wav file for writing. If it was already open with a different | |
| 1527 // sample frequency, close it first. | |
| 1528 static void ReopenWav(rtc_WavWriter** wav_file, | |
| 1529 const char* name, | |
| 1530 int seq1, | |
| 1531 int seq2, | |
| 1532 int sample_rate) { | |
| 1533 int written ATTRIBUTE_UNUSED; | |
| 1534 char filename[64]; | |
| 1535 if (*wav_file) { | |
| 1536 if (rtc_WavSampleRate(*wav_file) == sample_rate) | |
| 1537 return; | |
| 1538 rtc_WavClose(*wav_file); | |
| 1539 } | |
| 1540 written = snprintf(filename, sizeof(filename), "%s%d-%d.wav", | |
| 1541 name, seq1, seq2); | |
| 1542 assert(written >= 0); // no output error | |
| 1543 assert((size_t)written < sizeof(filename)); // buffer was large enough | |
| 1544 *wav_file = rtc_WavOpen(filename, sample_rate, 1); | |
| 1545 } | |
| 1546 #endif // WEBRTC_AEC_DEBUG_DUMP | |
| 1547 | |
| 1548 int WebRtcAec_InitAec(AecCore* aec, int sampFreq) { | 1530 int WebRtcAec_InitAec(AecCore* aec, int sampFreq) { |
| 1549 int i; | 1531 int i; |
| 1550 | 1532 |
| 1551 aec->sampFreq = sampFreq; | 1533 aec->sampFreq = sampFreq; |
| 1552 | 1534 |
| 1553 if (sampFreq == 8000) { | 1535 if (sampFreq == 8000) { |
| 1554 aec->normal_mu = 0.6f; | 1536 aec->normal_mu = 0.6f; |
| 1555 aec->normal_error_threshold = 2e-6f; | 1537 aec->normal_error_threshold = 2e-6f; |
| 1556 aec->num_bands = 1; | 1538 aec->num_bands = 1; |
| 1557 } else { | 1539 } else { |
| 1558 aec->normal_mu = 0.5f; | 1540 aec->normal_mu = 0.5f; |
| 1559 aec->normal_error_threshold = 1.5e-6f; | 1541 aec->normal_error_threshold = 1.5e-6f; |
| 1560 aec->num_bands = sampFreq / 16000; | 1542 aec->num_bands = sampFreq / 16000; |
| 1561 } | 1543 } |
| 1562 | 1544 |
| 1563 WebRtc_InitBuffer(aec->nearFrBuf); | 1545 WebRtc_InitBuffer(aec->nearFrBuf); |
| 1564 WebRtc_InitBuffer(aec->outFrBuf); | 1546 WebRtc_InitBuffer(aec->outFrBuf); |
| 1565 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { | 1547 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { |
| 1566 WebRtc_InitBuffer(aec->nearFrBufH[i]); | 1548 WebRtc_InitBuffer(aec->nearFrBufH[i]); |
| 1567 WebRtc_InitBuffer(aec->outFrBufH[i]); | 1549 WebRtc_InitBuffer(aec->outFrBufH[i]); |
| 1568 } | 1550 } |
| 1569 | 1551 |
| 1570 // Initialize far-end buffers. | 1552 // Initialize far-end buffers. |
| 1571 WebRtc_InitBuffer(aec->far_buf); | 1553 WebRtc_InitBuffer(aec->far_buf); |
| 1572 WebRtc_InitBuffer(aec->far_buf_windowed); | 1554 WebRtc_InitBuffer(aec->far_buf_windowed); |
| 1573 #ifdef WEBRTC_AEC_DEBUG_DUMP | 1555 #ifdef WEBRTC_AEC_DEBUG_DUMP |
| 1574 WebRtc_InitBuffer(aec->far_time_buf); | 1556 WebRtc_InitBuffer(aec->far_time_buf); |
| 1575 { | 1557 { |
| 1576 int process_rate = sampFreq > 16000 ? 16000 : sampFreq; | 1558 int process_rate = sampFreq > 16000 ? 16000 : sampFreq; |
| 1577 ReopenWav(&aec->farFile, "aec_far", | 1559 WEBRTC_AEC_DEBUG_WAV_REOPEN(&aec->farFile, "aec_far", |
| 1578 aec->instance_index, aec->debug_dump_count, process_rate); | 1560 aec->instance_index, aec->debug_dump_count, process_rate); |
| 1579 ReopenWav(&aec->nearFile, "aec_near", | 1561 WEBRTC_AEC_DEBUG_WAV_REOPEN(&aec->nearFile, "aec_near", |
| 1580 aec->instance_index, aec->debug_dump_count, process_rate); | 1562 aec->instance_index, aec->debug_dump_count, process_rate); |
| 1581 ReopenWav(&aec->outFile, "aec_out", | 1563 WEBRTC_AEC_DEBUG_WAV_REOPEN(&aec->outFile, "aec_out", |
| 1582 aec->instance_index, aec->debug_dump_count, process_rate); | 1564 aec->instance_index, aec->debug_dump_count, process_rate); |
| 1583 ReopenWav(&aec->outLinearFile, "aec_out_linear", | 1565 WEBRTC_AEC_DEBUG_WAV_REOPEN(&aec->outLinearFile, "aec_out_linear", |
| 1584 aec->instance_index, aec->debug_dump_count, process_rate); | 1566 aec->instance_index, aec->debug_dump_count, process_rate); |
| 1585 } | 1567 } |
| 1568 |
| 1569 WEBRTC_AEC_DEBUG_RAW_OPEN(&aec->e_fft_file, |
| 1570 "aec_eFFT", |
| 1571 aec->debug_dump_count); |
| 1572 |
| 1586 ++aec->debug_dump_count; | 1573 ++aec->debug_dump_count; |
| 1587 #endif | 1574 #endif |
| 1588 aec->system_delay = 0; | 1575 aec->system_delay = 0; |
| 1589 | 1576 |
| 1590 if (WebRtc_InitDelayEstimatorFarend(aec->delay_estimator_farend) != 0) { | 1577 if (WebRtc_InitDelayEstimatorFarend(aec->delay_estimator_farend) != 0) { |
| 1591 return -1; | 1578 return -1; |
| 1592 } | 1579 } |
| 1593 if (WebRtc_InitDelayEstimator(aec->delay_estimator) != 0) { | 1580 if (WebRtc_InitDelayEstimator(aec->delay_estimator) != 0) { |
| 1594 return -1; | 1581 return -1; |
| 1595 } | 1582 } |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1924 int WebRtcAec_extended_filter_enabled(AecCore* self) { | 1911 int WebRtcAec_extended_filter_enabled(AecCore* self) { |
| 1925 return self->extended_filter_enabled; | 1912 return self->extended_filter_enabled; |
| 1926 } | 1913 } |
| 1927 | 1914 |
| 1928 int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; } | 1915 int WebRtcAec_system_delay(AecCore* self) { return self->system_delay; } |
| 1929 | 1916 |
| 1930 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { | 1917 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { |
| 1931 assert(delay >= 0); | 1918 assert(delay >= 0); |
| 1932 self->system_delay = delay; | 1919 self->system_delay = delay; |
| 1933 } | 1920 } |
| OLD | NEW |