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