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