aboutsummaryrefslogtreecommitdiff
path: root/src/modules/audio_processing/level_estimator_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/audio_processing/level_estimator_impl.cc')
-rw-r--r--src/modules/audio_processing/level_estimator_impl.cc172
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