Bug Summary

File:root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc
Warning:line 140, column 41
Division by zero

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name gain_control_impl.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/modules/audio_processing/audio_processing_gn -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/modules/audio_processing/audio_processing_gn -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D ABSL_ALLOCATOR_NOTHROW=1 -D PROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII=0 -D RTC_DAV1D_IN_INTERNAL_DECODER_FACTORY -D RTC_ENABLE_VP9 -D WEBRTC_APM_DEBUG_DUMP=1 -D WEBRTC_DEPRECATE_PLAN_B -D WEBRTC_ENABLE_PROTOBUF=0 -D WEBRTC_ENCODER_PSNR_STATS -D WEBRTC_LIBRARY_IMPL -D WEBRTC_MOZILLA_BUILD -D WEBRTC_NON_STATIC_TRACE_EVENT_HANDLERS=0 -D WEBRTC_STRICT_FIELD_TRIALS=0 -D DYNAMIC_ANNOTATIONS_ENABLED=1 -D USE_AURA=1 -D USE_GLIB=1 -D USE_OZONE=1 -D USE_UDEV -D WEBRTC_LINUX -D WEBRTC_POSIX -D _FILE_OFFSET_BITS=64 -D _LARGEFILE64_SOURCE -D _LARGEFILE_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D WEBRTC_ENABLE_AVX2 -D _DEBUG -D _GNU_SOURCE -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/third_party/libwebrtc/modules/audio_processing/audio_processing_gn -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/modules/audio_processing/audio_processing_gn -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/libwebrtc_overrides -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/third_party/libwebrtc/gen -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/third_party/libwebrtc -I /root/firefox-clang/tools/profiler/public -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ /root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc
1/*
2 * Copyright (c) 2012 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/gain_control_impl.h"
12
13#include <algorithm>
14#include <array>
15#include <cstddef>
16#include <cstdint>
17#include <optional>
18#include <span>
19#include <vector>
20
21#include "api/audio/audio_processing.h"
22#include "common_audio/include/audio_util.h"
23#include "modules/audio_processing/agc/gain_control.h"
24#include "modules/audio_processing/agc/legacy/gain_control.h"
25#include "modules/audio_processing/audio_buffer.h"
26#include "modules/audio_processing/logging/apm_data_dumper.h"
27#include "rtc_base/checks.h"
28#include "rtc_base/logging.h"
29
30namespace webrtc {
31
32typedef void Handle;
33
34namespace {
35int16_t MapSetting(GainControl::Mode mode) {
36 switch (mode) {
37 case GainControl::kAdaptiveAnalog:
38 return kAgcModeAdaptiveAnalog;
39 case GainControl::kAdaptiveDigital:
40 return kAgcModeAdaptiveDigital;
41 case GainControl::kFixedDigital:
42 return kAgcModeFixedDigital;
43 }
44 RTC_DCHECK_NOTREACHED()(false) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 44, "false") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
45 return -1;
46}
47
48// Applies the sub-frame `gains` to all the bands in `out` and clamps the output
49// in the signed 16 bit range.
50void ApplyDigitalGain(const int32_t gains[11],
51 size_t num_bands,
52 float* const* out) {
53 constexpr float kScaling = 1.f / 65536.f;
54 constexpr int kNumSubSections = 16;
55 constexpr float kOneByNumSubSections = 1.f / kNumSubSections;
56
57 float gains_scaled[11];
58 for (int k = 0; k < 11; ++k) {
59 gains_scaled[k] = gains[k] * kScaling;
60 }
61
62 for (size_t b = 0; b < num_bands; ++b) {
63 float* out_band = out[b];
64 for (int k = 0, sample = 0; k < 10; ++k) {
65 const float delta =
66 (gains_scaled[k + 1] - gains_scaled[k]) * kOneByNumSubSections;
67 float gain = gains_scaled[k];
68 for (int n = 0; n < kNumSubSections; ++n, ++sample) {
69 RTC_DCHECK_EQ(k * kNumSubSections + n, sample)::webrtc::SafeEq((k * kNumSubSections + n), (sample)) ? static_cast
<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<
true>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 69, "k * kNumSubSections + n" " " "==" " " "sample") & ::
webrtc::webrtc_checks_impl::LogStreamer<>() << (k
* kNumSubSections + n) << (sample)
;
70 out_band[sample] *= gain;
71 out_band[sample] =
72 std::min(32767.f, std::max(-32768.f, out_band[sample]));
73 gain += delta;
74 }
75 }
76 }
77}
78
79} // namespace
80
81struct GainControlImpl::MonoAgcState {
82 MonoAgcState() {
83 state = WebRtcAgc_Create();
84 RTC_CHECK(state)(state) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 84, "state") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
85 }
86
87 ~MonoAgcState() {
88 RTC_DCHECK(state)(state) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 88, "state") & ::webrtc::webrtc_checks_impl::LogStreamer
<>()
;
89 WebRtcAgc_Free(state);
90 }
91
92 MonoAgcState(const MonoAgcState&) = delete;
93 MonoAgcState& operator=(const MonoAgcState&) = delete;
94 int32_t gains[11];
95 Handle* state;
96};
97
98int GainControlImpl::instance_counter_ = 0;
99
100GainControlImpl::GainControlImpl()
101 : data_dumper_(new ApmDataDumper(instance_counter_)),
102 mode_(kAdaptiveAnalog),
103 minimum_capture_level_(0),
104 maximum_capture_level_(255),
105 limiter_enabled_(true),
106 target_level_dbfs_(3),
107 compression_gain_db_(9),
108 analog_capture_level_(0),
109 was_analog_level_set_(false),
110 stream_is_saturated_(false) {}
111
112GainControlImpl::~GainControlImpl() = default;
113
114void GainControlImpl::ProcessRenderAudio(
115 std::span<const int16_t> packed_render_audio) {
116 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
117 WebRtcAgc_AddFarend(mono_agcs_[ch]->state, packed_render_audio.data(),
118 packed_render_audio.size());
119 }
120}
121
122void GainControlImpl::PackRenderAudioBuffer(
123 const AudioBuffer& audio,
124 std::vector<int16_t>* packed_buffer) {
125 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength, audio.num_frames_per_band())::webrtc::SafeGe((AudioBuffer::kMaxSplitFrameLength), (audio.
num_frames_per_band())) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<true>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 125, "AudioBuffer::kMaxSplitFrameLength" " " ">=" " " "audio.num_frames_per_band()"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(AudioBuffer::kMaxSplitFrameLength) << (audio.num_frames_per_band
())
;
1
'?' condition is true
126 std::array<int16_t, AudioBuffer::kMaxSplitFrameLength>
127 mixed_16_kHz_render_data;
128 std::span<const int16_t> mixed_16_kHz_render(mixed_16_kHz_render_data.data(),
129 audio.num_frames_per_band());
130 if (audio.num_channels() == 1) {
2
Assuming the condition is false
3
Taking false branch
131 FloatS16ToS16(audio.split_bands_const(0)[kBand0To8kHz],
132 audio.num_frames_per_band(), mixed_16_kHz_render_data.data());
133 } else {
134 const int num_channels = static_cast<int>(audio.num_channels());
4
'num_channels' initialized here
135 for (size_t i = 0; i < audio.num_frames_per_band(); ++i) {
5
Assuming the condition is true
6
Loop condition is true. Entering loop body
136 int32_t sum = 0;
137 for (int ch = 0; ch < num_channels; ++ch) {
7
Assuming 'ch' is >= 'num_channels'
8
Loop condition is false. Execution continues on line 140
138 sum += FloatS16ToS16(audio.split_channels_const(kBand0To8kHz)[ch][i]);
139 }
140 mixed_16_kHz_render_data[i] = sum / num_channels;
9
Division by zero
141 }
142 }
143
144 packed_buffer->clear();
145 packed_buffer->insert(
146 packed_buffer->end(), mixed_16_kHz_render.data(),
147 (mixed_16_kHz_render.data() + audio.num_frames_per_band()));
148}
149
150int GainControlImpl::AnalyzeCaptureAudio(const AudioBuffer& audio) {
151 RTC_DCHECK(num_proc_channels_)(num_proc_channels_) ? static_cast<void>(0) : ::webrtc::
webrtc_checks_impl::FatalLogCall<false>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 151, "num_proc_channels_") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
152 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength, audio.num_frames_per_band())::webrtc::SafeGe((AudioBuffer::kMaxSplitFrameLength), (audio.
num_frames_per_band())) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<true>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 152, "AudioBuffer::kMaxSplitFrameLength" " " ">=" " " "audio.num_frames_per_band()"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(AudioBuffer::kMaxSplitFrameLength) << (audio.num_frames_per_band
())
;
153 RTC_DCHECK_EQ(audio.num_channels(), *num_proc_channels_)::webrtc::SafeEq((audio.num_channels()), (*num_proc_channels_
)) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<true>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 153, "audio.num_channels()" " " "==" " " "*num_proc_channels_"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(audio.num_channels()) << (*num_proc_channels_)
;
154 RTC_DCHECK_LE(*num_proc_channels_, mono_agcs_.size())::webrtc::SafeLe((*num_proc_channels_), (mono_agcs_.size())) ?
static_cast<void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall
<true>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 154, "*num_proc_channels_" " " "<=" " " "mono_agcs_.size()"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(*num_proc_channels_) << (mono_agcs_.size())
;
155
156 int16_t split_band_data[AudioBuffer::kMaxNumBands]
157 [AudioBuffer::kMaxSplitFrameLength];
158 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
159 split_band_data[0], split_band_data[1], split_band_data[2]};
160
161 if (mode_ == kAdaptiveAnalog) {
162 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
163 capture_levels_[ch] = analog_capture_level_;
164
165 audio.ExportSplitChannelData(ch, split_bands);
166
167 int err =
168 WebRtcAgc_AddMic(mono_agcs_[ch]->state, split_bands,
169 audio.num_bands(), audio.num_frames_per_band());
170
171 if (err != AudioProcessing::kNoError) {
172 return AudioProcessing::kUnspecifiedError;
173 }
174 }
175 } else if (mode_ == kAdaptiveDigital) {
176 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
177 int32_t capture_level_out = 0;
178
179 audio.ExportSplitChannelData(ch, split_bands);
180
181 int err =
182 WebRtcAgc_VirtualMic(mono_agcs_[ch]->state, split_bands,
183 audio.num_bands(), audio.num_frames_per_band(),
184 analog_capture_level_, &capture_level_out);
185
186 capture_levels_[ch] = capture_level_out;
187
188 if (err != AudioProcessing::kNoError) {
189 return AudioProcessing::kUnspecifiedError;
190 }
191 }
192 }
193
194 return AudioProcessing::kNoError;
195}
196
197int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio,
198 bool stream_has_echo) {
199 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
200 return AudioProcessing::kStreamParameterNotSetError;
201 }
202
203 RTC_DCHECK(num_proc_channels_)(num_proc_channels_) ? static_cast<void>(0) : ::webrtc::
webrtc_checks_impl::FatalLogCall<false>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 203, "num_proc_channels_") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
204 RTC_DCHECK_GE(AudioBuffer::kMaxSplitFrameLength,::webrtc::SafeGe((AudioBuffer::kMaxSplitFrameLength), (audio->
num_frames_per_band())) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<true>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 205, "AudioBuffer::kMaxSplitFrameLength" " " ">=" " " "audio->num_frames_per_band()"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(AudioBuffer::kMaxSplitFrameLength) << (audio->num_frames_per_band
())
205 audio->num_frames_per_band())::webrtc::SafeGe((AudioBuffer::kMaxSplitFrameLength), (audio->
num_frames_per_band())) ? static_cast<void>(0) : ::webrtc
::webrtc_checks_impl::FatalLogCall<true>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 205, "AudioBuffer::kMaxSplitFrameLength" " " ">=" " " "audio->num_frames_per_band()"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(AudioBuffer::kMaxSplitFrameLength) << (audio->num_frames_per_band
())
;
206 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_)::webrtc::SafeEq((audio->num_channels()), (*num_proc_channels_
)) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<true>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 206, "audio->num_channels()" " " "==" " " "*num_proc_channels_"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>() <<
(audio->num_channels()) << (*num_proc_channels_)
;
207
208 stream_is_saturated_ = false;
209 bool error_reported = false;
210 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
211 int16_t split_band_data[AudioBuffer::kMaxNumBands]
212 [AudioBuffer::kMaxSplitFrameLength];
213 int16_t* split_bands[AudioBuffer::kMaxNumBands] = {
214 split_band_data[0], split_band_data[1], split_band_data[2]};
215 audio->ExportSplitChannelData(ch, split_bands);
216
217 // The call to stream_has_echo() is ok from a deadlock perspective
218 // as the capture lock is allready held.
219 int32_t new_capture_level = 0;
220 uint8_t saturation_warning = 0;
221 int err_analyze = WebRtcAgc_Analyze(
222 mono_agcs_[ch]->state, split_bands, audio->num_bands(),
223 audio->num_frames_per_band(), capture_levels_[ch], &new_capture_level,
224 stream_has_echo, &saturation_warning, mono_agcs_[ch]->gains);
225 capture_levels_[ch] = new_capture_level;
226
227 error_reported = error_reported || err_analyze != AudioProcessing::kNoError;
228
229 stream_is_saturated_ = stream_is_saturated_ || saturation_warning == 1;
230 }
231
232 // Choose the minimun gain for application
233 size_t index_to_apply = 0;
234 for (size_t ch = 1; ch < mono_agcs_.size(); ++ch) {
235 if (mono_agcs_[index_to_apply]->gains[10] < mono_agcs_[ch]->gains[10]) {
236 index_to_apply = ch;
237 }
238 }
239
240 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
241 ApplyDigitalGain(mono_agcs_[index_to_apply]->gains, audio->num_bands(),
242 audio->split_bands(ch));
243 }
244
245 RTC_DCHECK_LT(0ul, *num_proc_channels_)::webrtc::SafeLt((0ul), (*num_proc_channels_)) ? static_cast<
void>(0) : ::webrtc::webrtc_checks_impl::FatalLogCall<true
>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 245, "0ul" " " "<" " " "*num_proc_channels_") & ::webrtc
::webrtc_checks_impl::LogStreamer<>() << (0ul) <<
(*num_proc_channels_)
;
246 if (mode_ == kAdaptiveAnalog) {
247 // Take the analog level to be the minimum accross all channels.
248 analog_capture_level_ = capture_levels_[0];
249 for (size_t ch = 1; ch < mono_agcs_.size(); ++ch) {
250 analog_capture_level_ =
251 std::min(analog_capture_level_, capture_levels_[ch]);
252 }
253 }
254
255 if (error_reported) {
256 return AudioProcessing::kUnspecifiedError;
257 }
258
259 was_analog_level_set_ = false;
260
261 return AudioProcessing::kNoError;
262}
263
264// TODO(ajm): ensure this is called under kAdaptiveAnalog.
265int GainControlImpl::set_stream_analog_level(int level) {
266 data_dumper_->DumpRaw("gain_control_set_stream_analog_level", 1, &level);
267
268 was_analog_level_set_ = true;
269 if (level < minimum_capture_level_ || level > maximum_capture_level_) {
270 return AudioProcessing::kBadParameterError;
271 }
272 analog_capture_level_ = level;
273
274 return AudioProcessing::kNoError;
275}
276
277int GainControlImpl::stream_analog_level() const {
278 data_dumper_->DumpRaw("gain_control_stream_analog_level", 1,
279 &analog_capture_level_);
280 return analog_capture_level_;
281}
282
283int GainControlImpl::set_mode(Mode mode) {
284 if (MapSetting(mode) == -1) {
285 return AudioProcessing::kBadParameterError;
286 }
287
288 mode_ = mode;
289 RTC_DCHECK(num_proc_channels_)(num_proc_channels_) ? static_cast<void>(0) : ::webrtc::
webrtc_checks_impl::FatalLogCall<false>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 289, "num_proc_channels_") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
290 RTC_DCHECK(sample_rate_hz_)(sample_rate_hz_) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 290, "sample_rate_hz_") & ::webrtc::webrtc_checks_impl::
LogStreamer<>()
;
291 Initialize(*num_proc_channels_, *sample_rate_hz_);
292 return AudioProcessing::kNoError;
293}
294
295int GainControlImpl::set_analog_level_limits(int minimum, int maximum) {
296 if (minimum < 0 || maximum > 65535 || maximum < minimum) {
297 return AudioProcessing::kBadParameterError;
298 }
299
300 minimum_capture_level_ = minimum;
301 maximum_capture_level_ = maximum;
302
303 RTC_DCHECK(num_proc_channels_)(num_proc_channels_) ? static_cast<void>(0) : ::webrtc::
webrtc_checks_impl::FatalLogCall<false>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 303, "num_proc_channels_") & ::webrtc::webrtc_checks_impl
::LogStreamer<>()
;
304 RTC_DCHECK(sample_rate_hz_)(sample_rate_hz_) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 304, "sample_rate_hz_") & ::webrtc::webrtc_checks_impl::
LogStreamer<>()
;
305 Initialize(*num_proc_channels_, *sample_rate_hz_);
306 return AudioProcessing::kNoError;
307}
308
309int GainControlImpl::set_target_level_dbfs(int level) {
310 if (level > 31 || level < 0) {
311 return AudioProcessing::kBadParameterError;
312 }
313 target_level_dbfs_ = level;
314 return Configure();
315}
316
317int GainControlImpl::set_compression_gain_db(int gain) {
318 if (gain < 0 || gain > 90) {
319 RTC_LOG(LS_ERROR)!::webrtc::LogMessage::IsNoop<::webrtc::LS_ERROR>() &&
::webrtc::webrtc_logging_impl::LogCall() & ::webrtc::webrtc_logging_impl
::LogStreamer<>() << ::webrtc::webrtc_logging_impl
::LogMetadata("/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 319, ::webrtc::LS_ERROR)
<< "set_compression_gain_db(" << gain << ") failed.";
320 return AudioProcessing::kBadParameterError;
321 }
322 compression_gain_db_ = gain;
323 return Configure();
324}
325
326int GainControlImpl::enable_limiter(bool enable) {
327 limiter_enabled_ = enable;
328 return Configure();
329}
330
331void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) {
332 RTC_DCHECK(sample_rate_hz == 16000 || sample_rate_hz == 32000 ||(sample_rate_hz == 16000 || sample_rate_hz == 32000 || sample_rate_hz
== 48000) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 333, "sample_rate_hz == 16000 || sample_rate_hz == 32000 || sample_rate_hz == 48000"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
333 sample_rate_hz == 48000)(sample_rate_hz == 16000 || sample_rate_hz == 32000 || sample_rate_hz
== 48000) ? static_cast<void>(0) : ::webrtc::webrtc_checks_impl
::FatalLogCall<false>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 333, "sample_rate_hz == 16000 || sample_rate_hz == 32000 || sample_rate_hz == 48000"
) & ::webrtc::webrtc_checks_impl::LogStreamer<>()
;
334
335 num_proc_channels_ = num_proc_channels;
336 sample_rate_hz_ = sample_rate_hz;
337
338 mono_agcs_.resize(*num_proc_channels_);
339 capture_levels_.resize(*num_proc_channels_);
340 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
341 if (!mono_agcs_[ch]) {
342 mono_agcs_[ch].reset(new MonoAgcState());
343 }
344
345 int error = WebRtcAgc_Init(mono_agcs_[ch]->state, minimum_capture_level_,
346 maximum_capture_level_, MapSetting(mode_),
347 *sample_rate_hz_);
348 RTC_DCHECK_EQ(error, 0)::webrtc::SafeEq((error), (0)) ? static_cast<void>(0) :
::webrtc::webrtc_checks_impl::FatalLogCall<true>( "/root/firefox-clang/third_party/libwebrtc/modules/audio_processing/gain_control_impl.cc"
, 348, "error" " " "==" " " "0") & ::webrtc::webrtc_checks_impl
::LogStreamer<>() << (error) << (0)
;
349 capture_levels_[ch] = analog_capture_level_;
350 }
351
352 Configure();
353}
354
355int GainControlImpl::Configure() {
356 WebRtcAgcConfig config;
357 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
358 // change the interface.
359 // RTC_DCHECK_LE(target_level_dbfs_, 0);
360 // config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
361 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
362 config.compressionGaindB = static_cast<int16_t>(compression_gain_db_);
363 config.limiterEnable = limiter_enabled_;
364
365 int error = AudioProcessing::kNoError;
366 for (size_t ch = 0; ch < mono_agcs_.size(); ++ch) {
367 int error_ch = WebRtcAgc_set_config(mono_agcs_[ch]->state, config);
368 if (error_ch != AudioProcessing::kNoError) {
369 error = error_ch;
370 }
371 }
372 return error;
373}
374} // namespace webrtc