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