• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Level()30   Level()
31     : sum_square_(0.0),
32       sample_count_(0) {}
~Level()33   ~Level() {}
34 
Init()35   void Init() {
36     sum_square_ = 0.0;
37     sample_count_ = 0;
38   }
39 
Process(int16_t * data,int length)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 
ProcessMuted(int length)47   void ProcessMuted(int length) {
48     assert(length > 0);
49     sample_count_ += length;
50   }
51 
RMS()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:
SumSquare(int16_t * data,int length)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 
LevelEstimatorImpl(const AudioProcessingImpl * apm)87 LevelEstimatorImpl::LevelEstimatorImpl(const AudioProcessingImpl* apm)
88   : ProcessingComponent(apm),
89     apm_(apm) {}
90 
~LevelEstimatorImpl()91 LevelEstimatorImpl::~LevelEstimatorImpl() {}
92 
ProcessStream(AudioBuffer * audio)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 
Enable(bool enable)115 int LevelEstimatorImpl::Enable(bool enable) {
116   CriticalSectionScoped crit_scoped(*apm_->crit());
117   return EnableComponent(enable);
118 }
119 
is_enabled() const120 bool LevelEstimatorImpl::is_enabled() const {
121   return is_component_enabled();
122 }
123 
RMS()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 
get_version(char * version,int version_len_bytes) const133 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 
CreateHandle() const140 void* LevelEstimatorImpl::CreateHandle() const {
141   return new Level;
142 }
143 
DestroyHandle(void * handle) const144 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 
InitializeHandle(void * handle) const151 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 
ConfigureHandle(void *) const159 int LevelEstimatorImpl::ConfigureHandle(void* /*handle*/) const {
160   return apm_->kNoError;
161 }
162 
num_handles_required() const163 int LevelEstimatorImpl::num_handles_required() const {
164   return 1;
165 }
166 
GetHandleError(void * handle) const167 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