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 10 matching lines...) Expand all Loading... | |
21 #include <algorithm> | 21 #include <algorithm> |
22 #include <assert.h> | 22 #include <assert.h> |
23 #include <math.h> | 23 #include <math.h> |
24 #include <stddef.h> // size_t | 24 #include <stddef.h> // size_t |
25 #include <stdlib.h> | 25 #include <stdlib.h> |
26 #include <string.h> | 26 #include <string.h> |
27 | 27 |
28 extern "C" { | 28 extern "C" { |
29 #include "webrtc/common_audio/ring_buffer.h" | 29 #include "webrtc/common_audio/ring_buffer.h" |
30 } | 30 } |
31 #include "webrtc/base/checks.h" | |
31 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar y.h" | 32 #include "webrtc/common_audio/signal_processing/include/signal_processing_librar y.h" |
32 #include "webrtc/modules/audio_processing/aec/aec_common.h" | 33 #include "webrtc/modules/audio_processing/aec/aec_common.h" |
33 #include "webrtc/modules/audio_processing/aec/aec_core_internal.h" | 34 #include "webrtc/modules/audio_processing/aec/aec_core_internal.h" |
34 #include "webrtc/modules/audio_processing/aec/aec_rdft.h" | 35 #include "webrtc/modules/audio_processing/aec/aec_rdft.h" |
35 #include "webrtc/modules/audio_processing/logging/aec_logging.h" | 36 #include "webrtc/modules/audio_processing/logging/aec_logging.h" |
36 #include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" | 37 #include "webrtc/modules/audio_processing/utility/delay_estimator_wrapper.h" |
37 #include "webrtc/system_wrappers/include/cpu_features_wrapper.h" | 38 #include "webrtc/system_wrappers/include/cpu_features_wrapper.h" |
38 #include "webrtc/typedefs.h" | 39 #include "webrtc/typedefs.h" |
39 | 40 |
40 namespace webrtc { | 41 namespace webrtc { |
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
358 } | 359 } |
359 | 360 |
360 if (wfEn > wfEnMax) { | 361 if (wfEn > wfEnMax) { |
361 wfEnMax = wfEn; | 362 wfEnMax = wfEn; |
362 delay = i; | 363 delay = i; |
363 } | 364 } |
364 } | 365 } |
365 return delay; | 366 return delay; |
366 } | 367 } |
367 | 368 |
369 // Update metric with 10 * log10(numerator / denominator). | |
370 static void UpdateLogRatioMetric(Stats* metric, float numerator, | |
371 float denominator) { | |
372 RTC_DCHECK(metric); | |
373 RTC_CHECK(numerator >= 0); | |
tlegrand-webrtc
2016/04/25 13:09:56
Why isn't numerator = 0 allowed?
kwiberg-webrtc
2016/04/25 13:23:58
It is. But what I'm wondering is why we allow deno
minyue-webrtc
2016/04/25 13:26:56
It is allowed, isn't it?
tlegrand-webrtc
2016/04/28 08:17:30
Right, my mistake. I was thinking 0 wouldn't be al
| |
374 RTC_CHECK(denominator >= 0); | |
375 | |
376 const float log_numerator = log10(numerator + 1e-10f); | |
377 const float log_denominator = log10(denominator + 1e-10f); | |
tlegrand-webrtc
2016/04/25 13:09:56
Which is more computational complex, log10 or divi
kwiberg-webrtc
2016/04/25 13:23:58
Yes, I'd be surprised if division wasn't significa
minyue-webrtc
2016/04/25 13:26:56
Per also asked about this. My reasoning was that i
tlegrand-webrtc
2016/04/28 08:17:30
Acknowledged.
| |
378 metric->instant = 10.0f * (log_numerator - log_denominator); | |
379 | |
380 // Max. | |
tlegrand-webrtc
2016/04/25 13:09:56
This comment doesn't add any value. Same with "Min
minyue-webrtc
2016/04/25 13:26:56
I agree. I'd like to make a separate CL, which may
tlegrand-webrtc
2016/04/28 08:17:30
Acknowledged.
| |
381 if (metric->instant > metric->max) | |
382 metric->max = metric->instant; | |
383 | |
384 // Min. | |
385 if (metric->instant < metric->min) | |
386 metric->min = metric->instant; | |
387 | |
388 // Average. | |
389 metric->counter++; | |
390 // This is to protect overflow, which should almost never happen. | |
391 RTC_CHECK_NE(0u, metric->counter); | |
392 metric->sum += metric->instant; | |
393 metric->average = metric->sum / metric->counter; | |
394 | |
395 // Upper mean. | |
tlegrand-webrtc
2016/04/25 13:09:56
hicounter, hisum and himean doesn't follow the nam
minyue-webrtc
2016/04/25 13:26:56
True, this will need to refactor other part of AEC
tlegrand-webrtc
2016/04/28 08:17:30
Acknowledged.
| |
396 if (metric->instant > metric->average) { | |
397 metric->hicounter++; | |
398 // This is to protect overflow, which should almost never happen. | |
399 RTC_CHECK_NE(0u, metric->hicounter); | |
400 metric->hisum += metric->instant; | |
401 metric->himean = metric->hisum / metric->hicounter; | |
402 } | |
403 } | |
404 | |
368 // Threshold to protect against the ill-effects of a zero far-end. | 405 // Threshold to protect against the ill-effects of a zero far-end. |
369 const float WebRtcAec_kMinFarendPSD = 15; | 406 const float WebRtcAec_kMinFarendPSD = 15; |
370 | 407 |
371 // Updates the following smoothed Power Spectral Densities (PSD): | 408 // Updates the following smoothed Power Spectral Densities (PSD): |
372 // - sd : near-end | 409 // - sd : near-end |
373 // - se : residual echo | 410 // - se : residual echo |
374 // - sx : far-end | 411 // - sx : far-end |
375 // - sde : cross-PSD of near-end and residual echo | 412 // - sde : cross-PSD of near-end and residual echo |
376 // - sxd : cross-PSD of near-end and far-end | 413 // - sxd : cross-PSD of near-end and far-end |
377 // | 414 // |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
631 level->minlevel = new_frame_level; // New minimum. | 668 level->minlevel = new_frame_level; // New minimum. |
632 } else { | 669 } else { |
633 level->minlevel *= (1 + 0.001f); // Small increase. | 670 level->minlevel *= (1 + 0.001f); // Small increase. |
634 } | 671 } |
635 } | 672 } |
636 level->averagelevel.AddValue(new_frame_level); | 673 level->averagelevel.AddValue(new_frame_level); |
637 } | 674 } |
638 } | 675 } |
639 | 676 |
640 static void UpdateMetrics(AecCore* aec) { | 677 static void UpdateMetrics(AecCore* aec) { |
641 float dtmp; | |
642 | |
643 const float actThresholdNoisy = 8.0f; | 678 const float actThresholdNoisy = 8.0f; |
644 const float actThresholdClean = 40.0f; | 679 const float actThresholdClean = 40.0f; |
645 const float safety = 0.99995f; | |
646 | 680 |
647 const float noisyPower = 300000.0f; | 681 const float noisyPower = 300000.0f; |
648 | 682 |
649 float actThreshold; | 683 float actThreshold; |
650 float echo, suppressedEcho; | |
651 | 684 |
652 if (aec->echoState) { // Check if echo is likely present | 685 if (aec->echoState) { // Check if echo is likely present |
653 aec->stateCounter++; | 686 aec->stateCounter++; |
654 } | 687 } |
655 | 688 |
656 if (aec->linoutlevel.framelevel.EndOfBlock()) { | 689 if (aec->linoutlevel.framelevel.EndOfBlock()) { |
657 aec->divergent_filter_fraction.AddObservation(aec->nearlevel, | 690 aec->divergent_filter_fraction.AddObservation(aec->nearlevel, |
658 aec->linoutlevel, | 691 aec->linoutlevel, |
659 aec->nlpoutlevel); | 692 aec->nlpoutlevel); |
660 } | 693 } |
661 | 694 |
662 if (aec->farlevel.averagelevel.EndOfBlock()) { | 695 if (aec->farlevel.averagelevel.EndOfBlock()) { |
663 if (aec->farlevel.minlevel < noisyPower) { | 696 if (aec->farlevel.minlevel < noisyPower) { |
664 actThreshold = actThresholdClean; | 697 actThreshold = actThresholdClean; |
665 } else { | 698 } else { |
666 actThreshold = actThresholdNoisy; | 699 actThreshold = actThresholdNoisy; |
667 } | 700 } |
668 | 701 |
669 const float far_average_level = aec->farlevel.averagelevel.GetLatestMean(); | 702 const float far_average_level = aec->farlevel.averagelevel.GetLatestMean(); |
670 | 703 |
671 // The last condition is to let estimation be made in active far-end | 704 // The last condition is to let estimation be made in active far-end |
672 // segments only. | 705 // segments only. |
673 if ((aec->stateCounter > (0.5f * kCountLen * kSubCountLen)) && | 706 if ((aec->stateCounter > (0.5f * kCountLen * kSubCountLen)) && |
674 (aec->farlevel.framelevel.EndOfBlock()) && | 707 (aec->farlevel.framelevel.EndOfBlock()) && |
675 (far_average_level > (actThreshold * aec->farlevel.minlevel))) { | 708 (far_average_level > (actThreshold * aec->farlevel.minlevel))) { |
676 | 709 |
710 // ERL: error return loss. | |
677 const float near_average_level = | 711 const float near_average_level = |
678 aec->nearlevel.averagelevel.GetLatestMean(); | 712 aec->nearlevel.averagelevel.GetLatestMean(); |
713 UpdateLogRatioMetric(&aec->erl, far_average_level, near_average_level); | |
679 | 714 |
680 // Subtract noise power | 715 // A_NLP: error return loss enhanced before the nonlinear suppression. |
681 echo = near_average_level - safety * aec->nearlevel.minlevel; | |
682 | |
683 // ERL | |
684 dtmp = 10 * static_cast<float>(log10(far_average_level / | |
685 near_average_level + 1e-10f)); | |
686 | |
687 aec->erl.instant = dtmp; | |
688 if (dtmp > aec->erl.max) { | |
689 aec->erl.max = dtmp; | |
690 } | |
691 | |
692 if (dtmp < aec->erl.min) { | |
693 aec->erl.min = dtmp; | |
694 } | |
695 | |
696 aec->erl.counter++; | |
697 aec->erl.sum += dtmp; | |
698 aec->erl.average = aec->erl.sum / aec->erl.counter; | |
699 | |
700 // Upper mean | |
701 if (dtmp > aec->erl.average) { | |
702 aec->erl.hicounter++; | |
703 aec->erl.hisum += dtmp; | |
704 aec->erl.himean = aec->erl.hisum / aec->erl.hicounter; | |
705 } | |
706 | |
707 // A_NLP | |
708 const float linout_average_level = | 716 const float linout_average_level = |
709 aec->linoutlevel.averagelevel.GetLatestMean(); | 717 aec->linoutlevel.averagelevel.GetLatestMean(); |
710 dtmp = 10 * static_cast<float>(log10(near_average_level / | 718 UpdateLogRatioMetric(&aec->aNlp, near_average_level, |
711 linout_average_level + 1e-10f)); | 719 linout_average_level); |
712 | 720 |
713 // subtract noise power | 721 // ERLE: error return loss enhanced. |
714 suppressedEcho = | |
715 linout_average_level - safety * aec->linoutlevel.minlevel; | |
716 | |
717 aec->aNlp.instant = | |
718 10 * static_cast<float>(log10(echo / suppressedEcho + 1e-10f)); | |
719 | |
720 if (dtmp > aec->aNlp.max) { | |
721 aec->aNlp.max = dtmp; | |
722 } | |
723 | |
724 if (dtmp < aec->aNlp.min) { | |
725 aec->aNlp.min = dtmp; | |
726 } | |
727 | |
728 aec->aNlp.counter++; | |
729 aec->aNlp.sum += dtmp; | |
730 aec->aNlp.average = aec->aNlp.sum / aec->aNlp.counter; | |
731 | |
732 // Upper mean | |
733 if (dtmp > aec->aNlp.average) { | |
734 aec->aNlp.hicounter++; | |
735 aec->aNlp.hisum += dtmp; | |
736 aec->aNlp.himean = aec->aNlp.hisum / aec->aNlp.hicounter; | |
737 } | |
738 | |
739 // ERLE | |
740 const float nlpout_average_level = | 722 const float nlpout_average_level = |
741 aec->nlpoutlevel.averagelevel.GetLatestMean(); | 723 aec->nlpoutlevel.averagelevel.GetLatestMean(); |
742 // subtract noise power | 724 UpdateLogRatioMetric(&aec->erle, near_average_level, |
743 suppressedEcho = | 725 nlpout_average_level); |
744 nlpout_average_level - safety * aec->nlpoutlevel.minlevel; | |
745 dtmp = 10 * static_cast<float>(log10(echo / suppressedEcho + 1e-10f)); | |
746 | |
747 aec->erle.instant = dtmp; | |
748 if (dtmp > aec->erle.max) { | |
749 aec->erle.max = dtmp; | |
750 } | |
751 | |
752 if (dtmp < aec->erle.min) { | |
753 aec->erle.min = dtmp; | |
754 } | |
755 | |
756 aec->erle.counter++; | |
757 aec->erle.sum += dtmp; | |
758 aec->erle.average = aec->erle.sum / aec->erle.counter; | |
759 | |
760 // Upper mean | |
761 if (dtmp > aec->erle.average) { | |
762 aec->erle.hicounter++; | |
763 aec->erle.hisum += dtmp; | |
764 aec->erle.himean = aec->erle.hisum / aec->erle.hicounter; | |
765 } | |
766 } | 726 } |
767 | 727 |
768 aec->stateCounter = 0; | 728 aec->stateCounter = 0; |
769 } | 729 } |
770 } | 730 } |
771 | 731 |
772 static void UpdateDelayMetrics(AecCore* self) { | 732 static void UpdateDelayMetrics(AecCore* self) { |
773 int i = 0; | 733 int i = 0; |
774 int delay_values = 0; | 734 int delay_values = 0; |
775 int median = 0; | 735 int median = 0; |
(...skipping 1168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1944 | 1904 |
1945 int WebRtcAec_system_delay(AecCore* self) { | 1905 int WebRtcAec_system_delay(AecCore* self) { |
1946 return self->system_delay; | 1906 return self->system_delay; |
1947 } | 1907 } |
1948 | 1908 |
1949 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { | 1909 void WebRtcAec_SetSystemDelay(AecCore* self, int delay) { |
1950 assert(delay >= 0); | 1910 assert(delay >= 0); |
1951 self->system_delay = delay; | 1911 self->system_delay = delay; |
1952 } | 1912 } |
1953 } // namespace webrtc | 1913 } // namespace webrtc |
OLD | NEW |