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