webrtc_m130/src/modules/audio_processing/level_estimator_impl.cc
andrew@webrtc.org 755b04a06e Add RMS computation for the RTP level indicator.
- Compute RMS over a packet's worth of audio to be sent in Channel, rather than the captured audio in TransmitMixer.
- We now use the entire packet rather than the last 10 ms frame.
- Restore functionality to LevelEstimator.
- Fix a bug in the splitting filter.
- Fix a number of bugs in process_test related to a poorly named
  AudioFrame member.
- Update the unittest protobuf and float reference output.
- Add audioproc unittests.
- Reenable voe_extended_tests, and add a real function test.
- Use correct minimum level of 127.

TEST=audioproc_unittest, audioproc, voe_extended_test, voe_auto_test

Review URL: http://webrtc-codereview.appspot.com/279003

git-svn-id: http://webrtc.googlecode.com/svn/trunk@950 4adac7df-926f-26a2-2b94-8c16560cd09d
2011-11-15 16:57:56 +00:00

173 lines
3.9 KiB
C++

/*
* 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