1e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/*
2e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *
4e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  Use of this source code is governed by a BSD-style license
5e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  that can be found in the LICENSE file in the root of the source
6e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  tree. An additional intellectual property rights grant can be found
7e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  in the file PATENTS.  All contributing project authors may
8e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent *  be found in the AUTHORS file in the root of the source tree.
9e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */
10e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
11e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "gain_control_impl.h"
12e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
13e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include <cassert>
14e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
15e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "critical_section_wrapper.h"
16e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "gain_control.h"
17e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
18e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "audio_processing_impl.h"
19e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "audio_buffer.h"
20e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
21e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentnamespace webrtc {
22e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
23e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurenttypedef void Handle;
24e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
25e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/*template <class T>
26e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentclass GainControlHandle : public ComponentHandle<T> {
27e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  public:
28e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    GainControlHandle();
29e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    virtual ~GainControlHandle();
30e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
31e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    virtual int Create();
32e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    virtual T* ptr() const;
33e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
34e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  private:
35e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    T* handle;
36e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent};*/
37e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
38e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentnamespace {
39e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebRtc_Word16 MapSetting(GainControl::Mode mode) {
40e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  switch (mode) {
41e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    case GainControl::kAdaptiveAnalog:
42e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      return kAgcModeAdaptiveAnalog;
43e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      break;
44e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    case GainControl::kAdaptiveDigital:
45e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      return kAgcModeAdaptiveDigital;
46e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      break;
47e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    case GainControl::kFixedDigital:
48e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      return kAgcModeFixedDigital;
49e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      break;
50e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    default:
51e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      return -1;
52e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
53e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
54e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}  // namespace
55e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
56e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentGainControlImpl::GainControlImpl(const AudioProcessingImpl* apm)
57e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  : ProcessingComponent(apm),
58e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    apm_(apm),
59e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    mode_(kAdaptiveAnalog),
60e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    minimum_capture_level_(0),
61e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    maximum_capture_level_(255),
62e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    limiter_enabled_(true),
63e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    target_level_dbfs_(3),
64e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    compression_gain_db_(9),
65e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    analog_capture_level_(0),
66e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    was_analog_level_set_(false),
67e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    stream_is_saturated_(false) {}
68e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
69e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentGainControlImpl::~GainControlImpl() {}
70e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
71e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::ProcessRenderAudio(AudioBuffer* audio) {
72e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (!is_component_enabled()) {
73e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return apm_->kNoError;
74e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
75e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
76e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  assert(audio->samples_per_split_channel() <= 160);
77e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
78e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  WebRtc_Word16* mixed_data = audio->low_pass_split_data(0);
79e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (audio->num_channels() > 1) {
80e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    audio->CopyAndMixLowPass(1);
81e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    mixed_data = audio->mixed_low_pass_data(0);
82e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
83e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
84e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  for (int i = 0; i < num_handles(); i++) {
85e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    Handle* my_handle = static_cast<Handle*>(handle(i));
86e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int err = WebRtcAgc_AddFarend(
87e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        my_handle,
88e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        mixed_data,
89e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        static_cast<WebRtc_Word16>(audio->samples_per_split_channel()));
90e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
91e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (err != apm_->kNoError) {
92e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      return GetHandleError(my_handle);
93e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
94e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
95e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
96e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return apm_->kNoError;
97e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
98e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
99e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
100e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (!is_component_enabled()) {
101e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return apm_->kNoError;
102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
103e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
104e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  assert(audio->samples_per_split_channel() <= 160);
105e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  assert(audio->num_channels() == num_handles());
106e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
107e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  int err = apm_->kNoError;
108e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
109e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (mode_ == kAdaptiveAnalog) {
110e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (int i = 0; i < num_handles(); i++) {
111e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      Handle* my_handle = static_cast<Handle*>(handle(i));
112e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      err = WebRtcAgc_AddMic(
113e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          my_handle,
114e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          audio->low_pass_split_data(i),
115e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          audio->high_pass_split_data(i),
116e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          static_cast<WebRtc_Word16>(audio->samples_per_split_channel()));
117e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
118e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      if (err != apm_->kNoError) {
119e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return GetHandleError(my_handle);
120e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      }
121e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
122e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  } else if (mode_ == kAdaptiveDigital) {
123e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
124e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (int i = 0; i < num_handles(); i++) {
125e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      Handle* my_handle = static_cast<Handle*>(handle(i));
126e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      WebRtc_Word32 capture_level_out = 0;
127e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
128e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      err = WebRtcAgc_VirtualMic(
129e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          my_handle,
130e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          audio->low_pass_split_data(i),
131e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          audio->high_pass_split_data(i),
132e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          static_cast<WebRtc_Word16>(audio->samples_per_split_channel()),
133e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          //capture_levels_[i],
134e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          analog_capture_level_,
135e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent          &capture_level_out);
136e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
137e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      capture_levels_[i] = capture_level_out;
138e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
139e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      if (err != apm_->kNoError) {
140e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        return GetHandleError(my_handle);
141e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      }
142e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
143e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
144e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
145e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
146e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return apm_->kNoError;
147e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
148e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
149e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio) {
150e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (!is_component_enabled()) {
151e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return apm_->kNoError;
152e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
153e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
154e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
155e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return apm_->kStreamParameterNotSetError;
156e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
157e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
158e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  assert(audio->samples_per_split_channel() <= 160);
159e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  assert(audio->num_channels() == num_handles());
160e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
161e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  stream_is_saturated_ = false;
162e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  for (int i = 0; i < num_handles(); i++) {
163e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    Handle* my_handle = static_cast<Handle*>(handle(i));
164e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtc_Word32 capture_level_out = 0;
165e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    WebRtc_UWord8 saturation_warning = 0;
166e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
167e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    int err = WebRtcAgc_Process(
168e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        my_handle,
169e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        audio->low_pass_split_data(i),
170e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        audio->high_pass_split_data(i),
171e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        static_cast<WebRtc_Word16>(audio->samples_per_split_channel()),
172e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        audio->low_pass_split_data(i),
173e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        audio->high_pass_split_data(i),
174e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        capture_levels_[i],
175e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        &capture_level_out,
176e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        apm_->echo_cancellation()->stream_has_echo(),
177e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent        &saturation_warning);
178e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
179e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (err != apm_->kNoError) {
180e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      return GetHandleError(my_handle);
181e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
182e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
183e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    capture_levels_[i] = capture_level_out;
184e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (saturation_warning == 1) {
185e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      stream_is_saturated_ = true;
186e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
187e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
188e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
189e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (mode_ == kAdaptiveAnalog) {
190e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    // Take the analog level to be the average across the handles.
191e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    analog_capture_level_ = 0;
192e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    for (int i = 0; i < num_handles(); i++) {
193e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      analog_capture_level_ += capture_levels_[i];
194e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
195e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
196e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    analog_capture_level_ /= num_handles();
197e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
198e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
199e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  was_analog_level_set_ = false;
200e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return apm_->kNoError;
201e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
202e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
203e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent// TODO(ajm): ensure this is called under kAdaptiveAnalog.
204e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::set_stream_analog_level(int level) {
205e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  was_analog_level_set_ = true;
206e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (level < minimum_capture_level_ || level > maximum_capture_level_) {
207e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return apm_->kBadParameterError;
208e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
209e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
210e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (mode_ == kAdaptiveAnalog) {
211e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    if (level != analog_capture_level_) {
212e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      // The analog level has been changed; update our internal levels.
213e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      capture_levels_.assign(num_handles(), level);
214e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    }
215e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
216e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  analog_capture_level_ = level;
217e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
218e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return apm_->kNoError;
219e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
220e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
221e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::stream_analog_level() {
222e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // TODO(ajm): enable this assertion?
223e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  //assert(mode_ == kAdaptiveAnalog);
224e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
225e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return analog_capture_level_;
226e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
227e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
228e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::Enable(bool enable) {
229e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*apm_->crit());
230e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return EnableComponent(enable);
231e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
232e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
233e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentbool GainControlImpl::is_enabled() const {
234e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return is_component_enabled();
235e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
236e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
237e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::set_mode(Mode mode) {
238e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*apm_->crit());
239e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (MapSetting(mode) == -1) {
240e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return apm_->kBadParameterError;
241e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
242e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
243e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  mode_ = mode;
244e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return Initialize();
245e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
246e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
247e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentGainControl::Mode GainControlImpl::mode() const {
248e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return mode_;
249e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
250e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
251e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::set_analog_level_limits(int minimum,
252e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                                             int maximum) {
253e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*apm_->crit());
254e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (minimum < 0) {
255e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return apm_->kBadParameterError;
256e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
257e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
258e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (maximum > 65535) {
259e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return apm_->kBadParameterError;
260e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
261e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
262e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (maximum < minimum) {
263e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return apm_->kBadParameterError;
264e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
265e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
266e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  minimum_capture_level_ = minimum;
267e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  maximum_capture_level_ = maximum;
268e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
269e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return Initialize();
270e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
271e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
272e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::analog_level_minimum() const {
273e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return minimum_capture_level_;
274e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
275e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
276e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::analog_level_maximum() const {
277e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return maximum_capture_level_;
278e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
279e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
280e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentbool GainControlImpl::stream_is_saturated() const {
281e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return stream_is_saturated_;
282e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
283e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
284e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::set_target_level_dbfs(int level) {
285e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*apm_->crit());
286e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (level > 31 || level < 0) {
287e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return apm_->kBadParameterError;
288e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
289e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
290e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  target_level_dbfs_ = level;
291e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return Configure();
292e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
293e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
294e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::target_level_dbfs() const {
295e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return target_level_dbfs_;
296e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
297e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
298e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::set_compression_gain_db(int gain) {
299e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*apm_->crit());
300e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (gain < 0 || gain > 90) {
301e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return apm_->kBadParameterError;
302e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
303e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
304e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  compression_gain_db_ = gain;
305e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return Configure();
306e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
307e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
308e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::compression_gain_db() const {
309e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return compression_gain_db_;
310e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
311e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
312e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::enable_limiter(bool enable) {
313e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  CriticalSectionScoped crit_scoped(*apm_->crit());
314e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  limiter_enabled_ = enable;
315e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return Configure();
316e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
317e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
318e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentbool GainControlImpl::is_limiter_enabled() const {
319e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return limiter_enabled_;
320e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
321e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
322e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::Initialize() {
323e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  int err = ProcessingComponent::Initialize();
324e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (err != apm_->kNoError || !is_component_enabled()) {
325e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    return err;
326e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
327e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
328e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  analog_capture_level_ =
329e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      (maximum_capture_level_ - minimum_capture_level_) >> 1;
330e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  capture_levels_.assign(num_handles(), analog_capture_level_);
331e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  was_analog_level_set_ = false;
332e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
333e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return apm_->kNoError;
334e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
335e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
336e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::get_version(char* version, int version_len_bytes) const {
337e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (WebRtcAgc_Version(version, version_len_bytes) != 0) {
338e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      return apm_->kBadParameterError;
339e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
340e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
341e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return apm_->kNoError;
342e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
343e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
344e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentvoid* GainControlImpl::CreateHandle() const {
345e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  Handle* handle = NULL;
346e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  if (WebRtcAgc_Create(&handle) != apm_->kNoError) {
347e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    handle = NULL;
348e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  } else {
349e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent    assert(handle != NULL);
350e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  }
351e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
352e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return handle;
353e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
354e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
355e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::DestroyHandle(void* handle) const {
356e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return WebRtcAgc_Free(static_cast<Handle*>(handle));
357e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
358e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
359e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::InitializeHandle(void* handle) const {
360e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return WebRtcAgc_Init(static_cast<Handle*>(handle),
361e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                          minimum_capture_level_,
362e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                          maximum_capture_level_,
363e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                          MapSetting(mode_),
364e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent                          apm_->sample_rate_hz());
365e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
366e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
367e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::ConfigureHandle(void* handle) const {
368e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  WebRtcAgc_config_t config;
369e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
370e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  //            change the interface.
371e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  //assert(target_level_dbfs_ <= 0);
372e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  //config.targetLevelDbfs = static_cast<WebRtc_Word16>(-target_level_dbfs_);
373e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  config.targetLevelDbfs = static_cast<WebRtc_Word16>(target_level_dbfs_);
374e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  config.compressionGaindB =
375e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent      static_cast<WebRtc_Word16>(compression_gain_db_);
376e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  config.limiterEnable = limiter_enabled_;
377e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
378e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return WebRtcAgc_set_config(static_cast<Handle*>(handle), config);
379e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
380e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
381e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::num_handles_required() const {
382e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return apm_->num_output_channels();
383e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
384e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent
385e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurentint GainControlImpl::GetHandleError(void* handle) const {
386e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // The AGC has no get_error() function.
387e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  // (Despite listing errors in its interface...)
388e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  assert(handle != NULL);
389e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent  return apm_->kUnspecifiedError;
390e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}
391e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent}  // namespace webrtc
392