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 "level_estimator_impl.h"
     12 
     13 #include <assert.h>
     14 #include <math.h>
     15 #include <string.h>
     16 
     17 #include "audio_processing_impl.h"
     18 #include "audio_buffer.h"
     19 #include "critical_section_wrapper.h"
     20 
     21 namespace webrtc {
     22 namespace {
     23 
     24 const double kMaxSquaredLevel = 32768.0 * 32768.0;
     25 
     26 class Level {
     27  public:
     28   static const int kMinLevel = 127;
     29 
     30   Level()
     31     : sum_square_(0.0),
     32       sample_count_(0) {}
     33   ~Level() {}
     34 
     35   void Init() {
     36     sum_square_ = 0.0;
     37     sample_count_ = 0;
     38   }
     39 
     40   void Process(int16_t* data, int length) {
     41     assert(data != NULL);
     42     assert(length > 0);
     43     sum_square_ += SumSquare(data, length);
     44     sample_count_ += length;
     45   }
     46 
     47   void ProcessMuted(int length) {
     48     assert(length > 0);
     49     sample_count_ += length;
     50   }
     51 
     52   int RMS() {
     53     if (sample_count_ == 0 || sum_square_ == 0.0) {
     54       Init();
     55       return kMinLevel;
     56     }
     57 
     58     // Normalize by the max level.
     59     double rms = sum_square_ / (sample_count_ * kMaxSquaredLevel);
     60     // 20log_10(x^0.5) = 10log_10(x)
     61     rms = 10 * log10(rms);
     62     if (rms > 0)
     63       rms = 0;
     64     else if (rms < -kMinLevel)
     65       rms = -kMinLevel;
     66 
     67     rms = -rms;
     68     Init();
     69     return static_cast<int>(rms + 0.5);
     70   }
     71 
     72  private:
     73   static double SumSquare(int16_t* data, int length) {
     74     double sum_square = 0.0;
     75     for (int i = 0; i < length; ++i) {
     76       double data_d = static_cast<double>(data[i]);
     77       sum_square += data_d * data_d;
     78     }
     79     return sum_square;
     80   }
     81 
     82   double sum_square_;
     83   int sample_count_;
     84 };
     85 }  // namespace
     86 
     87 LevelEstimatorImpl::LevelEstimatorImpl(const AudioProcessingImpl* apm)
     88   : ProcessingComponent(apm),
     89     apm_(apm) {}
     90 
     91 LevelEstimatorImpl::~LevelEstimatorImpl() {}
     92 
     93 int LevelEstimatorImpl::ProcessStream(AudioBuffer* audio) {
     94   if (!is_component_enabled()) {
     95     return apm_->kNoError;
     96   }
     97 
     98   Level* level = static_cast<Level*>(handle(0));
     99   if (audio->is_muted()) {
    100     level->ProcessMuted(audio->samples_per_channel());
    101     return apm_->kNoError;
    102   }
    103 
    104   int16_t* mixed_data = audio->data(0);
    105   if (audio->num_channels() > 1) {
    106     audio->CopyAndMix(1);
    107     mixed_data = audio->mixed_data(0);
    108   }
    109 
    110   level->Process(mixed_data, audio->samples_per_channel());
    111 
    112   return apm_->kNoError;
    113 }
    114 
    115 int LevelEstimatorImpl::Enable(bool enable) {
    116   CriticalSectionScoped crit_scoped(*apm_->crit());
    117   return EnableComponent(enable);
    118 }
    119 
    120 bool LevelEstimatorImpl::is_enabled() const {
    121   return is_component_enabled();
    122 }
    123 
    124 int LevelEstimatorImpl::RMS() {
    125   if (!is_component_enabled()) {
    126     return apm_->kNotEnabledError;
    127   }
    128 
    129   Level* level = static_cast<Level*>(handle(0));
    130   return level->RMS();
    131 }
    132 
    133 int LevelEstimatorImpl::get_version(char* version,
    134                                     int version_len_bytes) const {
    135   // An empty string is used to indicate no version information.
    136   memset(version, 0, version_len_bytes);
    137   return apm_->kNoError;
    138 }
    139 
    140 void* LevelEstimatorImpl::CreateHandle() const {
    141   return new Level;
    142 }
    143 
    144 int LevelEstimatorImpl::DestroyHandle(void* handle) const {
    145   assert(handle != NULL);
    146   Level* level = static_cast<Level*>(handle);
    147   delete level;
    148   return apm_->kNoError;
    149 }
    150 
    151 int LevelEstimatorImpl::InitializeHandle(void* handle) const {
    152   assert(handle != NULL);
    153   Level* level = static_cast<Level*>(handle);
    154   level->Init();
    155 
    156   return apm_->kNoError;
    157 }
    158 
    159 int LevelEstimatorImpl::ConfigureHandle(void* /*handle*/) const {
    160   return apm_->kNoError;
    161 }
    162 
    163 int LevelEstimatorImpl::num_handles_required() const {
    164   return 1;
    165 }
    166 
    167 int LevelEstimatorImpl::GetHandleError(void* handle) const {
    168   // The component has no detailed errors.
    169   assert(handle != NULL);
    170   return apm_->kUnspecifiedError;
    171 }
    172 }  // namespace webrtc
    173