1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
119fb16139d917ba32720e031d3c871987d418668fpbos@webrtc.org#include "webrtc/modules/audio_processing/gain_control_impl.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
133f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <assert.h>
14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
15a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org#include "webrtc/modules/audio_processing/audio_buffer.h"
169fb16139d917ba32720e031d3c871987d418668fpbos@webrtc.org#include "webrtc/modules/audio_processing/agc/include/gain_control.h"
179fb16139d917ba32720e031d3c871987d418668fpbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc {
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgtypedef void Handle;
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace {
243f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.orgint16_t MapSetting(GainControl::Mode mode) {
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (mode) {
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case GainControl::kAdaptiveAnalog:
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kAgcModeAdaptiveAnalog;
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case GainControl::kAdaptiveDigital:
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kAgcModeAdaptiveDigital;
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case GainControl::kFixedDigital:
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kAgcModeFixedDigital;
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(false);
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return -1;
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
38a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.orgGainControlImpl::GainControlImpl(const AudioProcessing* apm,
39a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org                                 CriticalSectionWrapper* crit)
40a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org  : ProcessingComponent(),
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    apm_(apm),
42a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org    crit_(crit),
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    mode_(kAdaptiveAnalog),
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    minimum_capture_level_(0),
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    maximum_capture_level_(255),
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    limiter_enabled_(true),
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    target_level_dbfs_(3),
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    compression_gain_db_(9),
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    analog_capture_level_(0),
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    was_analog_level_set_(false),
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    stream_is_saturated_(false) {}
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgGainControlImpl::~GainControlImpl() {}
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) {
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (!is_component_enabled()) {
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return apm_->kNoError;
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(audio->samples_per_split_channel() <= 160);
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (int i = 0; i < num_handles(); i++) {
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    Handle* my_handle = static_cast<Handle*>(handle(i));
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int err = WebRtcAgc_AddFarend(
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        my_handle,
66eb15100c9bdb4c97ffda2c05a934aab270795c27aluebs@webrtc.org        audio->mixed_low_pass_data(),
673f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org        static_cast<int16_t>(audio->samples_per_split_channel()));
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (err != apm_->kNoError) {
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return GetHandleError(my_handle);
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return apm_->kNoError;
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (!is_component_enabled()) {
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return apm_->kNoError;
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(audio->samples_per_split_channel() <= 160);
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(audio->num_channels() == num_handles());
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err = apm_->kNoError;
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (mode_ == kAdaptiveAnalog) {
88e95dc25b14845cbf00ae363e88459c44e2341c47andrew@webrtc.org    capture_levels_.assign(num_handles(), analog_capture_level_);
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (int i = 0; i < num_handles(); i++) {
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      Handle* my_handle = static_cast<Handle*>(handle(i));
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      err = WebRtcAgc_AddMic(
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          my_handle,
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          audio->low_pass_split_data(i),
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          audio->high_pass_split_data(i),
953f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org          static_cast<int16_t>(audio->samples_per_split_channel()));
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (err != apm_->kNoError) {
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return GetHandleError(my_handle);
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else if (mode_ == kAdaptiveDigital) {
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (int i = 0; i < num_handles(); i++) {
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      Handle* my_handle = static_cast<Handle*>(handle(i));
1053f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org      int32_t capture_level_out = 0;
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      err = WebRtcAgc_VirtualMic(
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          my_handle,
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          audio->low_pass_split_data(i),
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          audio->high_pass_split_data(i),
1113f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org          static_cast<int16_t>(audio->samples_per_split_channel()),
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          analog_capture_level_,
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          &capture_level_out);
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      capture_levels_[i] = capture_level_out;
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (err != apm_->kNoError) {
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return GetHandleError(my_handle);
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return apm_->kNoError;
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) {
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (!is_component_enabled()) {
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return apm_->kNoError;
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return apm_->kStreamParameterNotSetError;
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(audio->samples_per_split_channel() <= 160);
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(audio->num_channels() == num_handles());
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  stream_is_saturated_ = false;
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (int i = 0; i < num_handles(); i++) {
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    Handle* my_handle = static_cast<Handle*>(handle(i));
1423f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org    int32_t capture_level_out = 0;
1433f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org    uint8_t saturation_warning = 0;
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int err = WebRtcAgc_Process(
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        my_handle,
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        audio->low_pass_split_data(i),
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        audio->high_pass_split_data(i),
1493f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org        static_cast<int16_t>(audio->samples_per_split_channel()),
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        audio->low_pass_split_data(i),
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        audio->high_pass_split_data(i),
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        capture_levels_[i],
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        &capture_level_out,
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        apm_->echo_cancellation()->stream_has_echo(),
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        &saturation_warning);
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (err != apm_->kNoError) {
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return GetHandleError(my_handle);
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    capture_levels_[i] = capture_level_out;
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (saturation_warning == 1) {
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      stream_is_saturated_ = true;
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (mode_ == kAdaptiveAnalog) {
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Take the analog level to be the average across the handles.
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    analog_capture_level_ = 0;
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (int i = 0; i < num_handles(); i++) {
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      analog_capture_level_ += capture_levels_[i];
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    analog_capture_level_ /= num_handles();
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  was_analog_level_set_ = false;
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return apm_->kNoError;
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// TODO(ajm): ensure this is called under kAdaptiveAnalog.
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::set_stream_analog_level(int level) {
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  was_analog_level_set_ = true;
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (level < minimum_capture_level_ || level > maximum_capture_level_) {
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return apm_->kBadParameterError;
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  analog_capture_level_ = level;
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return apm_->kNoError;
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::stream_analog_level() {
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // TODO(ajm): enable this assertion?
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  //assert(mode_ == kAdaptiveAnalog);
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return analog_capture_level_;
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::Enable(bool enable) {
200a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org  CriticalSectionScoped crit_scoped(crit_);
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return EnableComponent(enable);
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool GainControlImpl::is_enabled() const {
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return is_component_enabled();
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::set_mode(Mode mode) {
209a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org  CriticalSectionScoped crit_scoped(crit_);
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (MapSetting(mode) == -1) {
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return apm_->kBadParameterError;
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  mode_ = mode;
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return Initialize();
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgGainControl::Mode GainControlImpl::mode() const {
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return mode_;
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::set_analog_level_limits(int minimum,
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                             int maximum) {
224a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org  CriticalSectionScoped crit_scoped(crit_);
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (minimum < 0) {
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return apm_->kBadParameterError;
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (maximum > 65535) {
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return apm_->kBadParameterError;
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (maximum < minimum) {
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return apm_->kBadParameterError;
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  minimum_capture_level_ = minimum;
238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  maximum_capture_level_ = maximum;
239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return Initialize();
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::analog_level_minimum() const {
244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return minimum_capture_level_;
245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::analog_level_maximum() const {
248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return maximum_capture_level_;
249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool GainControlImpl::stream_is_saturated() const {
252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return stream_is_saturated_;
253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::set_target_level_dbfs(int level) {
256a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org  CriticalSectionScoped crit_scoped(crit_);
257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (level > 31 || level < 0) {
258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return apm_->kBadParameterError;
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  target_level_dbfs_ = level;
262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return Configure();
263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::target_level_dbfs() const {
266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return target_level_dbfs_;
267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::set_compression_gain_db(int gain) {
270a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org  CriticalSectionScoped crit_scoped(crit_);
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (gain < 0 || gain > 90) {
272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return apm_->kBadParameterError;
273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  compression_gain_db_ = gain;
276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return Configure();
277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::compression_gain_db() const {
280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return compression_gain_db_;
281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::enable_limiter(bool enable) {
284a1a60018a1f1ec863451ad0ed4eae58239882920andrew@webrtc.org  CriticalSectionScoped crit_scoped(crit_);
285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  limiter_enabled_ = enable;
286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return Configure();
287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool GainControlImpl::is_limiter_enabled() const {
290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return limiter_enabled_;
291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::Initialize() {
294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int err = ProcessingComponent::Initialize();
295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (err != apm_->kNoError || !is_component_enabled()) {
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return err;
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
29948b9892684682b60b8c4fbc01f1998ace1d32663andrew@webrtc.org  capture_levels_.assign(num_handles(), analog_capture_level_);
300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return apm_->kNoError;
301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid* GainControlImpl::CreateHandle() const {
304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Handle* handle = NULL;
305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (WebRtcAgc_Create(&handle) != apm_->kNoError) {
306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    handle = NULL;
307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    assert(handle != NULL);
309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return handle;
312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
314ffc2de0133683fb103eef61f21134f469bc099dbbjornv@webrtc.orgvoid GainControlImpl::DestroyHandle(void* handle) const {
315ffc2de0133683fb103eef61f21134f469bc099dbbjornv@webrtc.org  WebRtcAgc_Free(static_cast<Handle*>(handle));
316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::InitializeHandle(void* handle) const {
319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return WebRtcAgc_Init(static_cast<Handle*>(handle),
320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          minimum_capture_level_,
321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          maximum_capture_level_,
322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          MapSetting(mode_),
323467f7567c8befea153861e09f048f69932d6e3bdandrew@webrtc.org                          apm_->proc_sample_rate_hz());
324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::ConfigureHandle(void* handle) const {
327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WebRtcAgc_config_t config;
328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  //            change the interface.
330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  //assert(target_level_dbfs_ <= 0);
3313f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org  //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
3323f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org  config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  config.compressionGaindB =
3343f6d5e0bded85b8b0d055da8fa49e8d7137fe8edpbos@webrtc.org      static_cast<int16_t>(compression_gain_db_);
335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  config.limiterEnable = limiter_enabled_;
336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return WebRtcAgc_set_config(static_cast<Handle*>(handle), config);
338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::num_handles_required() const {
341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return apm_->num_output_channels();
342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint GainControlImpl::GetHandleError(void* handle) const {
345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // The AGC has no get_error() function.
346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // (Despite listing errors in its interface...)
347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(handle != NULL);
348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return apm_->kUnspecifiedError;
349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace webrtc
351