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