diff options
Diffstat (limited to 'src/modules/audio_processing/level_estimator_impl.cc')
-rw-r--r-- | src/modules/audio_processing/level_estimator_impl.cc | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/src/modules/audio_processing/level_estimator_impl.cc b/src/modules/audio_processing/level_estimator_impl.cc new file mode 100644 index 0000000000..f127d4abde --- /dev/null +++ b/src/modules/audio_processing/level_estimator_impl.cc @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "level_estimator_impl.h" + +#include <assert.h> +#include <math.h> +#include <string.h> + +#include "audio_processing_impl.h" +#include "audio_buffer.h" +#include "critical_section_wrapper.h" + +namespace webrtc { +namespace { + +const double kMaxSquaredLevel = 32768.0 * 32768.0; + +class Level { + public: + static const int kMinLevel = 127; + + Level() + : sum_square_(0.0), + sample_count_(0) {} + ~Level() {} + + void Init() { + sum_square_ = 0.0; + sample_count_ = 0; + } + + void Process(int16_t* data, int length) { + assert(data != NULL); + assert(length > 0); + sum_square_ += SumSquare(data, length); + sample_count_ += length; + } + + void ProcessMuted(int length) { + assert(length > 0); + sample_count_ += length; + } + + int RMS() { + if (sample_count_ == 0 || sum_square_ == 0.0) { + Init(); + return kMinLevel; + } + + // Normalize by the max level. + double rms = sum_square_ / (sample_count_ * kMaxSquaredLevel); + // 20log_10(x^0.5) = 10log_10(x) + rms = 10 * log10(rms); + if (rms > 0) + rms = 0; + else if (rms < -kMinLevel) + rms = -kMinLevel; + + rms = -rms; + Init(); + return static_cast<int>(rms + 0.5); + } + + private: + static double SumSquare(int16_t* data, int length) { + double sum_square = 0.0; + for (int i = 0; i < length; ++i) { + double data_d = static_cast<double>(data[i]); + sum_square += data_d * data_d; + } + return sum_square; + } + + double sum_square_; + int sample_count_; +}; +} // namespace + +LevelEstimatorImpl::LevelEstimatorImpl(const AudioProcessingImpl* apm) + : ProcessingComponent(apm), + apm_(apm) {} + +LevelEstimatorImpl::~LevelEstimatorImpl() {} + +int LevelEstimatorImpl::ProcessStream(AudioBuffer* audio) { + if (!is_component_enabled()) { + return apm_->kNoError; + } + + Level* level = static_cast<Level*>(handle(0)); + if (audio->is_muted()) { + level->ProcessMuted(audio->samples_per_channel()); + return apm_->kNoError; + } + + int16_t* mixed_data = audio->data(0); + if (audio->num_channels() > 1) { + audio->CopyAndMix(1); + mixed_data = audio->mixed_data(0); + } + + level->Process(mixed_data, audio->samples_per_channel()); + + return apm_->kNoError; +} + +int LevelEstimatorImpl::Enable(bool enable) { + CriticalSectionScoped crit_scoped(*apm_->crit()); + return EnableComponent(enable); +} + +bool LevelEstimatorImpl::is_enabled() const { + return is_component_enabled(); +} + +int LevelEstimatorImpl::RMS() { + if (!is_component_enabled()) { + return apm_->kNotEnabledError; + } + + Level* level = static_cast<Level*>(handle(0)); + return level->RMS(); +} + +int LevelEstimatorImpl::get_version(char* version, + int version_len_bytes) const { + // An empty string is used to indicate no version information. + memset(version, 0, version_len_bytes); + return apm_->kNoError; +} + +void* LevelEstimatorImpl::CreateHandle() const { + return new Level; +} + +int LevelEstimatorImpl::DestroyHandle(void* handle) const { + assert(handle != NULL); + Level* level = static_cast<Level*>(handle); + delete level; + return apm_->kNoError; +} + +int LevelEstimatorImpl::InitializeHandle(void* handle) const { + assert(handle != NULL); + Level* level = static_cast<Level*>(handle); + level->Init(); + + return apm_->kNoError; +} + +int LevelEstimatorImpl::ConfigureHandle(void* /*handle*/) const { + return apm_->kNoError; +} + +int LevelEstimatorImpl::num_handles_required() const { + return 1; +} + +int LevelEstimatorImpl::GetHandleError(void* handle) const { + // The component has no detailed errors. + assert(handle != NULL); + return apm_->kUnspecifiedError; +} +} // namespace webrtc |