LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/audio_processing - gain_control_impl.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 229 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 32 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "webrtc/base/constructormagic.h"
      14             : #include "webrtc/base/optional.h"
      15             : #include "webrtc/modules/audio_processing/audio_buffer.h"
      16             : #include "webrtc/modules/audio_processing/agc/legacy/gain_control.h"
      17             : #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
      18             : 
      19             : namespace webrtc {
      20             : 
      21             : typedef void Handle;
      22             : 
      23             : namespace {
      24           0 : int16_t MapSetting(GainControl::Mode mode) {
      25           0 :   switch (mode) {
      26             :     case GainControl::kAdaptiveAnalog:
      27           0 :       return kAgcModeAdaptiveAnalog;
      28             :     case GainControl::kAdaptiveDigital:
      29           0 :       return kAgcModeAdaptiveDigital;
      30             :     case GainControl::kFixedDigital:
      31           0 :       return kAgcModeFixedDigital;
      32             :   }
      33           0 :   RTC_NOTREACHED();
      34           0 :   return -1;
      35             : }
      36             : 
      37             : }  // namespace
      38             : 
      39             : class GainControlImpl::GainController {
      40             :  public:
      41           0 :   explicit GainController() {
      42           0 :     state_ = WebRtcAgc_Create();
      43           0 :     RTC_CHECK(state_);
      44           0 :   }
      45             : 
      46           0 :   ~GainController() {
      47           0 :     RTC_DCHECK(state_);
      48           0 :     WebRtcAgc_Free(state_);
      49           0 :   }
      50             : 
      51           0 :   Handle* state() {
      52           0 :     RTC_DCHECK(state_);
      53           0 :     return state_;
      54             :   }
      55             : 
      56           0 :   void Initialize(int minimum_capture_level,
      57             :                   int maximum_capture_level,
      58             :                   Mode mode,
      59             :                   int sample_rate_hz,
      60             :                   int capture_level) {
      61           0 :     RTC_DCHECK(state_);
      62             :     int error =
      63           0 :         WebRtcAgc_Init(state_, minimum_capture_level, maximum_capture_level,
      64           0 :                        MapSetting(mode), sample_rate_hz);
      65           0 :     RTC_DCHECK_EQ(0, error);
      66             : 
      67           0 :     set_capture_level(capture_level);
      68           0 :   }
      69             : 
      70           0 :   void set_capture_level(int capture_level) {
      71           0 :     capture_level_ = rtc::Optional<int>(capture_level);
      72           0 :   }
      73             : 
      74           0 :   int get_capture_level() {
      75           0 :     RTC_DCHECK(capture_level_);
      76           0 :     return *capture_level_;
      77             :   }
      78             : 
      79             :  private:
      80             :   Handle* state_;
      81             :   // TODO(peah): Remove the optional once the initialization is moved into the
      82             :   // ctor.
      83             :   rtc::Optional<int> capture_level_;
      84             : 
      85             :   RTC_DISALLOW_COPY_AND_ASSIGN(GainController);
      86             : };
      87             : 
      88             : int GainControlImpl::instance_counter_ = 0;
      89             : 
      90           0 : GainControlImpl::GainControlImpl(rtc::CriticalSection* crit_render,
      91           0 :                                  rtc::CriticalSection* crit_capture)
      92             :     : crit_render_(crit_render),
      93             :       crit_capture_(crit_capture),
      94           0 :       data_dumper_(new ApmDataDumper(instance_counter_)),
      95             :       mode_(kAdaptiveAnalog),
      96             :       minimum_capture_level_(0),
      97             :       maximum_capture_level_(255),
      98             :       limiter_enabled_(true),
      99             :       target_level_dbfs_(3),
     100             :       compression_gain_db_(9),
     101             :       analog_capture_level_(0),
     102             :       was_analog_level_set_(false),
     103           0 :       stream_is_saturated_(false) {
     104           0 :   RTC_DCHECK(crit_render);
     105           0 :   RTC_DCHECK(crit_capture);
     106           0 : }
     107             : 
     108           0 : GainControlImpl::~GainControlImpl() {}
     109             : 
     110           0 : void GainControlImpl::ProcessRenderAudio(
     111             :     rtc::ArrayView<const int16_t> packed_render_audio) {
     112           0 :   rtc::CritScope cs_capture(crit_capture_);
     113           0 :   if (!enabled_) {
     114           0 :     return;
     115             :   }
     116             : 
     117           0 :   for (auto& gain_controller : gain_controllers_) {
     118           0 :     WebRtcAgc_AddFarend(gain_controller->state(), packed_render_audio.data(),
     119           0 :                         packed_render_audio.size());
     120             :   }
     121             : }
     122             : 
     123           0 : void GainControlImpl::PackRenderAudioBuffer(
     124             :     AudioBuffer* audio,
     125             :     std::vector<int16_t>* packed_buffer) {
     126           0 :   RTC_DCHECK_GE(160, audio->num_frames_per_band());
     127             : 
     128           0 :   packed_buffer->clear();
     129             :   packed_buffer->insert(
     130           0 :       packed_buffer->end(), audio->mixed_low_pass_data(),
     131           0 :       (audio->mixed_low_pass_data() + audio->num_frames_per_band()));
     132           0 : }
     133             : 
     134           0 : int GainControlImpl::AnalyzeCaptureAudio(AudioBuffer* audio) {
     135           0 :   rtc::CritScope cs(crit_capture_);
     136             : 
     137           0 :   if (!enabled_) {
     138           0 :     return AudioProcessing::kNoError;
     139             :   }
     140             : 
     141           0 :   RTC_DCHECK(num_proc_channels_);
     142           0 :   RTC_DCHECK_GE(160, audio->num_frames_per_band());
     143           0 :   RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
     144           0 :   RTC_DCHECK_LE(*num_proc_channels_, gain_controllers_.size());
     145             : 
     146           0 :   if (mode_ == kAdaptiveAnalog) {
     147           0 :     int capture_channel = 0;
     148           0 :     for (auto& gain_controller : gain_controllers_) {
     149           0 :       gain_controller->set_capture_level(analog_capture_level_);
     150           0 :       int err = WebRtcAgc_AddMic(
     151             :           gain_controller->state(), audio->split_bands(capture_channel),
     152           0 :           audio->num_bands(), audio->num_frames_per_band());
     153             : 
     154           0 :       if (err != AudioProcessing::kNoError) {
     155           0 :         return AudioProcessing::kUnspecifiedError;
     156             :       }
     157           0 :       ++capture_channel;
     158             :     }
     159           0 :   } else if (mode_ == kAdaptiveDigital) {
     160           0 :     int capture_channel = 0;
     161           0 :     for (auto& gain_controller : gain_controllers_) {
     162           0 :       int32_t capture_level_out = 0;
     163           0 :       int err = WebRtcAgc_VirtualMic(
     164             :           gain_controller->state(), audio->split_bands(capture_channel),
     165             :           audio->num_bands(), audio->num_frames_per_band(),
     166           0 :           analog_capture_level_, &capture_level_out);
     167             : 
     168           0 :       gain_controller->set_capture_level(capture_level_out);
     169             : 
     170           0 :       if (err != AudioProcessing::kNoError) {
     171           0 :         return AudioProcessing::kUnspecifiedError;
     172             :       }
     173           0 :       ++capture_channel;
     174             :     }
     175             :   }
     176             : 
     177           0 :   return AudioProcessing::kNoError;
     178             : }
     179             : 
     180           0 : int GainControlImpl::ProcessCaptureAudio(AudioBuffer* audio,
     181             :                                          bool stream_has_echo) {
     182           0 :   rtc::CritScope cs(crit_capture_);
     183             : 
     184           0 :   if (!enabled_) {
     185           0 :     return AudioProcessing::kNoError;
     186             :   }
     187             : 
     188           0 :   if (mode_ == kAdaptiveAnalog && !was_analog_level_set_) {
     189           0 :     return AudioProcessing::kStreamParameterNotSetError;
     190             :   }
     191             : 
     192           0 :   RTC_DCHECK(num_proc_channels_);
     193           0 :   RTC_DCHECK_GE(160, audio->num_frames_per_band());
     194           0 :   RTC_DCHECK_EQ(audio->num_channels(), *num_proc_channels_);
     195             : 
     196           0 :   stream_is_saturated_ = false;
     197           0 :   int capture_channel = 0;
     198           0 :   for (auto& gain_controller : gain_controllers_) {
     199           0 :     int32_t capture_level_out = 0;
     200           0 :     uint8_t saturation_warning = 0;
     201             : 
     202             :     // The call to stream_has_echo() is ok from a deadlock perspective
     203             :     // as the capture lock is allready held.
     204           0 :     int err = WebRtcAgc_Process(
     205             :         gain_controller->state(), audio->split_bands_const(capture_channel),
     206             :         audio->num_bands(), audio->num_frames_per_band(),
     207             :         audio->split_bands(capture_channel),
     208             :         gain_controller->get_capture_level(), &capture_level_out,
     209           0 :         stream_has_echo, &saturation_warning);
     210             : 
     211           0 :     if (err != AudioProcessing::kNoError) {
     212           0 :       return AudioProcessing::kUnspecifiedError;
     213             :     }
     214             : 
     215           0 :     gain_controller->set_capture_level(capture_level_out);
     216           0 :     if (saturation_warning == 1) {
     217           0 :       stream_is_saturated_ = true;
     218             :     }
     219             : 
     220           0 :     ++capture_channel;
     221             :   }
     222             : 
     223           0 :   RTC_DCHECK_LT(0ul, *num_proc_channels_);
     224           0 :   if (mode_ == kAdaptiveAnalog) {
     225             :     // Take the analog level to be the average across the handles.
     226           0 :     analog_capture_level_ = 0;
     227           0 :     for (auto& gain_controller : gain_controllers_) {
     228           0 :       analog_capture_level_ += gain_controller->get_capture_level();
     229             :     }
     230             : 
     231           0 :     analog_capture_level_ /= (*num_proc_channels_);
     232             :   }
     233             : 
     234           0 :   was_analog_level_set_ = false;
     235           0 :   return AudioProcessing::kNoError;
     236             : }
     237             : 
     238           0 : int GainControlImpl::compression_gain_db() const {
     239           0 :   rtc::CritScope cs(crit_capture_);
     240           0 :   return compression_gain_db_;
     241             : }
     242             : 
     243             : // TODO(ajm): ensure this is called under kAdaptiveAnalog.
     244           0 : int GainControlImpl::set_stream_analog_level(int level) {
     245           0 :   rtc::CritScope cs(crit_capture_);
     246           0 :   data_dumper_->DumpRaw("gain_control_set_stream_analog_level", 1, &level);
     247             : 
     248           0 :   was_analog_level_set_ = true;
     249           0 :   if (level < minimum_capture_level_ || level > maximum_capture_level_) {
     250           0 :     return AudioProcessing::kBadParameterError;
     251             :   }
     252           0 :   analog_capture_level_ = level;
     253             : 
     254           0 :   return AudioProcessing::kNoError;
     255             : }
     256             : 
     257           0 : int GainControlImpl::stream_analog_level() {
     258           0 :   rtc::CritScope cs(crit_capture_);
     259           0 :   data_dumper_->DumpRaw("gain_control_stream_analog_level", 1,
     260           0 :                         &analog_capture_level_);
     261             :   // TODO(ajm): enable this assertion?
     262             :   //RTC_DCHECK_EQ(kAdaptiveAnalog, mode_);
     263             : 
     264           0 :   return analog_capture_level_;
     265             : }
     266             : 
     267           0 : int GainControlImpl::Enable(bool enable) {
     268           0 :   rtc::CritScope cs_render(crit_render_);
     269           0 :   rtc::CritScope cs_capture(crit_capture_);
     270           0 :   if (enable && !enabled_) {
     271           0 :     enabled_ = enable;  // Must be set before Initialize() is called.
     272             : 
     273           0 :     RTC_DCHECK(num_proc_channels_);
     274           0 :     RTC_DCHECK(sample_rate_hz_);
     275           0 :     Initialize(*num_proc_channels_, *sample_rate_hz_);
     276             :   } else {
     277           0 :     enabled_ = enable;
     278             :   }
     279           0 :   return AudioProcessing::kNoError;
     280             : }
     281             : 
     282           0 : bool GainControlImpl::is_enabled() const {
     283           0 :   rtc::CritScope cs(crit_capture_);
     284           0 :   return enabled_;
     285             : }
     286             : 
     287           0 : int GainControlImpl::set_mode(Mode mode) {
     288           0 :   rtc::CritScope cs_render(crit_render_);
     289           0 :   rtc::CritScope cs_capture(crit_capture_);
     290           0 :   if (MapSetting(mode) == -1) {
     291           0 :     return AudioProcessing::kBadParameterError;
     292             :   }
     293             : 
     294           0 :   mode_ = mode;
     295           0 :   RTC_DCHECK(num_proc_channels_);
     296           0 :   RTC_DCHECK(sample_rate_hz_);
     297           0 :   Initialize(*num_proc_channels_, *sample_rate_hz_);
     298           0 :   return AudioProcessing::kNoError;
     299             : }
     300             : 
     301           0 : GainControl::Mode GainControlImpl::mode() const {
     302           0 :   rtc::CritScope cs(crit_capture_);
     303           0 :   return mode_;
     304             : }
     305             : 
     306           0 : int GainControlImpl::set_analog_level_limits(int minimum,
     307             :                                              int maximum) {
     308           0 :   if (minimum < 0) {
     309           0 :     return AudioProcessing::kBadParameterError;
     310             :   }
     311             : 
     312           0 :   if (maximum > 65535) {
     313           0 :     return AudioProcessing::kBadParameterError;
     314             :   }
     315             : 
     316           0 :   if (maximum < minimum) {
     317           0 :     return AudioProcessing::kBadParameterError;
     318             :   }
     319             : 
     320           0 :   size_t num_proc_channels_local = 0u;
     321           0 :   int sample_rate_hz_local = 0;
     322             :   {
     323           0 :     rtc::CritScope cs(crit_capture_);
     324             : 
     325           0 :     minimum_capture_level_ = minimum;
     326           0 :     maximum_capture_level_ = maximum;
     327             : 
     328           0 :     RTC_DCHECK(num_proc_channels_);
     329           0 :     RTC_DCHECK(sample_rate_hz_);
     330           0 :     num_proc_channels_local = *num_proc_channels_;
     331           0 :     sample_rate_hz_local = *sample_rate_hz_;
     332             :   }
     333           0 :   Initialize(num_proc_channels_local, sample_rate_hz_local);
     334           0 :   return AudioProcessing::kNoError;
     335             : }
     336             : 
     337           0 : int GainControlImpl::analog_level_minimum() const {
     338           0 :   rtc::CritScope cs(crit_capture_);
     339           0 :   return minimum_capture_level_;
     340             : }
     341             : 
     342           0 : int GainControlImpl::analog_level_maximum() const {
     343           0 :   rtc::CritScope cs(crit_capture_);
     344           0 :   return maximum_capture_level_;
     345             : }
     346             : 
     347           0 : bool GainControlImpl::stream_is_saturated() const {
     348           0 :   rtc::CritScope cs(crit_capture_);
     349           0 :   return stream_is_saturated_;
     350             : }
     351             : 
     352           0 : int GainControlImpl::set_target_level_dbfs(int level) {
     353           0 :   if (level > 31 || level < 0) {
     354           0 :     return AudioProcessing::kBadParameterError;
     355             :   }
     356             :   {
     357           0 :     rtc::CritScope cs(crit_capture_);
     358           0 :     target_level_dbfs_ = level;
     359             :   }
     360           0 :   return Configure();
     361             : }
     362             : 
     363           0 : int GainControlImpl::target_level_dbfs() const {
     364           0 :   rtc::CritScope cs(crit_capture_);
     365           0 :   return target_level_dbfs_;
     366             : }
     367             : 
     368           0 : int GainControlImpl::set_compression_gain_db(int gain) {
     369           0 :   if (gain < 0 || gain > 90) {
     370           0 :     return AudioProcessing::kBadParameterError;
     371             :   }
     372             :   {
     373           0 :     rtc::CritScope cs(crit_capture_);
     374           0 :     compression_gain_db_ = gain;
     375             :   }
     376           0 :   return Configure();
     377             : }
     378             : 
     379           0 : int GainControlImpl::enable_limiter(bool enable) {
     380             :   {
     381           0 :     rtc::CritScope cs(crit_capture_);
     382           0 :     limiter_enabled_ = enable;
     383             :   }
     384           0 :   return Configure();
     385             : }
     386             : 
     387           0 : bool GainControlImpl::is_limiter_enabled() const {
     388           0 :   rtc::CritScope cs(crit_capture_);
     389           0 :   return limiter_enabled_;
     390             : }
     391             : 
     392           0 : void GainControlImpl::Initialize(size_t num_proc_channels, int sample_rate_hz) {
     393           0 :   rtc::CritScope cs_render(crit_render_);
     394           0 :   rtc::CritScope cs_capture(crit_capture_);
     395           0 :   data_dumper_->InitiateNewSetOfRecordings();
     396             : 
     397           0 :   num_proc_channels_ = rtc::Optional<size_t>(num_proc_channels);
     398           0 :   sample_rate_hz_ = rtc::Optional<int>(sample_rate_hz);
     399             : 
     400           0 :   if (!enabled_) {
     401           0 :     return;
     402             :   }
     403             : 
     404           0 :   gain_controllers_.resize(*num_proc_channels_);
     405           0 :   for (auto& gain_controller : gain_controllers_) {
     406           0 :     if (!gain_controller) {
     407           0 :       gain_controller.reset(new GainController());
     408             :     }
     409           0 :     gain_controller->Initialize(minimum_capture_level_, maximum_capture_level_,
     410           0 :                                 mode_, *sample_rate_hz_, analog_capture_level_);
     411             :   }
     412             : 
     413           0 :   Configure();
     414             : }
     415             : 
     416           0 : int GainControlImpl::Configure() {
     417           0 :   rtc::CritScope cs_render(crit_render_);
     418           0 :   rtc::CritScope cs_capture(crit_capture_);
     419             :   WebRtcAgcConfig config;
     420             :   // TODO(ajm): Flip the sign here (since AGC expects a positive value) if we
     421             :   //            change the interface.
     422             :   //RTC_DCHECK_LE(target_level_dbfs_, 0);
     423             :   //config.targetLevelDbfs = static_cast<int16_t>(-target_level_dbfs_);
     424           0 :   config.targetLevelDbfs = static_cast<int16_t>(target_level_dbfs_);
     425           0 :   config.compressionGaindB =
     426           0 :       static_cast<int16_t>(compression_gain_db_);
     427           0 :   config.limiterEnable = limiter_enabled_;
     428             : 
     429           0 :   int error = AudioProcessing::kNoError;
     430           0 :   for (auto& gain_controller : gain_controllers_) {
     431             :     const int handle_error =
     432           0 :         WebRtcAgc_set_config(gain_controller->state(), config);
     433           0 :     if (handle_error != AudioProcessing::kNoError) {
     434           0 :       error = handle_error;
     435             :     }
     436             :   }
     437           0 :   return error;
     438             : }
     439             : }  // namespace webrtc

Generated by: LCOV version 1.13