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 1090 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 } | 1101 } |
1102 | 1102 |
1103 // Apply the overdrive. | 1103 // Apply the overdrive. |
1104 WebRtcAec_Overdrive(aec->overdrive_scaling, hNlFb, hNl); | 1104 WebRtcAec_Overdrive(aec->overdrive_scaling, hNlFb, hNl); |
1105 } | 1105 } |
1106 | 1106 |
1107 static void EchoSuppression(AecCore* aec, | 1107 static void EchoSuppression(AecCore* aec, |
1108 float* nearend_extended_block_lowest_band, | 1108 float* nearend_extended_block_lowest_band, |
1109 float farend[PART_LEN2], | 1109 float farend[PART_LEN2], |
1110 float* echo_subtractor_output, | 1110 float* echo_subtractor_output, |
1111 float* output, | 1111 float output[NUM_HIGH_BANDS_MAX + 1][PART_LEN]) { |
1112 float* const* outputH) { | |
1113 float efw[2][PART_LEN1]; | 1112 float efw[2][PART_LEN1]; |
1114 float xfw[2][PART_LEN1]; | 1113 float xfw[2][PART_LEN1]; |
1115 float dfw[2][PART_LEN1]; | 1114 float dfw[2][PART_LEN1]; |
1116 float comfortNoiseHband[2][PART_LEN1]; | 1115 float comfortNoiseHband[2][PART_LEN1]; |
1117 float fft[PART_LEN2]; | 1116 float fft[PART_LEN2]; |
1118 float nlpGainHband; | 1117 float nlpGainHband; |
1119 int i; | 1118 int i; |
1120 size_t j; | 1119 size_t j; |
1121 | 1120 |
1122 // Coherence and non-linear filter | 1121 // Coherence and non-linear filter |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1186 | 1185 |
1187 // Add comfort noise. | 1186 // Add comfort noise. |
1188 ComfortNoise(aec->num_bands > 1, &aec->seed, efw, comfortNoiseHband, | 1187 ComfortNoise(aec->num_bands > 1, &aec->seed, efw, comfortNoiseHband, |
1189 aec->noisePow, hNl); | 1188 aec->noisePow, hNl); |
1190 | 1189 |
1191 // Inverse error fft. | 1190 // Inverse error fft. |
1192 ScaledInverseFft(efw, fft, 2.0f, 1); | 1191 ScaledInverseFft(efw, fft, 2.0f, 1); |
1193 | 1192 |
1194 // Overlap and add to obtain output. | 1193 // Overlap and add to obtain output. |
1195 for (i = 0; i < PART_LEN; i++) { | 1194 for (i = 0; i < PART_LEN; i++) { |
1196 output[i] = (fft[i] * WebRtcAec_sqrtHanning[i] + | 1195 output[0][i] = (fft[i] * WebRtcAec_sqrtHanning[i] + |
1197 aec->outBuf[i] * WebRtcAec_sqrtHanning[PART_LEN - i]); | 1196 aec->outBuf[i] * WebRtcAec_sqrtHanning[PART_LEN - i]); |
1198 | 1197 |
1199 // Saturate output to keep it in the allowed range. | 1198 // Saturate output to keep it in the allowed range. |
1200 output[i] = | 1199 output[0][i] = WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, output[0][i], |
1201 WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, output[i], WEBRTC_SPL_WORD16_MIN); | 1200 WEBRTC_SPL_WORD16_MIN); |
1202 } | 1201 } |
1203 memcpy(aec->outBuf, &fft[PART_LEN], PART_LEN * sizeof(aec->outBuf[0])); | 1202 memcpy(aec->outBuf, &fft[PART_LEN], PART_LEN * sizeof(aec->outBuf[0])); |
1204 | 1203 |
1205 // For H band | 1204 // For H band |
1206 if (aec->num_bands > 1) { | 1205 if (aec->num_bands > 1) { |
1207 // H band gain | 1206 // H band gain |
1208 // average nlp over low band: average over second half of freq spectrum | 1207 // average nlp over low band: average over second half of freq spectrum |
1209 // (4->8khz) | 1208 // (4->8khz) |
1210 GetHighbandGain(hNl, &nlpGainHband); | 1209 GetHighbandGain(hNl, &nlpGainHband); |
1211 | 1210 |
1212 // Inverse comfort_noise | 1211 // Inverse comfort_noise |
1213 ScaledInverseFft(comfortNoiseHband, fft, 2.0f, 0); | 1212 ScaledInverseFft(comfortNoiseHband, fft, 2.0f, 0); |
1214 | 1213 |
1215 // compute gain factor | 1214 // compute gain factor |
1216 for (j = 0; j < aec->num_bands - 1; ++j) { | 1215 for (j = 1; j < aec->num_bands; ++j) { |
1217 for (i = 0; i < PART_LEN; i++) { | 1216 for (i = 0; i < PART_LEN; i++) { |
1218 outputH[j][i] = aec->previous_nearend_block[j + 1][i] * nlpGainHband; | 1217 output[j][i] = aec->previous_nearend_block[j][i] * nlpGainHband; |
1219 } | 1218 } |
1220 } | 1219 } |
1221 | 1220 |
1222 // Add some comfort noise where Hband is attenuated. | 1221 // Add some comfort noise where Hband is attenuated. |
1223 for (i = 0; i < PART_LEN; i++) { | 1222 for (i = 0; i < PART_LEN; i++) { |
1224 outputH[0][i] += cnScaleHband * fft[i]; | 1223 output[1][i] += cnScaleHband * fft[i]; |
1225 } | 1224 } |
1226 | 1225 |
1227 // Saturate output to keep it in the allowed range. | 1226 // Saturate output to keep it in the allowed range. |
1228 for (j = 0; j < aec->num_bands - 1; ++j) { | 1227 for (j = 1; j < aec->num_bands; ++j) { |
1229 for (i = 0; i < PART_LEN; i++) { | 1228 for (i = 0; i < PART_LEN; i++) { |
1230 outputH[j][i] = WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, outputH[j][i], | 1229 output[j][i] = WEBRTC_SPL_SAT(WEBRTC_SPL_WORD16_MAX, output[j][i], |
1231 WEBRTC_SPL_WORD16_MIN); | 1230 WEBRTC_SPL_WORD16_MIN); |
1232 } | 1231 } |
1233 } | 1232 } |
1234 } | 1233 } |
1235 | 1234 |
1236 // Copy the current block to the old position. | 1235 // Copy the current block to the old position. |
1237 memcpy(aec->eBuf, aec->eBuf + PART_LEN, sizeof(float) * PART_LEN); | 1236 memcpy(aec->eBuf, aec->eBuf + PART_LEN, sizeof(float) * PART_LEN); |
1238 | 1237 |
1239 memmove(aec->xfwBuf + PART_LEN1, aec->xfwBuf, | 1238 memmove(aec->xfwBuf + PART_LEN1, aec->xfwBuf, |
1240 sizeof(aec->xfwBuf) - sizeof(complex_t) * PART_LEN1); | 1239 sizeof(aec->xfwBuf) - sizeof(complex_t) * PART_LEN1); |
1241 } | 1240 } |
1242 | 1241 |
1243 static void ProcessBlock(AecCore* aec, | 1242 static void ProcessBlock(AecCore* aec, |
1244 float nearend_block[NUM_HIGH_BANDS_MAX + 1] | 1243 float nearend_block[NUM_HIGH_BANDS_MAX + 1][PART_LEN], |
1245 [PART_LEN]) { | 1244 float output_block[NUM_HIGH_BANDS_MAX + 1][PART_LEN]) { |
1246 size_t i; | 1245 size_t i; |
1247 | 1246 |
1248 float fft[PART_LEN2]; | 1247 float fft[PART_LEN2]; |
1249 float nearend_extended_block_lowest_band[PART_LEN2]; | 1248 float nearend_extended_block_lowest_band[PART_LEN2]; |
1250 float x_fft[2][PART_LEN1]; | 1249 float x_fft[2][PART_LEN1]; |
1251 float df[2][PART_LEN1]; | 1250 float df[2][PART_LEN1]; |
1252 float far_spectrum = 0.0f; | 1251 float far_spectrum = 0.0f; |
1253 float near_spectrum = 0.0f; | 1252 float near_spectrum = 0.0f; |
1254 float abs_far_spectrum[PART_LEN1]; | 1253 float abs_far_spectrum[PART_LEN1]; |
1255 float abs_near_spectrum[PART_LEN1]; | 1254 float abs_near_spectrum[PART_LEN1]; |
1256 | 1255 |
1257 const float gPow[2] = {0.9f, 0.1f}; | 1256 const float gPow[2] = {0.9f, 0.1f}; |
1258 | 1257 |
1259 // Noise estimate constants. | 1258 // Noise estimate constants. |
1260 const int noiseInitBlocks = 500 * aec->mult; | 1259 const int noiseInitBlocks = 500 * aec->mult; |
1261 const float step = 0.1f; | 1260 const float step = 0.1f; |
1262 const float ramp = 1.0002f; | 1261 const float ramp = 1.0002f; |
1263 const float gInitNoise[2] = {0.999f, 0.001f}; | 1262 const float gInitNoise[2] = {0.999f, 0.001f}; |
1264 | 1263 |
1265 float farend[PART_LEN2]; | 1264 float farend[PART_LEN2]; |
1266 float* farend_ptr = NULL; | 1265 float* farend_ptr = NULL; |
1267 float echo_subtractor_output[PART_LEN]; | 1266 float echo_subtractor_output[PART_LEN]; |
1268 float output[PART_LEN]; | |
1269 float outputH[NUM_HIGH_BANDS_MAX][PART_LEN]; | |
1270 float* outputH_ptr[NUM_HIGH_BANDS_MAX]; | |
1271 float* x_fft_ptr = NULL; | 1267 float* x_fft_ptr = NULL; |
1272 | 1268 |
1273 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { | |
1274 outputH_ptr[i] = outputH[i]; | |
1275 } | |
1276 | |
1277 // We should always have at least one element stored in |far_buf|. | 1269 // We should always have at least one element stored in |far_buf|. |
1278 assert(WebRtc_available_read(aec->far_time_buf) > 0); | 1270 assert(WebRtc_available_read(aec->far_time_buf) > 0); |
1279 WebRtc_ReadBuffer(aec->far_time_buf, reinterpret_cast<void**>(&farend_ptr), | 1271 WebRtc_ReadBuffer(aec->far_time_buf, reinterpret_cast<void**>(&farend_ptr), |
1280 farend, 1); | 1272 farend, 1); |
1281 | 1273 |
1282 aec->data_dumper->DumpWav("aec_far", PART_LEN, &farend_ptr[PART_LEN], | 1274 aec->data_dumper->DumpWav("aec_far", PART_LEN, &farend_ptr[PART_LEN], |
1283 std::min(aec->sampFreq, 16000), 1); | 1275 std::min(aec->sampFreq, 16000), 1); |
1284 aec->data_dumper->DumpWav("aec_near", PART_LEN, &nearend_block[0][0], | 1276 aec->data_dumper->DumpWav("aec_near", PART_LEN, &nearend_block[0][0], |
1285 std::min(aec->sampFreq, 16000), 1); | 1277 std::min(aec->sampFreq, 16000), 1); |
1286 | 1278 |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 aec->data_dumper->DumpWav("aec_out_linear", PART_LEN, echo_subtractor_output, | 1388 aec->data_dumper->DumpWav("aec_out_linear", PART_LEN, echo_subtractor_output, |
1397 std::min(aec->sampFreq, 16000), 1); | 1389 std::min(aec->sampFreq, 16000), 1); |
1398 | 1390 |
1399 if (aec->metricsMode == 1) { | 1391 if (aec->metricsMode == 1) { |
1400 UpdateLevel(&aec->linoutlevel, | 1392 UpdateLevel(&aec->linoutlevel, |
1401 CalculatePower(echo_subtractor_output, PART_LEN)); | 1393 CalculatePower(echo_subtractor_output, PART_LEN)); |
1402 } | 1394 } |
1403 | 1395 |
1404 // Perform echo suppression. | 1396 // Perform echo suppression. |
1405 EchoSuppression(aec, nearend_extended_block_lowest_band, farend_ptr, | 1397 EchoSuppression(aec, nearend_extended_block_lowest_band, farend_ptr, |
1406 echo_subtractor_output, output, outputH_ptr); | 1398 echo_subtractor_output, output_block); |
1407 | 1399 |
1408 if (aec->metricsMode == 1) { | 1400 if (aec->metricsMode == 1) { |
1409 UpdateLevel(&aec->nlpoutlevel, CalculatePower(output, PART_LEN)); | 1401 UpdateLevel(&aec->nlpoutlevel, |
| 1402 CalculatePower(&output_block[0][0], PART_LEN)); |
1410 UpdateMetrics(aec); | 1403 UpdateMetrics(aec); |
1411 } | 1404 } |
1412 | 1405 |
1413 // Store the nearend signal until the next frame. | 1406 // Store the nearend signal until the next frame. |
1414 for (i = 0; i < aec->num_bands; ++i) { | 1407 for (i = 0; i < aec->num_bands; ++i) { |
1415 memcpy(&aec->previous_nearend_block[i][0], &nearend_block[i][0], | 1408 memcpy(&aec->previous_nearend_block[i][0], &nearend_block[i][0], |
1416 sizeof(float) * PART_LEN); | 1409 sizeof(float) * PART_LEN); |
1417 } | 1410 } |
1418 | 1411 |
1419 // Store the output block. | 1412 aec->data_dumper->DumpWav("aec_out", PART_LEN, &output_block[0][0], |
1420 WebRtc_WriteBuffer(aec->outFrBuf, output, PART_LEN); | |
1421 // For high bands | |
1422 for (i = 0; i < aec->num_bands - 1; ++i) { | |
1423 WebRtc_WriteBuffer(aec->outFrBufH[i], outputH[i], PART_LEN); | |
1424 } | |
1425 | |
1426 aec->data_dumper->DumpWav("aec_out", PART_LEN, output, | |
1427 std::min(aec->sampFreq, 16000), 1); | 1413 std::min(aec->sampFreq, 16000), 1); |
1428 } | 1414 } |
1429 | 1415 |
1430 AecCore* WebRtcAec_CreateAec(int instance_count) { | 1416 AecCore* WebRtcAec_CreateAec(int instance_count) { |
1431 int i; | |
1432 AecCore* aec = new AecCore(instance_count); | 1417 AecCore* aec = new AecCore(instance_count); |
1433 | 1418 |
1434 if (!aec) { | 1419 if (!aec) { |
1435 return NULL; | 1420 return NULL; |
1436 } | 1421 } |
1437 aec->nearend_buffer_size = 0; | 1422 aec->nearend_buffer_size = 0; |
1438 memset(&aec->nearend_buffer[0], 0, sizeof(aec->nearend_buffer)); | 1423 memset(&aec->nearend_buffer[0], 0, sizeof(aec->nearend_buffer)); |
1439 | 1424 // Start the output buffer with zeros to be able to produce |
1440 aec->outFrBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(float)); | 1425 // a full output frame in the first frame. |
1441 if (!aec->outFrBuf) { | 1426 aec->output_buffer_size = PART_LEN - (FRAME_LEN - PART_LEN); |
1442 WebRtcAec_FreeAec(aec); | 1427 memset(&aec->output_buffer[0], 0, sizeof(aec->output_buffer)); |
1443 return NULL; | |
1444 } | |
1445 | |
1446 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { | |
1447 aec->outFrBufH[i] = | |
1448 WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(float)); | |
1449 if (!aec->outFrBufH[i]) { | |
1450 WebRtcAec_FreeAec(aec); | |
1451 return NULL; | |
1452 } | |
1453 } | |
1454 | 1428 |
1455 // Create far-end buffers. | 1429 // Create far-end buffers. |
1456 // For bit exactness with legacy code, each element in |far_time_buf| is | 1430 // For bit exactness with legacy code, each element in |far_time_buf| is |
1457 // supposed to contain |PART_LEN2| samples with an overlap of |PART_LEN| | 1431 // supposed to contain |PART_LEN2| samples with an overlap of |PART_LEN| |
1458 // samples from the last frame. | 1432 // samples from the last frame. |
1459 // TODO(minyue): reduce |far_time_buf| to non-overlapped |PART_LEN| samples. | 1433 // TODO(minyue): reduce |far_time_buf| to non-overlapped |PART_LEN| samples. |
1460 aec->far_time_buf = | 1434 aec->far_time_buf = |
1461 WebRtc_CreateBuffer(kBufSizePartitions, sizeof(float) * PART_LEN2); | 1435 WebRtc_CreateBuffer(kBufSizePartitions, sizeof(float) * PART_LEN2); |
1462 if (!aec->far_time_buf) { | 1436 if (!aec->far_time_buf) { |
1463 WebRtcAec_FreeAec(aec); | 1437 WebRtcAec_FreeAec(aec); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1516 #if defined(WEBRTC_HAS_NEON) | 1490 #if defined(WEBRTC_HAS_NEON) |
1517 WebRtcAec_InitAec_neon(); | 1491 WebRtcAec_InitAec_neon(); |
1518 #endif | 1492 #endif |
1519 | 1493 |
1520 aec_rdft_init(); | 1494 aec_rdft_init(); |
1521 | 1495 |
1522 return aec; | 1496 return aec; |
1523 } | 1497 } |
1524 | 1498 |
1525 void WebRtcAec_FreeAec(AecCore* aec) { | 1499 void WebRtcAec_FreeAec(AecCore* aec) { |
1526 int i; | |
1527 if (aec == NULL) { | 1500 if (aec == NULL) { |
1528 return; | 1501 return; |
1529 } | 1502 } |
1530 | 1503 |
1531 WebRtc_FreeBuffer(aec->outFrBuf); | |
1532 | |
1533 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { | |
1534 WebRtc_FreeBuffer(aec->outFrBufH[i]); | |
1535 } | |
1536 | |
1537 WebRtc_FreeBuffer(aec->far_time_buf); | 1504 WebRtc_FreeBuffer(aec->far_time_buf); |
1538 | 1505 |
1539 WebRtc_FreeDelayEstimator(aec->delay_estimator); | 1506 WebRtc_FreeDelayEstimator(aec->delay_estimator); |
1540 WebRtc_FreeDelayEstimatorFarend(aec->delay_estimator_farend); | 1507 WebRtc_FreeDelayEstimatorFarend(aec->delay_estimator_farend); |
1541 | 1508 |
1542 delete aec; | 1509 delete aec; |
1543 } | 1510 } |
1544 | 1511 |
1545 static void SetAdaptiveFilterStepSize(AecCore* aec) { | 1512 static void SetAdaptiveFilterStepSize(AecCore* aec) { |
1546 // Extended filter adaptation parameter. | 1513 // Extended filter adaptation parameter. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1586 | 1553 |
1587 SetAdaptiveFilterStepSize(aec); | 1554 SetAdaptiveFilterStepSize(aec); |
1588 SetErrorThreshold(aec); | 1555 SetErrorThreshold(aec); |
1589 | 1556 |
1590 if (sampFreq == 8000) { | 1557 if (sampFreq == 8000) { |
1591 aec->num_bands = 1; | 1558 aec->num_bands = 1; |
1592 } else { | 1559 } else { |
1593 aec->num_bands = (size_t)(sampFreq / 16000); | 1560 aec->num_bands = (size_t)(sampFreq / 16000); |
1594 } | 1561 } |
1595 | 1562 |
| 1563 // Start the output buffer with zeros to be able to produce |
| 1564 // a full output frame in the first frame. |
| 1565 aec->output_buffer_size = PART_LEN - (FRAME_LEN - PART_LEN); |
| 1566 memset(&aec->output_buffer[0], 0, sizeof(aec->output_buffer)); |
1596 aec->nearend_buffer_size = 0; | 1567 aec->nearend_buffer_size = 0; |
1597 memset(&aec->nearend_buffer[0], 0, sizeof(aec->nearend_buffer)); | 1568 memset(&aec->nearend_buffer[0], 0, sizeof(aec->nearend_buffer)); |
1598 | 1569 |
1599 WebRtc_InitBuffer(aec->outFrBuf); | |
1600 for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) { | |
1601 WebRtc_InitBuffer(aec->outFrBufH[i]); | |
1602 } | |
1603 | |
1604 // Initialize far-end buffers. | 1570 // Initialize far-end buffers. |
1605 WebRtc_InitBuffer(aec->far_time_buf); | 1571 WebRtc_InitBuffer(aec->far_time_buf); |
1606 | 1572 |
1607 aec->system_delay = 0; | 1573 aec->system_delay = 0; |
1608 | 1574 |
1609 if (WebRtc_InitDelayEstimatorFarend(aec->delay_estimator_farend) != 0) { | 1575 if (WebRtc_InitDelayEstimatorFarend(aec->delay_estimator_farend) != 0) { |
1610 return -1; | 1576 return -1; |
1611 } | 1577 } |
1612 if (WebRtc_InitDelayEstimator(aec->delay_estimator) != 0) { | 1578 if (WebRtc_InitDelayEstimator(aec->delay_estimator) != 0) { |
1613 return -1; | 1579 return -1; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1733 | 1699 |
1734 WebRtc_WriteBuffer(aec->far_time_buf, farend, 1); | 1700 WebRtc_WriteBuffer(aec->far_time_buf, farend, 1); |
1735 } | 1701 } |
1736 | 1702 |
1737 int WebRtcAec_MoveFarReadPtr(AecCore* aec, int elements) { | 1703 int WebRtcAec_MoveFarReadPtr(AecCore* aec, int elements) { |
1738 int elements_moved = WebRtc_MoveReadPtr(aec->far_time_buf, elements); | 1704 int elements_moved = WebRtc_MoveReadPtr(aec->far_time_buf, elements); |
1739 aec->system_delay -= elements_moved * PART_LEN; | 1705 aec->system_delay -= elements_moved * PART_LEN; |
1740 return elements_moved; | 1706 return elements_moved; |
1741 } | 1707 } |
1742 | 1708 |
| 1709 void FormNearendBlock( |
| 1710 size_t nearend_start_index, |
| 1711 size_t num_bands, |
| 1712 const float* const* nearend_frame, |
| 1713 size_t num_samples_from_nearend_frame, |
| 1714 const float nearend_buffer[NUM_HIGH_BANDS_MAX + 1] |
| 1715 [PART_LEN - (FRAME_LEN - PART_LEN)], |
| 1716 float nearend_block[NUM_HIGH_BANDS_MAX + 1][PART_LEN]) { |
| 1717 RTC_DCHECK_LE(num_samples_from_nearend_frame, static_cast<size_t>(PART_LEN)); |
| 1718 const int num_samples_from_buffer = PART_LEN - num_samples_from_nearend_frame; |
| 1719 |
| 1720 if (num_samples_from_buffer > 0) { |
| 1721 for (size_t i = 0; i < num_bands; ++i) { |
| 1722 memcpy(&nearend_block[i][0], &nearend_buffer[i][0], |
| 1723 num_samples_from_buffer * sizeof(float)); |
| 1724 } |
| 1725 } |
| 1726 |
| 1727 for (size_t i = 0; i < num_bands; ++i) { |
| 1728 memcpy(&nearend_block[i][num_samples_from_buffer], |
| 1729 &nearend_frame[i][nearend_start_index], |
| 1730 num_samples_from_nearend_frame * sizeof(float)); |
| 1731 } |
| 1732 } |
| 1733 |
| 1734 void BufferNearendFrame( |
| 1735 size_t nearend_start_index, |
| 1736 size_t num_bands, |
| 1737 const float* const* nearend_frame, |
| 1738 size_t num_samples_to_buffer, |
| 1739 float nearend_buffer[NUM_HIGH_BANDS_MAX + 1] |
| 1740 [PART_LEN - (FRAME_LEN - PART_LEN)]) { |
| 1741 for (size_t i = 0; i < num_bands; ++i) { |
| 1742 memcpy( |
| 1743 &nearend_buffer[i][0], |
| 1744 &nearend_frame[i] |
| 1745 [nearend_start_index + FRAME_LEN - num_samples_to_buffer], |
| 1746 num_samples_to_buffer * sizeof(float)); |
| 1747 } |
| 1748 } |
| 1749 |
| 1750 void BufferOutputBlock(size_t num_bands, |
| 1751 const float output_block[NUM_HIGH_BANDS_MAX + 1] |
| 1752 [PART_LEN], |
| 1753 size_t* output_buffer_size, |
| 1754 float output_buffer[NUM_HIGH_BANDS_MAX + 1] |
| 1755 [2 * PART_LEN]) { |
| 1756 for (size_t i = 0; i < num_bands; ++i) { |
| 1757 memcpy(&output_buffer[i][*output_buffer_size], &output_block[i][0], |
| 1758 PART_LEN * sizeof(float)); |
| 1759 } |
| 1760 (*output_buffer_size) += PART_LEN; |
| 1761 } |
| 1762 |
| 1763 void FormOutputFrame(size_t output_start_index, |
| 1764 size_t num_bands, |
| 1765 size_t* output_buffer_size, |
| 1766 float output_buffer[NUM_HIGH_BANDS_MAX + 1][2 * PART_LEN], |
| 1767 float* const* output_frame) { |
| 1768 RTC_DCHECK_LE(static_cast<size_t>(FRAME_LEN), *output_buffer_size); |
| 1769 for (size_t i = 0; i < num_bands; ++i) { |
| 1770 memcpy(&output_frame[i][output_start_index], &output_buffer[i][0], |
| 1771 FRAME_LEN * sizeof(float)); |
| 1772 } |
| 1773 (*output_buffer_size) -= FRAME_LEN; |
| 1774 if (*output_buffer_size > 0) { |
| 1775 RTC_DCHECK_GE(static_cast<size_t>(2 * PART_LEN - FRAME_LEN), |
| 1776 (*output_buffer_size)); |
| 1777 for (size_t i = 0; i < num_bands; ++i) { |
| 1778 memcpy(&output_buffer[i][0], &output_buffer[i][FRAME_LEN], |
| 1779 (*output_buffer_size) * sizeof(float)); |
| 1780 } |
| 1781 } |
| 1782 } |
| 1783 |
1743 void WebRtcAec_ProcessFrames(AecCore* aec, | 1784 void WebRtcAec_ProcessFrames(AecCore* aec, |
1744 const float* const* nearend, | 1785 const float* const* nearend, |
1745 size_t num_bands, | 1786 size_t num_bands, |
1746 size_t num_samples, | 1787 size_t num_samples, |
1747 int knownDelay, | 1788 int knownDelay, |
1748 float* const* out) { | 1789 float* const* out) { |
1749 int out_elements = 0; | |
1750 | |
1751 RTC_DCHECK(num_samples == 80 || num_samples == 160); | 1790 RTC_DCHECK(num_samples == 80 || num_samples == 160); |
1752 | 1791 |
1753 aec->frame_count++; | 1792 aec->frame_count++; |
1754 // For each frame the process is as follows: | 1793 // For each frame the process is as follows: |
1755 // 1) If the system_delay indicates on being too small for processing a | 1794 // 1) If the system_delay indicates on being too small for processing a |
1756 // frame we stuff the buffer with enough data for 10 ms. | 1795 // frame we stuff the buffer with enough data for 10 ms. |
1757 // 2 a) Adjust the buffer to the system delay, by moving the read pointer. | 1796 // 2 a) Adjust the buffer to the system delay, by moving the read pointer. |
1758 // b) Apply signal based delay correction, if we have detected poor AEC | 1797 // b) Apply signal based delay correction, if we have detected poor AEC |
1759 // performance. | 1798 // performance. |
1760 // 3) TODO(bjornv): Investigate if we need to add this: | 1799 // 3) TODO(bjornv): Investigate if we need to add this: |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1820 // If we rely on reported system delay values only, a buffer underrun here | 1859 // If we rely on reported system delay values only, a buffer underrun here |
1821 // can never occur since we've taken care of that in 1) above. Here, we | 1860 // can never occur since we've taken care of that in 1) above. Here, we |
1822 // apply signal based delay correction and can therefore end up with | 1861 // apply signal based delay correction and can therefore end up with |
1823 // buffer underruns since the delay estimation can be wrong. We therefore | 1862 // buffer underruns since the delay estimation can be wrong. We therefore |
1824 // stuff the buffer with enough elements if needed. | 1863 // stuff the buffer with enough elements if needed. |
1825 if (far_near_buffer_diff < 0) { | 1864 if (far_near_buffer_diff < 0) { |
1826 WebRtcAec_MoveFarReadPtr(aec, far_near_buffer_diff); | 1865 WebRtcAec_MoveFarReadPtr(aec, far_near_buffer_diff); |
1827 } | 1866 } |
1828 } | 1867 } |
1829 | 1868 |
1830 // Form a process a block of samples. | 1869 static_assert( |
1831 RTC_DCHECK_EQ(16, FRAME_LEN - PART_LEN); | 1870 16 == (FRAME_LEN - PART_LEN), |
| 1871 "These constants need to be properly related for this code to work"); |
| 1872 float output_block[NUM_HIGH_BANDS_MAX + 1][PART_LEN]; |
1832 float nearend_block[NUM_HIGH_BANDS_MAX + 1][PART_LEN]; | 1873 float nearend_block[NUM_HIGH_BANDS_MAX + 1][PART_LEN]; |
1833 const int num_samples_to_block = PART_LEN - aec->nearend_buffer_size; | |
1834 const int num_samples_to_buffer = FRAME_LEN - num_samples_to_block; | |
1835 for (size_t i = 0; i < num_bands; ++i) { | |
1836 memcpy(&nearend_block[i][0], &aec->nearend_buffer[i][0], | |
1837 aec->nearend_buffer_size * sizeof(float)); | |
1838 memcpy(&nearend_block[i][aec->nearend_buffer_size], &nearend[i][j], | |
1839 num_samples_to_block * sizeof(float)); | |
1840 } | |
1841 ProcessBlock(aec, nearend_block); | |
1842 | 1874 |
1843 if (num_samples_to_buffer == PART_LEN) { | 1875 // Form and process a block of nearend samples, buffer the output block of |
1844 // If possible form and process a second block of samples. | 1876 // samples. |
1845 for (size_t i = 0; i < num_bands; ++i) { | 1877 FormNearendBlock(j, num_bands, nearend, PART_LEN - aec->nearend_buffer_size, |
1846 memcpy(&nearend_block[i][0], &nearend[i][j + num_samples_to_block], | 1878 aec->nearend_buffer, nearend_block); |
1847 num_samples_to_buffer * sizeof(float)); | 1879 ProcessBlock(aec, nearend_block, output_block); |
1848 } | 1880 BufferOutputBlock(num_bands, output_block, &aec->output_buffer_size, |
1849 ProcessBlock(aec, nearend_block); | 1881 aec->output_buffer); |
| 1882 |
| 1883 if ((FRAME_LEN - PART_LEN + aec->nearend_buffer_size) == PART_LEN) { |
| 1884 // When possible (every fourth frame) form and process a second block of |
| 1885 // nearend samples, buffer the output block of samples. |
| 1886 FormNearendBlock(j + FRAME_LEN - PART_LEN, num_bands, nearend, PART_LEN, |
| 1887 aec->nearend_buffer, nearend_block); |
| 1888 ProcessBlock(aec, nearend_block, output_block); |
| 1889 BufferOutputBlock(num_bands, output_block, &aec->output_buffer_size, |
| 1890 aec->output_buffer); |
| 1891 |
| 1892 // Reset the buffer size as there are no samples left in the nearend input |
| 1893 // to buffer. |
1850 aec->nearend_buffer_size = 0; | 1894 aec->nearend_buffer_size = 0; |
1851 } else { | 1895 } else { |
1852 // Buffer the remaining samples in the frame. | 1896 // Buffer the remaining samples in the nearend input. |
1853 for (size_t i = 0; i < num_bands; ++i) { | 1897 aec->nearend_buffer_size += FRAME_LEN - PART_LEN; |
1854 memcpy(&aec->nearend_buffer[i][0], | 1898 BufferNearendFrame(j, num_bands, nearend, aec->nearend_buffer_size, |
1855 &nearend[i][j + num_samples_to_block], | 1899 aec->nearend_buffer); |
1856 num_samples_to_buffer * sizeof(float)); | |
1857 } | |
1858 aec->nearend_buffer_size = num_samples_to_buffer; | |
1859 } | 1900 } |
1860 | 1901 |
1861 // 5) Update system delay with respect to the entire frame. | 1902 // 5) Update system delay with respect to the entire frame. |
1862 aec->system_delay -= FRAME_LEN; | 1903 aec->system_delay -= FRAME_LEN; |
1863 | 1904 |
1864 // 6) Update output frame. | 1905 // 6) Form the output frame. |
1865 // Stuff the out buffer if we have less than a frame to output. | 1906 FormOutputFrame(j, num_bands, &aec->output_buffer_size, aec->output_buffer, |
1866 // This should only happen for the first frame. | 1907 out); |
1867 out_elements = static_cast<int>(WebRtc_available_read(aec->outFrBuf)); | |
1868 if (out_elements < FRAME_LEN) { | |
1869 WebRtc_MoveReadPtr(aec->outFrBuf, out_elements - FRAME_LEN); | |
1870 for (size_t i = 0; i < num_bands - 1; ++i) { | |
1871 WebRtc_MoveReadPtr(aec->outFrBufH[i], out_elements - FRAME_LEN); | |
1872 } | |
1873 } | |
1874 // Obtain an output frame. | |
1875 WebRtc_ReadBuffer(aec->outFrBuf, NULL, &out[0][j], FRAME_LEN); | |
1876 // For H bands. | |
1877 for (size_t i = 1; i < num_bands; ++i) { | |
1878 WebRtc_ReadBuffer(aec->outFrBufH[i - 1], NULL, &out[i][j], FRAME_LEN); | |
1879 } | |
1880 } | 1908 } |
1881 } | 1909 } |
1882 | 1910 |
1883 int WebRtcAec_GetDelayMetricsCore(AecCore* self, | 1911 int WebRtcAec_GetDelayMetricsCore(AecCore* self, |
1884 int* median, | 1912 int* median, |
1885 int* std, | 1913 int* std, |
1886 float* fraction_poor_delays) { | 1914 float* fraction_poor_delays) { |
1887 assert(self != NULL); | 1915 assert(self != NULL); |
1888 assert(median != NULL); | 1916 assert(median != NULL); |
1889 assert(std != NULL); | 1917 assert(std != NULL); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1983 | 2011 |
1984 int WebRtcAec_system_delay(AecCore* self) { | 2012 int WebRtcAec_system_delay(AecCore* self) { |
1985 return self->system_delay; | 2013 return self->system_delay; |
1986 } | 2014 } |
1987 | 2015 |
1988 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { | 2016 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { |
1989 assert(delay >= 0); | 2017 assert(delay >= 0); |
1990 self->system_delay = delay; | 2018 self->system_delay = delay; |
1991 } | 2019 } |
1992 } // namespace webrtc | 2020 } // namespace webrtc |
OLD | NEW |