Added a pointer getter to the system_delay variable.

Tested with audioproc_unittest, trybots

TEST=None
BUG=None

Review URL: https://webrtc-codereview.appspot.com/1101015

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3549 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
bjornv@webrtc.org
2013-02-20 17:31:38 +00:00
parent 47b274de44
commit 4d1cfae622
4 changed files with 62 additions and 37 deletions

View File

@ -748,6 +748,7 @@ void WebRtcAec_GetEchoStats(aec_t* self, Stats* erl, Stats* erle,
*erle = self->erle; *erle = self->erle;
*a_nlp = self->aNlp; *a_nlp = self->aNlp;
} }
#ifdef WEBRTC_AEC_DEBUG_DUMP #ifdef WEBRTC_AEC_DEBUG_DUMP
void* WebRtcAec_far_time_buf(aec_t* self) { void* WebRtcAec_far_time_buf(aec_t* self) {
assert(self != NULL); assert(self != NULL);
@ -770,6 +771,17 @@ void WebRtcAec_SetConfigCore(aec_t* self, int nlp_mode, int metrics_mode,
} }
} }
int WebRtcAec_system_delay(aec_t* self) {
assert(self != NULL);
return self->system_delay;
}
void WebRtcAec_SetSystemDelay(aec_t* self, int delay) {
assert(self != NULL);
assert(delay >= 0);
self->system_delay = delay;
}
static void ProcessBlock(aec_t* aec) { static void ProcessBlock(aec_t* aec) {
int i; int i;
float d[PART_LEN], y[PART_LEN], e[PART_LEN], dH[PART_LEN]; float d[PART_LEN], y[PART_LEN], e[PART_LEN], dH[PART_LEN];

View File

@ -12,8 +12,8 @@
* Specifies the interface for the AEC core. * Specifies the interface for the AEC core.
*/ */
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_CORE_H_ #ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_AEC_CORE_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_CORE_H_ #define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_AEC_CORE_H_
#ifdef WEBRTC_AEC_DEBUG_DUMP #ifdef WEBRTC_AEC_DEBUG_DUMP
#include <stdio.h> #include <stdio.h>
@ -196,5 +196,12 @@ void* WebRtcAec_far_time_buf(aec_t* self);
// Sets local configuration modes. // Sets local configuration modes.
void WebRtcAec_SetConfigCore(aec_t* self, int nlp_mode, int metrics_mode, void WebRtcAec_SetConfigCore(aec_t* self, int nlp_mode, int metrics_mode,
int delay_logging); int delay_logging);
// Returns the current |system_delay|, i.e., the buffered difference between
// far-end and near-end.
int WebRtcAec_system_delay(aec_t* self);
// Sets the |system_delay| to |value|. Note that if the value is changed
// improperly, there can be a performance regression. So it should be used with
// care.
void WebRtcAec_SetSystemDelay(aec_t* self, int delay);
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_MAIN_SOURCE_AEC_CORE_H_ #endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_AEC_CORE_H_

View File

@ -268,7 +268,8 @@ WebRtc_Word32 WebRtcAec_BufferFarend(void *aecInst, const WebRtc_Word16 *farend,
farend_ptr = (const int16_t*) newFarend; farend_ptr = (const int16_t*) newFarend;
} }
aecpc->aec->system_delay += newNrOfSamples; WebRtcAec_SetSystemDelay(aecpc->aec, WebRtcAec_system_delay(aecpc->aec) +
newNrOfSamples);
#ifdef WEBRTC_AEC_DEBUG_DUMP #ifdef WEBRTC_AEC_DEBUG_DUMP
WebRtc_WriteBuffer(aecpc->far_pre_buf_s16, farend_ptr, WebRtc_WriteBuffer(aecpc->far_pre_buf_s16, farend_ptr,
@ -454,7 +455,8 @@ WebRtc_Word32 WebRtcAec_Process(void *aecInst, const WebRtc_Word16 *nearend,
// for too long). When the far-end buffer is filled with // for too long). When the far-end buffer is filled with
// approximately the same amount of data as reported by the system // approximately the same amount of data as reported by the system
// we end the startup phase. // we end the startup phase.
int overhead_elements = aecpc->aec->system_delay / PART_LEN - int overhead_elements =
WebRtcAec_system_delay(aecpc->aec) / PART_LEN -
aecpc->bufSizeStart; aecpc->bufSizeStart;
if (overhead_elements == 0) { if (overhead_elements == 0) {
// Enable the AEC // Enable the AEC
@ -493,7 +495,7 @@ WebRtc_Word32 WebRtcAec_Process(void *aecInst, const WebRtc_Word16 *nearend,
#ifdef WEBRTC_AEC_DEBUG_DUMP #ifdef WEBRTC_AEC_DEBUG_DUMP
{ {
int16_t far_buf_size_ms = (int16_t)(aecpc->aec->system_delay / int16_t far_buf_size_ms = (int16_t)(WebRtcAec_system_delay(aecpc->aec) /
(sampMsNb * aecpc->rate_factor)); (sampMsNb * aecpc->rate_factor));
(void)fwrite(&far_buf_size_ms, 2, 1, aecpc->bufFile); (void)fwrite(&far_buf_size_ms, 2, 1, aecpc->bufFile);
(void)fwrite(&aecpc->knownDelay, sizeof(aecpc->knownDelay), 1, (void)fwrite(&aecpc->knownDelay, sizeof(aecpc->knownDelay), 1,
@ -700,7 +702,7 @@ WebRtc_Word32 WebRtcAec_get_error_code(void *aecInst)
static int EstBufDelay(aecpc_t* aecpc) { static int EstBufDelay(aecpc_t* aecpc) {
int nSampSndCard = aecpc->msInSndCardBuf * sampMsNb * aecpc->rate_factor; int nSampSndCard = aecpc->msInSndCardBuf * sampMsNb * aecpc->rate_factor;
int current_delay = nSampSndCard - aecpc->aec->system_delay; int current_delay = nSampSndCard - WebRtcAec_system_delay(aecpc->aec);
int delay_difference = 0; int delay_difference = 0;
// Before we proceed with the delay estimate filtering we: // Before we proceed with the delay estimate filtering we:

View File

@ -8,11 +8,14 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "modules/audio_processing/aec/include/echo_cancellation.h" extern "C" {
#include "modules/audio_processing/aec/echo_cancellation_internal.h" #include "webrtc/modules/audio_processing/aec/aec_core.h"
#include "typedefs.h" }
#include "webrtc/modules/audio_processing/aec/echo_cancellation_internal.h"
#include "webrtc/modules/audio_processing/aec/include/echo_cancellation.h"
#include "webrtc/typedefs.h"
namespace { namespace {
@ -109,7 +112,7 @@ int SystemDelayTest::BufferFillUp() {
for (int i = 0; i < kDeviceBufMs / 10; i++) { for (int i = 0; i < kDeviceBufMs / 10; i++) {
EXPECT_EQ(0, WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_)); EXPECT_EQ(0, WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
buffer_size += samples_per_frame_; buffer_size += samples_per_frame_;
EXPECT_EQ(buffer_size, self_->aec->system_delay); EXPECT_EQ(buffer_size, WebRtcAec_system_delay(self_->aec));
} }
return buffer_size; return buffer_size;
} }
@ -133,7 +136,7 @@ void SystemDelayTest::RunStableStartup() {
// Verify convergence time. // Verify convergence time.
EXPECT_GT(kStableConvergenceMs, process_time_ms); EXPECT_GT(kStableConvergenceMs, process_time_ms);
// Verify that the buffer has been flushed. // Verify that the buffer has been flushed.
EXPECT_GE(buffer_size, self_->aec->system_delay); EXPECT_GE(buffer_size, WebRtcAec_system_delay(self_->aec));
} }
int SystemDelayTest::MapBufferSizeToSamples(int size_in_ms) { int SystemDelayTest::MapBufferSizeToSamples(int size_in_ms) {
@ -172,7 +175,7 @@ TEST_F(SystemDelayTest, CorrectIncreaseWhenBufferFarend) {
// correctly. // correctly.
for (int j = 1; j <= 5; j++) { for (int j = 1; j <= 5; j++) {
EXPECT_EQ(0, WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_)); EXPECT_EQ(0, WebRtcAec_BufferFarend(handle_, far_, samples_per_frame_));
EXPECT_EQ(j * samples_per_frame_, self_->aec->system_delay); EXPECT_EQ(j * samples_per_frame_, WebRtcAec_system_delay(self_->aec));
} }
} }
} }
@ -191,8 +194,9 @@ TEST_F(SystemDelayTest, CorrectDelayAfterStableStartup) {
// |system_delay| is in the interval [75%, 100%] of what's reported on the // |system_delay| is in the interval [75%, 100%] of what's reported on the
// average. // average.
int average_reported_delay = kDeviceBufMs * samples_per_frame_ / 10; int average_reported_delay = kDeviceBufMs * samples_per_frame_ / 10;
EXPECT_GE(average_reported_delay, self_->aec->system_delay); EXPECT_GE(average_reported_delay, WebRtcAec_system_delay(self_->aec));
EXPECT_LE(average_reported_delay * 3 / 4, self_->aec->system_delay); EXPECT_LE(average_reported_delay * 3 / 4,
WebRtcAec_system_delay(self_->aec));
} }
} }
@ -226,14 +230,14 @@ TEST_F(SystemDelayTest, CorrectDelayAfterUnstableStartup) {
// Verify convergence time. // Verify convergence time.
EXPECT_GE(kMaxConvergenceMs, process_time_ms); EXPECT_GE(kMaxConvergenceMs, process_time_ms);
// Verify that the buffer has been flushed. // Verify that the buffer has been flushed.
EXPECT_GE(buffer_size, self_->aec->system_delay); EXPECT_GE(buffer_size, WebRtcAec_system_delay(self_->aec));
// Verify system delay with respect to requirements, i.e., the // Verify system delay with respect to requirements, i.e., the
// |system_delay| is in the interval [60%, 100%] of what's last reported. // |system_delay| is in the interval [60%, 100%] of what's last reported.
EXPECT_GE(reported_delay_ms * samples_per_frame_ / 10, EXPECT_GE(reported_delay_ms * samples_per_frame_ / 10,
self_->aec->system_delay); WebRtcAec_system_delay(self_->aec));
EXPECT_LE(reported_delay_ms * samples_per_frame_ / 10 * 3 / 5, EXPECT_LE(reported_delay_ms * samples_per_frame_ / 10 * 3 / 5,
self_->aec->system_delay); WebRtcAec_system_delay(self_->aec));
} }
} }
@ -272,14 +276,14 @@ TEST_F(SystemDelayTest, CorrectDelayAfterStableBufferBuildUp) {
// Verify convergence time. // Verify convergence time.
EXPECT_GT(kMaxConvergenceMs, process_time_ms); EXPECT_GT(kMaxConvergenceMs, process_time_ms);
// Verify that the buffer has reached the desired size. // Verify that the buffer has reached the desired size.
EXPECT_LE(target_buffer_size, self_->aec->system_delay); EXPECT_LE(target_buffer_size, WebRtcAec_system_delay(self_->aec));
// Verify normal behavior (system delay is kept constant) after startup by // Verify normal behavior (system delay is kept constant) after startup by
// running a couple of calls to BufferFarend() and Process(). // running a couple of calls to BufferFarend() and Process().
for (int j = 0; j < 6; j++) { for (int j = 0; j < 6; j++) {
int system_delay_before_calls = self_->aec->system_delay; int system_delay_before_calls = WebRtcAec_system_delay(self_->aec);
RenderAndCapture(kDeviceBufMs); RenderAndCapture(kDeviceBufMs);
EXPECT_EQ(system_delay_before_calls, self_->aec->system_delay); EXPECT_EQ(system_delay_before_calls, WebRtcAec_system_delay(self_->aec));
} }
} }
} }
@ -299,7 +303,7 @@ TEST_F(SystemDelayTest, CorrectDelayWhenBufferUnderrun) {
for (int j = 0; j <= kStableConvergenceMs; j += 10) { for (int j = 0; j <= kStableConvergenceMs; j += 10) {
EXPECT_EQ(0, WebRtcAec_Process(handle_, near_, NULL, out_, NULL, EXPECT_EQ(0, WebRtcAec_Process(handle_, near_, NULL, out_, NULL,
samples_per_frame_, kDeviceBufMs, 0)); samples_per_frame_, kDeviceBufMs, 0));
EXPECT_LE(0, self_->aec->system_delay); EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
} }
} }
} }
@ -327,10 +331,10 @@ TEST_F(SystemDelayTest, CorrectDelayDuringDrift) {
RenderAndCapture(device_buf_ms); RenderAndCapture(device_buf_ms);
// Verify that the system delay does not exceed the device buffer. // Verify that the system delay does not exceed the device buffer.
EXPECT_GE(device_buf, self_->aec->system_delay); EXPECT_GE(device_buf, WebRtcAec_system_delay(self_->aec));
// Verify that the system delay is non-negative. // Verify that the system delay is non-negative.
EXPECT_LE(0, self_->aec->system_delay); EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
} }
} }
} }
@ -353,15 +357,15 @@ TEST_F(SystemDelayTest, ShouldRecoverAfterGlitch) {
} }
// Verify that we are in a non-causal state, i.e., // Verify that we are in a non-causal state, i.e.,
// |system_delay| > |device_buf|. // |system_delay| > |device_buf|.
EXPECT_LT(device_buf, self_->aec->system_delay); EXPECT_LT(device_buf, WebRtcAec_system_delay(self_->aec));
// Recover state. Should recover at least 4 ms of data per 10 ms, hence a // Recover state. Should recover at least 4 ms of data per 10 ms, hence a
// glitch of 200 ms will take at most 200 * 10 / 4 = 500 ms to recover from. // glitch of 200 ms will take at most 200 * 10 / 4 = 500 ms to recover from.
bool non_causal = true; // We are currently in a non-causal state. bool non_causal = true; // We are currently in a non-causal state.
for (int j = 0; j < 50; j++) { for (int j = 0; j < 50; j++) {
int system_delay_before = self_->aec->system_delay; int system_delay_before = WebRtcAec_system_delay(self_->aec);
RenderAndCapture(kDeviceBufMs); RenderAndCapture(kDeviceBufMs);
int system_delay_after = self_->aec->system_delay; int system_delay_after = WebRtcAec_system_delay(self_->aec);
// We have recovered if |device_buf| - |system_delay_after| >= 64 (one // We have recovered if |device_buf| - |system_delay_after| >= 64 (one
// block). During recovery |system_delay_after| < |system_delay_before|, // block). During recovery |system_delay_after| < |system_delay_before|,
@ -375,7 +379,7 @@ TEST_F(SystemDelayTest, ShouldRecoverAfterGlitch) {
EXPECT_EQ(system_delay_before, system_delay_after); EXPECT_EQ(system_delay_before, system_delay_after);
} }
// Verify that the system delay is non-negative. // Verify that the system delay is non-negative.
EXPECT_LE(0, self_->aec->system_delay); EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
} }
// Check that we have recovered. // Check that we have recovered.
EXPECT_FALSE(non_causal); EXPECT_FALSE(non_causal);
@ -397,7 +401,7 @@ TEST_F(SystemDelayTest, UnaffectedWhenSpuriousDeviceBufferValues) {
// Run 1 s and replace device buffer size with 500 ms every 100 ms. // Run 1 s and replace device buffer size with 500 ms every 100 ms.
for (int j = 0; j < 100; j++) { for (int j = 0; j < 100; j++) {
int system_delay_before_calls = self_->aec->system_delay; int system_delay_before_calls = WebRtcAec_system_delay(self_->aec);
int device_buf_ms = kDeviceBufMs; int device_buf_ms = kDeviceBufMs;
if (j % 10 == 0) { if (j % 10 == 0) {
device_buf_ms = 500; device_buf_ms = 500;
@ -405,14 +409,14 @@ TEST_F(SystemDelayTest, UnaffectedWhenSpuriousDeviceBufferValues) {
RenderAndCapture(device_buf_ms); RenderAndCapture(device_buf_ms);
// Check for non-causality. // Check for non-causality.
if (device_buf - self_->aec->system_delay < 64) { if (device_buf - WebRtcAec_system_delay(self_->aec) < 64) {
non_causal = true; non_causal = true;
} }
EXPECT_FALSE(non_causal); EXPECT_FALSE(non_causal);
EXPECT_EQ(system_delay_before_calls, self_->aec->system_delay); EXPECT_EQ(system_delay_before_calls, WebRtcAec_system_delay(self_->aec));
// Verify that the system delay is non-negative. // Verify that the system delay is non-negative.
EXPECT_LE(0, self_->aec->system_delay); EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
} }
} }
} }
@ -440,16 +444,16 @@ TEST_F(SystemDelayTest, CorrectImpactWhenTogglingDeviceBufferValues) {
// data. Every odd frame we set the device buffer size to 2 * |kDeviceBufMs| // data. Every odd frame we set the device buffer size to 2 * |kDeviceBufMs|
// and even frames we set the device buffer size to zero. // and even frames we set the device buffer size to zero.
for (int j = 0; j < 100; j++) { for (int j = 0; j < 100; j++) {
int system_delay_before_calls = self_->aec->system_delay; int system_delay_before_calls = WebRtcAec_system_delay(self_->aec);
int device_buf_ms = 2 * (j % 2) * kDeviceBufMs; int device_buf_ms = 2 * (j % 2) * kDeviceBufMs;
RenderAndCapture(device_buf_ms); RenderAndCapture(device_buf_ms);
// Check for non-causality, compared with the average device buffer size. // Check for non-causality, compared with the average device buffer size.
non_causal |= (device_buf - self_->aec->system_delay < 64); non_causal |= (device_buf - WebRtcAec_system_delay(self_->aec) < 64);
EXPECT_GE(system_delay_before_calls, self_->aec->system_delay); EXPECT_GE(system_delay_before_calls, WebRtcAec_system_delay(self_->aec));
// Verify that the system delay is non-negative. // Verify that the system delay is non-negative.
EXPECT_LE(0, self_->aec->system_delay); EXPECT_LE(0, WebRtcAec_system_delay(self_->aec));
} }
// Verify we are not in a non-causal state. // Verify we are not in a non-causal state.
EXPECT_FALSE(non_causal); EXPECT_FALSE(non_causal);