Added calls to set and get external echo channels.
Review URL: http://webrtc-codereview.appspot.com/62005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@196 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
a046202382
commit
c4b939cb61
@ -74,16 +74,14 @@ WebRtc_Word32 WebRtcAecm_Free(void *aecmInst);
|
||||
* -------------------------------------------------------------------
|
||||
* void *aecmInst Pointer to the AECM instance
|
||||
* WebRtc_Word32 sampFreq Sampling frequency of data
|
||||
* WebRtc_Word32 scSampFreq Soundcard sampling frequency
|
||||
*
|
||||
* Outputs Description
|
||||
* -------------------------------------------------------------------
|
||||
* WebRtc_Word32 return 0: OK
|
||||
* WebRtc_Word32 return 0: OK
|
||||
* -1: error
|
||||
*/
|
||||
WebRtc_Word32 WebRtcAecm_Init(void* aecmInst,
|
||||
WebRtc_Word32 sampFreq,
|
||||
WebRtc_Word32 scSampFreq);
|
||||
WebRtc_Word32 sampFreq);
|
||||
|
||||
/*
|
||||
* Inserts an 80 or 160 sample block of data into the farend buffer.
|
||||
@ -170,6 +168,52 @@ WebRtc_Word32 WebRtcAecm_set_config(void* aecmInst,
|
||||
WebRtc_Word32 WebRtcAecm_get_config(void *aecmInst,
|
||||
AecmConfig *config);
|
||||
|
||||
/*
|
||||
* This function enables the user to set the echo path on-the-fly.
|
||||
*
|
||||
* Inputs Description
|
||||
* -------------------------------------------------------------------
|
||||
* void* aecmInst Pointer to the AECM instance
|
||||
* void* echo_path Pointer to the echo path to be set
|
||||
* int size_bytes Size in bytes of the echo path
|
||||
*
|
||||
* Outputs Description
|
||||
* -------------------------------------------------------------------
|
||||
* WebRtc_Word32 return 0: OK
|
||||
* -1: error
|
||||
*/
|
||||
WebRtc_Word32 WebRtcAecm_InitEchoPath(void* aecmInst,
|
||||
const void* echo_path,
|
||||
int size_bytes);
|
||||
|
||||
/*
|
||||
* This function enables the user to get the currently used echo path
|
||||
* on-the-fly
|
||||
*
|
||||
* Inputs Description
|
||||
* -------------------------------------------------------------------
|
||||
* void* aecmInst Pointer to the AECM instance
|
||||
* void* echo_path Pointer to echo path
|
||||
* int size_bytes Size in bytes of the echo path
|
||||
*
|
||||
* Outputs Description
|
||||
* -------------------------------------------------------------------
|
||||
* WebRtc_Word32 return 0: OK
|
||||
* -1: error
|
||||
*/
|
||||
WebRtc_Word32 WebRtcAecm_GetEchoPath(void* aecmInst,
|
||||
void* echo_path,
|
||||
int size_bytes);
|
||||
|
||||
/*
|
||||
* This function enables the user to get the echo path size in bytes
|
||||
*
|
||||
* Outputs Description
|
||||
* -------------------------------------------------------------------
|
||||
* int return : size in bytes
|
||||
*/
|
||||
int WebRtcAecm_echo_path_size_bytes();
|
||||
|
||||
/*
|
||||
* Gets the last error code.
|
||||
*
|
||||
|
@ -253,6 +253,27 @@ int WebRtcAecm_CreateCore(AecmCore_t **aecmInst)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, const WebRtc_Word16* echo_path)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
// Reset the stored channel
|
||||
memcpy(aecm->channelStored, echo_path, sizeof(WebRtc_Word16) * PART_LEN1);
|
||||
// Reset the adapted channels
|
||||
memcpy(aecm->channelAdapt16, echo_path, sizeof(WebRtc_Word16) * PART_LEN1);
|
||||
for (i = 0; i < PART_LEN1; i++)
|
||||
{
|
||||
aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32(
|
||||
(WebRtc_Word32)(aecm->channelAdapt16[i]), 16);
|
||||
}
|
||||
|
||||
// Reset channel storing variables
|
||||
aecm->mseAdaptOld = 1000;
|
||||
aecm->mseStoredOld = 1000;
|
||||
aecm->mseThreshold = WEBRTC_SPL_WORD32_MAX;
|
||||
aecm->mseChannelCount = 0;
|
||||
}
|
||||
|
||||
// WebRtcAecm_InitCore(...)
|
||||
//
|
||||
// This function initializes the AECM instant created with WebRtcAecm_CreateCore(...)
|
||||
@ -329,17 +350,11 @@ int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq)
|
||||
// Initialize the echo channels with a stored shape.
|
||||
if (samplingFreq == 8000)
|
||||
{
|
||||
memcpy(aecm->channelAdapt16, kChannelStored8kHz, sizeof(WebRtc_Word16) * PART_LEN1);
|
||||
WebRtcAecm_InitEchoPathCore(aecm, kChannelStored8kHz);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(aecm->channelAdapt16, kChannelStored16kHz, sizeof(WebRtc_Word16) * PART_LEN1);
|
||||
}
|
||||
memcpy(aecm->channelStored, aecm->channelAdapt16, sizeof(WebRtc_Word16) * PART_LEN1);
|
||||
for (i = 0; i < PART_LEN1; i++)
|
||||
{
|
||||
aecm->channelAdapt32[i] = WEBRTC_SPL_LSHIFT_W32(
|
||||
(WebRtc_Word32)(aecm->channelAdapt16[i]), 16);
|
||||
WebRtcAecm_InitEchoPathCore(aecm, kChannelStored16kHz);
|
||||
}
|
||||
|
||||
memset(aecm->echoFilt, 0, sizeof(WebRtc_Word32) * PART_LEN1);
|
||||
@ -390,10 +405,6 @@ int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq)
|
||||
}
|
||||
#endif
|
||||
|
||||
aecm->mseAdaptOld = 1000;
|
||||
aecm->mseStoredOld = 1000;
|
||||
aecm->mseThreshold = WEBRTC_SPL_WORD32_MAX;
|
||||
|
||||
aecm->farEnergyMin = WEBRTC_SPL_WORD16_MAX;
|
||||
aecm->farEnergyMax = WEBRTC_SPL_WORD16_MIN;
|
||||
aecm->farEnergyMaxMin = 0;
|
||||
@ -410,7 +421,6 @@ int WebRtcAecm_InitCore(AecmCore_t * const aecm, int samplingFreq)
|
||||
memset(aecm->delayCorrelation, 0, sizeof(WebRtc_Word16) * ((CORR_MAX << 1) + 1));
|
||||
|
||||
aecm->startupState = 0;
|
||||
aecm->mseChannelCount = 0;
|
||||
aecm->supGain = SUPGAIN_DEFAULT;
|
||||
aecm->supGainOld = SUPGAIN_DEFAULT;
|
||||
aecm->delayOffsetFlag = 0;
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "typedefs.h"
|
||||
#include "signal_processing_library.h"
|
||||
// TODO(bjornv): Will be removed in final version.
|
||||
//#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Algorithm parameters
|
||||
|
||||
@ -267,6 +267,19 @@ int WebRtcAecm_FreeCore(AecmCore_t *aecm);
|
||||
|
||||
int WebRtcAecm_Control(AecmCore_t *aecm, int delay, int nlpFlag, int delayOffsetFlag);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// WebRtcAecm_InitEchoPathCore(...)
|
||||
//
|
||||
// This function resets the echo channel adaptation with the specified channel.
|
||||
// Input:
|
||||
// - aecm : Pointer to the AECM instance
|
||||
// - echo_path : Pointer to the data that should initialize the echo path
|
||||
//
|
||||
// Output:
|
||||
// - aecm : Initialized instance
|
||||
//
|
||||
void WebRtcAecm_InitEchoPathCore(AecmCore_t* aecm, const WebRtc_Word16* echo_path);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// WebRtcAecm_ProcessFrame(...)
|
||||
//
|
||||
|
@ -159,7 +159,7 @@ WebRtc_Word32 WebRtcAecm_Free(void *aecmInst)
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32 WebRtcAecm_Init(void *aecmInst, WebRtc_Word32 sampFreq, WebRtc_Word32 scSampFreq)
|
||||
WebRtc_Word32 WebRtcAecm_Init(void *aecmInst, WebRtc_Word32 sampFreq)
|
||||
{
|
||||
aecmob_t *aecm = aecmInst;
|
||||
AecmConfig aecConfig;
|
||||
@ -176,13 +176,6 @@ WebRtc_Word32 WebRtcAecm_Init(void *aecmInst, WebRtc_Word32 sampFreq, WebRtc_Wor
|
||||
}
|
||||
aecm->sampFreq = sampFreq;
|
||||
|
||||
if (scSampFreq < 1 || scSampFreq > 96000)
|
||||
{
|
||||
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
|
||||
return -1;
|
||||
}
|
||||
aecm->scSampFreq = scSampFreq;
|
||||
|
||||
// Initialize AECM core
|
||||
if (WebRtcAecm_InitCore(aecm->aecmCore, aecm->sampFreq) == -1)
|
||||
{
|
||||
@ -627,6 +620,68 @@ WebRtc_Word32 WebRtcAecm_get_config(void *aecmInst, AecmConfig *config)
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32 WebRtcAecm_InitEchoPath(void* aecmInst,
|
||||
const void* echo_path,
|
||||
int size_bytes)
|
||||
{
|
||||
aecmob_t *aecm = aecmInst;
|
||||
const WebRtc_Word16* echo_path_ptr = echo_path;
|
||||
|
||||
if ((aecm == NULL) || (echo_path == NULL))
|
||||
{
|
||||
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
|
||||
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
|
||||
return -1;
|
||||
}
|
||||
if (aecm->initFlag != kInitCheck)
|
||||
{
|
||||
aecm->lastError = AECM_UNINITIALIZED_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
WebRtcAecm_InitEchoPathCore(aecm->aecmCore, echo_path_ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WebRtc_Word32 WebRtcAecm_GetEchoPath(void* aecmInst,
|
||||
void* echo_path,
|
||||
int size_bytes)
|
||||
{
|
||||
aecmob_t *aecm = aecmInst;
|
||||
WebRtc_Word16* echo_path_ptr = echo_path;
|
||||
|
||||
if ((aecm == NULL) || (echo_path == NULL))
|
||||
{
|
||||
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
|
||||
aecm->lastError = AECM_BAD_PARAMETER_ERROR;
|
||||
return -1;
|
||||
}
|
||||
if (aecm->initFlag != kInitCheck)
|
||||
{
|
||||
aecm->lastError = AECM_UNINITIALIZED_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(echo_path_ptr, aecm->aecmCore->channelStored, size_bytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WebRtcAecm_echo_path_size_bytes()
|
||||
{
|
||||
return (PART_LEN1 * sizeof(WebRtc_Word16));
|
||||
}
|
||||
|
||||
WebRtc_Word32 WebRtcAecm_get_version(WebRtc_Word8 *versionStr, WebRtc_Word16 len)
|
||||
{
|
||||
const char version[] = "AECM 1.2.0";
|
||||
|
@ -356,6 +356,20 @@ class EchoControlMobile {
|
||||
virtual int enable_comfort_noise(bool enable) = 0;
|
||||
virtual bool is_comfort_noise_enabled() const = 0;
|
||||
|
||||
// A typical use case is to initialize the component with an echo path from a
|
||||
// previous call. The echo path is retrieved using |GetEchoPath()| typically
|
||||
// at the end of a call. The data can then be stored for later use as
|
||||
// initializer, using |SetEchoPath()|.
|
||||
// Controlling the echo path this way requires the data |size_bytes| to match
|
||||
// the internal echo path size. This size can be acquired using
|
||||
// |echo_path_size_bytes()|. |SetEchoPath()| causes an entire reset, worth
|
||||
// noting if it is to be called during an ongoing call. It is possible that
|
||||
// version incompatibilities may result in a stored echo path of the
|
||||
// incorrect size. In this case, the stored path should be discarded.
|
||||
virtual int SetEchoPath(const void* echo_path, int size_bytes) = 0;
|
||||
virtual int GetEchoPath(void* echo_path, int size_bytes) const = 0;
|
||||
virtual const int echo_path_size_bytes() const = 0;
|
||||
|
||||
protected:
|
||||
virtual ~EchoControlMobile() {};
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "echo_control_mobile_impl.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include "critical_section_wrapper.h"
|
||||
#include "echo_control_mobile.h"
|
||||
@ -44,14 +45,15 @@ int 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:
|
||||
// AECMOBFIX_UNSPECIFIED_ERROR
|
||||
// AECMOBFIX_UNINITIALIZED_ERROR
|
||||
// AECMOBFIX_NULL_POINTER_ERROR
|
||||
// AECM_UNSPECIFIED_ERROR
|
||||
// AECM_UNINITIALIZED_ERROR
|
||||
return AudioProcessing::kUnspecifiedError;
|
||||
}
|
||||
}
|
||||
@ -61,9 +63,16 @@ EchoControlMobileImpl::EchoControlMobileImpl(const AudioProcessingImpl* apm)
|
||||
: ProcessingComponent(apm),
|
||||
apm_(apm),
|
||||
routing_mode_(kSpeakerphone),
|
||||
comfort_noise_enabled_(true) {}
|
||||
comfort_noise_enabled_(true),
|
||||
echo_path_size_bytes_(WebRtcAecm_echo_path_size_bytes()),
|
||||
external_echo_path_(NULL) {}
|
||||
|
||||
EchoControlMobileImpl::~EchoControlMobileImpl() {}
|
||||
EchoControlMobileImpl::~EchoControlMobileImpl() {
|
||||
if (external_echo_path_ != NULL) {
|
||||
delete [] external_echo_path_;
|
||||
external_echo_path_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int EchoControlMobileImpl::ProcessRenderAudio(const AudioBuffer* audio) {
|
||||
if (!is_component_enabled()) {
|
||||
@ -181,6 +190,52 @@ bool EchoControlMobileImpl::is_comfort_noise_enabled() const {
|
||||
return comfort_noise_enabled_;
|
||||
}
|
||||
|
||||
int EchoControlMobileImpl::SetEchoPath(const void* echo_path,
|
||||
int size_bytes) {
|
||||
CriticalSectionScoped crit_scoped(*apm_->crit());
|
||||
if (echo_path == NULL) {
|
||||
return apm_->kNullPointerError;
|
||||
}
|
||||
if (size_bytes != echo_path_size_bytes_) {
|
||||
// Size mismatch
|
||||
return apm_->kBadParameterError;
|
||||
}
|
||||
|
||||
if (external_echo_path_ == NULL) {
|
||||
external_echo_path_ = new unsigned char[size_bytes];
|
||||
}
|
||||
memcpy(external_echo_path_, echo_path, size_bytes);
|
||||
|
||||
return Initialize();
|
||||
}
|
||||
|
||||
int EchoControlMobileImpl::GetEchoPath(void* echo_path,
|
||||
int size_bytes) const {
|
||||
CriticalSectionScoped crit_scoped(*apm_->crit());
|
||||
if (echo_path == NULL) {
|
||||
return apm_->kNullPointerError;
|
||||
}
|
||||
if (size_bytes != echo_path_size_bytes_) {
|
||||
// Size mismatch
|
||||
return apm_->kBadParameterError;
|
||||
}
|
||||
if (!is_component_enabled()) {
|
||||
return apm_->kNotEnabledError;
|
||||
}
|
||||
|
||||
// Get the echo path from the first channel
|
||||
Handle* my_handle = static_cast<Handle*>(handle(0));
|
||||
if (WebRtcAecm_GetEchoPath(my_handle, echo_path, size_bytes) != 0) {
|
||||
return GetHandleError(my_handle);
|
||||
}
|
||||
|
||||
return apm_->kNoError;
|
||||
}
|
||||
|
||||
const int EchoControlMobileImpl::echo_path_size_bytes() const {
|
||||
return echo_path_size_bytes_;
|
||||
}
|
||||
|
||||
int EchoControlMobileImpl::Initialize() {
|
||||
if (!is_component_enabled()) {
|
||||
return apm_->kNoError;
|
||||
@ -197,7 +252,7 @@ int EchoControlMobileImpl::Initialize() {
|
||||
int EchoControlMobileImpl::get_version(char* version,
|
||||
int version_len_bytes) const {
|
||||
if (WebRtcAecm_get_version(version, version_len_bytes) != 0) {
|
||||
return apm_->kBadParameterError;
|
||||
return apm_->kBadParameterError;
|
||||
}
|
||||
|
||||
return apm_->kNoError;
|
||||
@ -219,10 +274,20 @@ int EchoControlMobileImpl::DestroyHandle(void* handle) const {
|
||||
}
|
||||
|
||||
int EchoControlMobileImpl::InitializeHandle(void* handle) const {
|
||||
return WebRtcAecm_Init(static_cast<Handle*>(handle),
|
||||
apm_->sample_rate_hz(),
|
||||
48000); // Dummy value. This isn't actually
|
||||
// required by AECM.
|
||||
assert(handle != NULL);
|
||||
Handle* my_handle = static_cast<Handle*>(handle);
|
||||
if (WebRtcAecm_Init(my_handle, apm_->sample_rate_hz()) != 0) {
|
||||
return GetHandleError(my_handle);
|
||||
}
|
||||
if (external_echo_path_ != NULL) {
|
||||
if (WebRtcAecm_InitEchoPath(my_handle,
|
||||
external_echo_path_,
|
||||
echo_path_size_bytes_) != 0) {
|
||||
return GetHandleError(my_handle);
|
||||
}
|
||||
}
|
||||
|
||||
return apm_->kNoError;
|
||||
}
|
||||
|
||||
int EchoControlMobileImpl::ConfigureHandle(void* handle) const {
|
||||
|
@ -41,6 +41,9 @@ class EchoControlMobileImpl : public EchoControlMobile,
|
||||
virtual RoutingMode routing_mode() const;
|
||||
virtual int enable_comfort_noise(bool enable);
|
||||
virtual bool is_comfort_noise_enabled() const;
|
||||
virtual int SetEchoPath(const void* echo_path, int size_bytes);
|
||||
virtual int GetEchoPath(void* echo_path, int size_bytes) const;
|
||||
virtual const int echo_path_size_bytes() const;
|
||||
|
||||
// ProcessingComponent implementation.
|
||||
virtual void* CreateHandle() const;
|
||||
@ -53,6 +56,8 @@ class EchoControlMobileImpl : public EchoControlMobile,
|
||||
const AudioProcessingImpl* apm_;
|
||||
RoutingMode routing_mode_;
|
||||
bool comfort_noise_enabled_;
|
||||
const int echo_path_size_bytes_;
|
||||
unsigned char* external_echo_path_;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
|
@ -56,6 +56,8 @@ void usage() {
|
||||
printf(" --drift_compensation\n");
|
||||
printf(" --no_drift_compensation\n");
|
||||
printf("\n -aecm Echo control mobile\n");
|
||||
printf(" --aecm_echo_path_in_file FILE");
|
||||
printf(" --aecm_echo_path_out_file FILE");
|
||||
printf("\n -agc Gain control\n");
|
||||
printf(" --analog\n");
|
||||
printf(" --adaptive_digital\n");
|
||||
@ -103,6 +105,8 @@ void void_main(int argc, char* argv[]) {
|
||||
const char* near_filename = NULL;
|
||||
const char* out_filename = NULL;
|
||||
const char* vad_out_filename = NULL;
|
||||
const char* aecm_echo_path_in_filename = NULL;
|
||||
const char* aecm_echo_path_out_filename = NULL;
|
||||
|
||||
int32_t sample_rate_hz = 16000;
|
||||
int32_t device_sample_rate_hz = 16000;
|
||||
@ -185,6 +189,16 @@ void void_main(int argc, char* argv[]) {
|
||||
} else if (strcmp(argv[i], "-aecm") == 0) {
|
||||
ASSERT_EQ(apm->kNoError, apm->echo_control_mobile()->Enable(true));
|
||||
|
||||
} else if (strcmp(argv[i], "--aecm_echo_path_in_file") == 0) {
|
||||
i++;
|
||||
ASSERT_LT(i, argc) << "Specify filename after --aecm_echo_path_in_file";
|
||||
aecm_echo_path_in_filename = argv[i];
|
||||
|
||||
} else if (strcmp(argv[i], "--aecm_echo_path_out_file") == 0) {
|
||||
i++;
|
||||
ASSERT_LT(i, argc) << "Specify filename after --aecm_echo_path_out_file";
|
||||
aecm_echo_path_out_filename = argv[i];
|
||||
|
||||
} else if (strcmp(argv[i], "-agc") == 0) {
|
||||
ASSERT_EQ(apm->kNoError, apm->gain_control()->Enable(true));
|
||||
|
||||
@ -323,6 +337,8 @@ void void_main(int argc, char* argv[]) {
|
||||
FILE* delay_file = NULL;
|
||||
FILE* drift_file = NULL;
|
||||
FILE* vad_out_file = NULL;
|
||||
FILE* aecm_echo_path_in_file = NULL;
|
||||
FILE* aecm_echo_path_out_file = NULL;
|
||||
|
||||
if (far_filename != NULL) {
|
||||
far_file = fopen(far_filename, "rb");
|
||||
@ -361,6 +377,30 @@ void void_main(int argc, char* argv[]) {
|
||||
<< vad_out_file;
|
||||
}
|
||||
|
||||
if (aecm_echo_path_in_filename != NULL) {
|
||||
aecm_echo_path_in_file = fopen(aecm_echo_path_in_filename, "rb");
|
||||
ASSERT_TRUE(NULL != aecm_echo_path_in_file) << "Unable to open file "
|
||||
<< aecm_echo_path_in_filename;
|
||||
|
||||
const int path_size = apm->echo_control_mobile()->echo_path_size_bytes();
|
||||
unsigned char echo_path[path_size];
|
||||
ASSERT_EQ(path_size, fread(echo_path,
|
||||
sizeof(unsigned char),
|
||||
path_size,
|
||||
aecm_echo_path_in_file));
|
||||
EXPECT_EQ(apm->kNoError,
|
||||
apm->echo_control_mobile()->SetEchoPath(echo_path, path_size));
|
||||
fclose(aecm_echo_path_in_file);
|
||||
aecm_echo_path_in_file = NULL;
|
||||
}
|
||||
|
||||
if (aecm_echo_path_out_filename != NULL) {
|
||||
aecm_echo_path_out_file = fopen(aecm_echo_path_out_filename, "wb");
|
||||
ASSERT_TRUE(NULL != aecm_echo_path_out_file) << "Unable to open file "
|
||||
<< aecm_echo_path_out_filename;
|
||||
|
||||
}
|
||||
|
||||
enum Events {
|
||||
kInitializeEvent,
|
||||
kRenderEvent,
|
||||
@ -579,6 +619,18 @@ void void_main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
if (aecm_echo_path_out_file != NULL) {
|
||||
const int path_size = apm->echo_control_mobile()->echo_path_size_bytes();
|
||||
unsigned char echo_path[path_size];
|
||||
apm->echo_control_mobile()->GetEchoPath(echo_path, path_size);
|
||||
ASSERT_EQ(path_size, fwrite(echo_path,
|
||||
sizeof(unsigned char),
|
||||
path_size,
|
||||
aecm_echo_path_out_file));
|
||||
fclose(aecm_echo_path_out_file);
|
||||
aecm_echo_path_out_file = NULL;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("\nProcessed frames: %d (primary), %d (reverse)\n",
|
||||
primary_count, reverse_count);
|
||||
|
@ -638,6 +638,31 @@ TEST_F(ApmTest, EchoControlMobile) {
|
||||
EXPECT_EQ(apm_->kNoError,
|
||||
apm_->echo_control_mobile()->enable_comfort_noise(true));
|
||||
EXPECT_TRUE(apm_->echo_control_mobile()->is_comfort_noise_enabled());
|
||||
// Set and get echo path
|
||||
const int echo_path_size = apm_->echo_control_mobile()->echo_path_size_bytes();
|
||||
unsigned char echo_path_in[echo_path_size];
|
||||
unsigned char echo_path_out[echo_path_size];
|
||||
EXPECT_EQ(apm_->kNullPointerError,
|
||||
apm_->echo_control_mobile()->SetEchoPath(NULL, echo_path_size));
|
||||
EXPECT_EQ(apm_->kNullPointerError,
|
||||
apm_->echo_control_mobile()->GetEchoPath(NULL, echo_path_size));
|
||||
EXPECT_EQ(apm_->kBadParameterError,
|
||||
apm_->echo_control_mobile()->GetEchoPath(echo_path_out, 1));
|
||||
EXPECT_EQ(apm_->kNoError,
|
||||
apm_->echo_control_mobile()->GetEchoPath(echo_path_out,
|
||||
echo_path_size));
|
||||
for (int i = 0; i < echo_path_size; i++) {
|
||||
echo_path_in[i] = echo_path_out[i] + 1;
|
||||
}
|
||||
EXPECT_EQ(apm_->kBadParameterError,
|
||||
apm_->echo_control_mobile()->SetEchoPath(echo_path_in, 1));
|
||||
EXPECT_EQ(apm_->kNoError,
|
||||
apm_->echo_control_mobile()->SetEchoPath(echo_path_in, echo_path_size));
|
||||
EXPECT_EQ(apm_->kNoError,
|
||||
apm_->echo_control_mobile()->GetEchoPath(echo_path_out, echo_path_size));
|
||||
for (int i = 0; i < echo_path_size; i++) {
|
||||
EXPECT_EQ(echo_path_in[i], echo_path_out[i]);
|
||||
}
|
||||
// Turn AECM off
|
||||
EXPECT_EQ(apm_->kNoError, apm_->echo_control_mobile()->Enable(false));
|
||||
EXPECT_FALSE(apm_->echo_control_mobile()->is_enabled());
|
||||
|
Loading…
Reference in New Issue
Block a user