OLD | NEW |
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 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 | 83 |
84 private: | 84 private: |
85 Handle* state_; | 85 Handle* state_; |
86 // TODO(peah): Remove the optional once the initialization is moved into the | 86 // TODO(peah): Remove the optional once the initialization is moved into the |
87 // ctor. | 87 // ctor. |
88 rtc::Optional<int> capture_level_; | 88 rtc::Optional<int> capture_level_; |
89 | 89 |
90 RTC_DISALLOW_COPY_AND_ASSIGN(GainController); | 90 RTC_DISALLOW_COPY_AND_ASSIGN(GainController); |
91 }; | 91 }; |
92 | 92 |
93 GainControlImpl::GainControlImpl(const AudioProcessing* apm, | 93 GainControlImpl::GainControlImpl(rtc::CriticalSection* crit_render, |
94 rtc::CriticalSection* crit_render, | |
95 rtc::CriticalSection* crit_capture) | 94 rtc::CriticalSection* crit_capture) |
96 : apm_(apm), | 95 : crit_render_(crit_render), |
97 crit_render_(crit_render), | |
98 crit_capture_(crit_capture), | 96 crit_capture_(crit_capture), |
99 mode_(kAdaptiveAnalog), | 97 mode_(kAdaptiveAnalog), |
100 minimum_capture_level_(0), | 98 minimum_capture_level_(0), |
101 maximum_capture_level_(255), | 99 maximum_capture_level_(255), |
102 limiter_enabled_(true), | 100 limiter_enabled_(true), |
103 target_level_dbfs_(3), | 101 target_level_dbfs_(3), |
104 compression_gain_db_(9), | 102 compression_gain_db_(9), |
105 analog_capture_level_(0), | 103 analog_capture_level_(0), |
106 was_analog_level_set_(false), | 104 was_analog_level_set_(false), |
107 stream_is_saturated_(false), | 105 stream_is_saturated_(false), |
108 render_queue_element_max_size_(0) { | 106 render_queue_element_max_size_(0) { |
109 RTC_DCHECK(apm); | |
110 RTC_DCHECK(crit_render); | 107 RTC_DCHECK(crit_render); |
111 RTC_DCHECK(crit_capture); | 108 RTC_DCHECK(crit_capture); |
112 } | 109 } |
113 | 110 |
114 GainControlImpl::~GainControlImpl() {} | 111 GainControlImpl::~GainControlImpl() {} |
115 | 112 |
116 int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) { | 113 int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) { |
117 rtc::CritScope cs(crit_render_); | 114 rtc::CritScope cs(crit_render_); |
118 if (!enabled_) { | 115 if (!enabled_) { |
119 return AudioProcessing::kNoError; | 116 return AudioProcessing::kNoError; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 // a queue. All the data chunks are buffered into the farend signal of the AGC. | 149 // a queue. All the data chunks are buffered into the farend signal of the AGC. |
153 void GainControlImpl::ReadQueuedRenderData() { | 150 void GainControlImpl::ReadQueuedRenderData() { |
154 rtc::CritScope cs(crit_capture_); | 151 rtc::CritScope cs(crit_capture_); |
155 | 152 |
156 if (!enabled_) { | 153 if (!enabled_) { |
157 return; | 154 return; |
158 } | 155 } |
159 | 156 |
160 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { | 157 while (render_signal_queue_->Remove(&capture_queue_buffer_)) { |
161 size_t buffer_index = 0; | 158 size_t buffer_index = 0; |
| 159 RTC_DCHECK(num_proc_channels_); |
| 160 RTC_DCHECK_LT(0ul, *num_proc_channels_); |
162 const size_t num_frames_per_band = | 161 const size_t num_frames_per_band = |
163 capture_queue_buffer_.size() / num_handles_required(); | 162 capture_queue_buffer_.size() / (*num_proc_channels_); |
164 for (auto& gain_controller : gain_controllers_) { | 163 for (auto& gain_controller : gain_controllers_) { |
165 WebRtcAgc_AddFarend(gain_controller->state(), | 164 WebRtcAgc_AddFarend(gain_controller->state(), |
166 &capture_queue_buffer_[buffer_index], | 165 &capture_queue_buffer_[buffer_index], |
167 num_frames_per_band); | 166 num_frames_per_band); |
168 | 167 |
169 buffer_index += num_frames_per_band; | 168 buffer_index += num_frames_per_band; |
170 } | 169 } |
171 } | 170 } |
172 } | 171 } |
173 | 172 |
174 int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { | 173 int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) { |
175 rtc::CritScope cs(crit_capture_); | 174 rtc::CritScope cs(crit_capture_); |
176 | 175 |
177 if (!enabled_) { | 176 if (!enabled_) { |
178 return AudioProcessing::kNoError; | 177 return AudioProcessing::kNoError; |
179 } | 178 } |
180 | 179 |
| 180 RTC_DCHECK(num_proc_channels_); |
181 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); | 181 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
182 RTC_DCHECK_EQ(audio->num_channels(), num_handles_required()); | 182 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_); |
183 RTC_DCHECK_LE(num_handles_required(), gain_controllers_.size()); | 183 RTC_DCHECK_LE(*num_proc_channels_, gain_controllers_.size()); |
184 | 184 |
185 if (mode_ == kAdaptiveAnalog) { | 185 if (mode_ == kAdaptiveAnalog) { |
186 int capture_channel = 0; | 186 int capture_channel = 0; |
187 for (auto& gain_controller : gain_controllers_) { | 187 for (auto& gain_controller : gain_controllers_) { |
188 gain_controller->set_capture_level(analog_capture_level_); | 188 gain_controller->set_capture_level(analog_capture_level_); |
189 int err = WebRtcAgc_AddMic( | 189 int err = WebRtcAgc_AddMic( |
190 gain_controller->state(), audio->split_bands(capture_channel), | 190 gain_controller->state(), audio->split_bands(capture_channel), |
191 audio->num_bands(), audio->num_frames_per_band()); | 191 audio->num_bands(), audio->num_frames_per_band()); |
192 | 192 |
193 if (err != AudioProcessing::kNoError) { | 193 if (err != AudioProcessing::kNoError) { |
(...skipping 15 matching lines...) Expand all Loading... |
209 if (err != AudioProcessing::kNoError) { | 209 if (err != AudioProcessing::kNoError) { |
210 return AudioProcessing::kUnspecifiedError; | 210 return AudioProcessing::kUnspecifiedError; |
211 } | 211 } |
212 ++capture_channel; | 212 ++capture_channel; |
213 } | 213 } |
214 } | 214 } |
215 | 215 |
216 return AudioProcessing::kNoError; | 216 return AudioProcessing::kNoError; |
217 } | 217 } |
218 | 218 |
219 int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) { | 219 int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio, |
| 220 bool stream_has_echo) { |
220 rtc::CritScope cs(crit_capture_); | 221 rtc::CritScope cs(crit_capture_); |
221 | 222 |
222 if (!enabled_) { | 223 if (!enabled_) { |
223 return AudioProcessing::kNoError; | 224 return AudioProcessing::kNoError; |
224 } | 225 } |
225 | 226 |
226 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) { | 227 if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) { |
227 return AudioProcessing::kStreamParameterNotSetError; | 228 return AudioProcessing::kStreamParameterNotSetError; |
228 } | 229 } |
229 | 230 |
| 231 RTC_DCHECK(num_proc_channels_); |
230 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); | 232 RTC_DCHECK_GE(160u, audio->num_frames_per_band()); |
231 RTC_DCHECK_EQ(audio->num_channels(), num_handles_required()); | 233 RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_); |
232 | 234 |
233 stream_is_saturated_ = false; | 235 stream_is_saturated_ = false; |
234 int capture_channel = 0; | 236 int capture_channel = 0; |
235 for (auto& gain_controller : gain_controllers_) { | 237 for (auto& gain_controller : gain_controllers_) { |
236 int32_t capture_level_out = 0; | 238 int32_t capture_level_out = 0; |
237 uint8_t saturation_warning = 0; | 239 uint8_t saturation_warning = 0; |
238 | 240 |
239 // 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 |
240 // as the capture lock is allready held. | 242 // as the capture lock is allready held. |
241 int err = WebRtcAgc_Process( | 243 int err = WebRtcAgc_Process( |
242 gain_controller->state(), audio->split_bands_const(capture_channel), | 244 gain_controller->state(), audio->split_bands_const(capture_channel), |
243 audio->num_bands(), audio->num_frames_per_band(), | 245 audio->num_bands(), audio->num_frames_per_band(), |
244 audio->split_bands(capture_channel), | 246 audio->split_bands(capture_channel), |
245 gain_controller->get_capture_level(), &capture_level_out, | 247 gain_controller->get_capture_level(), &capture_level_out, |
246 apm_->echo_cancellation()->stream_has_echo(), &saturation_warning); | 248 stream_has_echo, &saturation_warning); |
247 | 249 |
248 if (err != AudioProcessing::kNoError) { | 250 if (err != AudioProcessing::kNoError) { |
249 return AudioProcessing::kUnspecifiedError; | 251 return AudioProcessing::kUnspecifiedError; |
250 } | 252 } |
251 | 253 |
252 gain_controller->set_capture_level(capture_level_out); | 254 gain_controller->set_capture_level(capture_level_out); |
253 if (saturation_warning == 1) { | 255 if (saturation_warning == 1) { |
254 stream_is_saturated_ = true; | 256 stream_is_saturated_ = true; |
255 } | 257 } |
256 | 258 |
257 ++capture_channel; | 259 ++capture_channel; |
258 } | 260 } |
259 | 261 |
| 262 RTC_DCHECK_LT(0ul, *num_proc_channels_); |
260 if (mode_ == kAdaptiveAnalog) { | 263 if (mode_ == kAdaptiveAnalog) { |
261 // Take the analog level to be the average across the handles. | 264 // Take the analog level to be the average across the handles. |
262 analog_capture_level_ = 0; | 265 analog_capture_level_ = 0; |
263 for (auto& gain_controller : gain_controllers_) { | 266 for (auto& gain_controller : gain_controllers_) { |
264 analog_capture_level_ += gain_controller->get_capture_level(); | 267 analog_capture_level_ += gain_controller->get_capture_level(); |
265 } | 268 } |
266 | 269 |
267 analog_capture_level_ /= num_handles_required(); | 270 analog_capture_level_ /= (*num_proc_channels_); |
268 } | 271 } |
269 | 272 |
270 was_analog_level_set_ = false; | 273 was_analog_level_set_ = false; |
271 return AudioProcessing::kNoError; | 274 return AudioProcessing::kNoError; |
272 } | 275 } |
273 | 276 |
274 // TODO(ajm): ensure this is called under kAdaptiveAnalog. | 277 // TODO(ajm): ensure this is called under kAdaptiveAnalog. |
275 int GainControlImpl::set_stream_analog_level(int level) { | 278 int GainControlImpl::set_stream_analog_level(int level) { |
276 rtc::CritScope cs(crit_capture_); | 279 rtc::CritScope cs(crit_capture_); |
277 | 280 |
(...skipping 12 matching lines...) Expand all Loading... |
290 //assert(mode_ == kAdaptiveAnalog); | 293 //assert(mode_ == kAdaptiveAnalog); |
291 | 294 |
292 return analog_capture_level_; | 295 return analog_capture_level_; |
293 } | 296 } |
294 | 297 |
295 int GainControlImpl::Enable(bool enable) { | 298 int GainControlImpl::Enable(bool enable) { |
296 rtc::CritScope cs_render(crit_render_); | 299 rtc::CritScope cs_render(crit_render_); |
297 rtc::CritScope cs_capture(crit_capture_); | 300 rtc::CritScope cs_capture(crit_capture_); |
298 if (enable && !enabled_) { | 301 if (enable && !enabled_) { |
299 enabled_ = enable; // Must be set before Initialize() is called. | 302 enabled_ = enable; // Must be set before Initialize() is called. |
300 Initialize(); | 303 |
| 304 RTC_DCHECK(num_proc_channels_); |
| 305 RTC_DCHECK(sample_rate_hz_); |
| 306 Initialize(*num_proc_channels_, *sample_rate_hz_); |
301 } else { | 307 } else { |
302 enabled_ = enable; | 308 enabled_ = enable; |
303 } | 309 } |
304 return AudioProcessing::kNoError; | 310 return AudioProcessing::kNoError; |
305 } | 311 } |
306 | 312 |
307 bool GainControlImpl::is_enabled() const { | 313 bool GainControlImpl::is_enabled() const { |
308 rtc::CritScope cs(crit_capture_); | 314 rtc::CritScope cs(crit_capture_); |
309 return enabled_; | 315 return enabled_; |
310 } | 316 } |
311 | 317 |
312 int GainControlImpl::set_mode(Mode mode) { | 318 int GainControlImpl::set_mode(Mode mode) { |
313 rtc::CritScope cs_render(crit_render_); | 319 rtc::CritScope cs_render(crit_render_); |
314 rtc::CritScope cs_capture(crit_capture_); | 320 rtc::CritScope cs_capture(crit_capture_); |
315 if (MapSetting(mode) == -1) { | 321 if (MapSetting(mode) == -1) { |
316 return AudioProcessing::kBadParameterError; | 322 return AudioProcessing::kBadParameterError; |
317 } | 323 } |
318 | 324 |
319 mode_ = mode; | 325 mode_ = mode; |
320 Initialize(); | 326 RTC_DCHECK(num_proc_channels_); |
| 327 RTC_DCHECK(sample_rate_hz_); |
| 328 Initialize(*num_proc_channels_, *sample_rate_hz_); |
321 return AudioProcessing::kNoError; | 329 return AudioProcessing::kNoError; |
322 } | 330 } |
323 | 331 |
324 GainControl::Mode GainControlImpl::mode() const { | 332 GainControl::Mode GainControlImpl::mode() const { |
325 rtc::CritScope cs(crit_capture_); | 333 rtc::CritScope cs(crit_capture_); |
326 return mode_; | 334 return mode_; |
327 } | 335 } |
328 | 336 |
329 int GainControlImpl::set_analog_level_limits(int minimum, | 337 int GainControlImpl::set_analog_level_limits(int minimum, |
330 int maximum) { | 338 int maximum) { |
331 rtc::CritScope cs(crit_capture_); | 339 rtc::CritScope cs(crit_capture_); |
332 if (minimum < 0) { | 340 if (minimum < 0) { |
333 return AudioProcessing::kBadParameterError; | 341 return AudioProcessing::kBadParameterError; |
334 } | 342 } |
335 | 343 |
336 if (maximum > 65535) { | 344 if (maximum > 65535) { |
337 return AudioProcessing::kBadParameterError; | 345 return AudioProcessing::kBadParameterError; |
338 } | 346 } |
339 | 347 |
340 if (maximum < minimum) { | 348 if (maximum < minimum) { |
341 return AudioProcessing::kBadParameterError; | 349 return AudioProcessing::kBadParameterError; |
342 } | 350 } |
343 | 351 |
344 minimum_capture_level_ = minimum; | 352 minimum_capture_level_ = minimum; |
345 maximum_capture_level_ = maximum; | 353 maximum_capture_level_ = maximum; |
346 | 354 |
347 Initialize(); | 355 RTC_DCHECK(num_proc_channels_); |
| 356 RTC_DCHECK(sample_rate_hz_); |
| 357 Initialize(*num_proc_channels_, *sample_rate_hz_); |
348 return AudioProcessing::kNoError; | 358 return AudioProcessing::kNoError; |
349 } | 359 } |
350 | 360 |
351 int GainControlImpl::analog_level_minimum() const { | 361 int GainControlImpl::analog_level_minimum() const { |
352 rtc::CritScope cs(crit_capture_); | 362 rtc::CritScope cs(crit_capture_); |
353 return minimum_capture_level_; | 363 return minimum_capture_level_; |
354 } | 364 } |
355 | 365 |
356 int GainControlImpl::analog_level_maximum() const { | 366 int GainControlImpl::analog_level_maximum() const { |
357 rtc::CritScope cs(crit_capture_); | 367 rtc::CritScope cs(crit_capture_); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 limiter_enabled_ = enable; | 411 limiter_enabled_ = enable; |
402 } | 412 } |
403 return Configure(); | 413 return Configure(); |
404 } | 414 } |
405 | 415 |
406 bool GainControlImpl::is_limiter_enabled() const { | 416 bool GainControlImpl::is_limiter_enabled() const { |
407 rtc::CritScope cs(crit_capture_); | 417 rtc::CritScope cs(crit_capture_); |
408 return limiter_enabled_; | 418 return limiter_enabled_; |
409 } | 419 } |
410 | 420 |
411 void GainControlImpl::Initialize() { | 421 void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) { |
412 rtc::CritScope cs_render(crit_render_); | 422 rtc::CritScope cs_render(crit_render_); |
413 rtc::CritScope cs_capture(crit_capture_); | 423 rtc::CritScope cs_capture(crit_capture_); |
| 424 |
| 425 num_proc_channels_ = rtc::Optional<size_t>(num_proc_channels); |
| 426 sample_rate_hz_ = rtc::Optional<int>(sample_rate_hz); |
| 427 |
414 if (!enabled_) { | 428 if (!enabled_) { |
415 return; | 429 return; |
416 } | 430 } |
417 | 431 |
418 int sample_rate_hz = apm_->proc_sample_rate_hz(); | 432 gain_controllers_.resize(*num_proc_channels_); |
419 gain_controllers_.resize(num_handles_required()); | |
420 for (auto& gain_controller : gain_controllers_) { | 433 for (auto& gain_controller : gain_controllers_) { |
421 if (!gain_controller) { | 434 if (!gain_controller) { |
422 gain_controller.reset(new GainController()); | 435 gain_controller.reset(new GainController()); |
423 } | 436 } |
424 gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_, | 437 gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_, |
425 mode_, sample_rate_hz, analog_capture_level_); | 438 mode_, *sample_rate_hz_, analog_capture_level_); |
426 } | 439 } |
427 | 440 |
428 Configure(); | 441 Configure(); |
429 | 442 |
430 AllocateRenderQueue(); | 443 AllocateRenderQueue(); |
431 } | 444 } |
432 | 445 |
433 void GainControlImpl::AllocateRenderQueue() { | 446 void GainControlImpl::AllocateRenderQueue() { |
| 447 rtc::CritScope cs_render(crit_render_); |
| 448 rtc::CritScope cs_capture(crit_capture_); |
| 449 |
| 450 RTC_DCHECK(num_proc_channels_); |
434 const size_t new_render_queue_element_max_size = std::max<size_t>( | 451 const size_t new_render_queue_element_max_size = std::max<size_t>( |
435 static_cast<size_t>(1), | 452 static_cast<size_t>(1), |
436 kMaxAllowedValuesOfSamplesPerFrame * num_handles_required()); | 453 kMaxAllowedValuesOfSamplesPerFrame * (*num_proc_channels_)); |
437 | |
438 rtc::CritScope cs_render(crit_render_); | |
439 rtc::CritScope cs_capture(crit_capture_); | |
440 | 454 |
441 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { | 455 if (render_queue_element_max_size_ < new_render_queue_element_max_size) { |
442 render_queue_element_max_size_ = new_render_queue_element_max_size; | 456 render_queue_element_max_size_ = new_render_queue_element_max_size; |
443 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); | 457 std::vector<int16_t> template_queue_element(render_queue_element_max_size_); |
444 | 458 |
445 render_signal_queue_.reset( | 459 render_signal_queue_.reset( |
446 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>( | 460 new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>( |
447 kMaxNumFramesToBuffer, template_queue_element, | 461 kMaxNumFramesToBuffer, template_queue_element, |
448 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_))); | 462 RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_))); |
449 | 463 |
(...skipping 20 matching lines...) Expand all Loading... |
470 int error = AudioProcessing::kNoError; | 484 int error = AudioProcessing::kNoError; |
471 for (auto& gain_controller : gain_controllers_) { | 485 for (auto& gain_controller : gain_controllers_) { |
472 const int handle_error = | 486 const int handle_error = |
473 WebRtcAgc_set_config(gain_controller->state(), config); | 487 WebRtcAgc_set_config(gain_controller->state(), config); |
474 if (handle_error != AudioProcessing::kNoError) { | 488 if (handle_error != AudioProcessing::kNoError) { |
475 error = handle_error; | 489 error = handle_error; |
476 } | 490 } |
477 } | 491 } |
478 return error; | 492 return error; |
479 } | 493 } |
480 | |
481 size_t GainControlImpl::num_handles_required() const { | |
482 // Not locked as it only relies on APM public API which is threadsafe. | |
483 return apm_->num_proc_channels(); | |
484 } | |
485 } // namespace webrtc | 494 } // namespace webrtc |
OLD | NEW |