1 /* 2 * Copyright (c) 2013 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 #ifndef MODULES_AUDIO_PROCESSING_AGC_AGC_MANAGER_DIRECT_H_ 12 #define MODULES_AUDIO_PROCESSING_AGC_AGC_MANAGER_DIRECT_H_ 13 14 #include <memory> 15 16 #include "absl/types/optional.h" 17 #include "modules/audio_processing/agc/agc.h" 18 #include "modules/audio_processing/audio_buffer.h" 19 #include "modules/audio_processing/logging/apm_data_dumper.h" 20 #include "rtc_base/gtest_prod_util.h" 21 22 namespace webrtc { 23 24 class MonoAgc; 25 class GainControl; 26 27 // Direct interface to use AGC to set volume and compression values. 28 // AudioProcessing uses this interface directly to integrate the callback-less 29 // AGC. 30 // 31 // This class is not thread-safe. 32 class AgcManagerDirect final { 33 public: 34 // AgcManagerDirect will configure GainControl internally. The user is 35 // responsible for processing the audio using it after the call to Process. 36 // The operating range of startup_min_level is [12, 255] and any input value 37 // outside that range will be clamped. 38 AgcManagerDirect(int num_capture_channels, 39 int startup_min_level, 40 int clipped_level_min, 41 bool use_agc2_level_estimation, 42 bool disable_digital_adaptive, 43 int sample_rate_hz); 44 45 ~AgcManagerDirect(); 46 AgcManagerDirect(const AgcManagerDirect&) = delete; 47 AgcManagerDirect& operator=(const AgcManagerDirect&) = delete; 48 49 void Initialize(); 50 void SetupDigitalGainControl(GainControl* gain_control) const; 51 52 void AnalyzePreProcess(const AudioBuffer* audio); 53 void Process(const AudioBuffer* audio); 54 55 // Call when the capture stream has been muted/unmuted. This causes the 56 // manager to disregard all incoming audio; chances are good it's background 57 // noise to which we'd like to avoid adapting. 58 void SetCaptureMuted(bool muted); 59 float voice_probability() const; 60 stream_analog_level()61 int stream_analog_level() const { return stream_analog_level_; } 62 void set_stream_analog_level(int level); num_channels()63 int num_channels() const { return num_capture_channels_; } sample_rate_hz()64 int sample_rate_hz() const { return sample_rate_hz_; } 65 66 // If available, returns a new compression gain for the digital gain control. 67 absl::optional<int> GetDigitalComressionGain(); 68 69 private: 70 friend class AgcManagerDirectTest; 71 72 FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest, 73 DisableDigitalDisablesDigital); 74 FRIEND_TEST_ALL_PREFIXES(AgcManagerDirectStandaloneTest, 75 AgcMinMicLevelExperiment); 76 77 // Dependency injection for testing. Don't delete |agc| as the memory is owned 78 // by the manager. 79 AgcManagerDirect(Agc* agc, 80 int startup_min_level, 81 int clipped_level_min, 82 int sample_rate_hz); 83 84 void AnalyzePreProcess(const float* const* audio, size_t samples_per_channel); 85 86 void AggregateChannelLevels(); 87 88 std::unique_ptr<ApmDataDumper> data_dumper_; 89 static int instance_counter_; 90 const bool use_min_channel_level_; 91 const int sample_rate_hz_; 92 const int num_capture_channels_; 93 const bool disable_digital_adaptive_; 94 95 int frames_since_clipped_; 96 int stream_analog_level_ = 0; 97 bool capture_muted_; 98 int channel_controlling_gain_ = 0; 99 100 std::vector<std::unique_ptr<MonoAgc>> channel_agcs_; 101 std::vector<absl::optional<int>> new_compressions_to_set_; 102 }; 103 104 class MonoAgc { 105 public: 106 MonoAgc(ApmDataDumper* data_dumper, 107 int startup_min_level, 108 int clipped_level_min, 109 bool use_agc2_level_estimation, 110 bool disable_digital_adaptive, 111 int min_mic_level); 112 ~MonoAgc(); 113 MonoAgc(const MonoAgc&) = delete; 114 MonoAgc& operator=(const MonoAgc&) = delete; 115 116 void Initialize(); 117 void SetCaptureMuted(bool muted); 118 119 void HandleClipping(); 120 121 void Process(const int16_t* audio, 122 size_t samples_per_channel, 123 int sample_rate_hz); 124 set_stream_analog_level(int level)125 void set_stream_analog_level(int level) { stream_analog_level_ = level; } stream_analog_level()126 int stream_analog_level() const { return stream_analog_level_; } voice_probability()127 float voice_probability() const { return agc_->voice_probability(); } ActivateLogging()128 void ActivateLogging() { log_to_histograms_ = true; } new_compression()129 absl::optional<int> new_compression() const { 130 return new_compression_to_set_; 131 } 132 133 // Only used for testing. set_agc(Agc * agc)134 void set_agc(Agc* agc) { agc_.reset(agc); } min_mic_level()135 int min_mic_level() const { return min_mic_level_; } startup_min_level()136 int startup_min_level() const { return startup_min_level_; } 137 138 private: 139 // Sets a new microphone level, after first checking that it hasn't been 140 // updated by the user, in which case no action is taken. 141 void SetLevel(int new_level); 142 143 // Set the maximum level the AGC is allowed to apply. Also updates the 144 // maximum compression gain to compensate. The level must be at least 145 // |kClippedLevelMin|. 146 void SetMaxLevel(int level); 147 148 int CheckVolumeAndReset(); 149 void UpdateGain(); 150 void UpdateCompressor(); 151 152 const int min_mic_level_; 153 const bool disable_digital_adaptive_; 154 std::unique_ptr<Agc> agc_; 155 int level_ = 0; 156 int max_level_; 157 int max_compression_gain_; 158 int target_compression_; 159 int compression_; 160 float compression_accumulator_; 161 bool capture_muted_ = false; 162 bool check_volume_on_next_process_ = true; 163 bool startup_ = true; 164 int startup_min_level_; 165 int calls_since_last_gain_log_ = 0; 166 int stream_analog_level_ = 0; 167 absl::optional<int> new_compression_to_set_; 168 bool log_to_histograms_ = false; 169 const int clipped_level_min_; 170 }; 171 172 } // namespace webrtc 173 174 #endif // MODULES_AUDIO_PROCESSING_AGC_AGC_MANAGER_DIRECT_H_ 175