| 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 28 matching lines...) Expand all Loading... |
| 39 } | 39 } |
| 40 #include "webrtc/system_wrappers/include/cpu_features_wrapper.h" | 40 #include "webrtc/system_wrappers/include/cpu_features_wrapper.h" |
| 41 #include "webrtc/typedefs.h" | 41 #include "webrtc/typedefs.h" |
| 42 | 42 |
| 43 namespace webrtc { | 43 namespace webrtc { |
| 44 | 44 |
| 45 // Buffer size (samples) | 45 // Buffer size (samples) |
| 46 static const size_t kBufSizePartitions = 250; // 1 second of audio in 16 kHz. | 46 static const size_t kBufSizePartitions = 250; // 1 second of audio in 16 kHz. |
| 47 | 47 |
| 48 // Metrics | 48 // Metrics |
| 49 static const int subCountLen = 4; | 49 static const size_t kSubCountLen = 4; |
| 50 static const int countLen = 50; | 50 static const size_t kCountLen = 50; |
| 51 static const int kDelayMetricsAggregationWindow = 1250; // 5 seconds at 16 kHz. | 51 static const int kDelayMetricsAggregationWindow = 1250; // 5 seconds at 16 kHz. |
| 52 | 52 |
| 53 // Quantities to control H band scaling for SWB input | 53 // Quantities to control H band scaling for SWB input |
| 54 static const float cnScaleHband = 0.4f; // scale for comfort noise in H band. | 54 static const float cnScaleHband = 0.4f; // scale for comfort noise in H band. |
| 55 // Initial bin for averaging nlp gain in low band | 55 // Initial bin for averaging nlp gain in low band |
| 56 static const int freqAvgIc = PART_LEN / 2; | 56 static const int freqAvgIc = PART_LEN / 2; |
| 57 | 57 |
| 58 // Matlab code to produce table: | 58 // Matlab code to produce table: |
| 59 // win = sqrt(hanning(63)); win = [0 ; win(1:32)]; | 59 // win = sqrt(hanning(63)); win = [0 ; win(1:32)]; |
| 60 // fprintf(1, '\t%.14f, %.14f, %.14f,\n', win); | 60 // fprintf(1, '\t%.14f, %.14f, %.14f,\n', win); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 WebRtcAecWindowData WebRtcAec_WindowData; | 143 WebRtcAecWindowData WebRtcAec_WindowData; |
| 144 | 144 |
| 145 __inline static float MulRe(float aRe, float aIm, float bRe, float bIm) { | 145 __inline static float MulRe(float aRe, float aIm, float bRe, float bIm) { |
| 146 return aRe * bRe - aIm * bIm; | 146 return aRe * bRe - aIm * bIm; |
| 147 } | 147 } |
| 148 | 148 |
| 149 __inline static float MulIm(float aRe, float aIm, float bRe, float bIm) { | 149 __inline static float MulIm(float aRe, float aIm, float bRe, float bIm) { |
| 150 return aRe * bIm + aIm * bRe; | 150 return aRe * bIm + aIm * bRe; |
| 151 } | 151 } |
| 152 | 152 |
| 153 PowerLevel::PowerLevel() |
| 154 // TODO(minyue): Due to a legacy bug, |framelevel| and |averagelevel| use a |
| 155 // window, of which the length is 1 unit longer than indicated. Remove "+1" |
| 156 // when the code is refactored. |
| 157 : framelevel(kSubCountLen + 1), |
| 158 averagelevel(kCountLen + 1) { |
| 159 } |
| 160 |
| 161 // TODO(minyue): Moving some initialization from WebRtcAec_CreateAec() to ctor. |
| 162 AecCore::AecCore() = default; |
| 163 |
| 153 static int CmpFloat(const void* a, const void* b) { | 164 static int CmpFloat(const void* a, const void* b) { |
| 154 const float* da = (const float*)a; | 165 const float* da = (const float*)a; |
| 155 const float* db = (const float*)b; | 166 const float* db = (const float*)b; |
| 156 | 167 |
| 157 return (*da > *db) - (*da < *db); | 168 return (*da > *db) - (*da < *db); |
| 158 } | 169 } |
| 159 | 170 |
| 160 static void FilterFar(int num_partitions, | 171 static void FilterFar(int num_partitions, |
| 161 int x_fft_buf_block_pos, | 172 int x_fft_buf_block_pos, |
| 162 float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1], | 173 float x_fft_buf[2][kExtendedNumPartitions * PART_LEN1], |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 comfortNoiseHband[1][i] = tmpAvg * u[1][i]; | 527 comfortNoiseHband[1][i] = tmpAvg * u[1][i]; |
| 517 } | 528 } |
| 518 } else { | 529 } else { |
| 519 memset(comfortNoiseHband, 0, | 530 memset(comfortNoiseHband, 0, |
| 520 2 * PART_LEN1 * sizeof(comfortNoiseHband[0][0])); | 531 2 * PART_LEN1 * sizeof(comfortNoiseHband[0][0])); |
| 521 } | 532 } |
| 522 } | 533 } |
| 523 | 534 |
| 524 static void InitLevel(PowerLevel* level) { | 535 static void InitLevel(PowerLevel* level) { |
| 525 const float kBigFloat = 1E17f; | 536 const float kBigFloat = 1E17f; |
| 526 | 537 level->averagelevel.Reset(); |
| 527 level->averagelevel = 0; | 538 level->framelevel.Reset(); |
| 528 level->framelevel = 0; | |
| 529 level->minlevel = kBigFloat; | 539 level->minlevel = kBigFloat; |
| 530 level->frsum = 0; | |
| 531 level->sfrsum = 0; | |
| 532 level->frcounter = 0; | |
| 533 level->sfrcounter = 0; | |
| 534 } | 540 } |
| 535 | 541 |
| 536 static void InitStats(Stats* stats) { | 542 static void InitStats(Stats* stats) { |
| 537 stats->instant = kOffsetLevel; | 543 stats->instant = kOffsetLevel; |
| 538 stats->average = kOffsetLevel; | 544 stats->average = kOffsetLevel; |
| 539 stats->max = kOffsetLevel; | 545 stats->max = kOffsetLevel; |
| 540 stats->min = kOffsetLevel * (-1); | 546 stats->min = kOffsetLevel * (-1); |
| 541 stats->sum = 0; | 547 stats->sum = 0; |
| 542 stats->hisum = 0; | 548 stats->hisum = 0; |
| 543 stats->himean = kOffsetLevel; | 549 stats->himean = kOffsetLevel; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 562 size_t k; | 568 size_t k; |
| 563 float energy = 0.0f; | 569 float energy = 0.0f; |
| 564 | 570 |
| 565 for (k = 0; k < num_samples; ++k) { | 571 for (k = 0; k < num_samples; ++k) { |
| 566 energy += in[k] * in[k]; | 572 energy += in[k] * in[k]; |
| 567 } | 573 } |
| 568 return energy / num_samples; | 574 return energy / num_samples; |
| 569 } | 575 } |
| 570 | 576 |
| 571 static void UpdateLevel(PowerLevel* level, float power) { | 577 static void UpdateLevel(PowerLevel* level, float power) { |
| 572 level->sfrsum += power; | 578 level->framelevel.AddValue(power); |
| 573 level->sfrcounter++; | 579 if (level->framelevel.EndOfBlock()) { |
| 574 | 580 const float new_frame_level = level->framelevel.GetLatestMean(); |
| 575 if (level->sfrcounter > subCountLen) { | 581 if (new_frame_level > 0) { |
| 576 level->framelevel = level->sfrsum / subCountLen; | 582 if (new_frame_level < level->minlevel) { |
| 577 level->sfrsum = 0; | 583 level->minlevel = new_frame_level; // New minimum. |
| 578 level->sfrcounter = 0; | |
| 579 if (level->framelevel > 0) { | |
| 580 if (level->framelevel < level->minlevel) { | |
| 581 level->minlevel = level->framelevel; // New minimum. | |
| 582 } else { | 584 } else { |
| 583 level->minlevel *= (1 + 0.001f); // Small increase. | 585 level->minlevel *= (1 + 0.001f); // Small increase. |
| 584 } | 586 } |
| 585 } | 587 } |
| 586 level->frcounter++; | 588 level->averagelevel.AddValue(new_frame_level); |
| 587 level->frsum += level->framelevel; | |
| 588 if (level->frcounter > countLen) { | |
| 589 level->averagelevel = level->frsum / countLen; | |
| 590 level->frsum = 0; | |
| 591 level->frcounter = 0; | |
| 592 } | |
| 593 } | 589 } |
| 594 } | 590 } |
| 595 | 591 |
| 596 static void UpdateMetrics(AecCore* aec) { | 592 static void UpdateMetrics(AecCore* aec) { |
| 597 float dtmp, dtmp2; | 593 float dtmp, dtmp2; |
| 598 | 594 |
| 599 const float actThresholdNoisy = 8.0f; | 595 const float actThresholdNoisy = 8.0f; |
| 600 const float actThresholdClean = 40.0f; | 596 const float actThresholdClean = 40.0f; |
| 601 const float safety = 0.99995f; | 597 const float safety = 0.99995f; |
| 602 | 598 |
| 603 const float noisyPower = 300000.0f; | 599 const float noisyPower = 300000.0f; |
| 604 | 600 |
| 605 float actThreshold; | 601 float actThreshold; |
| 606 float echo, suppressedEcho; | 602 float echo, suppressedEcho; |
| 607 | 603 |
| 608 if (aec->echoState) { // Check if echo is likely present | 604 if (aec->echoState) { // Check if echo is likely present |
| 609 aec->stateCounter++; | 605 aec->stateCounter++; |
| 610 } | 606 } |
| 611 | 607 |
| 612 if (aec->farlevel.frcounter == 0) { | 608 if (aec->farlevel.averagelevel.EndOfBlock()) { |
| 613 if (aec->farlevel.minlevel < noisyPower) { | 609 if (aec->farlevel.minlevel < noisyPower) { |
| 614 actThreshold = actThresholdClean; | 610 actThreshold = actThresholdClean; |
| 615 } else { | 611 } else { |
| 616 actThreshold = actThresholdNoisy; | 612 actThreshold = actThresholdNoisy; |
| 617 } | 613 } |
| 618 | 614 |
| 619 if ((aec->stateCounter > (0.5f * countLen * subCountLen)) && | 615 const float far_average_level = aec->farlevel.averagelevel.GetLatestMean(); |
| 620 (aec->farlevel.sfrcounter == 0) | |
| 621 | 616 |
| 622 // Estimate in active far-end segments only | 617 // The last condition is to let estimation be made in active far-end |
| 623 && (aec->farlevel.averagelevel > | 618 // segments only. |
| 624 (actThreshold * aec->farlevel.minlevel))) { | 619 if ((aec->stateCounter > (0.5f * kCountLen * kSubCountLen)) && |
| 620 (aec->farlevel.framelevel.EndOfBlock()) && |
| 621 (far_average_level > (actThreshold * aec->farlevel.minlevel))) { |
| 622 |
| 623 const float near_average_level = |
| 624 aec->nearlevel.averagelevel.GetLatestMean(); |
| 625 |
| 625 // Subtract noise power | 626 // Subtract noise power |
| 626 echo = aec->nearlevel.averagelevel - safety * aec->nearlevel.minlevel; | 627 echo = near_average_level - safety * aec->nearlevel.minlevel; |
| 627 | 628 |
| 628 // ERL | 629 // ERL |
| 629 dtmp = 10 * static_cast<float>(log10(aec->farlevel.averagelevel / | 630 dtmp = 10 * static_cast<float>(log10(far_average_level / |
| 630 aec->nearlevel.averagelevel + | 631 near_average_level + 1e-10f)); |
| 631 1e-10f)); | 632 dtmp2 = 10 * static_cast<float>(log10(far_average_level / echo + 1e-10f)); |
| 632 dtmp2 = 10 * static_cast<float>(log10(aec->farlevel.averagelevel / | |
| 633 echo + | |
| 634 1e-10f)); | |
| 635 | 633 |
| 636 aec->erl.instant = dtmp; | 634 aec->erl.instant = dtmp; |
| 637 if (dtmp > aec->erl.max) { | 635 if (dtmp > aec->erl.max) { |
| 638 aec->erl.max = dtmp; | 636 aec->erl.max = dtmp; |
| 639 } | 637 } |
| 640 | 638 |
| 641 if (dtmp < aec->erl.min) { | 639 if (dtmp < aec->erl.min) { |
| 642 aec->erl.min = dtmp; | 640 aec->erl.min = dtmp; |
| 643 } | 641 } |
| 644 | 642 |
| 645 aec->erl.counter++; | 643 aec->erl.counter++; |
| 646 aec->erl.sum += dtmp; | 644 aec->erl.sum += dtmp; |
| 647 aec->erl.average = aec->erl.sum / aec->erl.counter; | 645 aec->erl.average = aec->erl.sum / aec->erl.counter; |
| 648 | 646 |
| 649 // Upper mean | 647 // Upper mean |
| 650 if (dtmp > aec->erl.average) { | 648 if (dtmp > aec->erl.average) { |
| 651 aec->erl.hicounter++; | 649 aec->erl.hicounter++; |
| 652 aec->erl.hisum += dtmp; | 650 aec->erl.hisum += dtmp; |
| 653 aec->erl.himean = aec->erl.hisum / aec->erl.hicounter; | 651 aec->erl.himean = aec->erl.hisum / aec->erl.hicounter; |
| 654 } | 652 } |
| 655 | 653 |
| 656 // A_NLP | 654 // A_NLP |
| 657 dtmp = 10 * static_cast<float>(log10(aec->nearlevel.averagelevel / | 655 const float linout_average_level = |
| 658 aec->linoutlevel.averagelevel + | 656 aec->linoutlevel.averagelevel.GetLatestMean(); |
| 659 1e-10f)); | 657 dtmp = 10 * static_cast<float>(log10(near_average_level / |
| 658 linout_average_level + 1e-10f)); |
| 660 | 659 |
| 661 // subtract noise power | 660 // subtract noise power |
| 662 suppressedEcho = aec->linoutlevel.averagelevel - | 661 suppressedEcho = |
| 663 safety * aec->linoutlevel.minlevel; | 662 linout_average_level - safety * aec->linoutlevel.minlevel; |
| 664 | 663 |
| 665 dtmp2 = 10 * static_cast<float>(log10(echo / suppressedEcho + 1e-10f)); | 664 dtmp2 = 10 * static_cast<float>(log10(echo / suppressedEcho + 1e-10f)); |
| 666 | 665 |
| 667 aec->aNlp.instant = dtmp2; | 666 aec->aNlp.instant = dtmp2; |
| 668 if (dtmp > aec->aNlp.max) { | 667 if (dtmp > aec->aNlp.max) { |
| 669 aec->aNlp.max = dtmp; | 668 aec->aNlp.max = dtmp; |
| 670 } | 669 } |
| 671 | 670 |
| 672 if (dtmp < aec->aNlp.min) { | 671 if (dtmp < aec->aNlp.min) { |
| 673 aec->aNlp.min = dtmp; | 672 aec->aNlp.min = dtmp; |
| 674 } | 673 } |
| 675 | 674 |
| 676 aec->aNlp.counter++; | 675 aec->aNlp.counter++; |
| 677 aec->aNlp.sum += dtmp; | 676 aec->aNlp.sum += dtmp; |
| 678 aec->aNlp.average = aec->aNlp.sum / aec->aNlp.counter; | 677 aec->aNlp.average = aec->aNlp.sum / aec->aNlp.counter; |
| 679 | 678 |
| 680 // Upper mean | 679 // Upper mean |
| 681 if (dtmp > aec->aNlp.average) { | 680 if (dtmp > aec->aNlp.average) { |
| 682 aec->aNlp.hicounter++; | 681 aec->aNlp.hicounter++; |
| 683 aec->aNlp.hisum += dtmp; | 682 aec->aNlp.hisum += dtmp; |
| 684 aec->aNlp.himean = aec->aNlp.hisum / aec->aNlp.hicounter; | 683 aec->aNlp.himean = aec->aNlp.hisum / aec->aNlp.hicounter; |
| 685 } | 684 } |
| 686 | 685 |
| 687 // ERLE | 686 // ERLE |
| 687 const float nlpout_average_level = |
| 688 aec->nlpoutlevel.averagelevel.GetLatestMean(); |
| 689 // subtract noise power |
| 690 suppressedEcho = |
| 691 nlpout_average_level - safety * aec->nlpoutlevel.minlevel; |
| 688 | 692 |
| 689 // subtract noise power | 693 dtmp = 10 * static_cast<float>(log10(near_average_level / |
| 690 suppressedEcho = aec->nlpoutlevel.averagelevel - | 694 nlpout_average_level + 1e-10f)); |
| 691 safety * aec->nlpoutlevel.minlevel; | |
| 692 | |
| 693 dtmp = 10 * static_cast<float>(log10(aec->nearlevel.averagelevel / | |
| 694 aec->nlpoutlevel.averagelevel + 1e-10f)); | |
| 695 dtmp2 = 10 * static_cast<float>(log10(echo / suppressedEcho + 1e-10f)); | 695 dtmp2 = 10 * static_cast<float>(log10(echo / suppressedEcho + 1e-10f)); |
| 696 | 696 |
| 697 dtmp = dtmp2; | 697 dtmp = dtmp2; |
| 698 aec->erle.instant = dtmp; | 698 aec->erle.instant = dtmp; |
| 699 if (dtmp > aec->erle.max) { | 699 if (dtmp > aec->erle.max) { |
| 700 aec->erle.max = dtmp; | 700 aec->erle.max = dtmp; |
| 701 } | 701 } |
| 702 | 702 |
| 703 if (dtmp < aec->erle.min) { | 703 if (dtmp < aec->erle.min) { |
| 704 aec->erle.min = dtmp; | 704 aec->erle.min = dtmp; |
| (...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1354 // For high bands | 1354 // For high bands |
| 1355 for (i = 0; i < aec->num_bands - 1; ++i) { | 1355 for (i = 0; i < aec->num_bands - 1; ++i) { |
| 1356 WebRtc_WriteBuffer(aec->outFrBufH[i], outputH[i], PART_LEN); | 1356 WebRtc_WriteBuffer(aec->outFrBufH[i], outputH[i], PART_LEN); |
| 1357 } | 1357 } |
| 1358 | 1358 |
| 1359 RTC_AEC_DEBUG_WAV_WRITE(aec->outFile, output, PART_LEN); | 1359 RTC_AEC_DEBUG_WAV_WRITE(aec->outFile, output, PART_LEN); |
| 1360 } | 1360 } |
| 1361 | 1361 |
| 1362 AecCore* WebRtcAec_CreateAec() { | 1362 AecCore* WebRtcAec_CreateAec() { |
| 1363 int i; | 1363 int i; |
| 1364 AecCore* aec = reinterpret_cast<AecCore*>(malloc(sizeof(AecCore))); | 1364 AecCore* aec = new AecCore; |
| 1365 if (!aec) { | 1365 if (!aec) { |
| 1366 return NULL; | 1366 return NULL; |
| 1367 } | 1367 } |
| 1368 | 1368 |
| 1369 aec->nearFrBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(float)); | 1369 aec->nearFrBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(float)); |
| 1370 if (!aec->nearFrBuf) { | 1370 if (!aec->nearFrBuf) { |
| 1371 WebRtcAec_FreeAec(aec); | 1371 WebRtcAec_FreeAec(aec); |
| 1372 return NULL; | 1372 return NULL; |
| 1373 } | 1373 } |
| 1374 | 1374 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1489 | 1489 |
| 1490 RTC_AEC_DEBUG_WAV_CLOSE(aec->farFile); | 1490 RTC_AEC_DEBUG_WAV_CLOSE(aec->farFile); |
| 1491 RTC_AEC_DEBUG_WAV_CLOSE(aec->nearFile); | 1491 RTC_AEC_DEBUG_WAV_CLOSE(aec->nearFile); |
| 1492 RTC_AEC_DEBUG_WAV_CLOSE(aec->outFile); | 1492 RTC_AEC_DEBUG_WAV_CLOSE(aec->outFile); |
| 1493 RTC_AEC_DEBUG_WAV_CLOSE(aec->outLinearFile); | 1493 RTC_AEC_DEBUG_WAV_CLOSE(aec->outLinearFile); |
| 1494 RTC_AEC_DEBUG_RAW_CLOSE(aec->e_fft_file); | 1494 RTC_AEC_DEBUG_RAW_CLOSE(aec->e_fft_file); |
| 1495 | 1495 |
| 1496 WebRtc_FreeDelayEstimator(aec->delay_estimator); | 1496 WebRtc_FreeDelayEstimator(aec->delay_estimator); |
| 1497 WebRtc_FreeDelayEstimatorFarend(aec->delay_estimator_farend); | 1497 WebRtc_FreeDelayEstimatorFarend(aec->delay_estimator_farend); |
| 1498 | 1498 |
| 1499 free(aec); | 1499 delete aec; |
| 1500 } | 1500 } |
| 1501 | 1501 |
| 1502 int WebRtcAec_InitAec(AecCore* aec, int sampFreq) { | 1502 int WebRtcAec_InitAec(AecCore* aec, int sampFreq) { |
| 1503 int i; | 1503 int i; |
| 1504 | 1504 |
| 1505 aec->sampFreq = sampFreq; | 1505 aec->sampFreq = sampFreq; |
| 1506 | 1506 |
| 1507 if (sampFreq == 8000) { | 1507 if (sampFreq == 8000) { |
| 1508 aec->normal_mu = 0.6f; | 1508 aec->normal_mu = 0.6f; |
| 1509 aec->normal_error_threshold = 2e-6f; | 1509 aec->normal_error_threshold = 2e-6f; |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1892 | 1892 |
| 1893 int WebRtcAec_system_delay(AecCore* self) { | 1893 int WebRtcAec_system_delay(AecCore* self) { |
| 1894 return self->system_delay; | 1894 return self->system_delay; |
| 1895 } | 1895 } |
| 1896 | 1896 |
| 1897 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { | 1897 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { |
| 1898 assert(delay >= 0); | 1898 assert(delay >= 0); |
| 1899 self->system_delay = delay; | 1899 self->system_delay = delay; |
| 1900 } | 1900 } |
| 1901 } // namespace webrtc | 1901 } // namespace webrtc |
| OLD | NEW |