Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(443)

Side by Side Diff: webrtc/modules/audio_processing/gain_control_impl.cc

Issue 1768943002: Removed the dependency in GainControlImpl on the ProcessingComponent class (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@RemoveComponentFromAECM_CL
Patch Set: Changes in response to reviewer comments Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/modules/audio_processing/gain_control_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/audio_processing/gain_control_impl.h" 11 #include "webrtc/modules/audio_processing/gain_control_impl.h"
12 12
13 #include <assert.h> 13 #include "webrtc/base/optional.h"
14
15 #include "webrtc/modules/audio_processing/audio_buffer.h" 14 #include "webrtc/modules/audio_processing/audio_buffer.h"
16 #include "webrtc/modules/audio_processing/agc/legacy/gain_control.h" 15 #include "webrtc/modules/audio_processing/agc/legacy/gain_control.h"
17 16
18 namespace webrtc { 17 namespace webrtc {
19 18
20 typedef void Handle; 19 typedef void Handle;
21 20
22 namespace { 21 namespace {
23 int16_t MapSetting(GainControl::Mode mode) { 22 int16_t MapSetting(GainControl::Mode mode) {
24 switch (mode) { 23 switch (mode) {
(...skipping 10 matching lines...) Expand all
35 34
36 // Maximum length that a frame of samples can have. 35 // Maximum length that a frame of samples can have.
37 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160; 36 static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160;
38 // Maximum number of frames to buffer in the render queue. 37 // Maximum number of frames to buffer in the render queue.
39 // TODO(peah): Decrease this once we properly handle hugely unbalanced 38 // TODO(peah): Decrease this once we properly handle hugely unbalanced
40 // reverse and forward call numbers. 39 // reverse and forward call numbers.
41 static const size_t kMaxNumFramesToBuffer = 100; 40 static const size_t kMaxNumFramesToBuffer = 100;
42 41
43 } // namespace 42 } // namespace
44 43
44 class GainControlImpl::GainController {
45 public:
46 explicit GainController() {
47 state_ = WebRtcAgc_Create();
48 RTC_CHECK(state_);
49 }
50
51 ~GainController() { WebRtcAgc_Free(state_); }
the sun 2016/03/09 13:01:53 Add DCHECK here or remove in the other places (and
peah-webrtc 2016/03/09 21:06:44 Done.
52
53 Handle* state() {
54 RTC_DCHECK(state_);
55 return state_;
56 }
57
58 void Initialize(int minimum_capture_level,
59 int maximum_capture_level,
60 Mode mode,
61 int sample_rate_hz,
62 int capture_level) {
63 RTC_DCHECK(state_);
64 const int error =
the sun 2016/03/09 13:01:53 remove const
peah-webrtc 2016/03/09 21:06:44 Done.
65 WebRtcAgc_Init(state_, minimum_capture_level, maximum_capture_level,
66 MapSetting(mode), sample_rate_hz);
67 RTC_DCHECK_EQ(0, error);
68
69 set_capture_level(capture_level);
70 }
71
72 void set_capture_level(int capture_level) {
73 capture_level_ = rtc::Optional<int>(capture_level);
74 }
75
76 int get_capture_level() {
77 RTC_DCHECK(capture_level_);
78 return *capture_level_;
79 }
80
81 private:
82 Handle* state_;
83 rtc::Optional<int> capture_level_;
the sun 2016/03/09 13:01:53 The Optional seems a bit overkill in this situatio
peah-webrtc 2016/03/09 21:06:44 Done.
84
85 RTC_DISALLOW_COPY_AND_ASSIGN(GainController);
86 };
87
45 GainControlImpl::GainControlImpl(const AudioProcessing* apm, 88 GainControlImpl::GainControlImpl(const AudioProcessing* apm,
46 rtc::CriticalSection* crit_render, 89 rtc::CriticalSection* crit_render,
47 rtc::CriticalSection* crit_capture) 90 rtc::CriticalSection* crit_capture)
48 : ProcessingComponent(), 91 : apm_(apm),
49 apm_(apm),
50 crit_render_(crit_render), 92 crit_render_(crit_render),
51 crit_capture_(crit_capture), 93 crit_capture_(crit_capture),
52 mode_(kAdaptiveAnalog), 94 mode_(kAdaptiveAnalog),
53 minimum_capture_level_(0), 95 minimum_capture_level_(0),
54 maximum_capture_level_(255), 96 maximum_capture_level_(255),
55 limiter_enabled_(true), 97 limiter_enabled_(true),
56 target_level_dbfs_(3), 98 target_level_dbfs_(3),
57 compression_gain_db_(9), 99 compression_gain_db_(9),
58 analog_capture_level_(0), 100 analog_capture_level_(0),
59 was_analog_level_set_(false), 101 was_analog_level_set_(false),
60 stream_is_saturated_(false), 102 stream_is_saturated_(false),
61 render_queue_element_max_size_(0) { 103 render_queue_element_max_size_(0) {
62 RTC_DCHECK(apm); 104 RTC_DCHECK(apm);
63 RTC_DCHECK(crit_render); 105 RTC_DCHECK(crit_render);
64 RTC_DCHECK(crit_capture); 106 RTC_DCHECK(crit_capture);
65 } 107 }
66 108
67 GainControlImpl::~GainControlImpl() {} 109 GainControlImpl::~GainControlImpl() {}
68 110
69 int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) { 111 int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) {
70 rtc::CritScope cs(crit_render_); 112 rtc::CritScope cs(crit_render_);
71 if (!is_component_enabled()) { 113 if (!enabled_) {
72 return AudioProcessing::kNoError; 114 return AudioProcessing::kNoError;
73 } 115 }
74 116
75 assert(audio->num_frames_per_band() <= 160); 117 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
76 118
77 render_queue_buffer_.resize(0); 119 render_queue_buffer_.resize(0);
78 for (size_t i = 0; i < num_handles(); i++) { 120 for (size_t i = 0; i < num_handles_required(); i++) {
79 Handle* my_handle = static_cast<Handle*>(handle(i)); 121 Handle* my_handle = gain_controllers_[i]->state();
80 int err = 122 int err =
81 WebRtcAgc_GetAddFarendError(my_handle, audio->num_frames_per_band()); 123 WebRtcAgc_GetAddFarendError(my_handle, audio->num_frames_per_band());
82 124
83 if (err != AudioProcessing::kNoError) 125 if (err != AudioProcessing::kNoError)
84 return GetHandleError(my_handle); 126 return AudioProcessing::kUnspecifiedError;
85 127
86 // Buffer the samples in the render queue. 128 // Buffer the samples in the render queue.
87 render_queue_buffer_.insert( 129 render_queue_buffer_.insert(
88 render_queue_buffer_.end(), audio->mixed_low_pass_data(), 130 render_queue_buffer_.end(), audio->mixed_low_pass_data(),
89 (audio->mixed_low_pass_data() + audio->num_frames_per_band())); 131 (audio->mixed_low_pass_data() + audio->num_frames_per_band()));
90 } 132 }
91 133
92 // Insert the samples into the queue. 134 // Insert the samples into the queue.
93 if (!render_signal_queue_->Insert(&render_queue_buffer_)) { 135 if (!render_signal_queue_->Insert(&render_queue_buffer_)) {
94 // The data queue is full and needs to be emptied. 136 // The data queue is full and needs to be emptied.
95 ReadQueuedRenderData(); 137 ReadQueuedRenderData();
96 138
97 // Retry the insert (should always work). 139 // Retry the insert (should always work).
98 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true); 140 RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true);
99 } 141 }
100 142
101 return AudioProcessing::kNoError; 143 return AudioProcessing::kNoError;
102 } 144 }
103 145
104 // Read chunks of data that were received and queued on the render side from 146 // Read chunks of data that were received and queued on the render side from
105 // a queue. All the data chunks are buffered into the farend signal of the AGC. 147 // a queue. All the data chunks are buffered into the farend signal of the AGC.
106 void GainControlImpl::ReadQueuedRenderData() { 148 void GainControlImpl::ReadQueuedRenderData() {
107 rtc::CritScope cs(crit_capture_); 149 rtc::CritScope cs(crit_capture_);
108 150
109 if (!is_component_enabled()) { 151 if (!enabled_) {
110 return; 152 return;
111 } 153 }
112 154
113 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { 155 while (render_signal_queue_->Remove(&capture_queue_buffer_)) {
114 size_t buffer_index = 0; 156 size_t buffer_index = 0;
115 const size_t num_frames_per_band = 157 const size_t num_frames_per_band =
116 capture_queue_buffer_.size() / num_handles(); 158 capture_queue_buffer_.size() / num_handles_required();
117 for (size_t i = 0; i < num_handles(); i++) { 159 for (size_t i = 0; i < num_handles_required(); i++) {
118 Handle* my_handle = static_cast<Handle*>(handle(i)); 160 Handle* my_handle = gain_controllers_[i]->state();
119 WebRtcAgc_AddFarend(my_handle, &capture_queue_buffer_[buffer_index], 161 WebRtcAgc_AddFarend(my_handle, &capture_queue_buffer_[buffer_index],
120 num_frames_per_band); 162 num_frames_per_band);
121 163
122 buffer_index += num_frames_per_band; 164 buffer_index += num_frames_per_band;
123 } 165 }
124 } 166 }
125 } 167 }
126 168
127 int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { 169 int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
128 rtc::CritScope cs(crit_capture_); 170 rtc::CritScope cs(crit_capture_);
129 171
130 if (!is_component_enabled()) { 172 if (!enabled_) {
131 return AudioProcessing::kNoError; 173 return AudioProcessing::kNoError;
132 } 174 }
133 175
134 assert(audio->num_frames_per_band() <= 160); 176 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
135 assert(audio->num_channels() == num_handles()); 177 RTC_DCHECK_EQ(audio->num_channels(), num_handles_required());
178 RTC_DCHECK_LE(num_handles_required(), gain_controllers_.size());
136 179
137 int err = AudioProcessing::kNoError; 180 int err = AudioProcessing::kNoError;
138 181
139 if (mode_ == kAdaptiveAnalog) { 182 if (mode_ == kAdaptiveAnalog) {
140 capture_levels_.assign(num_handles(), analog_capture_level_); 183 for (size_t i = 0; i < num_handles_required(); i++) {
141 for (size_t i = 0; i < num_handles(); i++) { 184 gain_controllers_[i]->set_capture_level(analog_capture_level_);
142 Handle* my_handle = static_cast<Handle*>(handle(i)); 185 Handle* my_handle = gain_controllers_[i]->state();
143 err = WebRtcAgc_AddMic( 186 err = WebRtcAgc_AddMic(
144 my_handle, 187 my_handle,
145 audio->split_bands(i), 188 audio->split_bands(i),
146 audio->num_bands(), 189 audio->num_bands(),
147 audio->num_frames_per_band()); 190 audio->num_frames_per_band());
148 191
149 if (err != AudioProcessing::kNoError) { 192 if (err != AudioProcessing::kNoError) {
150 return GetHandleError(my_handle); 193 return AudioProcessing::kUnspecifiedError;
151 } 194 }
152 } 195 }
153 } else if (mode_ == kAdaptiveDigital) { 196 } else if (mode_ == kAdaptiveDigital) {
154 197 for (size_t i = 0; i < num_handles_required(); i++) {
155 for (size_t i = 0; i < num_handles(); i++) { 198 Handle* my_handle = gain_controllers_[i]->state();
156 Handle* my_handle = static_cast<Handle*>(handle(i));
157 int32_t capture_level_out = 0; 199 int32_t capture_level_out = 0;
158 200
159 err = WebRtcAgc_VirtualMic( 201 err = WebRtcAgc_VirtualMic(
160 my_handle, 202 my_handle,
161 audio->split_bands(i), 203 audio->split_bands(i),
162 audio->num_bands(), 204 audio->num_bands(),
163 audio->num_frames_per_band(), 205 audio->num_frames_per_band(),
164 analog_capture_level_, 206 analog_capture_level_,
165 &capture_level_out); 207 &capture_level_out);
166 208
167 capture_levels_[i] = capture_level_out; 209 gain_controllers_[i]->set_capture_level(capture_level_out);
168 210
169 if (err != AudioProcessing::kNoError) { 211 if (err != AudioProcessing::kNoError) {
170 return GetHandleError(my_handle); 212 return AudioProcessing::kUnspecifiedError;
171 } 213 }
172 214
173 } 215 }
174 } 216 }
175 217
176 return AudioProcessing::kNoError; 218 return AudioProcessing::kNoError;
177 } 219 }
178 220
179 int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) { 221 int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) {
180 rtc::CritScope cs(crit_capture_); 222 rtc::CritScope cs(crit_capture_);
181 223
182 if (!is_component_enabled()) { 224 if (!enabled_) {
183 return AudioProcessing::kNoError; 225 return AudioProcessing::kNoError;
184 } 226 }
185 227
186 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) { 228 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
187 return AudioProcessing::kStreamParameterNotSetError; 229 return AudioProcessing::kStreamParameterNotSetError;
188 } 230 }
189 231
190 assert(audio->num_frames_per_band() <= 160); 232 RTC_DCHECK_GE(160u, audio->num_frames_per_band());
191 assert(audio->num_channels() == num_handles()); 233 RTC_DCHECK_EQ(audio->num_channels(), num_handles_required());
192 234
193 stream_is_saturated_ = false; 235 stream_is_saturated_ = false;
194 for (size_t i = 0; i < num_handles(); i++) { 236 for (size_t i = 0; i < num_handles_required(); i++) {
195 Handle* my_handle = static_cast<Handle*>(handle(i)); 237 Handle* my_handle = gain_controllers_[i]->state();
196 int32_t capture_level_out = 0; 238 int32_t capture_level_out = 0;
197 uint8_t saturation_warning = 0; 239 uint8_t saturation_warning = 0;
198 240
199 // The call to stream_has_echo() is ok from a deadlock perspective 241 // The call to stream_has_echo() is ok from a deadlock perspective
200 // as the capture lock is allready held. 242 // as the capture lock is allready held.
201 int err = WebRtcAgc_Process( 243 int err = WebRtcAgc_Process(
202 my_handle, 244 my_handle, audio->split_bands_const(i), audio->num_bands(),
203 audio->split_bands_const(i), 245 audio->num_frames_per_band(), audio->split_bands(i),
204 audio->num_bands(), 246 gain_controllers_[i]->get_capture_level(), &capture_level_out,
205 audio->num_frames_per_band(), 247 apm_->echo_cancellation()->stream_has_echo(), &saturation_warning);
206 audio->split_bands(i),
207 capture_levels_[i],
208 &capture_level_out,
209 apm_->echo_cancellation()->stream_has_echo(),
210 &saturation_warning);
211 248
212 if (err != AudioProcessing::kNoError) { 249 if (err != AudioProcessing::kNoError) {
213 return GetHandleError(my_handle); 250 return AudioProcessing::kUnspecifiedError;
214 } 251 }
215 252
216 capture_levels_[i] = capture_level_out; 253 gain_controllers_[i]->set_capture_level(capture_level_out);
217 if (saturation_warning == 1) { 254 if (saturation_warning == 1) {
218 stream_is_saturated_ = true; 255 stream_is_saturated_ = true;
219 } 256 }
220 } 257 }
221 258
222 if (mode_ == kAdaptiveAnalog) { 259 if (mode_ == kAdaptiveAnalog) {
223 // Take the analog level to be the average across the handles. 260 // Take the analog level to be the average across the handles.
224 analog_capture_level_ = 0; 261 analog_capture_level_ = 0;
225 for (size_t i = 0; i < num_handles(); i++) { 262 for (size_t i = 0; i < num_handles_required(); i++) {
226 analog_capture_level_ += capture_levels_[i]; 263 analog_capture_level_ += gain_controllers_[i]->get_capture_level();
227 } 264 }
228 265
229 analog_capture_level_ /= num_handles(); 266 analog_capture_level_ /= num_handles_required();
230 } 267 }
231 268
232 was_analog_level_set_ = false; 269 was_analog_level_set_ = false;
233 return AudioProcessing::kNoError; 270 return AudioProcessing::kNoError;
234 } 271 }
235 272
236 // TODO(ajm): ensure this is called under kAdaptiveAnalog. 273 // TODO(ajm): ensure this is called under kAdaptiveAnalog.
237 int GainControlImpl::set_stream_analog_level(int level) { 274 int GainControlImpl::set_stream_analog_level(int level) {
238 rtc::CritScope cs(crit_capture_); 275 rtc::CritScope cs(crit_capture_);
239 276
(...skipping 10 matching lines...) Expand all
250 rtc::CritScope cs(crit_capture_); 287 rtc::CritScope cs(crit_capture_);
251 // TODO(ajm): enable this assertion? 288 // TODO(ajm): enable this assertion?
252 //assert(mode_ == kAdaptiveAnalog); 289 //assert(mode_ == kAdaptiveAnalog);
253 290
254 return analog_capture_level_; 291 return analog_capture_level_;
255 } 292 }
256 293
257 int GainControlImpl::Enable(bool enable) { 294 int GainControlImpl::Enable(bool enable) {
258 rtc::CritScope cs_render(crit_render_); 295 rtc::CritScope cs_render(crit_render_);
259 rtc::CritScope cs_capture(crit_capture_); 296 rtc::CritScope cs_capture(crit_capture_);
260 return EnableComponent(enable); 297 if (enable && !enabled_) {
298 enabled_ = enable; // Must be set before Initialize() is called.
299 Initialize();
300 } else {
301 enabled_ = enable;
302 }
303 return AudioProcessing::kNoError;
261 } 304 }
262 305
263 bool GainControlImpl::is_enabled() const { 306 bool GainControlImpl::is_enabled() const {
264 rtc::CritScope cs(crit_capture_); 307 rtc::CritScope cs(crit_capture_);
265 return is_component_enabled(); 308 return enabled_;
266 } 309 }
267 310
268 int GainControlImpl::set_mode(Mode mode) { 311 int GainControlImpl::set_mode(Mode mode) {
269 rtc::CritScope cs_render(crit_render_); 312 rtc::CritScope cs_render(crit_render_);
270 rtc::CritScope cs_capture(crit_capture_); 313 rtc::CritScope cs_capture(crit_capture_);
271 if (MapSetting(mode) == -1) { 314 if (MapSetting(mode) == -1) {
272 return AudioProcessing::kBadParameterError; 315 return AudioProcessing::kBadParameterError;
273 } 316 }
274 317
275 mode_ = mode; 318 mode_ = mode;
276 return Initialize(); 319 Initialize();
320 return AudioProcessing::kNoError;
277 } 321 }
278 322
279 GainControl::Mode GainControlImpl::mode() const { 323 GainControl::Mode GainControlImpl::mode() const {
280 rtc::CritScope cs(crit_capture_); 324 rtc::CritScope cs(crit_capture_);
281 return mode_; 325 return mode_;
282 } 326 }
283 327
284 int GainControlImpl::set_analog_level_limits(int minimum, 328 int GainControlImpl::set_analog_level_limits(int minimum,
285 int maximum) { 329 int maximum) {
286 rtc::CritScope cs(crit_capture_); 330 rtc::CritScope cs(crit_capture_);
287 if (minimum < 0) { 331 if (minimum < 0) {
288 return AudioProcessing::kBadParameterError; 332 return AudioProcessing::kBadParameterError;
289 } 333 }
290 334
291 if (maximum > 65535) { 335 if (maximum > 65535) {
292 return AudioProcessing::kBadParameterError; 336 return AudioProcessing::kBadParameterError;
293 } 337 }
294 338
295 if (maximum < minimum) { 339 if (maximum < minimum) {
296 return AudioProcessing::kBadParameterError; 340 return AudioProcessing::kBadParameterError;
297 } 341 }
298 342
299 minimum_capture_level_ = minimum; 343 minimum_capture_level_ = minimum;
300 maximum_capture_level_ = maximum; 344 maximum_capture_level_ = maximum;
301 345
302 return Initialize(); 346 Initialize();
347 return AudioProcessing::kNoError;
303 } 348 }
304 349
305 int GainControlImpl::analog_level_minimum() const { 350 int GainControlImpl::analog_level_minimum() const {
306 rtc::CritScope cs(crit_capture_); 351 rtc::CritScope cs(crit_capture_);
307 return minimum_capture_level_; 352 return minimum_capture_level_;
308 } 353 }
309 354
310 int GainControlImpl::analog_level_maximum() const { 355 int GainControlImpl::analog_level_maximum() const {
311 rtc::CritScope cs(crit_capture_); 356 rtc::CritScope cs(crit_capture_);
312 return maximum_capture_level_; 357 return maximum_capture_level_;
313 } 358 }
314 359
315 bool GainControlImpl::stream_is_saturated() const { 360 bool GainControlImpl::stream_is_saturated() const {
316 rtc::CritScope cs(crit_capture_); 361 rtc::CritScope cs(crit_capture_);
317 return stream_is_saturated_; 362 return stream_is_saturated_;
318 } 363 }
319 364
320 int GainControlImpl::set_target_level_dbfs(int level) { 365 int GainControlImpl::set_target_level_dbfs(int level) {
321 rtc::CritScope cs(crit_capture_); 366 {
322 if (level > 31 || level < 0) { 367 if (level > 31 || level < 0) {
the sun 2016/03/09 13:01:53 Move out of scope; scope is there to control the C
peah-webrtc 2016/03/09 21:06:44 Done.
323 return AudioProcessing::kBadParameterError; 368 return AudioProcessing::kBadParameterError;
369 }
370
371 rtc::CritScope cs(crit_capture_);
372 target_level_dbfs_ = level;
324 } 373 }
325
326 target_level_dbfs_ = level;
327 return Configure(); 374 return Configure();
328 } 375 }
329 376
330 int GainControlImpl::target_level_dbfs() const { 377 int GainControlImpl::target_level_dbfs() const {
331 rtc::CritScope cs(crit_capture_); 378 rtc::CritScope cs(crit_capture_);
332 return target_level_dbfs_; 379 return target_level_dbfs_;
333 } 380 }
334 381
335 int GainControlImpl::set_compression_gain_db(int gain) { 382 int GainControlImpl::set_compression_gain_db(int gain) {
336 rtc::CritScope cs(crit_capture_); 383 {
337 if (gain < 0 || gain > 90) { 384 if (gain < 0 || gain > 90) {
the sun 2016/03/09 13:01:53 ditto
peah-webrtc 2016/03/09 21:06:44 Done.
338 return AudioProcessing::kBadParameterError; 385 return AudioProcessing::kBadParameterError;
386 }
387
388 rtc::CritScope cs(crit_capture_);
389 compression_gain_db_ = gain;
339 } 390 }
340
341 compression_gain_db_ = gain;
342 return Configure(); 391 return Configure();
343 } 392 }
344 393
345 int GainControlImpl::compression_gain_db() const { 394 int GainControlImpl::compression_gain_db() const {
346 rtc::CritScope cs(crit_capture_); 395 rtc::CritScope cs(crit_capture_);
347 return compression_gain_db_; 396 return compression_gain_db_;
348 } 397 }
349 398
350 int GainControlImpl::enable_limiter(bool enable) { 399 int GainControlImpl::enable_limiter(bool enable) {
351 rtc::CritScope cs(crit_capture_); 400 {
352 limiter_enabled_ = enable; 401 rtc::CritScope cs(crit_capture_);
402 limiter_enabled_ = enable;
403 }
353 return Configure(); 404 return Configure();
354 } 405 }
355 406
356 bool GainControlImpl::is_limiter_enabled() const { 407 bool GainControlImpl::is_limiter_enabled() const {
357 rtc::CritScope cs(crit_capture_); 408 rtc::CritScope cs(crit_capture_);
358 return limiter_enabled_; 409 return limiter_enabled_;
359 } 410 }
360 411
361 int GainControlImpl::Initialize() { 412 void GainControlImpl::Initialize() {
362 int err = ProcessingComponent::Initialize(); 413 rtc::CritScope cs_render(crit_render_);
363 if (err != AudioProcessing::kNoError || !is_component_enabled()) { 414 rtc::CritScope cs_capture(crit_capture_);
364 return err; 415 if (!enabled_) {
416 return;
365 } 417 }
366 418
419 int sample_rate_hz = apm_->proc_sample_rate_hz();
420
421 if (num_handles_required() > gain_controllers_.size()) {
422 size_t gain_controllers_old_size = gain_controllers_.size();
423 gain_controllers_.resize(num_handles_required());
424
425 for (size_t i = gain_controllers_old_size; i < gain_controllers_.size();
426 ++i) {
427 gain_controllers_[i].reset(new GainController());
428 }
429 }
430
431 for (auto& gain_controller : gain_controllers_) {
432 gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_,
433 mode_, sample_rate_hz, analog_capture_level_);
434 }
435
436 Configure();
437
367 AllocateRenderQueue(); 438 AllocateRenderQueue();
368
369 rtc::CritScope cs_capture(crit_capture_);
370 const int n = num_handles();
371 RTC_CHECK_GE(n, 0) << "Bad number of handles: " << n;
372
373 capture_levels_.assign(n, analog_capture_level_);
374 return AudioProcessing::kNoError;
375 } 439 }
376 440
377 void GainControlImpl::AllocateRenderQueue() { 441 void GainControlImpl::AllocateRenderQueue() {
378 const size_t new_render_queue_element_max_size = 442 const size_t new_render_queue_element_max_size = std::max<size_t>(
379 std::max<size_t>(static_cast<size_t>(1), 443 static_cast<size_t>(1),
380 kMaxAllowedValuesOfSamplesPerFrame * num_handles()); 444 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required());
381 445
382 rtc::CritScope cs_render(crit_render_); 446 rtc::CritScope cs_render(crit_render_);
383 rtc::CritScope cs_capture(crit_capture_); 447 rtc::CritScope cs_capture(crit_capture_);
384 448
385 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { 449 if (render_queue_element_max_size_ < new_render_queue_element_max_size) {
386 render_queue_element_max_size_ = new_render_queue_element_max_size; 450 render_queue_element_max_size_ = new_render_queue_element_max_size;
387 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); 451 std::vector<int16_t> template_queue_element(render_queue_element_max_size_);
388 452
389 render_signal_queue_.reset( 453 render_signal_queue_.reset(
390 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>( 454 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>(
391 kMaxNumFramesToBuffer, template_queue_element, 455 kMaxNumFramesToBuffer, template_queue_element,
392 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_))); 456 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_)));
393 457
394 render_queue_buffer_.resize(render_queue_element_max_size_); 458 render_queue_buffer_.resize(render_queue_element_max_size_);
395 capture_queue_buffer_.resize(render_queue_element_max_size_); 459 capture_queue_buffer_.resize(render_queue_element_max_size_);
396 } else { 460 } else {
397 render_signal_queue_->Clear(); 461 render_signal_queue_->Clear();
398 } 462 }
399 } 463 }
400 464
401 void* GainControlImpl::CreateHandle() const { 465 int GainControlImpl::Configure() {
402 return WebRtcAgc_Create();
403 }
404
405 void GainControlImpl::DestroyHandle(void* handle) const {
406 WebRtcAgc_Free(static_cast<Handle*>(handle));
407 }
408
409 int GainControlImpl::InitializeHandle(void* handle) const {
410 rtc::CritScope cs_render(crit_render_);
411 rtc::CritScope cs_capture(crit_capture_);
412
413 return WebRtcAgc_Init(static_cast<Handle*>(handle),
414 minimum_capture_level_,
415 maximum_capture_level_,
416 MapSetting(mode_),
417 apm_->proc_sample_rate_hz());
418 }
419
420 int GainControlImpl::ConfigureHandle(void* handle) const {
421 rtc::CritScope cs_render(crit_render_); 466 rtc::CritScope cs_render(crit_render_);
422 rtc::CritScope cs_capture(crit_capture_); 467 rtc::CritScope cs_capture(crit_capture_);
423 WebRtcAgcConfig config; 468 WebRtcAgcConfig config;
424 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we 469 // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
425 // change the interface. 470 // change the interface.
426 //assert(target_level_dbfs_ <= 0); 471 //assert(target_level_dbfs_ <= 0);
427 //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_); 472 //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
428 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_); 473 config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
429 config.compressionGaindB = 474 config.compressionGaindB =
430 static_cast<int16_t>(compression_gain_db_); 475 static_cast<int16_t>(compression_gain_db_);
431 config.limiterEnable = limiter_enabled_; 476 config.limiterEnable = limiter_enabled_;
432 477
433 return WebRtcAgc_set_config(static_cast<Handle*>(handle), config); 478 int error = AudioProcessing::kNoError;
479 for (auto& gain_controller : gain_controllers_) {
480 const int handle_error =
481 WebRtcAgc_set_config(gain_controller->state(), config);
482 if (handle_error != AudioProcessing::kNoError) {
483 error = handle_error;
484 }
485 }
486 return error;
434 } 487 }
435 488
436 size_t GainControlImpl::num_handles_required() const { 489 size_t GainControlImpl::num_handles_required() const {
437 // Not locked as it only relies on APM public API which is threadsafe. 490 // Not locked as it only relies on APM public API which is threadsafe.
438 return apm_->num_proc_channels(); 491 return apm_->num_proc_channels();
439 } 492 }
440
441 int GainControlImpl::GetHandleError(void* handle) const {
442 // The AGC has no get_error() function.
443 // (Despite listing errors in its interface...)
444 assert(handle != NULL);
445 return AudioProcessing::kUnspecifiedError;
446 }
447 } // namespace webrtc 493 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_processing/gain_control_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698