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_digital_gain_controller.h"
12
13 #include <algorithm>
14
15 #include "common_audio/include/audio_util.h"
16 #include "modules/audio_processing/logging/apm_data_dumper.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/logging.h"
19
20 namespace webrtc {
21 namespace {
22
23 // Peak and RMS audio levels in dBFS.
24 struct AudioLevels {
25 float peak_dbfs;
26 float rms_dbfs;
27 };
28
29 // Computes the audio levels for the first channel in `frame`.
ComputeAudioLevels(AudioFrameView<float> frame)30 AudioLevels ComputeAudioLevels(AudioFrameView<float> frame) {
31 float peak = 0.0f;
32 float rms = 0.0f;
33 for (const auto& x : frame.channel(0)) {
34 peak = std::max(std::fabs(x), peak);
35 rms += x * x;
36 }
37 return {FloatS16ToDbfs(peak),
38 FloatS16ToDbfs(std::sqrt(rms / frame.samples_per_channel()))};
39 }
40
41 } // namespace
42
AdaptiveDigitalGainController(ApmDataDumper * apm_data_dumper,const AudioProcessing::Config::GainController2::AdaptiveDigital & config,int sample_rate_hz,int num_channels)43 AdaptiveDigitalGainController::AdaptiveDigitalGainController(
44 ApmDataDumper* apm_data_dumper,
45 const AudioProcessing::Config::GainController2::AdaptiveDigital& config,
46 int sample_rate_hz,
47 int num_channels)
48 : speech_level_estimator_(apm_data_dumper, config),
49 gain_controller_(apm_data_dumper, config, sample_rate_hz, num_channels),
50 apm_data_dumper_(apm_data_dumper),
51 noise_level_estimator_(CreateNoiseFloorEstimator(apm_data_dumper)),
52 saturation_protector_(
53 CreateSaturationProtector(kSaturationProtectorInitialHeadroomDb,
54 config.adjacent_speech_frames_threshold,
55 apm_data_dumper)) {
56 RTC_DCHECK(apm_data_dumper);
57 RTC_DCHECK(noise_level_estimator_);
58 RTC_DCHECK(saturation_protector_);
59 }
60
61 AdaptiveDigitalGainController::~AdaptiveDigitalGainController() = default;
62
Initialize(int sample_rate_hz,int num_channels)63 void AdaptiveDigitalGainController::Initialize(int sample_rate_hz,
64 int num_channels) {
65 gain_controller_.Initialize(sample_rate_hz, num_channels);
66 }
67
Process(AudioFrameView<float> frame,float speech_probability,float limiter_envelope)68 void AdaptiveDigitalGainController::Process(AudioFrameView<float> frame,
69 float speech_probability,
70 float limiter_envelope) {
71 AudioLevels levels = ComputeAudioLevels(frame);
72 apm_data_dumper_->DumpRaw("agc2_input_rms_dbfs", levels.rms_dbfs);
73 apm_data_dumper_->DumpRaw("agc2_input_peak_dbfs", levels.peak_dbfs);
74
75 AdaptiveDigitalGainApplier::FrameInfo info;
76
77 info.speech_probability = speech_probability;
78
79 speech_level_estimator_.Update(levels.rms_dbfs, levels.peak_dbfs,
80 info.speech_probability);
81 info.speech_level_dbfs = speech_level_estimator_.level_dbfs();
82 info.speech_level_reliable = speech_level_estimator_.IsConfident();
83 apm_data_dumper_->DumpRaw("agc2_speech_level_dbfs", info.speech_level_dbfs);
84 apm_data_dumper_->DumpRaw("agc2_speech_level_reliable",
85 info.speech_level_reliable);
86
87 info.noise_rms_dbfs = noise_level_estimator_->Analyze(frame);
88 apm_data_dumper_->DumpRaw("agc2_noise_rms_dbfs", info.noise_rms_dbfs);
89
90 saturation_protector_->Analyze(info.speech_probability, levels.peak_dbfs,
91 info.speech_level_dbfs);
92 info.headroom_db = saturation_protector_->HeadroomDb();
93 apm_data_dumper_->DumpRaw("agc2_headroom_db", info.headroom_db);
94
95 info.limiter_envelope_dbfs = FloatS16ToDbfs(limiter_envelope);
96 apm_data_dumper_->DumpRaw("agc2_limiter_envelope_dbfs",
97 info.limiter_envelope_dbfs);
98
99 gain_controller_.Process(info, frame);
100 }
101
HandleInputGainChange()102 void AdaptiveDigitalGainController::HandleInputGainChange() {
103 speech_level_estimator_.Reset();
104 saturation_protector_->Reset();
105 }
106
107 absl::optional<float>
GetSpeechLevelDbfsIfConfident() const108 AdaptiveDigitalGainController::GetSpeechLevelDbfsIfConfident() const {
109 return speech_level_estimator_.IsConfident()
110 ? absl::optional<float>(speech_level_estimator_.level_dbfs())
111 : absl::nullopt;
112 }
113
114 } // namespace webrtc
115