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 "webrtc/modules/audio_processing/gain_control_impl.h"
12
13#include <assert.h>
14
15#include "webrtc/modules/audio_processing/audio_buffer.h"
16#include "webrtc/modules/audio_processing/agc/legacy/gain_control.h"
17
18namespace webrtc {
19
20typedef void Handle;
21
22namespace {
23int16_t MapSetting(GainControl::Mode mode) {
24  switch (mode) {
25    case GainControl::kAdaptiveAnalog:
26      return kAgcModeAdaptiveAnalog;
27    case GainControl::kAdaptiveDigital:
28      return kAgcModeAdaptiveDigital;
29    case GainControl::kFixedDigital:
30      return kAgcModeFixedDigital;
31  }
32  assert(false);
33  return -1;
34}
35
36// Maximum length that a frame of samples can have.
37static const size_t kMaxAllowedValuesOfSamplesPerFrame = 160;
38// Maximum number of frames to buffer in the render queue.
39// TODO(peah): Decrease this once we properly handle hugely unbalanced
40// reverse and forward call numbers.
41static const size_t kMaxNumFramesToBuffer = 100;
42
43}  // namespace
44
45GainControlImpl::GainControlImpl(const AudioProcessing* apm,
46                                 rtc::CriticalSection* crit_render,
47                                 rtc::CriticalSection* crit_capture)
48    : ProcessingComponent(),
49      apm_(apm),
50      crit_render_(crit_render),
51      crit_capture_(crit_capture),
52      mode_(kAdaptiveAnalog),
53      minimum_capture_level_(0),
54      maximum_capture_level_(255),
55      limiter_enabled_(true),
56      target_level_dbfs_(3),
57      compression_gain_db_(9),
58      analog_capture_level_(0),
59      was_analog_level_set_(false),
60      stream_is_saturated_(false),
61      render_queue_element_max_size_(0) {
62  RTC_DCHECK(apm);
63  RTC_DCHECK(crit_render);
64  RTC_DCHECK(crit_capture);
65}
66
67GainControlImpl::~GainControlImpl() {}
68
69int GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) {
70  rtc::CritScope cs(crit_render_);
71  if (!is_component_enabled()) {
72    return AudioProcessing::kNoError;
73  }
74
75  assert(audio->num_frames_per_band() <= 160);
76
77  render_queue_buffer_.resize(0);
78  for (size_t i = 0; i < num_handles(); i++) {
79    Handle* my_handle = static_cast<Handle*>(handle(i));
80    int err =
81        WebRtcAgc_GetAddFarendError(my_handle, audio->num_frames_per_band());
82
83    if (err != AudioProcessing::kNoError)
84      return GetHandleError(my_handle);
85
86    // Buffer the samples in the render queue.
87    render_queue_buffer_.insert(
88        render_queue_buffer_.end(), audio->mixed_low_pass_data(),
89        (audio->mixed_low_pass_data() + audio->num_frames_per_band()));
90  }
91
92  // Insert the samples into the queue.
93  if (!render_signal_queue_->Insert(&render_queue_buffer_)) {
94    // The data queue is full and needs to be emptied.
95    ReadQueuedRenderData();
96
97    // Retry the insert (should always work).
98    RTC_DCHECK_EQ(render_signal_queue_->Insert(&render_queue_buffer_), true);
99  }
100
101  return AudioProcessing::kNoError;
102}
103
104// 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.
106void GainControlImpl::ReadQueuedRenderData() {
107  rtc::CritScope cs(crit_capture_);
108
109  if (!is_component_enabled()) {
110    return;
111  }
112
113  while (render_signal_queue_->Remove(&capture_queue_buffer_)) {
114    size_t buffer_index = 0;
115    const size_t num_frames_per_band =
116        capture_queue_buffer_.size() / num_handles();
117    for (size_t i = 0; i < num_handles(); i++) {
118      Handle* my_handle = static_cast<Handle*>(handle(i));
119      WebRtcAgc_AddFarend(my_handle, &capture_queue_buffer_[buffer_index],
120                          num_frames_per_band);
121
122      buffer_index += num_frames_per_band;
123    }
124  }
125}
126
127int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
128  rtc::CritScope cs(crit_capture_);
129
130  if (!is_component_enabled()) {
131    return AudioProcessing::kNoError;
132  }
133
134  assert(audio->num_frames_per_band() <= 160);
135  assert(audio->num_channels() == num_handles());
136
137  int err = AudioProcessing::kNoError;
138
139  if (mode_ == kAdaptiveAnalog) {
140    capture_levels_.assign(num_handles(), analog_capture_level_);
141    for (size_t i = 0; i < num_handles(); i++) {
142      Handle* my_handle = static_cast<Handle*>(handle(i));
143      err = WebRtcAgc_AddMic(
144          my_handle,
145          audio->split_bands(i),
146          audio->num_bands(),
147          audio->num_frames_per_band());
148
149      if (err != AudioProcessing::kNoError) {
150        return GetHandleError(my_handle);
151      }
152    }
153  } else if (mode_ == kAdaptiveDigital) {
154
155    for (size_t i = 0; i < num_handles(); i++) {
156      Handle* my_handle = static_cast<Handle*>(handle(i));
157      int32_t capture_level_out = 0;
158
159      err = WebRtcAgc_VirtualMic(
160          my_handle,
161          audio->split_bands(i),
162          audio->num_bands(),
163          audio->num_frames_per_band(),
164          analog_capture_level_,
165          &capture_level_out);
166
167      capture_levels_[i] = capture_level_out;
168
169      if (err != AudioProcessing::kNoError) {
170        return GetHandleError(my_handle);
171      }
172
173    }
174  }
175
176  return AudioProcessing::kNoError;
177}
178
179int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) {
180  rtc::CritScope cs(crit_capture_);
181
182  if (!is_component_enabled()) {
183    return AudioProcessing::kNoError;
184  }
185
186  if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
187    return AudioProcessing::kStreamParameterNotSetError;
188  }
189
190  assert(audio->num_frames_per_band() <= 160);
191  assert(audio->num_channels() == num_handles());
192
193  stream_is_saturated_ = false;
194  for (size_t i = 0; i < num_handles(); i++) {
195    Handle* my_handle = static_cast<Handle*>(handle(i));
196    int32_t capture_level_out = 0;
197    uint8_t saturation_warning = 0;
198
199    // The call to stream_has_echo() is ok from a deadlock perspective
200    // as the capture lock is allready held.
201    int err = WebRtcAgc_Process(
202        my_handle,
203        audio->split_bands_const(i),
204        audio->num_bands(),
205        audio->num_frames_per_band(),
206        audio->split_bands(i),
207        capture_levels_[i],
208        &capture_level_out,
209        apm_->echo_cancellation()->stream_has_echo(),
210        &saturation_warning);
211
212    if (err != AudioProcessing::kNoError) {
213      return GetHandleError(my_handle);
214    }
215
216    capture_levels_[i] = capture_level_out;
217    if (saturation_warning == 1) {
218      stream_is_saturated_ = true;
219    }
220  }
221
222  if (mode_ == kAdaptiveAnalog) {
223    // Take the analog level to be the average across the handles.
224    analog_capture_level_ = 0;
225    for (size_t i = 0; i < num_handles(); i++) {
226      analog_capture_level_ += capture_levels_[i];
227    }
228
229    analog_capture_level_ /= num_handles();
230  }
231
232  was_analog_level_set_ = false;
233  return AudioProcessing::kNoError;
234}
235
236// TODO(ajm): ensure this is called under kAdaptiveAnalog.
237int GainControlImpl::set_stream_analog_level(int level) {
238  rtc::CritScope cs(crit_capture_);
239
240  was_analog_level_set_ = true;
241  if (level < minimum_capture_level_ || level > maximum_capture_level_) {
242    return AudioProcessing::kBadParameterError;
243  }
244  analog_capture_level_ = level;
245
246  return AudioProcessing::kNoError;
247}
248
249int GainControlImpl::stream_analog_level() {
250  rtc::CritScope cs(crit_capture_);
251  // TODO(ajm): enable this assertion?
252  //assert(mode_ == kAdaptiveAnalog);
253
254  return analog_capture_level_;
255}
256
257int GainControlImpl::Enable(bool enable) {
258  rtc::CritScope cs_render(crit_render_);
259  rtc::CritScope cs_capture(crit_capture_);
260  return EnableComponent(enable);
261}
262
263bool GainControlImpl::is_enabled() const {
264  rtc::CritScope cs(crit_capture_);
265  return is_component_enabled();
266}
267
268int GainControlImpl::set_mode(Mode mode) {
269  rtc::CritScope cs_render(crit_render_);
270  rtc::CritScope cs_capture(crit_capture_);
271  if (MapSetting(mode) == -1) {
272    return AudioProcessing::kBadParameterError;
273  }
274
275  mode_ = mode;
276  return Initialize();
277}
278
279GainControl::Mode GainControlImpl::mode() const {
280  rtc::CritScope cs(crit_capture_);
281  return mode_;
282}
283
284int GainControlImpl::set_analog_level_limits(int minimum,
285                                             int maximum) {
286  rtc::CritScope cs(crit_capture_);
287  if (minimum < 0) {
288    return AudioProcessing::kBadParameterError;
289  }
290
291  if (maximum > 65535) {
292    return AudioProcessing::kBadParameterError;
293  }
294
295  if (maximum < minimum) {
296    return AudioProcessing::kBadParameterError;
297  }
298
299  minimum_capture_level_ = minimum;
300  maximum_capture_level_ = maximum;
301
302  return Initialize();
303}
304
305int GainControlImpl::analog_level_minimum() const {
306  rtc::CritScope cs(crit_capture_);
307  return minimum_capture_level_;
308}
309
310int GainControlImpl::analog_level_maximum() const {
311  rtc::CritScope cs(crit_capture_);
312  return maximum_capture_level_;
313}
314
315bool GainControlImpl::stream_is_saturated() const {
316  rtc::CritScope cs(crit_capture_);
317  return stream_is_saturated_;
318}
319
320int GainControlImpl::set_target_level_dbfs(int level) {
321  rtc::CritScope cs(crit_capture_);
322  if (level > 31 || level < 0) {
323    return AudioProcessing::kBadParameterError;
324  }
325
326  target_level_dbfs_ = level;
327  return Configure();
328}
329
330int GainControlImpl::target_level_dbfs() const {
331  rtc::CritScope cs(crit_capture_);
332  return target_level_dbfs_;
333}
334
335int GainControlImpl::set_compression_gain_db(int gain) {
336  rtc::CritScope cs(crit_capture_);
337  if (gain < 0 || gain > 90) {
338    return AudioProcessing::kBadParameterError;
339  }
340
341  compression_gain_db_ = gain;
342  return Configure();
343}
344
345int GainControlImpl::compression_gain_db() const {
346  rtc::CritScope cs(crit_capture_);
347  return compression_gain_db_;
348}
349
350int GainControlImpl::enable_limiter(bool enable) {
351  rtc::CritScope cs(crit_capture_);
352  limiter_enabled_ = enable;
353  return Configure();
354}
355
356bool GainControlImpl::is_limiter_enabled() const {
357  rtc::CritScope cs(crit_capture_);
358  return limiter_enabled_;
359}
360
361int GainControlImpl::Initialize() {
362  int err = ProcessingComponent::Initialize();
363  if (err != AudioProcessing::kNoError || !is_component_enabled()) {
364    return err;
365  }
366
367  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}
376
377void GainControlImpl::AllocateRenderQueue() {
378  const size_t new_render_queue_element_max_size =
379      std::max<size_t>(static_cast<size_t>(1),
380                       kMaxAllowedValuesOfSamplesPerFrame * num_handles());
381
382  rtc::CritScope cs_render(crit_render_);
383  rtc::CritScope cs_capture(crit_capture_);
384
385  if (render_queue_element_max_size_ < new_render_queue_element_max_size) {
386    render_queue_element_max_size_ = new_render_queue_element_max_size;
387    std::vector<int16_t> template_queue_element(render_queue_element_max_size_);
388
389    render_signal_queue_.reset(
390        new SwapQueue<std::vector<int16_t>, RenderQueueItemVerifier<int16_t>>(
391            kMaxNumFramesToBuffer, template_queue_element,
392            RenderQueueItemVerifier<int16_t>(render_queue_element_max_size_)));
393
394    render_queue_buffer_.resize(render_queue_element_max_size_);
395    capture_queue_buffer_.resize(render_queue_element_max_size_);
396  } else {
397    render_signal_queue_->Clear();
398  }
399}
400
401void* GainControlImpl::CreateHandle() const {
402  return WebRtcAgc_Create();
403}
404
405void GainControlImpl::DestroyHandle(void* handle) const {
406  WebRtcAgc_Free(static_cast<Handle*>(handle));
407}
408
409int 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
420int GainControlImpl::ConfigureHandle(void* handle) const {
421  rtc::CritScope cs_render(crit_render_);
422  rtc::CritScope cs_capture(crit_capture_);
423  WebRtcAgcConfig config;
424  // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
425  //            change the interface.
426  //assert(target_level_dbfs_ <= 0);
427  //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
428  config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
429  config.compressionGaindB =
430      static_cast<int16_t>(compression_gain_db_);
431  config.limiterEnable = limiter_enabled_;
432
433  return WebRtcAgc_set_config(static_cast<Handle*>(handle), config);
434}
435
436size_t GainControlImpl::num_handles_required() const {
437  // Not locked as it only relies on APM public API which is threadsafe.
438  return apm_->num_proc_channels();
439}
440
441int 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
448