Backed out 2 changesets (bug 1226347) for build bustage CLOSED TREE

Backed out changeset da34ad5d6957 (bug 1226347)
Backed out changeset 63d13b6b43ee (bug 1226347)

--HG--
extra : commitid : 4yYcYyidto4
This commit is contained in:
Wes Kocher 2015-11-24 09:02:03 -08:00
parent 593a471c03
commit dba42704d1
23 changed files with 613 additions and 486 deletions

View File

@ -23,8 +23,6 @@
#include "mozilla/Telemetry.h"
#endif
#include "webrtc/common.h"
#include "webrtc/modules/audio_processing/include/audio_processing.h"
#include "webrtc/voice_engine/include/voe_errors.h"
#include "webrtc/system_wrappers/interface/clock.h"
#include "browser_logging/WebRtcLog.h"
@ -233,25 +231,9 @@ MediaConduitErrorCode WebrtcAudioConduit::Init()
return kMediaConduitSessionNotInited;
}
#endif
webrtc::Config config;
bool aec_extended_filter = true; // Always default to the extended filter length
bool aec_delay_agnostic = false;
#if !defined(MOZILLA_EXTERNAL_LINKAGE)
nsresult rv;
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
prefs->GetBoolPref("media.getusermedia.aec_extended_filter", &aec_extended_filter);
rv = prefs->GetBoolPref("media.getusermedia.aec_delay_agnostic", &aec_delay_agnostic);
if (NS_SUCCEEDED(rv)) {
// Only override platform setting if pref is defined.
config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(aec_delay_agnostic));
}
}
#endif
config.Set<webrtc::ExtendedFilter>(new webrtc::ExtendedFilter(aec_extended_filter));
// Per WebRTC APIs below function calls return nullptr on failure
if(!(mVoiceEngine = webrtc::VoiceEngine::Create(config)))
if(!(mVoiceEngine = webrtc::VoiceEngine::Create()))
{
CSFLogError(logTag, "%s Unable to create voice engine", __FUNCTION__);
return kMediaConduitSessionNotInited;

View File

@ -396,10 +396,15 @@ class MediaPipelineTest : public ::testing::Test {
// Setup transport flows
InitTransports(aIsRtcpMux);
#if 0 //DEBUG(pkerr)
mozilla::SyncRunnable::DispatchToThread(
test_utils->sts_target(),
WrapRunnable(&p1_, &TestAgent::CreatePipelines_s, aIsRtcpMux));
#else
NS_DispatchToMainThread(
WrapRunnable(&p1_, &TestAgent::CreatePipelines_s, aIsRtcpMux),
NS_DISPATCH_SYNC);
#endif
mozilla::SyncRunnable::DispatchToThread(
test_utils->sts_target(),
WrapRunnable(&p2_, &TestAgent::CreatePipelines_s, aIsRtcpMux));

View File

@ -104,13 +104,9 @@ ALIGN16_BEG const float ALIGN16_END WebRtcAec_overDriveCurve[65] = {
1.9354f, 1.9437f, 1.9520f, 1.9601f, 1.9682f, 1.9763f, 1.9843f, 1.9922f,
2.0000f};
// Delay Agnostic AEC parameters, still under development and may change.
// TODO(bjornv): These parameters will be tuned.
static const float kDelayQualityThresholdMax = 0.07f;
static const float kDelayQualityThresholdMin = 0.01f;
static const int kInitialShiftOffset = 5;
#if !defined(WEBRTC_ANDROID) && !defined(WEBRTC_GONK)
static const int kDelayCorrectionStart = 1500; // 10 ms chunks
#endif
// Target suppression levels for nlp modes.
// log{0.001, 0.00001, 0.00000001}
@ -824,11 +820,8 @@ static void UpdateDelayMetrics(AecCore* self) {
// negative (anti-causal system) or larger than the AEC filter length.
{
int num_delays_out_of_bounds = self->num_delay_values;
const int histogram_length = sizeof(self->delay_histogram) /
sizeof(self->delay_histogram[0]);
for (i = lookahead; i < lookahead + self->num_partitions; ++i) {
if (i < histogram_length)
num_delays_out_of_bounds -= self->delay_histogram[i];
num_delays_out_of_bounds -= self->delay_histogram[i];
}
self->fraction_poor_delays = (float)num_delays_out_of_bounds /
self->num_delay_values;
@ -866,28 +859,10 @@ static void TimeToFrequency(float time_data[PART_LEN2],
}
}
static int MoveFarReadPtrWithoutSystemDelayUpdate(AecCore* self, int elements) {
WebRtc_MoveReadPtr(self->far_buf_windowed, elements);
#ifdef WEBRTC_AEC_DEBUG_DUMP
WebRtc_MoveReadPtr(self->far_time_buf, elements);
#endif
return WebRtc_MoveReadPtr(self->far_buf, elements);
}
static int SignalBasedDelayCorrection(AecCore* self) {
int delay_correction = 0;
int last_delay = -2;
assert(self != NULL);
#if !defined(WEBRTC_ANDROID) && !defined(WEBRTC_GONK)
// On desktops, turn on correction after |kDelayCorrectionStart| frames. This
// is to let the delay estimation get a chance to converge. Also, if the
// playout audio volume is low (or even muted) the delay estimation can return
// a very large delay, which will break the AEC if it is applied.
if (self->frame_count < kDelayCorrectionStart) {
return 0;
}
#endif
// 1. Check for non-negative delay estimate. Note that the estimates we get
// from the delay estimation are not compensated for lookahead. Hence, a
// negative |last_delay| is an invalid one.
@ -905,22 +880,15 @@ static int SignalBasedDelayCorrection(AecCore* self) {
(WebRtc_last_delay_quality(self->delay_estimator) >
self->delay_quality_threshold)) {
int delay = last_delay - WebRtc_lookahead(self->delay_estimator);
// Allow for a slack in the actual delay, defined by a |lower_bound| and an
// |upper_bound|. The adaptive echo cancellation filter is currently
// |num_partitions| (of 64 samples) long. If the delay estimate is negative
// or at least 3/4 of the filter length we open up for correction.
const int lower_bound = 0;
const int upper_bound = self->num_partitions * 3 / 4;
const int do_correction = delay <= lower_bound || delay > upper_bound;
if (do_correction == 1) {
// Allow for a slack in the actual delay. The adaptive echo cancellation
// filter is currently |num_partitions| (of 64 samples) long. If the
// delay estimate indicates a delay of at least one quarter of the filter
// length we open up for correction.
if (delay <= 0 || delay > (self->num_partitions / 4)) {
int available_read = (int)WebRtc_available_read(self->far_buf);
// With |shift_offset| we gradually rely on the delay estimates. For
// positive delays we reduce the correction by |shift_offset| to lower the
// risk of pushing the AEC into a non causal state. For negative delays
// we rely on the values up to a rounding error, hence compensate by 1
// element to make sure to push the delay into the causal region.
delay_correction = -delay;
delay_correction += delay > self->shift_offset ? self->shift_offset : 1;
// Adjust w.r.t. a |shift_offset| to account for not as reliable estimates
// in the beginning, hence we are more conservative.
delay_correction = -(delay - self->shift_offset);
self->shift_offset--;
self->shift_offset = (self->shift_offset <= 1 ? 1 : self->shift_offset);
if (delay_correction > available_read - self->mult - 1) {
@ -999,8 +967,6 @@ OpenCoreDebugFiles(AecCore* aec, int *aec_instance_count)
aec->instance_index, aec->debug_dump_count, process_rate);
ReopenWav(&aec->outLinearFile, "aec_out_linear",
aec->instance_index, aec->debug_dump_count, process_rate);
ReopenWav(&aec->e_fft_file, "aec_fft",
aec->instance_index, aec->debug_dump_count, process_rate);
++aec->debug_dump_count;
}
} else {
@ -1016,10 +982,7 @@ OpenCoreDebugFiles(AecCore* aec, int *aec_instance_count)
if (aec->outLinearFile) {
rtc_WavClose(aec->outLinearFile);
}
if (aec->e_fft_file) {
rtc_WavClose(aec->e_fft_file);
}
aec->outLinearFile = aec->outFile = aec->nearFile = aec->farFile = aec->e_fft_file = NULL;
aec->outLinearFile = aec->outFile = aec->nearFile = aec->farFile = NULL;
aec->debugWritten = 0;
}
}
@ -1033,8 +996,7 @@ static void NonLinearProcessing(AecCore* aec,
float fft[PART_LEN2];
float scale, dtmp;
float nlpGainHband;
int i;
size_t j;
int i, j;
// Coherence and non-linear filter
float cohde[PART_LEN1], cohxd[PART_LEN1];
@ -1249,8 +1211,8 @@ static void NonLinearProcessing(AecCore* aec,
memcpy(aec->eBuf, aec->eBuf + PART_LEN, sizeof(float) * PART_LEN);
// Copy the current block to the old position for H band
for (j = 0; j < aec->num_bands - 1; ++j) {
memcpy(aec->dBufH[j], aec->dBufH[j] + PART_LEN, sizeof(float) * PART_LEN);
for (i = 0; i < aec->num_bands - 1; ++i) {
memcpy(aec->dBufH[i], aec->dBufH[i] + PART_LEN, sizeof(float) * PART_LEN);
}
memmove(aec->xfwBuf + PART_LEN1,
@ -1259,7 +1221,7 @@ static void NonLinearProcessing(AecCore* aec,
}
static void ProcessBlock(AecCore* aec) {
size_t i;
int i;
float y[PART_LEN], e[PART_LEN];
float scale;
@ -1443,13 +1405,6 @@ static void ProcessBlock(AecCore* aec) {
ef[1][i] = fft[2 * i + 1];
}
#ifdef WEBRTC_AEC_DEBUG_DUMP
if (aec->e_fft_file) {
rtc_WavWriteSamples(aec->e_fft_file, &ef[0][0],
sizeof(ef[0][0]) * PART_LEN1 * 2);
}
#endif
if (aec->metricsMode == 1) {
// Note that the first PART_LEN samples in fft (before transformation) are
// zero. Hence, the scaling by two in UpdateLevel() should not be
@ -1485,23 +1440,26 @@ static void ProcessBlock(AecCore* aec) {
#endif
}
AecCore* WebRtcAec_CreateAec() {
int WebRtcAec_CreateAec(AecCore** aecInst) {
int i;
AecCore* aec = malloc(sizeof(AecCore));
if (!aec) {
return NULL;
*aecInst = aec;
if (aec == NULL) {
return -1;
}
aec->nearFrBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(float));
if (!aec->nearFrBuf) {
WebRtcAec_FreeAec(aec);
return NULL;
aec = NULL;
return -1;
}
aec->outFrBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN, sizeof(float));
if (!aec->outFrBuf) {
WebRtcAec_FreeAec(aec);
return NULL;
aec = NULL;
return -1;
}
for (i = 0; i < NUM_HIGH_BANDS_MAX; ++i) {
@ -1509,13 +1467,15 @@ AecCore* WebRtcAec_CreateAec() {
sizeof(float));
if (!aec->nearFrBufH[i]) {
WebRtcAec_FreeAec(aec);
return NULL;
aec = NULL;
return -1;
}
aec->outFrBufH[i] = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
sizeof(float));
if (!aec->outFrBufH[i]) {
WebRtcAec_FreeAec(aec);
return NULL;
aec = NULL;
return -1;
}
}
@ -1524,13 +1484,15 @@ AecCore* WebRtcAec_CreateAec() {
WebRtc_CreateBuffer(kBufSizePartitions, sizeof(float) * 2 * PART_LEN1);
if (!aec->far_buf) {
WebRtcAec_FreeAec(aec);
return NULL;
aec = NULL;
return -1;
}
aec->far_buf_windowed =
WebRtc_CreateBuffer(kBufSizePartitions, sizeof(float) * 2 * PART_LEN1);
if (!aec->far_buf_windowed) {
WebRtcAec_FreeAec(aec);
return NULL;
aec = NULL;
return -1;
}
#ifdef WEBRTC_AEC_DEBUG_DUMP
aec->instance_index = webrtc_aec_instance_count;
@ -1538,9 +1500,10 @@ AecCore* WebRtcAec_CreateAec() {
WebRtc_CreateBuffer(kBufSizePartitions, sizeof(float) * PART_LEN);
if (!aec->far_time_buf) {
WebRtcAec_FreeAec(aec);
return NULL;
aec = NULL;
return -1;
}
aec->farFile = aec->nearFile = aec->outFile = aec->outLinearFile = aec->e_fft_file = NULL;
aec->farFile = aec->nearFile = aec->outFile = aec->outLinearFile = NULL;
aec->debug_dump_count = 0;
aec->debugWritten = 0;
OpenCoreDebugFiles(aec, &webrtc_aec_instance_count);
@ -1549,7 +1512,8 @@ AecCore* WebRtcAec_CreateAec() {
WebRtc_CreateDelayEstimatorFarend(PART_LEN1, kHistorySizeBlocks);
if (aec->delay_estimator_farend == NULL) {
WebRtcAec_FreeAec(aec);
return NULL;
aec = NULL;
return -1;
}
// We create the delay_estimator with the same amount of maximum lookahead as
// the delay history size (kHistorySizeBlocks) for symmetry reasons.
@ -1557,18 +1521,16 @@ AecCore* WebRtcAec_CreateAec() {
aec->delay_estimator_farend, kHistorySizeBlocks);
if (aec->delay_estimator == NULL) {
WebRtcAec_FreeAec(aec);
return NULL;
aec = NULL;
return -1;
}
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_GONK)
aec->delay_agnostic_enabled = 1; // DA-AEC enabled by default.
#ifdef WEBRTC_ANDROID
// DA-AEC assumes the system is causal from the beginning and will self adjust
// the lookahead when shifting is required.
WebRtc_set_lookahead(aec->delay_estimator, 0);
#else
aec->delay_agnostic_enabled = 0;
WebRtc_set_lookahead(aec->delay_estimator, kLookaheadBlocks);
#endif
aec->extended_filter_enabled = 0;
// Assembly optimization
WebRtcAec_FilterFar = FilterFar;
@ -1598,13 +1560,13 @@ AecCore* WebRtcAec_CreateAec() {
aec_rdft_init();
return aec;
return 0;
}
void WebRtcAec_FreeAec(AecCore* aec) {
int WebRtcAec_FreeAec(AecCore* aec) {
int i;
if (aec == NULL) {
return;
return -1;
}
WebRtc_FreeBuffer(aec->nearFrBuf);
@ -1625,13 +1587,13 @@ void WebRtcAec_FreeAec(AecCore* aec) {
rtc_WavClose(aec->nearFile);
rtc_WavClose(aec->outFile);
rtc_WavClose(aec->outLinearFile);
rtc_WavClose(aec->e_fft_file);
}
#endif
WebRtc_FreeDelayEstimator(aec->delay_estimator);
WebRtc_FreeDelayEstimatorFarend(aec->delay_estimator_farend);
free(aec);
return 0;
}
int WebRtcAec_InitAec(AecCore* aec, int sampFreq) {
@ -1646,7 +1608,7 @@ int WebRtcAec_InitAec(AecCore* aec, int sampFreq) {
} else {
aec->normal_mu = 0.5f;
aec->normal_error_threshold = 1.5e-6f;
aec->num_bands = (size_t)(sampFreq / 16000);
aec->num_bands = sampFreq / 16000;
}
WebRtc_InitBuffer(aec->nearFrBuf);
@ -1684,8 +1646,14 @@ int WebRtcAec_InitAec(AecCore* aec, int sampFreq) {
aec->previous_delay = -2; // (-2): Uninitialized.
aec->delay_correction_count = 0;
aec->shift_offset = kInitialShiftOffset;
aec->delay_quality_threshold = kDelayQualityThresholdMin;
aec->delay_quality_threshold = 0;
#ifdef WEBRTC_ANDROID
aec->reported_delay_enabled = 0; // Disabled by default.
#else
aec->reported_delay_enabled = 1;
#endif
aec->extended_filter_enabled = 0;
aec->num_partitions = kNormalNumPartitions;
// Update the delay estimator with filter length. We use half the
@ -1698,16 +1666,14 @@ int WebRtcAec_InitAec(AecCore* aec, int sampFreq) {
// all the time and the APIs to turn it on/off will be removed. Hence, remove
// this line then.
WebRtc_enable_robust_validation(aec->delay_estimator, 1);
aec->frame_count = 0;
// Default target suppression mode.
aec->nlp_mode = 1;
// Sampling frequency multiplier w.r.t. 8 kHz.
// In case of multiple bands we process the lower band in 16 kHz, hence the
// multiplier is always 2.
// Sampling frequency multiplier
// SWB is processed as 160 frame size
if (aec->num_bands > 1) {
aec->mult = 2;
aec->mult = (short)aec->sampFreq / 16000;
} else {
aec->mult = (short)aec->sampFreq / 8000;
}
@ -1803,21 +1769,24 @@ void WebRtcAec_BufferFarendPartition(AecCore* aec, const float* farend) {
}
int WebRtcAec_MoveFarReadPtr(AecCore* aec, int elements) {
int elements_moved = MoveFarReadPtrWithoutSystemDelayUpdate(aec, elements);
int elements_moved = WebRtc_MoveReadPtr(aec->far_buf_windowed, elements);
WebRtc_MoveReadPtr(aec->far_buf, elements);
#ifdef WEBRTC_AEC_DEBUG_DUMP
WebRtc_MoveReadPtr(aec->far_time_buf, elements);
#endif
aec->system_delay -= elements_moved * PART_LEN;
return elements_moved;
}
void WebRtcAec_ProcessFrames(AecCore* aec,
const float* const* nearend,
size_t num_bands,
size_t num_samples,
int num_bands,
int num_samples,
int knownDelay,
float* const* out) {
size_t i, j;
int i, j;
int out_elements = 0;
aec->frame_count++;
// For each frame the process is as follows:
// 1) If the system_delay indicates on being too small for processing a
// frame we stuff the buffer with enough data for 10 ms.
@ -1865,7 +1834,7 @@ void WebRtcAec_ProcessFrames(AecCore* aec,
WebRtcAec_MoveFarReadPtr(aec, -(aec->mult + 1));
}
if (!aec->delay_agnostic_enabled) {
if (aec->reported_delay_enabled) {
// 2 a) Compensate for a possible change in the system delay.
// TODO(bjornv): Investigate how we should round the delay difference;
@ -1876,27 +1845,42 @@ void WebRtcAec_ProcessFrames(AecCore* aec,
// which should be investigated. Maybe, allow for a non-symmetric
// rounding, like -16.
int move_elements = (aec->knownDelay - knownDelay - 32) / PART_LEN;
int moved_elements =
MoveFarReadPtrWithoutSystemDelayUpdate(aec, move_elements);
int moved_elements = WebRtc_MoveReadPtr(aec->far_buf, move_elements);
WebRtc_MoveReadPtr(aec->far_buf_windowed, move_elements);
aec->knownDelay -= moved_elements * PART_LEN;
#ifdef WEBRTC_AEC_DEBUG_DUMP
WebRtc_MoveReadPtr(aec->far_time_buf, move_elements);
#endif
} else {
// 2 b) Apply signal based delay correction.
int move_elements = SignalBasedDelayCorrection(aec);
int moved_elements =
MoveFarReadPtrWithoutSystemDelayUpdate(aec, move_elements);
int far_near_buffer_diff = WebRtc_available_read(aec->far_buf) -
WebRtc_available_read(aec->nearFrBuf) / PART_LEN;
int moved_elements = WebRtc_MoveReadPtr(aec->far_buf, move_elements);
WebRtc_MoveReadPtr(aec->far_buf_windowed, move_elements);
#ifdef WEBRTC_AEC_DEBUG_DUMP
WebRtc_MoveReadPtr(aec->far_time_buf, move_elements);
#endif
WebRtc_SoftResetDelayEstimator(aec->delay_estimator, moved_elements);
WebRtc_SoftResetDelayEstimatorFarend(aec->delay_estimator_farend,
moved_elements);
aec->signal_delay_correction += moved_elements;
// If we rely on reported system delay values only, a buffer underrun here
// can never occur since we've taken care of that in 1) above. Here, we
// apply signal based delay correction and can therefore end up with
// buffer underruns since the delay estimation can be wrong. We therefore
// stuff the buffer with enough elements if needed.
if (far_near_buffer_diff < 0) {
WebRtcAec_MoveFarReadPtr(aec, far_near_buffer_diff);
// TODO(bjornv): Investigate if this is reasonable. I had to add this
// guard when the signal based delay correction replaces the system based
// one. Otherwise there was a buffer underrun in the "qa-new/01/"
// recording when adding 44 ms extra delay. This was not seen if we kept
// both delay correction algorithms running in parallel.
// A first investigation showed that we have a drift in this case that
// causes the buffer underrun. Compared to when delay correction was
// turned off, we get buffer underrun as well which was triggered in 1)
// above. In addition there was a shift in |knownDelay| later increasing
// the buffer. When running in parallel, this if statement was not
// triggered. This suggests two alternatives; (a) use both algorithms, or
// (b) allow for smaller delay corrections when we operate close to the
// buffer limit. At the time of testing we required a change of 6 blocks,
// but could change it to, e.g., 2 blocks. It requires some testing
// though.
if ((int)WebRtc_available_read(aec->far_buf) < (aec->mult + 1)) {
// We don't have enough data so we stuff the far-end buffers.
WebRtcAec_MoveFarReadPtr(aec, -(aec->mult + 1));
}
}
@ -1979,28 +1963,28 @@ void WebRtcAec_SetConfigCore(AecCore* self,
}
// Turn on delay logging if it is either set explicitly or if delay agnostic
// AEC is enabled (which requires delay estimates).
self->delay_logging_enabled = delay_logging || self->delay_agnostic_enabled;
self->delay_logging_enabled = delay_logging || !self->reported_delay_enabled;
if (self->delay_logging_enabled) {
memset(self->delay_histogram, 0, sizeof(self->delay_histogram));
}
}
void WebRtcAec_enable_delay_agnostic(AecCore* self, int enable) {
self->delay_agnostic_enabled = enable;
void WebRtcAec_enable_reported_delay(AecCore* self, int enable) {
self->reported_delay_enabled = enable;
}
int WebRtcAec_delay_agnostic_enabled(AecCore* self) {
return self->delay_agnostic_enabled;
int WebRtcAec_reported_delay_enabled(AecCore* self) {
return self->reported_delay_enabled;
}
void WebRtcAec_enable_extended_filter(AecCore* self, int enable) {
void WebRtcAec_enable_delay_correction(AecCore* self, int enable) {
self->extended_filter_enabled = enable;
self->num_partitions = enable ? kExtendedNumPartitions : kNormalNumPartitions;
// Update the delay estimator with filter length. See InitAEC() for details.
WebRtc_set_allowed_offset(self->delay_estimator, self->num_partitions / 2);
}
int WebRtcAec_extended_filter_enabled(AecCore* self) {
int WebRtcAec_delay_correction_enabled(AecCore* self) {
return self->extended_filter_enabled;
}

View File

@ -15,8 +15,6 @@
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_AEC_CORE_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_AEC_CORE_H_
#include <stddef.h>
#include "webrtc/typedefs.h"
#define FRAME_LEN 80
@ -53,8 +51,8 @@ typedef struct Stats {
typedef struct AecCore AecCore;
AecCore* WebRtcAec_CreateAec(); // Returns NULL on error.
void WebRtcAec_FreeAec(AecCore* aec);
int WebRtcAec_CreateAec(AecCore** aec);
int WebRtcAec_FreeAec(AecCore* aec);
int WebRtcAec_InitAec(AecCore* aec, int sampFreq);
void WebRtcAec_InitAec_SSE2(void);
#if defined(MIPS_FPU_LE)
@ -67,8 +65,8 @@ void WebRtcAec_InitAec_neon(void);
void WebRtcAec_BufferFarendPartition(AecCore* aec, const float* farend);
void WebRtcAec_ProcessFrames(AecCore* aec,
const float* const* nearend,
size_t num_bands,
size_t num_samples,
int num_bands,
int num_samples,
int knownDelay,
float* const* out);
@ -105,17 +103,19 @@ void WebRtcAec_SetConfigCore(AecCore* self,
int delay_logging);
// Non-zero enables, zero disables.
void WebRtcAec_enable_delay_agnostic(AecCore* self, int enable);
void WebRtcAec_enable_reported_delay(AecCore* self, int enable);
// Returns non-zero if delay agnostic (i.e., signal based delay estimation) is
// enabled and zero if disabled.
int WebRtcAec_delay_agnostic_enabled(AecCore* self);
// Returns non-zero if reported delay is enabled and zero if disabled.
int WebRtcAec_reported_delay_enabled(AecCore* self);
// Enables or disables extended filter mode. Non-zero enables, zero disables.
void WebRtcAec_enable_extended_filter(AecCore* self, int enable);
// We now interpret delay correction to mean an extended filter length feature.
// We reuse the delay correction infrastructure to avoid changes through to
// libjingle. See details along with |DelayCorrection| in
// echo_cancellation_impl.h. Non-zero enables, zero disables.
void WebRtcAec_enable_delay_correction(AecCore* self, int enable);
// Returns non-zero if extended filter mode is enabled and zero if disabled.
int WebRtcAec_extended_filter_enabled(AecCore* self);
// Returns non-zero if delay correction is enabled and zero if disabled.
int WebRtcAec_delay_correction_enabled(AecCore* self);
// Returns the current |system_delay|, i.e., the buffered difference between
// far-end and near-end.

View File

@ -101,7 +101,7 @@ struct AecCore {
int mult; // sampling frequency multiple
int sampFreq;
size_t num_bands;
int num_bands;
uint32_t seed;
float normal_mu; // stepsize
@ -142,11 +142,10 @@ struct AecCore {
int delay_correction_count;
int shift_offset;
float delay_quality_threshold;
int frame_count;
// 0 = delay agnostic mode (signal based delay correction) disabled.
// Otherwise enabled.
int delay_agnostic_enabled;
// 0 = reported delay mode disabled (signal based delay correction enabled).
// otherwise enabled
int reported_delay_enabled;
// 1 = extended filter mode enabled, 0 = disabled.
int extended_filter_enabled;
// Runtime selection of number of filter partitions.
@ -166,7 +165,6 @@ struct AecCore {
rtc_WavWriter* nearFile;
rtc_WavWriter* outFile;
rtc_WavWriter* outLinearFile;
rtc_WavWriter* e_fft_file;
uint32_t debugWritten;
#endif
};

View File

@ -40,8 +40,14 @@ static int EstimateSkew(const int* rawSkew,
int absLimit,
float* skewEst);
void* WebRtcAec_CreateResampler() {
return malloc(sizeof(AecResampler));
int WebRtcAec_CreateResampler(void** resampInst) {
AecResampler* obj = malloc(sizeof(AecResampler));
*resampInst = obj;
if (obj == NULL) {
return -1;
}
return 0;
}
int WebRtcAec_InitResampler(void* resampInst, int deviceSampleRateHz) {
@ -57,24 +63,26 @@ int WebRtcAec_InitResampler(void* resampInst, int deviceSampleRateHz) {
return 0;
}
void WebRtcAec_FreeResampler(void* resampInst) {
int WebRtcAec_FreeResampler(void* resampInst) {
AecResampler* obj = (AecResampler*)resampInst;
free(obj);
return 0;
}
void WebRtcAec_ResampleLinear(void* resampInst,
const float* inspeech,
size_t size,
int size,
float skew,
float* outspeech,
size_t* size_out) {
int* size_out) {
AecResampler* obj = (AecResampler*)resampInst;
float* y;
float be, tnew;
size_t tn, mm;
int tn, mm;
assert(size <= 2 * FRAME_LEN);
assert(!(size < 0 || size > 2 * FRAME_LEN));
assert(resampInst != NULL);
assert(inspeech != NULL);
assert(outspeech != NULL);
@ -93,7 +101,7 @@ void WebRtcAec_ResampleLinear(void* resampInst,
y = &obj->buffer[FRAME_LEN]; // Point at current frame
tnew = be * mm + obj->position;
tn = (size_t)tnew;
tn = (int)tnew;
while (tn < size) {

View File

@ -20,10 +20,10 @@ enum {
kResamplerBufferSize = FRAME_LEN * 4
};
// Unless otherwise specified, functions return 0 on success and -1 on error.
void* WebRtcAec_CreateResampler(); // Returns NULL on error.
// Unless otherwise specified, functions return 0 on success and -1 on error
int WebRtcAec_CreateResampler(void** resampInst);
int WebRtcAec_InitResampler(void* resampInst, int deviceSampleRateHz);
void WebRtcAec_FreeResampler(void* resampInst);
int WebRtcAec_FreeResampler(void* resampInst);
// Estimates skew from raw measurement.
int WebRtcAec_GetSkew(void* resampInst, int rawSkew, float* skewEst);
@ -31,9 +31,9 @@ int WebRtcAec_GetSkew(void* resampInst, int rawSkew, float* skewEst);
// Resamples input using linear interpolation.
void WebRtcAec_ResampleLinear(void* resampInst,
const float* inspeech,
size_t size,
int size,
float skew,
float* outspeech,
size_t* size_out);
int* size_out);
#endif // WEBRTC_MODULES_AUDIO_PROCESSING_AEC_AEC_RESAMPLER_H_

View File

@ -111,35 +111,41 @@ static void EstBufDelayNormal(Aec* aecInst);
static void EstBufDelayExtended(Aec* aecInst);
static int ProcessNormal(Aec* self,
const float* const* near,
size_t num_bands,
int num_bands,
float* const* out,
size_t num_samples,
int16_t num_samples,
int16_t reported_delay_ms,
int32_t skew);
static void ProcessExtended(Aec* self,
const float* const* near,
size_t num_bands,
int num_bands,
float* const* out,
size_t num_samples,
int16_t num_samples,
int16_t reported_delay_ms,
int32_t skew);
void* WebRtcAec_Create() {
Aec* aecpc = malloc(sizeof(Aec));
if (!aecpc) {
return NULL;
int32_t WebRtcAec_Create(void** aecInst) {
Aec* aecpc;
if (aecInst == NULL) {
return -1;
}
aecpc->aec = WebRtcAec_CreateAec();
if (!aecpc->aec) {
WebRtcAec_Free(aecpc);
return NULL;
aecpc = malloc(sizeof(Aec));
*aecInst = aecpc;
if (aecpc == NULL) {
return -1;
}
aecpc->resampler = WebRtcAec_CreateResampler();
if (!aecpc->resampler) {
if (WebRtcAec_CreateAec(&aecpc->aec) == -1) {
WebRtcAec_Free(aecpc);
return NULL;
aecpc = NULL;
return -1;
}
if (WebRtcAec_CreateResampler(&aecpc->resampler) == -1) {
WebRtcAec_Free(aecpc);
aecpc = NULL;
return -1;
}
// Create far-end pre-buffer. The buffer size has to be large enough for
// largest possible drift compensation (kResamplerBufferSize) + "almost" an
@ -148,24 +154,26 @@ void* WebRtcAec_Create() {
WebRtc_CreateBuffer(PART_LEN2 + kResamplerBufferSize, sizeof(float));
if (!aecpc->far_pre_buf) {
WebRtcAec_Free(aecpc);
return NULL;
aecpc = NULL;
return -1;
}
aecpc->initFlag = 0;
aecpc->lastError = 0;
#ifdef WEBRTC_AEC_DEBUG_DUMP
aecpc->bufFile = aecpc->skewFile = aecpc->delayFile = NULL;
OpenDebugFiles(aecpc, &webrtc_aec_instance_count);
#endif
return aecpc;
return 0;
}
void WebRtcAec_Free(void* aecInst) {
int32_t WebRtcAec_Free(void* aecInst) {
Aec* aecpc = aecInst;
if (aecpc == NULL) {
return;
return -1;
}
WebRtc_FreeBuffer(aecpc->far_pre_buf);
@ -182,6 +190,8 @@ void WebRtcAec_Free(void* aecInst) {
WebRtcAec_FreeAec(aecpc->aec);
WebRtcAec_FreeResampler(aecpc->resampler);
free(aecpc);
return 0;
}
int32_t WebRtcAec_Init(void* aecInst, int32_t sampFreq, int32_t scSampFreq) {
@ -192,22 +202,26 @@ int32_t WebRtcAec_Init(void* aecInst, int32_t sampFreq, int32_t scSampFreq) {
sampFreq != 16000 &&
sampFreq != 32000 &&
sampFreq != 48000) {
return AEC_BAD_PARAMETER_ERROR;
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
aecpc->sampFreq = sampFreq;
if (scSampFreq < 1 || scSampFreq > 96000) {
return AEC_BAD_PARAMETER_ERROR;
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
aecpc->scSampFreq = scSampFreq;
// Initialize echo canceller core
if (WebRtcAec_InitAec(aecpc->aec, aecpc->sampFreq) == -1) {
return AEC_UNSPECIFIED_ERROR;
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
return -1;
}
if (WebRtcAec_InitResampler(aecpc->resampler, aecpc->scSampFreq) == -1) {
return AEC_UNSPECIFIED_ERROR;
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
return -1;
}
WebRtc_InitBuffer(aecpc->far_pre_buf);
@ -231,10 +245,7 @@ int32_t WebRtcAec_Init(void* aecInst, int32_t sampFreq, int32_t scSampFreq) {
aecpc->checkBuffSize = 1;
aecpc->firstVal = 0;
// We skip the startup_phase completely (setting to 0) if DA-AEC is enabled,
// but not extended_filter mode.
aecpc->startup_phase = WebRtcAec_extended_filter_enabled(aecpc->aec) ||
!WebRtcAec_delay_agnostic_enabled(aecpc->aec);
aecpc->startup_phase = WebRtcAec_reported_delay_enabled(aecpc->aec);
aecpc->bufSizeStart = 0;
aecpc->checkBufSizeCtr = 0;
aecpc->msInSndCardBuf = 0;
@ -257,48 +268,37 @@ int32_t WebRtcAec_Init(void* aecInst, int32_t sampFreq, int32_t scSampFreq) {
aecConfig.delay_logging = kAecFalse;
if (WebRtcAec_set_config(aecpc, aecConfig) == -1) {
return AEC_UNSPECIFIED_ERROR;
aecpc->lastError = AEC_UNSPECIFIED_ERROR;
return -1;
}
return 0;
}
// Returns any error that is caused when buffering the
// far-end signal.
int32_t WebRtcAec_GetBufferFarendError(void* aecInst,
const float* farend,
size_t nrOfSamples) {
Aec* aecpc = aecInst;
if (!farend)
return AEC_NULL_POINTER_ERROR;
if (aecpc->initFlag != initCheck)
return AEC_UNINITIALIZED_ERROR;
// number of samples == 160 for SWB input
if (nrOfSamples != 80 && nrOfSamples != 160)
return AEC_BAD_PARAMETER_ERROR;
return 0;
}
// only buffer L band for farend
int32_t WebRtcAec_BufferFarend(void* aecInst,
const float* farend,
size_t nrOfSamples) {
int16_t nrOfSamples) {
Aec* aecpc = aecInst;
size_t newNrOfSamples = nrOfSamples;
int newNrOfSamples = (int)nrOfSamples;
float new_farend[MAX_RESAMP_LEN];
const float* farend_ptr = farend;
// Get any error caused by buffering the farend signal.
int32_t error_code = WebRtcAec_GetBufferFarendError(aecInst, farend,
nrOfSamples);
if (farend == NULL) {
aecpc->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (error_code != 0)
return error_code;
if (aecpc->initFlag != initCheck) {
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
}
// number of samples == 160 for SWB input
if (nrOfSamples != 80 && nrOfSamples != 160) {
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
if (aecpc->skewMode == kAecTrue && aecpc->resample == kAecTrue) {
// Resample and get a new number of samples
@ -312,11 +312,11 @@ int32_t WebRtcAec_BufferFarend(void* aecInst,
}
aecpc->farend_started = 1;
WebRtcAec_SetSystemDelay(
aecpc->aec, WebRtcAec_system_delay(aecpc->aec) + (int)newNrOfSamples);
WebRtcAec_SetSystemDelay(aecpc->aec,
WebRtcAec_system_delay(aecpc->aec) + newNrOfSamples);
// Write the time-domain data to |far_pre_buf|.
WebRtc_WriteBuffer(aecpc->far_pre_buf, farend_ptr, newNrOfSamples);
WebRtc_WriteBuffer(aecpc->far_pre_buf, farend_ptr, (size_t)newNrOfSamples);
// Transform to frequency domain if we have enough data.
while (WebRtc_available_read(aecpc->far_pre_buf) >= PART_LEN2) {
@ -341,37 +341,42 @@ int32_t WebRtcAec_BufferFarend(void* aecInst,
int32_t WebRtcAec_Process(void* aecInst,
const float* const* nearend,
size_t num_bands,
int num_bands,
float* const* out,
size_t nrOfSamples,
int16_t nrOfSamples,
int16_t msInSndCardBuf,
int32_t skew) {
Aec* aecpc = aecInst;
int32_t retVal = 0;
if (out == NULL) {
return AEC_NULL_POINTER_ERROR;
aecpc->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (aecpc->initFlag != initCheck) {
return AEC_UNINITIALIZED_ERROR;
aecpc->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
}
// number of samples == 160 for SWB input
if (nrOfSamples != 80 && nrOfSamples != 160) {
return AEC_BAD_PARAMETER_ERROR;
aecpc->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
if (msInSndCardBuf < 0) {
msInSndCardBuf = 0;
retVal = AEC_BAD_PARAMETER_WARNING;
aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
retVal = -1;
} else if (msInSndCardBuf > kMaxTrustedDelayMs) {
// The clamping is now done in ProcessExtended/Normal().
retVal = AEC_BAD_PARAMETER_WARNING;
aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
retVal = -1;
}
// This returns the value of aec->extended_filter_enabled.
if (WebRtcAec_extended_filter_enabled(aecpc->aec)) {
if (WebRtcAec_delay_correction_enabled(aecpc->aec)) {
ProcessExtended(aecpc,
nearend,
num_bands,
@ -380,13 +385,15 @@ int32_t WebRtcAec_Process(void* aecInst,
msInSndCardBuf,
skew);
} else {
retVal = ProcessNormal(aecpc,
nearend,
num_bands,
out,
nrOfSamples,
msInSndCardBuf,
skew);
if (ProcessNormal(aecpc,
nearend,
num_bands,
out,
nrOfSamples,
msInSndCardBuf,
skew) != 0) {
retVal = -1;
}
}
#ifdef WEBRTC_AEC_DEBUG_DUMP
@ -408,26 +415,31 @@ int32_t WebRtcAec_Process(void* aecInst,
int WebRtcAec_set_config(void* handle, AecConfig config) {
Aec* self = (Aec*)handle;
if (self->initFlag != initCheck) {
return AEC_UNINITIALIZED_ERROR;
self->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
}
if (config.skewMode != kAecFalse && config.skewMode != kAecTrue) {
return AEC_BAD_PARAMETER_ERROR;
self->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
self->skewMode = config.skewMode;
if (config.nlpMode != kAecNlpConservative &&
config.nlpMode != kAecNlpModerate &&
config.nlpMode != kAecNlpAggressive) {
return AEC_BAD_PARAMETER_ERROR;
self->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
if (config.metricsMode != kAecFalse && config.metricsMode != kAecTrue) {
return AEC_BAD_PARAMETER_ERROR;
self->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
if (config.delay_logging != kAecFalse && config.delay_logging != kAecTrue) {
return AEC_BAD_PARAMETER_ERROR;
self->lastError = AEC_BAD_PARAMETER_ERROR;
return -1;
}
WebRtcAec_SetConfigCore(
@ -438,10 +450,12 @@ int WebRtcAec_set_config(void* handle, AecConfig config) {
int WebRtcAec_get_echo_status(void* handle, int* status) {
Aec* self = (Aec*)handle;
if (status == NULL) {
return AEC_NULL_POINTER_ERROR;
self->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (self->initFlag != initCheck) {
return AEC_UNINITIALIZED_ERROR;
self->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
}
*status = WebRtcAec_echo_state(self->aec);
@ -462,10 +476,12 @@ int WebRtcAec_GetMetrics(void* handle, AecMetrics* metrics) {
return -1;
}
if (metrics == NULL) {
return AEC_NULL_POINTER_ERROR;
self->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (self->initFlag != initCheck) {
return AEC_UNINITIALIZED_ERROR;
self->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
}
WebRtcAec_GetEchoStats(self->aec, &erl, &erle, &a_nlp);
@ -550,24 +566,32 @@ int WebRtcAec_GetDelayMetrics(void* handle,
float* fraction_poor_delays) {
Aec* self = handle;
if (median == NULL) {
return AEC_NULL_POINTER_ERROR;
self->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (std == NULL) {
return AEC_NULL_POINTER_ERROR;
self->lastError = AEC_NULL_POINTER_ERROR;
return -1;
}
if (self->initFlag != initCheck) {
return AEC_UNINITIALIZED_ERROR;
self->lastError = AEC_UNINITIALIZED_ERROR;
return -1;
}
if (WebRtcAec_GetDelayMetricsCore(self->aec, median, std,
fraction_poor_delays) ==
-1) {
// Logging disabled.
return AEC_UNSUPPORTED_FUNCTION_ERROR;
self->lastError = AEC_UNSUPPORTED_FUNCTION_ERROR;
return -1;
}
return 0;
}
int32_t WebRtcAec_get_error_code(void* aecInst) {
Aec* aecpc = aecInst;
return aecpc->lastError;
}
AecCore* WebRtcAec_aec_core(void* handle) {
if (!handle) {
@ -578,14 +602,14 @@ AecCore* WebRtcAec_aec_core(void* handle) {
static int ProcessNormal(Aec* aecpc,
const float* const* nearend,
size_t num_bands,
int num_bands,
float* const* out,
size_t nrOfSamples,
int16_t nrOfSamples,
int16_t msInSndCardBuf,
int32_t skew) {
int retVal = 0;
size_t i;
size_t nBlocks10ms;
short i;
short nBlocks10ms;
// Limit resampling to doubling/halving of signal
const float minSkewEst = -0.5f;
const float maxSkewEst = 1.0f;
@ -603,7 +627,7 @@ static int ProcessNormal(Aec* aecpc,
retVal = WebRtcAec_GetSkew(aecpc->resampler, skew, &aecpc->skew);
if (retVal == -1) {
aecpc->skew = 0;
retVal = AEC_BAD_PARAMETER_WARNING;
aecpc->lastError = AEC_BAD_PARAMETER_WARNING;
}
aecpc->skew /= aecpc->sampFactor * nrOfSamples;
@ -710,7 +734,9 @@ static int ProcessNormal(Aec* aecpc,
}
} else {
// AEC is enabled.
if (WebRtcAec_reported_delay_enabled(aecpc->aec)) {
EstBufDelayNormal(aecpc);
}
// Call the AEC.
// TODO(bjornv): Re-structure such that we don't have to pass
@ -729,12 +755,12 @@ static int ProcessNormal(Aec* aecpc,
static void ProcessExtended(Aec* self,
const float* const* near,
size_t num_bands,
int num_bands,
float* const* out,
size_t num_samples,
int16_t num_samples,
int16_t reported_delay_ms,
int32_t skew) {
size_t i;
int i;
const int delay_diff_offset = kDelayDiffOffsetSamples;
#if defined(WEBRTC_UNTRUSTED_DELAY)
reported_delay_ms = kFixedDelayMs;
@ -772,21 +798,16 @@ static void ProcessExtended(Aec* self,
// measurement.
int startup_size_ms =
reported_delay_ms < kFixedDelayMs ? kFixedDelayMs : reported_delay_ms;
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_GONK)
int target_delay = startup_size_ms * self->rate_factor * 8;
#else
// To avoid putting the AEC in a non-causal state we're being slightly
// conservative and scale by 2. On Android we use a fixed delay and
// therefore there is no need to scale the target_delay.
int target_delay = startup_size_ms * self->rate_factor * 8 / 2;
#endif
int overhead_elements =
(WebRtcAec_system_delay(self->aec) - target_delay) / PART_LEN;
int overhead_elements = (WebRtcAec_system_delay(self->aec) -
startup_size_ms / 2 * self->rate_factor * 8) /
PART_LEN;
WebRtcAec_MoveFarReadPtr(self->aec, overhead_elements);
self->startup_phase = 0;
}
EstBufDelayExtended(self);
if (WebRtcAec_reported_delay_enabled(self->aec)) {
EstBufDelayExtended(self);
}
{
// |delay_diff_offset| gives us the option to manually rewind the delay on

View File

@ -57,6 +57,8 @@ typedef struct {
RingBuffer* far_pre_buf; // Time domain far-end pre-buffer.
int lastError;
int farend_started;
AecCore* aec;

View File

@ -11,8 +11,6 @@
#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_AEC_INCLUDE_ECHO_CANCELLATION_H_
#define WEBRTC_MODULES_AUDIO_PROCESSING_AEC_INCLUDE_ECHO_CANCELLATION_H_
#include <stddef.h>
#include "webrtc/typedefs.h"
// Errors
@ -66,10 +64,19 @@ extern "C" {
/*
* Allocates the memory needed by the AEC. The memory needs to be initialized
* separately using the WebRtcAec_Init() function. Returns a pointer to the
* object or NULL on error.
* separately using the WebRtcAec_Init() function.
*
* Inputs Description
* -------------------------------------------------------------------
* void** aecInst Pointer to the AEC instance to be created
* and initialized
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* -1: error
*/
void* WebRtcAec_Create();
int32_t WebRtcAec_Create(void** aecInst);
/*
* This function releases the memory allocated by WebRtcAec_Create().
@ -77,8 +84,13 @@ void* WebRtcAec_Create();
* Inputs Description
* -------------------------------------------------------------------
* void* aecInst Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* -1: error
*/
void WebRtcAec_Free(void* aecInst);
int32_t WebRtcAec_Free(void* aecInst);
/*
* Initializes an AEC instance.
@ -91,7 +103,7 @@ void WebRtcAec_Free(void* aecInst);
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* int32_t return 0: OK
* -1: error
*/
int32_t WebRtcAec_Init(void* aecInst, int32_t sampFreq, int32_t scSampFreq);
@ -109,30 +121,11 @@ int32_t WebRtcAec_Init(void* aecInst, int32_t sampFreq, int32_t scSampFreq);
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* 12000-12050: error code
* -1: error
*/
int32_t WebRtcAec_BufferFarend(void* aecInst,
const float* farend,
size_t nrOfSamples);
/*
* Reports any errors that would arise if buffering a farend buffer
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecInst Pointer to the AEC instance
* const float* farend In buffer containing one frame of
* farend signal for L band
* int16_t nrOfSamples Number of samples in farend buffer
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* 12000-12050: error code
*/
int32_t WebRtcAec_GetBufferFarendError(void* aecInst,
const float* farend,
size_t nrOfSamples);
int16_t nrOfSamples);
/*
* Runs the echo canceller on an 80 or 160 sample blocks of data.
@ -155,13 +148,13 @@ int32_t WebRtcAec_GetBufferFarendError(void* aecInst,
* float* const* out Out buffer, one frame of processed nearend
* for each band
* int32_t return 0: OK
* 12000-12050: error code
* -1: error
*/
int32_t WebRtcAec_Process(void* aecInst,
const float* const* nearend,
size_t num_bands,
int num_bands,
float* const* out,
size_t nrOfSamples,
int16_t nrOfSamples,
int16_t msInSndCardBuf,
int32_t skew);
@ -177,7 +170,7 @@ int32_t WebRtcAec_Process(void* aecInst,
* Outputs Description
* -------------------------------------------------------------------
* int return 0: OK
* 12000-12050: error code
* -1: error
*/
int WebRtcAec_set_config(void* handle, AecConfig config);
@ -193,7 +186,7 @@ int WebRtcAec_set_config(void* handle, AecConfig config);
* int* status 0: Almost certainly nearend single-talk
* 1: Might not be neared single-talk
* int return 0: OK
* 12000-12050: error code
* -1: error
*/
int WebRtcAec_get_echo_status(void* handle, int* status);
@ -209,7 +202,7 @@ int WebRtcAec_get_echo_status(void* handle, int* status);
* AecMetrics* metrics Struct which will be filled out with the
* current echo metrics.
* int return 0: OK
* 12000-12050: error code
* -1: error
*/
int WebRtcAec_GetMetrics(void* handle, AecMetrics* metrics);
@ -228,13 +221,26 @@ int WebRtcAec_GetMetrics(void* handle, AecMetrics* metrics);
* cause the AEC to perform poorly.
*
* int return 0: OK
* 12000-12050: error code
* -1: error
*/
int WebRtcAec_GetDelayMetrics(void* handle,
int* median,
int* std,
float* fraction_poor_delays);
/*
* Gets the last error code.
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecInst Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 11000-11100: error code
*/
int32_t WebRtcAec_get_error_code(void* aecInst);
// Returns a pointer to the low level AEC handle.
//
// Input:

View File

@ -207,15 +207,21 @@ CalcLinearEnergies WebRtcAecm_CalcLinearEnergies;
StoreAdaptiveChannel WebRtcAecm_StoreAdaptiveChannel;
ResetAdaptiveChannel WebRtcAecm_ResetAdaptiveChannel;
AecmCore* WebRtcAecm_CreateCore() {
int WebRtcAecm_CreateCore(AecmCore** aecmInst) {
AecmCore* aecm = malloc(sizeof(AecmCore));
*aecmInst = aecm;
if (aecm == NULL)
{
return -1;
}
aecm->farFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
sizeof(int16_t));
if (!aecm->farFrameBuf)
{
WebRtcAecm_FreeCore(aecm);
return NULL;
aecm = NULL;
return -1;
}
aecm->nearNoisyFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
@ -223,7 +229,8 @@ AecmCore* WebRtcAecm_CreateCore() {
if (!aecm->nearNoisyFrameBuf)
{
WebRtcAecm_FreeCore(aecm);
return NULL;
aecm = NULL;
return -1;
}
aecm->nearCleanFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
@ -231,7 +238,8 @@ AecmCore* WebRtcAecm_CreateCore() {
if (!aecm->nearCleanFrameBuf)
{
WebRtcAecm_FreeCore(aecm);
return NULL;
aecm = NULL;
return -1;
}
aecm->outFrameBuf = WebRtc_CreateBuffer(FRAME_LEN + PART_LEN,
@ -239,20 +247,23 @@ AecmCore* WebRtcAecm_CreateCore() {
if (!aecm->outFrameBuf)
{
WebRtcAecm_FreeCore(aecm);
return NULL;
aecm = NULL;
return -1;
}
aecm->delay_estimator_farend = WebRtc_CreateDelayEstimatorFarend(PART_LEN1,
MAX_DELAY);
if (aecm->delay_estimator_farend == NULL) {
WebRtcAecm_FreeCore(aecm);
return NULL;
aecm = NULL;
return -1;
}
aecm->delay_estimator =
WebRtc_CreateDelayEstimator(aecm->delay_estimator_farend, 0);
if (aecm->delay_estimator == NULL) {
WebRtcAecm_FreeCore(aecm);
return NULL;
aecm = NULL;
return -1;
}
// TODO(bjornv): Explicitly disable robust delay validation until no
// performance regression has been established. Then remove the line.
@ -261,7 +272,8 @@ AecmCore* WebRtcAecm_CreateCore() {
aecm->real_fft = WebRtcSpl_CreateRealFFT(PART_LEN_SHIFT);
if (aecm->real_fft == NULL) {
WebRtcAecm_FreeCore(aecm);
return NULL;
aecm = NULL;
return -1;
}
// Init some aecm pointers. 16 and 32 byte alignment is only necessary
@ -277,7 +289,7 @@ AecmCore* WebRtcAecm_CreateCore() {
aecm->channelAdapt32 = (int32_t*) (((uintptr_t)
aecm->channelAdapt32_buf + 31) & ~ 31);
return aecm;
return 0;
}
void WebRtcAecm_InitEchoPathCore(AecmCore* aecm, const int16_t* echo_path) {
@ -534,9 +546,10 @@ int WebRtcAecm_Control(AecmCore* aecm, int delay, int nlpFlag) {
return 0;
}
void WebRtcAecm_FreeCore(AecmCore* aecm) {
if (aecm == NULL) {
return;
int WebRtcAecm_FreeCore(AecmCore* aecm) {
if (aecm == NULL)
{
return -1;
}
WebRtc_FreeBuffer(aecm->farFrameBuf);
@ -549,6 +562,8 @@ void WebRtcAecm_FreeCore(AecmCore* aecm) {
WebRtcSpl_FreeRealFFT(aecm->real_fft);
free(aecm);
return 0;
}
int WebRtcAecm_ProcessFrame(AecmCore* aecm,

View File

@ -134,18 +134,27 @@ typedef struct {
} AecmCore;
////////////////////////////////////////////////////////////////////////////////
// WebRtcAecm_CreateCore()
// WebRtcAecm_CreateCore(...)
//
// Allocates the memory needed by the AECM. The memory needs to be
// initialized separately using the WebRtcAecm_InitCore() function.
// Returns a pointer to the instance and a nullptr at failure.
AecmCore* WebRtcAecm_CreateCore();
//
// Input:
// - aecm : Instance that should be created
//
// Output:
// - aecm : Created instance
//
// Return value : 0 - Ok
// -1 - Error
//
int WebRtcAecm_CreateCore(AecmCore** aecm);
////////////////////////////////////////////////////////////////////////////////
// WebRtcAecm_InitCore(...)
//
// This function initializes the AECM instant created with
// WebRtcAecm_CreateCore()
// WebRtcAecm_CreateCore(...)
// Input:
// - aecm : Pointer to the AECM instance
// - samplingFreq : Sampling Frequency
@ -165,7 +174,11 @@ int WebRtcAecm_InitCore(AecmCore* const aecm, int samplingFreq);
// Input:
// - aecm : Pointer to the AECM instance
//
void WebRtcAecm_FreeCore(AecmCore* aecm);
// Return value : 0 - Ok
// -1 - Error
// 11001-11016: Error
//
int WebRtcAecm_FreeCore(AecmCore* aecm);
int WebRtcAecm_Control(AecmCore* aecm, int delay, int nlpFlag);

View File

@ -68,6 +68,8 @@ typedef struct
// Structures
RingBuffer *farendBuf;
int lastError;
AecmCore* aecmCore;
} AecMobile;
@ -78,15 +80,28 @@ static int WebRtcAecm_EstBufDelay(AecMobile* aecmInst, short msInSndCardBuf);
// Stuffs the farend buffer if the estimated delay is too large
static int WebRtcAecm_DelayComp(AecMobile* aecmInst);
void* WebRtcAecm_Create() {
AecMobile* aecm = malloc(sizeof(AecMobile));
int32_t WebRtcAecm_Create(void **aecmInst)
{
AecMobile* aecm;
if (aecmInst == NULL)
{
return -1;
}
aecm = malloc(sizeof(AecMobile));
*aecmInst = aecm;
if (aecm == NULL)
{
return -1;
}
WebRtcSpl_Init();
aecm->aecmCore = WebRtcAecm_CreateCore();
if (!aecm->aecmCore) {
if (WebRtcAecm_CreateCore(&aecm->aecmCore) == -1)
{
WebRtcAecm_Free(aecm);
return NULL;
aecm = NULL;
return -1;
}
aecm->farendBuf = WebRtc_CreateBuffer(kBufSizeSamp,
@ -94,10 +109,12 @@ void* WebRtcAecm_Create() {
if (!aecm->farendBuf)
{
WebRtcAecm_Free(aecm);
return NULL;
aecm = NULL;
return -1;
}
aecm->initFlag = 0;
aecm->lastError = 0;
#ifdef AEC_DEBUG
aecm->aecmCore->farFile = fopen("aecFar.pcm","wb");
@ -110,14 +127,16 @@ void* WebRtcAecm_Create() {
aecm->preCompFile = fopen("preComp.pcm", "wb");
aecm->postCompFile = fopen("postComp.pcm", "wb");
#endif // AEC_DEBUG
return aecm;
return 0;
}
void WebRtcAecm_Free(void* aecmInst) {
int32_t WebRtcAecm_Free(void *aecmInst)
{
AecMobile* aecm = aecmInst;
if (aecm == NULL) {
return;
if (aecm == NULL)
{
return -1;
}
#ifdef AEC_DEBUG
@ -134,6 +153,8 @@ void WebRtcAecm_Free(void* aecmInst) {
WebRtcAecm_FreeCore(aecm->aecmCore);
WebRtc_FreeBuffer(aecm->farendBuf);
free(aecm);
return 0;
}
int32_t WebRtcAecm_Init(void *aecmInst, int32_t sampFreq)
@ -148,14 +169,16 @@ int32_t WebRtcAecm_Init(void *aecmInst, int32_t sampFreq)
if (sampFreq != 8000 && sampFreq != 16000)
{
return AECM_BAD_PARAMETER_ERROR;
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
aecm->sampFreq = sampFreq;
// Initialize AECM core
if (WebRtcAecm_InitCore(aecm->aecmCore, aecm->sampFreq) == -1)
{
return AECM_UNSPECIFIED_ERROR;
aecm->lastError = AECM_UNSPECIFIED_ERROR;
return -1;
}
// Initialize farend buffer
@ -186,65 +209,63 @@ int32_t WebRtcAecm_Init(void *aecmInst, int32_t sampFreq)
if (WebRtcAecm_set_config(aecm, aecConfig) == -1)
{
return AECM_UNSPECIFIED_ERROR;
aecm->lastError = AECM_UNSPECIFIED_ERROR;
return -1;
}
return 0;
}
// Returns any error that is caused when buffering the
// farend signal.
int32_t WebRtcAecm_GetBufferFarendError(void *aecmInst, const int16_t *farend,
size_t nrOfSamples) {
AecMobile* aecm = aecmInst;
if (aecm == NULL)
return -1;
if (farend == NULL)
return AECM_NULL_POINTER_ERROR;
if (aecm->initFlag != kInitCheck)
return AECM_UNINITIALIZED_ERROR;
if (nrOfSamples != 80 && nrOfSamples != 160)
return AECM_BAD_PARAMETER_ERROR;
return 0;
}
int32_t WebRtcAecm_BufferFarend(void *aecmInst, const int16_t *farend,
size_t nrOfSamples) {
int16_t nrOfSamples)
{
AecMobile* aecm = aecmInst;
int32_t retVal = 0;
const int32_t err =
WebRtcAecm_GetBufferFarendError(aecmInst, farend, nrOfSamples);
if (aecm == NULL)
{
return -1;
}
if (err != 0)
return err;
if (farend == NULL)
{
aecm->lastError = AECM_NULL_POINTER_ERROR;
return -1;
}
// TODO(unknown): Is this really a good idea?
if (!aecm->ECstartup)
{
WebRtcAecm_DelayComp(aecm);
}
if (aecm->initFlag != kInitCheck)
{
aecm->lastError = AECM_UNINITIALIZED_ERROR;
return -1;
}
WebRtc_WriteBuffer(aecm->farendBuf, farend, nrOfSamples);
if (nrOfSamples != 80 && nrOfSamples != 160)
{
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
return 0;
// TODO: Is this really a good idea?
if (!aecm->ECstartup)
{
WebRtcAecm_DelayComp(aecm);
}
WebRtc_WriteBuffer(aecm->farendBuf, farend, (size_t) nrOfSamples);
return retVal;
}
int32_t WebRtcAecm_Process(void *aecmInst, const int16_t *nearendNoisy,
const int16_t *nearendClean, int16_t *out,
size_t nrOfSamples, int16_t msInSndCardBuf)
int16_t nrOfSamples, int16_t msInSndCardBuf)
{
AecMobile* aecm = aecmInst;
int32_t retVal = 0;
size_t i;
short i;
short nmbrOfFilledBuffers;
size_t nBlocks10ms;
size_t nFrames;
short nBlocks10ms;
short nFrames;
#ifdef AEC_DEBUG
short msInAECBuf;
#endif
@ -256,32 +277,38 @@ int32_t WebRtcAecm_Process(void *aecmInst, const int16_t *nearendNoisy,
if (nearendNoisy == NULL)
{
return AECM_NULL_POINTER_ERROR;
aecm->lastError = AECM_NULL_POINTER_ERROR;
return -1;
}
if (out == NULL)
{
return AECM_NULL_POINTER_ERROR;
aecm->lastError = AECM_NULL_POINTER_ERROR;
return -1;
}
if (aecm->initFlag != kInitCheck)
{
return AECM_UNINITIALIZED_ERROR;
aecm->lastError = AECM_UNINITIALIZED_ERROR;
return -1;
}
if (nrOfSamples != 80 && nrOfSamples != 160)
{
return AECM_BAD_PARAMETER_ERROR;
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
if (msInSndCardBuf < 0)
{
msInSndCardBuf = 0;
retVal = AECM_BAD_PARAMETER_WARNING;
aecm->lastError = AECM_BAD_PARAMETER_WARNING;
retVal = -1;
} else if (msInSndCardBuf > 500)
{
msInSndCardBuf = 500;
retVal = AECM_BAD_PARAMETER_WARNING;
aecm->lastError = AECM_BAD_PARAMETER_WARNING;
retVal = -1;
}
msInSndCardBuf += 10;
aecm->msInSndCardBuf = msInSndCardBuf;
@ -444,18 +471,21 @@ int32_t WebRtcAecm_set_config(void *aecmInst, AecmConfig config)
if (aecm->initFlag != kInitCheck)
{
return AECM_UNINITIALIZED_ERROR;
aecm->lastError = AECM_UNINITIALIZED_ERROR;
return -1;
}
if (config.cngMode != AecmFalse && config.cngMode != AecmTrue)
{
return AECM_BAD_PARAMETER_ERROR;
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
aecm->aecmCore->cngMode = config.cngMode;
if (config.echoMode < 0 || config.echoMode > 4)
{
return AECM_BAD_PARAMETER_ERROR;
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
aecm->echoMode = config.echoMode;
@ -512,6 +542,33 @@ int32_t WebRtcAecm_set_config(void *aecmInst, AecmConfig config)
return 0;
}
int32_t WebRtcAecm_get_config(void *aecmInst, AecmConfig *config)
{
AecMobile* aecm = aecmInst;
if (aecm == NULL)
{
return -1;
}
if (config == NULL)
{
aecm->lastError = AECM_NULL_POINTER_ERROR;
return -1;
}
if (aecm->initFlag != kInitCheck)
{
aecm->lastError = AECM_UNINITIALIZED_ERROR;
return -1;
}
config->cngMode = aecm->aecmCore->cngMode;
config->echoMode = aecm->echoMode;
return 0;
}
int32_t WebRtcAecm_InitEchoPath(void* aecmInst,
const void* echo_path,
size_t size_bytes)
@ -523,16 +580,19 @@ int32_t WebRtcAecm_InitEchoPath(void* aecmInst,
return -1;
}
if (echo_path == NULL) {
return AECM_NULL_POINTER_ERROR;
aecm->lastError = AECM_NULL_POINTER_ERROR;
return -1;
}
if (size_bytes != WebRtcAecm_echo_path_size_bytes())
{
// Input channel size does not match the size of AECM
return AECM_BAD_PARAMETER_ERROR;
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
if (aecm->initFlag != kInitCheck)
{
return AECM_UNINITIALIZED_ERROR;
aecm->lastError = AECM_UNINITIALIZED_ERROR;
return -1;
}
WebRtcAecm_InitEchoPathCore(aecm->aecmCore, echo_path_ptr);
@ -551,16 +611,19 @@ int32_t WebRtcAecm_GetEchoPath(void* aecmInst,
return -1;
}
if (echo_path == NULL) {
return AECM_NULL_POINTER_ERROR;
aecm->lastError = AECM_NULL_POINTER_ERROR;
return -1;
}
if (size_bytes != WebRtcAecm_echo_path_size_bytes())
{
// Input channel size does not match the size of AECM
return AECM_BAD_PARAMETER_ERROR;
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
return -1;
}
if (aecm->initFlag != kInitCheck)
{
return AECM_UNINITIALIZED_ERROR;
aecm->lastError = AECM_UNINITIALIZED_ERROR;
return -1;
}
memcpy(echo_path_ptr, aecm->aecmCore->channelStored, size_bytes);
@ -572,6 +635,17 @@ size_t WebRtcAecm_echo_path_size_bytes()
return (PART_LEN1 * sizeof(int16_t));
}
int32_t WebRtcAecm_get_error_code(void *aecmInst)
{
AecMobile* aecm = aecmInst;
if (aecm == NULL)
{
return -1;
}
return aecm->lastError;
}
static int WebRtcAecm_EstBufDelay(AecMobile* aecm, short msInSndCardBuf) {
short delayNew, nSampSndCard;

View File

@ -42,31 +42,45 @@ extern "C" {
/*
* Allocates the memory needed by the AECM. The memory needs to be
* initialized separately using the WebRtcAecm_Init() function.
* Returns a pointer to the instance and a nullptr at failure.
*
* Inputs Description
* -------------------------------------------------------------------
* void** aecmInst Pointer to the AECM instance to be
* created and initialized
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* -1: error
*/
void* WebRtcAecm_Create();
int32_t WebRtcAecm_Create(void **aecmInst);
/*
* This function releases the memory allocated by WebRtcAecm_Create()
*
* Inputs Description
* Inputs Description
* -------------------------------------------------------------------
* void* aecmInst Pointer to the AECM instance
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* -1: error
*/
void WebRtcAecm_Free(void* aecmInst);
int32_t WebRtcAecm_Free(void *aecmInst);
/*
* Initializes an AECM instance.
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecmInst Pointer to the AECM instance
* void* aecmInst Pointer to the AECM instance
* int32_t sampFreq Sampling frequency of data
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* 1200-12004,12100: error/warning
* int32_t return 0: OK
* -1: error
*/
int32_t WebRtcAecm_Init(void* aecmInst, int32_t sampFreq);
@ -83,30 +97,11 @@ int32_t WebRtcAecm_Init(void* aecmInst, int32_t sampFreq);
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* 1200-12004,12100: error/warning
* -1: error
*/
int32_t WebRtcAecm_BufferFarend(void* aecmInst,
const int16_t* farend,
size_t nrOfSamples);
/*
* Reports any errors that would arise when buffering a farend buffer.
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecmInst Pointer to the AECM instance
* int16_t* farend In buffer containing one frame of
* farend signal
* int16_t nrOfSamples Number of samples in farend buffer
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* 1200-12004,12100: error/warning
*/
int32_t WebRtcAecm_GetBufferFarendError(void* aecmInst,
const int16_t* farend,
size_t nrOfSamples);
int16_t nrOfSamples);
/*
* Runs the AECM on an 80 or 160 sample blocks of data.
@ -131,13 +126,13 @@ int32_t WebRtcAecm_GetBufferFarendError(void* aecmInst,
* -------------------------------------------------------------------
* int16_t* out Out buffer, one frame of processed nearend
* int32_t return 0: OK
* 1200-12004,12100: error/warning
* -1: error
*/
int32_t WebRtcAecm_Process(void* aecmInst,
const int16_t* nearendNoisy,
const int16_t* nearendClean,
int16_t* out,
size_t nrOfSamples,
int16_t nrOfSamples,
int16_t msInSndCardBuf);
/*
@ -152,10 +147,26 @@ int32_t WebRtcAecm_Process(void* aecmInst,
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* 1200-12004,12100: error/warning
* -1: error
*/
int32_t WebRtcAecm_set_config(void* aecmInst, AecmConfig config);
/*
* This function enables the user to set certain parameters on-the-fly
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecmInst Pointer to the AECM instance
*
* Outputs Description
* -------------------------------------------------------------------
* AecmConfig* config Pointer to the config instance that
* all properties will be written to
* int32_t return 0: OK
* -1: error
*/
int32_t WebRtcAecm_get_config(void *aecmInst, AecmConfig *config);
/*
* This function enables the user to set the echo path on-the-fly.
*
@ -168,7 +179,7 @@ int32_t WebRtcAecm_set_config(void* aecmInst, AecmConfig config);
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* 1200-12004,12100: error/warning
* -1: error
*/
int32_t WebRtcAecm_InitEchoPath(void* aecmInst,
const void* echo_path,
@ -187,7 +198,7 @@ int32_t WebRtcAecm_InitEchoPath(void* aecmInst,
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* 1200-12004,12100: error/warning
* -1: error
*/
int32_t WebRtcAecm_GetEchoPath(void* aecmInst,
void* echo_path,
@ -202,6 +213,18 @@ int32_t WebRtcAecm_GetEchoPath(void* aecmInst,
*/
size_t WebRtcAecm_echo_path_size_bytes();
/*
* Gets the last error code.
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecmInst Pointer to the AECM instance
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 11000-11100: error code
*/
int32_t WebRtcAecm_get_error_code(void *aecmInst);
#ifdef __cplusplus
}

View File

@ -67,9 +67,8 @@ EchoCancellationImpl::EchoCancellationImpl(const AudioProcessing* apm,
was_stream_drift_set_(false),
stream_has_echo_(false),
delay_logging_enabled_(false),
extended_filter_enabled_(false),
delay_agnostic_enabled_(false) {
}
delay_correction_enabled_(true), // default to long AEC tail in Mozilla
reported_delay_enabled_(true) {}
EchoCancellationImpl::~EchoCancellationImpl() {}
@ -91,7 +90,7 @@ int EchoCancellationImpl::ProcessRenderAudio(const AudioBuffer* audio) {
err = WebRtcAec_BufferFarend(
my_handle,
audio->split_bands_const_f(j)[kBand0To8kHz],
audio->num_frames_per_band());
static_cast<int16_t>(audio->num_frames_per_band()));
if (err != apm_->kNoError) {
return GetHandleError(my_handle); // TODO(ajm): warning possible?
@ -133,7 +132,7 @@ int EchoCancellationImpl::ProcessCaptureAudio(AudioBuffer* audio) {
audio->split_bands_const_f(i),
audio->num_bands(),
audio->split_bands_f(i),
audio->num_frames_per_band(),
static_cast<int16_t>(audio->num_frames_per_band()),
apm_->stream_delay_ms(),
stream_drift_samples_);
@ -280,14 +279,6 @@ bool EchoCancellationImpl::is_delay_logging_enabled() const {
return delay_logging_enabled_;
}
bool EchoCancellationImpl::is_delay_agnostic_enabled() const {
return delay_agnostic_enabled_;
}
bool EchoCancellationImpl::is_extended_filter_enabled() const {
return extended_filter_enabled_;
}
// TODO(bjornv): How should we handle the multi-channel case?
int EchoCancellationImpl::GetDelayMetrics(int* median, int* std) {
float fraction_poor_delays = 0;
@ -336,13 +327,22 @@ int EchoCancellationImpl::Initialize() {
}
void EchoCancellationImpl::SetExtraOptions(const Config& config) {
extended_filter_enabled_ = config.Get<ExtendedFilter>().enabled;
delay_agnostic_enabled_ = config.Get<DelayAgnostic>().enabled;
#if 0
delay_correction_enabled_ = config.Get<DelayCorrection>().enabled;
#endif
reported_delay_enabled_ = config.Get<ReportedDelay>().enabled;
Configure();
}
void* EchoCancellationImpl::CreateHandle() const {
return WebRtcAec_Create();
Handle* handle = NULL;
if (WebRtcAec_Create(&handle) != apm_->kNoError) {
handle = NULL;
} else {
assert(handle != NULL);
}
return handle;
}
void EchoCancellationImpl::DestroyHandle(void* handle) const {
@ -368,12 +368,10 @@ int EchoCancellationImpl::ConfigureHandle(void* handle) const {
config.skewMode = drift_compensation_enabled_;
config.delay_logging = delay_logging_enabled_;
WebRtcAec_enable_extended_filter(
WebRtcAec_aec_core(static_cast<Handle*>(handle)),
extended_filter_enabled_ ? 1 : 0);
WebRtcAec_enable_delay_agnostic(
WebRtcAec_aec_core(static_cast<Handle*>(handle)),
delay_agnostic_enabled_ ? 1 : 0);
WebRtcAec_enable_delay_correction(WebRtcAec_aec_core(
static_cast<Handle*>(handle)), delay_correction_enabled_ ? 1 : 0);
WebRtcAec_enable_reported_delay(WebRtcAec_aec_core(
static_cast<Handle*>(handle)), reported_delay_enabled_ ? 1 : 0);
return WebRtcAec_set_config(static_cast<Handle*>(handle), config);
}
@ -384,6 +382,6 @@ int EchoCancellationImpl::num_handles_required() const {
int EchoCancellationImpl::GetHandleError(void* handle) const {
assert(handle != NULL);
return AudioProcessing::kUnspecifiedError;
return MapError(WebRtcAec_get_error_code(static_cast<Handle*>(handle)));
}
} // namespace webrtc

View File

@ -32,22 +32,19 @@ class EchoCancellationImpl : public EchoCancellation,
// EchoCancellation implementation.
bool is_enabled() const override;
int stream_drift_samples() const override;
SuppressionLevel suppression_level() const override;
bool is_drift_compensation_enabled() const override;
// ProcessingComponent implementation.
int Initialize() override;
void SetExtraOptions(const Config& config) override;
bool is_delay_agnostic_enabled() const;
bool is_extended_filter_enabled() const;
private:
// EchoCancellation implementation.
int Enable(bool enable) override;
int enable_drift_compensation(bool enable) override;
bool is_drift_compensation_enabled() const override;
void set_stream_drift_samples(int drift) override;
int set_suppression_level(SuppressionLevel level) override;
SuppressionLevel suppression_level() const override;
int enable_metrics(bool enable) override;
bool are_metrics_enabled() const override;
bool stream_has_echo() const override;
@ -77,8 +74,8 @@ class EchoCancellationImpl : public EchoCancellation,
bool was_stream_drift_set_;
bool stream_has_echo_;
bool delay_logging_enabled_;
bool extended_filter_enabled_;
bool delay_agnostic_enabled_;
bool delay_correction_enabled_;
bool reported_delay_enabled_;
};
} // namespace webrtc

View File

@ -40,6 +40,22 @@ int16_t MapSetting(EchoControlMobile::RoutingMode mode) {
return -1;
}
AudioProcessing::Error MapError(int err) {
switch (err) {
case AECM_UNSUPPORTED_FUNCTION_ERROR:
return AudioProcessing::kUnsupportedFunctionError;
case AECM_NULL_POINTER_ERROR:
return AudioProcessing::kNullPointerError;
case AECM_BAD_PARAMETER_ERROR:
return AudioProcessing::kBadParameterError;
case AECM_BAD_PARAMETER_WARNING:
return AudioProcessing::kBadStreamParameterWarning;
default:
// AECM_UNSPECIFIED_ERROR
// AECM_UNINITIALIZED_ERROR
return AudioProcessing::kUnspecifiedError;
}
}
} // namespace
size_t EchoControlMobile::echo_path_size_bytes() {
@ -80,7 +96,7 @@ int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) {
err = WebRtcAecm_BufferFarend(
my_handle,
audio->split_bands_const(j)[kBand0To8kHz],
audio->num_frames_per_band());
static_cast<int16_t>(audio->num_frames_per_band()));
if (err != apm_->kNoError) {
return GetHandleError(my_handle); // TODO(ajm): warning possible?
@ -125,7 +141,7 @@ int EchoControlMobileImpl::ProcessCaptureAudio(AudioBuffer* audio) {
noisy,
clean,
audio->split_bands(i)[kBand0To8kHz],
audio->num_frames_per_band(),
static_cast<int16_t>(audio->num_frames_per_band()),
apm_->stream_delay_ms());
if (err != apm_->kNoError) {
@ -234,7 +250,14 @@ int EchoControlMobileImpl::Initialize() {
}
void* EchoControlMobileImpl::CreateHandle() const {
return WebRtcAecm_Create();
Handle* handle = NULL;
if (WebRtcAecm_Create(&handle) != apm_->kNoError) {
handle = NULL;
} else {
assert(handle != NULL);
}
return handle;
}
void EchoControlMobileImpl::DestroyHandle(void* handle) const {
@ -273,6 +296,6 @@ int EchoControlMobileImpl::num_handles_required() const {
int EchoControlMobileImpl::GetHandleError(void* handle) const {
assert(handle != NULL);
return AudioProcessing::kUnspecifiedError;
return MapError(WebRtcAecm_get_error_code(static_cast<Handle*>(handle)));
}
} // namespace webrtc

View File

@ -37,18 +37,6 @@ class LevelEstimator;
class NoiseSuppression;
class VoiceDetection;
struct ExtendedFilter {
ExtendedFilter() : enabled(false) {}
explicit ExtendedFilter(bool enabled) : enabled(enabled) {}
bool enabled;
};
struct DelayAgnostic {
DelayAgnostic() : enabled(false) {}
explicit DelayAgnostic(bool enabled) : enabled(enabled) {}
bool enabled;
};
// Use to enable the delay correction feature. This now engages an extended
// filter mode in the AEC, along with robustness measures around the reported
// system delays. It comes with a significant increase in AEC complexity, but is

View File

@ -849,10 +849,6 @@ Channel::Channel(int32_t channelId,
Config audioproc_config;
audioproc_config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
audioproc_config.Set<ExtendedFilter>(
new ExtendedFilter(config.Get<ExtendedFilter>().enabled));
audioproc_config.Set<DelayAgnostic>(
new DelayAgnostic(config.Get<DelayAgnostic>().enabled));
rx_audioproc_.reset(AudioProcessing::Create(audioproc_config));
}

View File

@ -46,11 +46,10 @@ ChannelOwner::ChannelRef::ChannelRef(class Channel* channel)
: channel(channel), ref_count(1) {}
ChannelManager::ChannelManager(uint32_t instance_id, const Config& config)
: config_(config),
instance_id_(instance_id),
: instance_id_(instance_id),
last_channel_id_(-1),
lock_(CriticalSectionWrapper::CreateCriticalSection())
{}
lock_(CriticalSectionWrapper::CreateCriticalSection()),
config_(config) {}
ChannelOwner ChannelManager::CreateChannel() {
return CreateChannelInternal(config_);

View File

@ -109,7 +109,6 @@ class ChannelManager {
void DestroyAllChannels();
size_t NumOfChannels() const;
const Config& config_;
private:
// Create a channel given a configuration, |config|.
@ -122,6 +121,8 @@ class ChannelManager {
rtc::scoped_ptr<CriticalSectionWrapper> lock_;
std::vector<ChannelOwner> channels_;
const Config& config_;
DISALLOW_COPY_AND_ASSIGN(ChannelManager);
};
} // namespace voe

View File

@ -424,7 +424,7 @@ int VoEBaseImpl::Init(AudioDeviceModule* external_adm,
}
if (!audioproc) {
audioproc = AudioProcessing::Create(_shared->channel_manager().config_);
audioproc = AudioProcessing::Create();
if (!audioproc) {
LOG(LS_ERROR) << "Failed to create AudioProcessing.";
_shared->SetLastError(VE_NO_MEMORY);

View File

@ -439,12 +439,6 @@ pref("media.getusermedia.noise_enabled", false);
pref("media.getusermedia.aec_enabled", true);
pref("media.getusermedia.noise_enabled", true);
#endif
pref("media.getusermedia.aec_extended_filter", true);
#if defined(ANDROID)
pref("media.getusermedia.aec_delay_agnostic", true);
#else
pref("media.getusermedia.aec_delay_agnostic", false);
#endif
pref("media.getusermedia.noise", 1);
pref("media.getusermedia.agc_enabled", false);
pref("media.getusermedia.agc", 1);