1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "modules/audio_processing/agc2/adaptive_mode_level_estimator.h"
12
13 #include "modules/audio_processing/agc2/agc2_common.h"
14 #include "modules/audio_processing/logging/apm_data_dumper.h"
15 #include "rtc_base/checks.h"
16 #include "rtc_base/numerics/safe_minmax.h"
17
18 namespace webrtc {
19
AdaptiveModeLevelEstimator(ApmDataDumper * apm_data_dumper)20 AdaptiveModeLevelEstimator::AdaptiveModeLevelEstimator(
21 ApmDataDumper* apm_data_dumper)
22 : level_estimator_(
23 AudioProcessing::Config::GainController2::LevelEstimator::kRms),
24 use_saturation_protector_(true),
25 saturation_protector_(apm_data_dumper),
26 apm_data_dumper_(apm_data_dumper) {}
27
AdaptiveModeLevelEstimator(ApmDataDumper * apm_data_dumper,AudioProcessing::Config::GainController2::LevelEstimator level_estimator,bool use_saturation_protector,float extra_saturation_margin_db)28 AdaptiveModeLevelEstimator::AdaptiveModeLevelEstimator(
29 ApmDataDumper* apm_data_dumper,
30 AudioProcessing::Config::GainController2::LevelEstimator level_estimator,
31 bool use_saturation_protector,
32 float extra_saturation_margin_db)
33 : level_estimator_(level_estimator),
34 use_saturation_protector_(use_saturation_protector),
35 saturation_protector_(apm_data_dumper, extra_saturation_margin_db),
36 apm_data_dumper_(apm_data_dumper) {}
37
UpdateEstimation(const VadWithLevel::LevelAndProbability & vad_data)38 void AdaptiveModeLevelEstimator::UpdateEstimation(
39 const VadWithLevel::LevelAndProbability& vad_data) {
40 RTC_DCHECK_GT(vad_data.speech_rms_dbfs, -150.f);
41 RTC_DCHECK_LT(vad_data.speech_rms_dbfs, 50.f);
42 RTC_DCHECK_GT(vad_data.speech_peak_dbfs, -150.f);
43 RTC_DCHECK_LT(vad_data.speech_peak_dbfs, 50.f);
44 RTC_DCHECK_GE(vad_data.speech_probability, 0.f);
45 RTC_DCHECK_LE(vad_data.speech_probability, 1.f);
46
47 if (vad_data.speech_probability < kVadConfidenceThreshold) {
48 DebugDumpEstimate();
49 return;
50 }
51
52 const bool buffer_is_full = buffer_size_ms_ >= kFullBufferSizeMs;
53 if (!buffer_is_full) {
54 buffer_size_ms_ += kFrameDurationMs;
55 }
56
57 const float leak_factor = buffer_is_full ? kFullBufferLeakFactor : 1.f;
58
59 // Read speech level estimation.
60 float speech_level_dbfs = 0.f;
61 using LevelEstimatorType =
62 AudioProcessing::Config::GainController2::LevelEstimator;
63 switch (level_estimator_) {
64 case LevelEstimatorType::kRms:
65 speech_level_dbfs = vad_data.speech_rms_dbfs;
66 break;
67 case LevelEstimatorType::kPeak:
68 speech_level_dbfs = vad_data.speech_peak_dbfs;
69 break;
70 }
71
72 // Update speech level estimation.
73 estimate_numerator_ = estimate_numerator_ * leak_factor +
74 speech_level_dbfs * vad_data.speech_probability;
75 estimate_denominator_ =
76 estimate_denominator_ * leak_factor + vad_data.speech_probability;
77 last_estimate_with_offset_dbfs_ = estimate_numerator_ / estimate_denominator_;
78
79 if (use_saturation_protector_) {
80 saturation_protector_.UpdateMargin(vad_data,
81 last_estimate_with_offset_dbfs_);
82 DebugDumpEstimate();
83 }
84 }
85
LatestLevelEstimate() const86 float AdaptiveModeLevelEstimator::LatestLevelEstimate() const {
87 return rtc::SafeClamp<float>(
88 last_estimate_with_offset_dbfs_ +
89 (use_saturation_protector_ ? saturation_protector_.LastMargin()
90 : 0.f),
91 -90.f, 30.f);
92 }
93
Reset()94 void AdaptiveModeLevelEstimator::Reset() {
95 buffer_size_ms_ = 0;
96 last_estimate_with_offset_dbfs_ = kInitialSpeechLevelEstimateDbfs;
97 estimate_numerator_ = 0.f;
98 estimate_denominator_ = 0.f;
99 saturation_protector_.Reset();
100 }
101
DebugDumpEstimate()102 void AdaptiveModeLevelEstimator::DebugDumpEstimate() {
103 if (apm_data_dumper_) {
104 apm_data_dumper_->DumpRaw("agc2_adaptive_level_estimate_with_offset_dbfs",
105 last_estimate_with_offset_dbfs_);
106 apm_data_dumper_->DumpRaw("agc2_adaptive_level_estimate_dbfs",
107 LatestLevelEstimate());
108 }
109 saturation_protector_.DebugDumpEstimate();
110 }
111 } // namespace webrtc
112