Delay Estimator Unit tests
This CL includes unit tests to verify correct behavior of the delay estimator used in AEC and AECM. Tested with audioproc_unittest BUG= TEST= Review URL: https://webrtc-codereview.appspot.com/491009 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2049 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
2e729762c7
commit
4ade5506eb
@ -32,6 +32,7 @@
|
||||
'sources': [
|
||||
'aec/system_delay_unittest.cc',
|
||||
'test/unit_test.cc',
|
||||
'utility/delay_estimator_unittest.cc',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@ -131,7 +131,7 @@ BinaryDelayEstimator* WebRtc_CreateBinaryDelayEstimator(int max_delay,
|
||||
return self;
|
||||
}
|
||||
|
||||
int WebRtc_InitBinaryDelayEstimator(BinaryDelayEstimator* handle) {
|
||||
void WebRtc_InitBinaryDelayEstimator(BinaryDelayEstimator* handle) {
|
||||
int i = 0;
|
||||
assert(handle != NULL);
|
||||
|
||||
@ -149,8 +149,6 @@ int WebRtc_InitBinaryDelayEstimator(BinaryDelayEstimator* handle) {
|
||||
|
||||
// Default return value if we're unable to estimate. -1 is used for errors.
|
||||
handle->last_delay = -2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebRtc_ProcessBinarySpectrum(BinaryDelayEstimator* handle,
|
||||
|
||||
@ -63,7 +63,7 @@ BinaryDelayEstimator* WebRtc_CreateBinaryDelayEstimator(int max_delay,
|
||||
// Output:
|
||||
// - handle : Initialized instance.
|
||||
//
|
||||
int WebRtc_InitBinaryDelayEstimator(BinaryDelayEstimator* handle);
|
||||
void WebRtc_InitBinaryDelayEstimator(BinaryDelayEstimator* handle);
|
||||
|
||||
// Estimates and returns the delay between the binary far-end and binary near-
|
||||
// end spectra. The value will be offset by the lookahead (i.e. the lookahead
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
// Header file including the delay estimator handle used for testing.
|
||||
|
||||
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_INTERNAL_H_
|
||||
#define WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_INTERNAL_H_
|
||||
|
||||
#include "modules/audio_processing/utility/delay_estimator.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
typedef union {
|
||||
float float_;
|
||||
int32_t int32_;
|
||||
} SpectrumType;
|
||||
|
||||
typedef struct {
|
||||
// Pointers to mean values of spectrum.
|
||||
SpectrumType* mean_far_spectrum;
|
||||
SpectrumType* mean_near_spectrum;
|
||||
// |mean_*_spectrum| initialization indicator.
|
||||
int far_spectrum_initialized;
|
||||
int near_spectrum_initialized;
|
||||
|
||||
int spectrum_size;
|
||||
|
||||
// Binary spectrum based delay estimator
|
||||
BinaryDelayEstimator* binary_handle;
|
||||
} DelayEstimator;
|
||||
|
||||
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_UTILITY_DELAY_ESTIMATOR_INTERNAL_H_
|
||||
260
src/modules/audio_processing/utility/delay_estimator_unittest.cc
Normal file
260
src/modules/audio_processing/utility/delay_estimator_unittest.cc
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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 "gtest/gtest.h"
|
||||
|
||||
extern "C" {
|
||||
#include "modules/audio_processing/utility/delay_estimator.h"
|
||||
#include "modules/audio_processing/utility/delay_estimator_internal.h"
|
||||
#include "modules/audio_processing/utility/delay_estimator_wrapper.h"
|
||||
}
|
||||
#include "typedefs.h"
|
||||
|
||||
namespace {
|
||||
|
||||
enum { kSpectrumSize = 65 };
|
||||
|
||||
class DelayEstimatorTest : public ::testing::Test {
|
||||
protected:
|
||||
DelayEstimatorTest();
|
||||
virtual void SetUp();
|
||||
virtual void TearDown();
|
||||
|
||||
void Init();
|
||||
|
||||
void InitBinary();
|
||||
|
||||
void* handle_;
|
||||
DelayEstimator* self_;
|
||||
BinaryDelayEstimator* binary_handle_;
|
||||
int spectrum_size_;
|
||||
// Dummy input spectra.
|
||||
float far_f_[kSpectrumSize];
|
||||
float near_f_[kSpectrumSize];
|
||||
uint16_t far_u16_[kSpectrumSize];
|
||||
uint16_t near_u16_[kSpectrumSize];
|
||||
};
|
||||
|
||||
DelayEstimatorTest::DelayEstimatorTest()
|
||||
: handle_(NULL),
|
||||
self_(NULL),
|
||||
binary_handle_(NULL),
|
||||
spectrum_size_(kSpectrumSize) {
|
||||
// Dummy input data are set with more or less arbitrary non-zero values.
|
||||
memset(far_f_, 1, sizeof(far_f_));
|
||||
memset(near_f_, 2, sizeof(near_f_));
|
||||
memset(far_u16_, 1, sizeof(far_u16_));
|
||||
memset(near_u16_, 2, sizeof(near_u16_));
|
||||
}
|
||||
|
||||
void DelayEstimatorTest::SetUp() {
|
||||
ASSERT_EQ(0, WebRtc_CreateDelayEstimator(&handle_, kSpectrumSize, 100, 10));
|
||||
ASSERT_TRUE(handle_ != NULL);
|
||||
self_ = reinterpret_cast<DelayEstimator*>(handle_);
|
||||
binary_handle_ = self_->binary_handle;
|
||||
}
|
||||
|
||||
void DelayEstimatorTest::TearDown() {
|
||||
WebRtc_FreeDelayEstimator(handle_);
|
||||
handle_ = NULL;
|
||||
self_ = NULL;
|
||||
binary_handle_ = NULL;
|
||||
}
|
||||
|
||||
void DelayEstimatorTest::Init() {
|
||||
// Initialize Delay Estimator
|
||||
EXPECT_EQ(0, WebRtc_InitDelayEstimator(handle_));
|
||||
// Verify initialization.
|
||||
EXPECT_EQ(0, self_->far_spectrum_initialized);
|
||||
EXPECT_EQ(0, self_->near_spectrum_initialized);
|
||||
}
|
||||
|
||||
void DelayEstimatorTest::InitBinary() {
|
||||
// Initialize Binary Delay Estimator
|
||||
WebRtc_InitBinaryDelayEstimator(binary_handle_);
|
||||
// Verify initialization. This does not guarantee a complete check, since
|
||||
// |last_delay| may be equal to -2 before initialization if done on the fly.
|
||||
EXPECT_EQ(-2, binary_handle_->last_delay);
|
||||
}
|
||||
|
||||
TEST_F(DelayEstimatorTest, CorrectErrorReturnsOfWrapper) {
|
||||
// In this test we verify correct error returns on invalid API calls.
|
||||
|
||||
// WebRtc_CreateDelayEstimator() should return -1 if we have a NULL pointer
|
||||
// as |handle| or invalid input values. Upon failure, the handle should be
|
||||
// NULL.
|
||||
// Make sure we have a non-NULL value at start, so we can detect NULL after
|
||||
// create failure.
|
||||
void* handle = handle_;
|
||||
EXPECT_EQ(-1, WebRtc_CreateDelayEstimator(NULL, kSpectrumSize, 100, 10));
|
||||
EXPECT_EQ(-1, WebRtc_CreateDelayEstimator(&handle, 33, 100, 10));
|
||||
EXPECT_TRUE(handle == NULL);
|
||||
handle = handle_;
|
||||
EXPECT_EQ(-1, WebRtc_CreateDelayEstimator(&handle, kSpectrumSize, -1, 10));
|
||||
EXPECT_TRUE(handle == NULL);
|
||||
handle = handle_;
|
||||
EXPECT_EQ(-1, WebRtc_CreateDelayEstimator(&handle, kSpectrumSize, 100, -1));
|
||||
EXPECT_TRUE(handle == NULL);
|
||||
handle = handle_;
|
||||
EXPECT_EQ(-1, WebRtc_CreateDelayEstimator(&handle, kSpectrumSize, 0, 0));
|
||||
EXPECT_TRUE(handle == NULL);
|
||||
|
||||
// WebRtc_InitDelayEstimator() should return -1 if we have a NULL pointer as
|
||||
// |handle|.
|
||||
EXPECT_EQ(-1, WebRtc_InitDelayEstimator(NULL));
|
||||
|
||||
// WebRtc_DelayEstimatorProcessFloat() should return -1 if we have:
|
||||
// 1) NULL pointer as |handle|.
|
||||
// 2) NULL pointer as far-end spectrum.
|
||||
// 3) NULL pointer as near-end spectrum.
|
||||
// 4) Incorrect spectrum size.
|
||||
EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(NULL, far_f_, near_f_,
|
||||
spectrum_size_));
|
||||
// Use |handle_| which is properly created at SetUp().
|
||||
EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(handle_, NULL, near_f_,
|
||||
spectrum_size_));
|
||||
EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(handle_, far_f_, NULL,
|
||||
spectrum_size_));
|
||||
EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFloat(handle_, far_f_, near_f_,
|
||||
spectrum_size_ + 1));
|
||||
|
||||
// WebRtc_DelayEstimatorProcessFix() should return -1 if we have:
|
||||
// 1) NULL pointer as |handle|.
|
||||
// 2) NULL pointer as far-end spectrum.
|
||||
// 3) NULL pointer as near-end spectrum.
|
||||
// 4) Incorrect spectrum size.
|
||||
// 5) Too high precision in far-end spectrum (Q-domain > 15).
|
||||
// 6) Too high precision in near-end spectrum (Q-domain > 15).
|
||||
EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(NULL, far_u16_, near_u16_,
|
||||
spectrum_size_, 0, 0));
|
||||
// Use |handle_| which is properly created at SetUp().
|
||||
EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, NULL, near_u16_,
|
||||
spectrum_size_, 0, 0));
|
||||
EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, far_u16_, NULL,
|
||||
spectrum_size_, 0, 0));
|
||||
EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, far_u16_, near_u16_,
|
||||
spectrum_size_ + 1, 0, 0));
|
||||
EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, far_u16_, near_u16_,
|
||||
spectrum_size_, 16, 0));
|
||||
EXPECT_EQ(-1, WebRtc_DelayEstimatorProcessFix(handle_, far_u16_, near_u16_,
|
||||
spectrum_size_, 0, 16));
|
||||
|
||||
// WebRtc_last_delay() should return -1 if we have a NULL pointer as |handle|.
|
||||
EXPECT_EQ(-1, WebRtc_last_delay(NULL));
|
||||
|
||||
// Free any local memory if needed.
|
||||
WebRtc_FreeDelayEstimator(handle);
|
||||
}
|
||||
|
||||
TEST_F(DelayEstimatorTest, InitializedSpectrumAfterProcess) {
|
||||
// In this test we verify that the mean spectra are initialized after first
|
||||
// time we call Process().
|
||||
|
||||
// For floating point operations, process one frame and verify initialization
|
||||
// flag.
|
||||
Init();
|
||||
EXPECT_EQ(-2, WebRtc_DelayEstimatorProcessFloat(handle_, far_f_, near_f_,
|
||||
spectrum_size_));
|
||||
EXPECT_EQ(1, self_->far_spectrum_initialized);
|
||||
EXPECT_EQ(1, self_->near_spectrum_initialized);
|
||||
|
||||
// For fixed point operations, process one frame and verify initialization
|
||||
// flag.
|
||||
Init();
|
||||
EXPECT_EQ(-2, WebRtc_DelayEstimatorProcessFix(handle_, far_u16_, near_u16_,
|
||||
spectrum_size_, 0, 0));
|
||||
EXPECT_EQ(1, self_->far_spectrum_initialized);
|
||||
EXPECT_EQ(1, self_->near_spectrum_initialized);
|
||||
}
|
||||
|
||||
TEST_F(DelayEstimatorTest, CorrectLastDelay) {
|
||||
// In this test we verify that we get the correct last delay upon valid call.
|
||||
// We simply process the same data until we leave the initialized state
|
||||
// (|last_delay| = -2). Then we compare the Process() output with the
|
||||
// last_delay() call.
|
||||
|
||||
int last_delay = 0;
|
||||
// Floating point operations.
|
||||
Init();
|
||||
for (int i = 0; i < 200; i++) {
|
||||
last_delay = WebRtc_DelayEstimatorProcessFloat(handle_, far_f_, near_f_,
|
||||
spectrum_size_);
|
||||
if (last_delay != -2) {
|
||||
EXPECT_EQ(last_delay, WebRtc_last_delay(handle_));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Fixed point operations.
|
||||
Init();
|
||||
for (int i = 0; i < 200; i++) {
|
||||
last_delay = WebRtc_DelayEstimatorProcessFix(handle_, far_u16_, near_u16_,
|
||||
spectrum_size_, 0, 0);
|
||||
if (last_delay != -2) {
|
||||
EXPECT_EQ(last_delay, WebRtc_last_delay(handle_));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DelayEstimatorTest, CorrectErrorReturnsOfBinaryEstimator) {
|
||||
// In this test we verify correct output on invalid API calls to the Binary
|
||||
// Delay Estimator.
|
||||
|
||||
BinaryDelayEstimator* binary_handle = binary_handle_;
|
||||
// WebRtc_CreateBinaryDelayEstimator() should return -1 if we have a NULL
|
||||
// pointer as |binary_handle| or invalid input values. Upon failure, the
|
||||
// |binary_handle| should be NULL.
|
||||
// Make sure we have a non-NULL value at start, so we can detect NULL after
|
||||
// create failure.
|
||||
binary_handle = WebRtc_CreateBinaryDelayEstimator(-1, 10);
|
||||
EXPECT_TRUE(binary_handle == NULL);
|
||||
binary_handle = binary_handle_;
|
||||
binary_handle = WebRtc_CreateBinaryDelayEstimator(100, -1);
|
||||
EXPECT_TRUE(binary_handle == NULL);
|
||||
binary_handle = binary_handle_;
|
||||
binary_handle = WebRtc_CreateBinaryDelayEstimator(0, 0);
|
||||
EXPECT_TRUE(binary_handle == NULL);
|
||||
|
||||
// TODO(bjornv): It is not feasible to force an error of
|
||||
// WebRtc_ProcessBinarySpectrum(). This can only happen if we have more than
|
||||
// 32 bits in our binary spectrum comparison, which by definition can't
|
||||
// happen.
|
||||
// We should therefore remove that option from the code.
|
||||
|
||||
// WebRtc_binary_last_delay() can't return -1 either.
|
||||
}
|
||||
|
||||
TEST_F(DelayEstimatorTest, MeanEstimatorFix) {
|
||||
// In this test we verify that we update the mean value in correct direction
|
||||
// only. With "direction" we mean increase or decrease.
|
||||
|
||||
InitBinary();
|
||||
|
||||
int32_t mean_value = 4000;
|
||||
int32_t mean_value_before = mean_value;
|
||||
int32_t new_mean_value = mean_value * 2;
|
||||
|
||||
// Increasing |mean_value|.
|
||||
WebRtc_MeanEstimatorFix(new_mean_value, 10, &mean_value);
|
||||
EXPECT_LT(mean_value_before, mean_value);
|
||||
EXPECT_GT(new_mean_value, mean_value);
|
||||
|
||||
// Decreasing |mean_value|.
|
||||
new_mean_value = mean_value / 2;
|
||||
mean_value_before = mean_value;
|
||||
WebRtc_MeanEstimatorFix(new_mean_value, 10, &mean_value);
|
||||
EXPECT_GT(mean_value_before, mean_value);
|
||||
EXPECT_LT(new_mean_value, mean_value);
|
||||
}
|
||||
|
||||
// TODO(bjornv): Add a test to verify correct delay
|
||||
|
||||
} // namespace
|
||||
@ -15,25 +15,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "delay_estimator.h"
|
||||
|
||||
typedef union {
|
||||
float float_;
|
||||
int32_t int32_;
|
||||
} SpectrumType;
|
||||
|
||||
typedef struct {
|
||||
// Pointers to mean values of spectrum.
|
||||
SpectrumType* mean_far_spectrum;
|
||||
SpectrumType* mean_near_spectrum;
|
||||
// |mean_*_spectrum| initialization indicator.
|
||||
int far_spectrum_initialized;
|
||||
int near_spectrum_initialized;
|
||||
|
||||
int spectrum_size;
|
||||
|
||||
// Binary spectrum based delay estimator
|
||||
BinaryDelayEstimator* binary_handle;
|
||||
} DelayEstimator;
|
||||
#include "modules/audio_processing/utility/delay_estimator_internal.h"
|
||||
|
||||
// Only bit |kBandFirst| through bit |kBandLast| are processed and
|
||||
// |kBandFirst| - |kBandLast| must be < 32.
|
||||
@ -205,7 +187,7 @@ int WebRtc_CreateDelayEstimator(void** handle,
|
||||
|
||||
self->spectrum_size = spectrum_size;
|
||||
|
||||
if (return_value == -1) {
|
||||
if (return_value < 0) {
|
||||
WebRtc_FreeDelayEstimator(self);
|
||||
*handle = NULL;
|
||||
}
|
||||
@ -220,9 +202,8 @@ int WebRtc_InitDelayEstimator(void* handle) {
|
||||
}
|
||||
|
||||
// Initialize binary delay estimator.
|
||||
if (WebRtc_InitBinaryDelayEstimator(self->binary_handle) != 0) {
|
||||
return -1;
|
||||
}
|
||||
WebRtc_InitBinaryDelayEstimator(self->binary_handle);
|
||||
|
||||
// Set averaged far and near end spectra to zero.
|
||||
memset(self->mean_far_spectrum, 0,
|
||||
sizeof(SpectrumType) * self->spectrum_size);
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
'sources': [
|
||||
'delay_estimator.c',
|
||||
'delay_estimator.h',
|
||||
'delay_estimator_internal.h',
|
||||
'delay_estimator_wrapper.c',
|
||||
'delay_estimator_wrapper.h',
|
||||
'fft4g.c',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user