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 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
362 } | 362 } |
363 | 363 |
364 if (wfEn > wfEnMax) { | 364 if (wfEn > wfEnMax) { |
365 wfEnMax = wfEn; | 365 wfEnMax = wfEn; |
366 delay = i; | 366 delay = i; |
367 } | 367 } |
368 } | 368 } |
369 return delay; | 369 return delay; |
370 } | 370 } |
371 | 371 |
372 // Update metric with 10 * log10(nomin / denom), | |
373 static void UpdateMetric(Stats* metric, float nomin, float denom) { | |
tlegrand-webrtc
2016/04/13 14:33:31
How do we test this function, to make sure it hand
peah-webrtc
2016/04/14 13:46:10
Since it is local within aec_core.cc, I think a DC
peah-webrtc
2016/04/14 13:46:10
Breaking out the computation of the metric in a se
minyue-webrtc
2016/04/14 14:11:12
Yes, it is good to sanity check on |metric|, added
peah-webrtc
2016/04/15 10:46:37
Would it be possible to change the names of nomin
peah-webrtc
2016/04/15 10:46:37
Maybe it is ok and a good solution, but to me it f
minyue-webrtc
2016/04/18 10:56:25
I think one reason for inf is that we calculate di
minyue-webrtc
2016/04/18 10:56:25
Done.
| |
374 const float temp = nomin / denom; | |
tlegrand-webrtc
2016/04/13 14:33:31
Is division with 0 allowed for float?
peah-webrtc
2016/04/14 13:46:10
Please rename this variable to what is is, as it i
peah-webrtc
2016/04/14 13:46:10
No, we should never do that. (If happening on the
minyue-webrtc
2016/04/14 14:11:12
For float, denom = 0 will not crash.
peah-webrtc
2016/04/15 10:46:37
Ah, you are right, I did not know that.
But I sti
minyue-webrtc
2016/04/18 10:56:25
Done.
| |
375 if (!std::isfinite(temp)) | |
peah-webrtc
2016/04/14 13:46:10
I think it is better to check for denom being zero
| |
376 return; | |
377 | |
378 // Instant. | |
379 // Adding 1e-10 to set the lower bound to -100. | |
380 metric->instant = 10.0 * log10(temp + 1e-10); | |
381 | |
382 // Max. | |
383 if (metric->instant > metric->max) | |
384 metric->max = metric->instant; | |
385 | |
386 // Min. | |
387 if (metric->instant < metric->min) | |
388 metric->min = metric->instant; | |
389 | |
390 // Average. | |
391 metric->counter++; | |
tlegrand-webrtc
2016/04/13 14:33:31
Do we ever reset these counters? I realize you did
peah-webrtc
2016/04/14 13:46:10
I think it is nice to have a controlled wraparound
minyue-webrtc
2016/04/14 14:11:12
Very good point. I am not fully sure what we would
minyue-webrtc
2016/04/14 14:11:12
After 391, I added a RTC_CHECK_NE(0u, metric->coun
peah-webrtc
2016/04/15 10:46:37
Acknowledged.
| |
392 metric->sum += metric->instant; | |
393 metric->average = metric->sum / metric->counter; | |
394 | |
395 // Upper mean. | |
396 if (metric->instant > metric->average) { | |
397 metric->hicounter++; | |
398 metric->hisum += metric->instant; | |
399 metric->himean = metric->hisum / metric->hicounter; | |
400 } | |
401 } | |
402 | |
372 // Threshold to protect against the ill-effects of a zero far-end. | 403 // Threshold to protect against the ill-effects of a zero far-end. |
373 const float WebRtcAec_kMinFarendPSD = 15; | 404 const float WebRtcAec_kMinFarendPSD = 15; |
374 | 405 |
375 // Updates the following smoothed Power Spectral Densities (PSD): | 406 // Updates the following smoothed Power Spectral Densities (PSD): |
376 // - sd : near-end | 407 // - sd : near-end |
377 // - se : residual echo | 408 // - se : residual echo |
378 // - sx : far-end | 409 // - sx : far-end |
379 // - sde : cross-PSD of near-end and residual echo | 410 // - sde : cross-PSD of near-end and residual echo |
380 // - sxd : cross-PSD of near-end and far-end | 411 // - sxd : cross-PSD of near-end and far-end |
381 // | 412 // |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
635 level->minlevel = new_frame_level; // New minimum. | 666 level->minlevel = new_frame_level; // New minimum. |
636 } else { | 667 } else { |
637 level->minlevel *= (1 + 0.001f); // Small increase. | 668 level->minlevel *= (1 + 0.001f); // Small increase. |
638 } | 669 } |
639 } | 670 } |
640 level->averagelevel.AddValue(new_frame_level); | 671 level->averagelevel.AddValue(new_frame_level); |
641 } | 672 } |
642 } | 673 } |
643 | 674 |
644 static void UpdateMetrics(AecCore* aec) { | 675 static void UpdateMetrics(AecCore* aec) { |
645 float dtmp; | |
646 | |
647 const float actThresholdNoisy = 8.0f; | 676 const float actThresholdNoisy = 8.0f; |
648 const float actThresholdClean = 40.0f; | 677 const float actThresholdClean = 40.0f; |
649 const float safety = 0.99995f; | |
650 | 678 |
651 const float noisyPower = 300000.0f; | 679 const float noisyPower = 300000.0f; |
652 | 680 |
653 float actThreshold; | 681 float actThreshold; |
654 float echo, suppressedEcho; | |
655 | 682 |
656 if (aec->echoState) { // Check if echo is likely present | 683 if (aec->echoState) { // Check if echo is likely present |
657 aec->stateCounter++; | 684 aec->stateCounter++; |
658 } | 685 } |
659 | 686 |
660 if (aec->linoutlevel.framelevel.EndOfBlock()) { | 687 if (aec->linoutlevel.framelevel.EndOfBlock()) { |
661 aec->divergent_filter_fraction.AddObservation(aec->nearlevel, | 688 aec->divergent_filter_fraction.AddObservation(aec->nearlevel, |
662 aec->linoutlevel, | 689 aec->linoutlevel, |
663 aec->nlpoutlevel); | 690 aec->nlpoutlevel); |
664 } | 691 } |
665 | 692 |
666 if (aec->farlevel.averagelevel.EndOfBlock()) { | 693 if (aec->farlevel.averagelevel.EndOfBlock()) { |
667 if (aec->farlevel.minlevel < noisyPower) { | 694 if (aec->farlevel.minlevel < noisyPower) { |
668 actThreshold = actThresholdClean; | 695 actThreshold = actThresholdClean; |
669 } else { | 696 } else { |
670 actThreshold = actThresholdNoisy; | 697 actThreshold = actThresholdNoisy; |
671 } | 698 } |
672 | 699 |
673 const float far_average_level = aec->farlevel.averagelevel.GetLatestMean(); | 700 const float far_average_level = aec->farlevel.averagelevel.GetLatestMean(); |
674 | 701 |
675 // The last condition is to let estimation be made in active far-end | 702 // The last condition is to let estimation be made in active far-end |
676 // segments only. | 703 // segments only. |
677 if ((aec->stateCounter > (0.5f * kCountLen * kSubCountLen)) && | 704 if ((aec->stateCounter > (0.5f * kCountLen * kSubCountLen)) && |
678 (aec->farlevel.framelevel.EndOfBlock()) && | 705 (aec->farlevel.framelevel.EndOfBlock()) && |
679 (far_average_level > (actThreshold * aec->farlevel.minlevel))) { | 706 (far_average_level > (actThreshold * aec->farlevel.minlevel))) { |
680 | 707 |
708 // ERL | |
peah-webrtc
2016/04/14 13:46:10
Comment should be terminated with a period. Furthe
minyue-webrtc
2016/04/18 10:56:25
Done.
| |
681 const float near_average_level = | 709 const float near_average_level = |
682 aec->nearlevel.averagelevel.GetLatestMean(); | 710 aec->nearlevel.averagelevel.GetLatestMean(); |
683 | 711 |
peah-webrtc
2016/04/14 13:46:10
To be consistent with how it is done below, I thin
minyue-webrtc
2016/04/18 10:56:25
Done.
| |
684 // Subtract noise power | 712 UpdateMetric(&aec->erl, far_average_level, near_average_level); |
685 echo = near_average_level - safety * aec->nearlevel.minlevel; | |
686 | |
687 // ERL | |
688 dtmp = 10 * static_cast<float>(log10(far_average_level / | |
689 near_average_level + 1e-10f)); | |
690 | |
691 aec->erl.instant = dtmp; | |
692 if (dtmp > aec->erl.max) { | |
693 aec->erl.max = dtmp; | |
694 } | |
695 | |
696 if (dtmp < aec->erl.min) { | |
697 aec->erl.min = dtmp; | |
698 } | |
699 | |
700 aec->erl.counter++; | |
701 aec->erl.sum += dtmp; | |
702 aec->erl.average = aec->erl.sum / aec->erl.counter; | |
703 | |
704 // Upper mean | |
705 if (dtmp > aec->erl.average) { | |
706 aec->erl.hicounter++; | |
707 aec->erl.hisum += dtmp; | |
708 aec->erl.himean = aec->erl.hisum / aec->erl.hicounter; | |
709 } | |
710 | 713 |
711 // A_NLP | 714 // A_NLP |
peah-webrtc
2016/04/14 13:46:10
See comment above.
minyue-webrtc
2016/04/18 10:56:25
done, although I am not sure if I name it properly
| |
712 const float linout_average_level = | 715 const float linout_average_level = |
713 aec->linoutlevel.averagelevel.GetLatestMean(); | 716 aec->linoutlevel.averagelevel.GetLatestMean(); |
714 dtmp = 10 * static_cast<float>(log10(near_average_level / | 717 UpdateMetric(&aec->aNlp, near_average_level, linout_average_level); |
715 linout_average_level + 1e-10f)); | |
716 | |
717 // subtract noise power | |
718 suppressedEcho = | |
719 linout_average_level - safety * aec->linoutlevel.minlevel; | |
720 | |
721 aec->aNlp.instant = | |
722 10 * static_cast<float>(log10(echo / suppressedEcho + 1e-10f)); | |
723 | |
724 if (dtmp > aec->aNlp.max) { | |
725 aec->aNlp.max = dtmp; | |
726 } | |
727 | |
728 if (dtmp < aec->aNlp.min) { | |
729 aec->aNlp.min = dtmp; | |
730 } | |
731 | |
732 aec->aNlp.counter++; | |
733 aec->aNlp.sum += dtmp; | |
734 aec->aNlp.average = aec->aNlp.sum / aec->aNlp.counter; | |
735 | |
736 // Upper mean | |
737 if (dtmp > aec->aNlp.average) { | |
738 aec->aNlp.hicounter++; | |
739 aec->aNlp.hisum += dtmp; | |
740 aec->aNlp.himean = aec->aNlp.hisum / aec->aNlp.hicounter; | |
741 } | |
742 | 718 |
743 // ERLE | 719 // ERLE |
peah-webrtc
2016/04/14 13:46:10
See comment above.
minyue-webrtc
2016/04/18 10:56:25
Done.
| |
744 const float nlpout_average_level = | 720 const float nlpout_average_level = |
745 aec->nlpoutlevel.averagelevel.GetLatestMean(); | 721 aec->nlpoutlevel.averagelevel.GetLatestMean(); |
746 // subtract noise power | 722 UpdateMetric(&aec->erle, near_average_level, nlpout_average_level); |
747 suppressedEcho = | |
748 nlpout_average_level - safety * aec->nlpoutlevel.minlevel; | |
749 dtmp = 10 * static_cast<float>(log10(echo / suppressedEcho + 1e-10f)); | |
750 | |
751 aec->erle.instant = dtmp; | |
752 if (dtmp > aec->erle.max) { | |
753 aec->erle.max = dtmp; | |
754 } | |
755 | |
756 if (dtmp < aec->erle.min) { | |
757 aec->erle.min = dtmp; | |
758 } | |
759 | |
760 aec->erle.counter++; | |
761 aec->erle.sum += dtmp; | |
762 aec->erle.average = aec->erle.sum / aec->erle.counter; | |
763 | |
764 // Upper mean | |
765 if (dtmp > aec->erle.average) { | |
766 aec->erle.hicounter++; | |
767 aec->erle.hisum += dtmp; | |
768 aec->erle.himean = aec->erle.hisum / aec->erle.hicounter; | |
769 } | |
770 } | 723 } |
771 | 724 |
772 aec->stateCounter = 0; | 725 aec->stateCounter = 0; |
773 } | 726 } |
774 } | 727 } |
775 | 728 |
776 static void UpdateDelayMetrics(AecCore* self) { | 729 static void UpdateDelayMetrics(AecCore* self) { |
777 int i = 0; | 730 int i = 0; |
778 int delay_values = 0; | 731 int delay_values = 0; |
779 int median = 0; | 732 int median = 0; |
(...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1948 | 1901 |
1949 int WebRtcAec_system_delay(AecCore* self) { | 1902 int WebRtcAec_system_delay(AecCore* self) { |
1950 return self->system_delay; | 1903 return self->system_delay; |
1951 } | 1904 } |
1952 | 1905 |
1953 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { | 1906 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { |
1954 assert(delay >= 0); | 1907 assert(delay >= 0); |
1955 self->system_delay = delay; | 1908 self->system_delay = delay; |
1956 } | 1909 } |
1957 } // namespace webrtc | 1910 } // namespace webrtc |
OLD | NEW |