在Android源码路径"external\webrtc"集成了webRTC的相关源码,而需要在音频hal层做相关3A处理的时候,我们就可直接对其进行封装调用,具体的音频3A处理模块为"external\webrtc\webrtc\modules\audio_processing",其中声学处理模块为:WebRTC Audio Processing 模块的 Acoustic Echo Cancelling(AEC)主要使用在PC端、Acoustic Echo Cancelling Mobile(AECM)因为暂用资源少主要以移动端设备使用较多、Automatic Gain Control(AGC)、Active Noise Control(ANC,也被称为noise cancellation、noise suppression)
1 、封装接口包括四个部分:AEC、AECM(针对移动设备的回声处理模块)、NS和AGC,每个模块都包含init模块、process模块和deinit模块;
aec_nsx_agc_preprocess.c实现如下:
可用版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cutils/log.h>
#define LOG_TAG "aec_nsx_agc_preprocess"
#include "aec_nsx_agc_preprocess.h"
#define FRAME_VALUE 160
#define NUM_BANDS NULL
#define NSX_MODE 0
enum {
WEBRTC_OK = 0,
WEBRTC_PARA_INV,
AEC_INIT_FAIL,
AEC_PROC_FAIL,
AGC_INIT_FAIL,
AGC_PROC_FAIL,
NSX_INIT_FAIL,
NSX_PROC_FAIL,
};
void *aec_inst = NULL;
void *ns_inst = NULL;
void *agc_inst = NULL;
int32_t webrtc_aec_init(int32_t samp_freq, int32_t scsamp_freq)
{
int32_t ret;
//创建webRtc aec模块
aec_inst = WebRtcAec_Create();
if (aec_inst == NULL)
{
ALOGE("Failed to create the AEC module!");
return -AEC_INIT_FAIL;//创建失败退出
}
ret = WebRtcAec_Init(aec_inst, samp_freq, scsamp_freq);
if (ret != 0)
{
WebRtcAec_Free(aec_inst); //初始化失败则释放Aec模块
ALOGE("The AEC module failed to be initialized!");
return -AEC_INIT_FAIL;
}
//WebRtcAec_enable_extended_filter(aec_inst, 1);
WebRtcAec_enable_delay_agnostic(aec_inst, 1);//开启延迟估计获取
AecConfig config;
config.skewMode = kAecFalse;
config.metricsMode = kAecFalse;
config.delay_logging = kAecFalse;
config.nlpMode = kAecNlpAggressive; //Aec模块参数配置
ret = WebRtcAec_set_config(aec_inst, config );
if (ret != 0)
{
WebRtcAec_Free(aec_inst); //初始化失败则释放Aec模块
ALOGE("Failed to configure AEC parameters!");
return -AEC_INIT_FAIL;
}
return WEBRTC_OK;
}
int32_t webrtc_aec_bufferFarend(int nDataLen, void *szData)
{
short *sPointer = (short *)szData;
float m_sFar_frame[80];
memset(m_sFar_frame, 0x00, sizeof(float)*80);
int i = 0;
for (i = 0; (i * 2) < nDataLen; i++)
{
m_sFar_frame[i] = *(sPointer + i);
}
const float* ptr = m_sFar_frame;
int nRet = WebRtcAec_BufferFarend(aec_inst, ptr, 80);
if(nRet != 0){
WebRtcAec_Free(aec_inst); //参考音频加载失败则释放Aec模块
ALOGE("Failed to load the reference audio!");
return -AEC_PROC_FAIL;
}
return WEBRTC_OK;
}
int32_t webrtc_aec_pro( int nDataLen, void *szInData, void *szOutData)
{
short *sInPointer = (short *)szInData;
short *sOutPointer= (short *)szOutData;
float m_sOutNear_frame[80];
float m_sInNear_frame[80];
memset(m_sInNear_frame, 0x00, sizeof(float) * 80);
memset(m_sOutNear_frame, 0x00, sizeof(float) * 80);
int i = 0;
for (i = 0; (i * 2) < nDataLen; i++)
{
m_sInNear_frame[i] = *(sInPointer + i);
}
const float* const p = m_sInNear_frame;
const float* const* ptr = &p;
float* const q = m_sOutNear_frame;
float* const* ptr2 = &q;
int ret = WebRtcAec_Process(aec_inst, ptr, 1, ptr2, 80, 0, 0);
if(ret != 0){
WebRtcAec_Free(aec_inst); //回声消除失败则释放Aec模块
ALOGE("The AEC processing module failed. Procedure!");
return -AEC_PROC_FAIL;
}
for (i = 0; (i * 2) < nDataLen; i++)
{
*(sOutPointer + i) = (short)m_sOutNear_frame[i];
}
return WEBRTC_OK;
}
int32_t webrtc_aec_deinit() //释放回声消除模块
{
if(aec_inst != NULL){
WebRtcAec_Free(aec_inst);
aec_inst = NULL;
}
return WEBRTC_OK;
}
int32_t webrtc_nsx_init(int32_t samp_freq)
{
int32_t ret;
ns_inst = WebRtcNs_Create();
if(ns_inst==NULL){
ALOGE("Failed to create the ANS module!");
return -NSX_INIT_FAIL;
}
ret = WebRtcNs_Init(ns_inst, samp_freq/2);
if (ret != 0)
{
WebRtcNs_Free(ns_inst);
ALOGE("Failed to initialize the ANS module!");
return -NSX_INIT_FAIL;
}
ret = WebRtcNs_set_policy(ns_inst,3);
if (ret != 0)
{
WebRtcNs_Free(ns_inst);
ALOGE("Failed to configure the parameters of the ANS module!");
return -NSX_INIT_FAIL;
}
return WEBRTC_OK;
}
int32_t webrtc_nsx_process(void *in_buf, void *out_buf)
{
short *sInPointer = (short *)in_buf;
short *sOutPointer= (short *)out_buf;
float m_sOutNear_frame[80];
float m_sInNear_frame[80];
int i = 0;
memset(m_sInNear_frame, 0, sizeof(float) * 80);
memset(m_sOutNear_frame, 0, sizeof(float) * 80);
for (i = 0; (i * 2) < 160; i++)
{
m_sInNear_frame[i] = *(sInPointer + i);
}
WebRtcNs_Analyze(ns_inst,(const float*)m_sInNear_frame);//降噪参考数据读取
const float* const p = m_sInNear_frame;
const float* const* ptr = &p;
float* const q = m_sOutNear_frame;
float* const* ptr2 = &q;
WebRtcNs_Process(ns_inst, ptr, 0, ptr2); //做音频降噪处理,无返回值
for (i = 0; (i * 2) < 160; i++)
{
*(sOutPointer + i) = (float)m_sOutNear_frame[i];
}
return WEBRTC_OK;
}
int32_t webrtc_nsx_deinit()
{
if(ns_inst != NULL){
WebRtcNs_Free(ns_inst);
ns_inst = NULL;
}
return WEBRTC_OK;
}
int32_t webrtc_agc_init(uint32_t fs)
{
int32_t ret;
agc_inst = WebRtcAgc_Create();
int minLevel = 0;
int maxLevel = 255;
int agcMode = 3;
ret = WebRtcAgc_Init(agc_inst, minLevel, maxLevel, agcMode, fs);
if (ret != 0)
{
WebRtcAgc_Free(agc_inst);
ALOGE("Failed to initial the AGC!");
return -AGC_INIT_FAIL;
}
/*WebRtcAgcConfig agcConfig;
agcConfig.compressionGaindB = 9;
agcConfig.limiterEnable = ;
agcConfig.targetLevelDbfs = 3;
ret = WebRtcAgc_set_config(agc_inst, agcConfig);
if (ret != 0)
{
WebRtcAgc_Free(agc_inst);
ALOGE("Failed to config the AGC!");
return -AGC_INIT_FAIL;
}*/
return WEBRTC_OK;
}
int32_t webrtc_agc_process(void *in_near, void *out)
{
int32_t ret;
int16_t *input = in_near;
int16_t *output = out;
int inMicLevel = 0;
int outMicLevel = 0;
uint8_t saturationWarning;
ret = WebRtcAgc_Process(agc_inst, (const int16_t *const *)&input, 1, FRAME_VALUE, (int16_t *const *)&output,inMicLevel, &outMicLevel, 1, &saturationWarning);
if (ret != 0)
{
WebRtcAgc_Free(agc_inst);
ALOGE("Failed to process the AGC!");
return -AGC_PROC_FAIL;
}
//memcpy(input, out_buffer, samples * sizeof(int16_t));
return WEBRTC_OK;
}
int32_t webrtc_agc_deinit()
{
if(agc_inst != NULL){
WebRtcAgc_Free(agc_inst);
agc_inst = NULL;
}
return 0;
}
调试版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cutils/log.h>
#include "aec_nsx_agc_preprocess.h"
#define FRAME_VALUE 160
#define NUM_BANDS NULL
#define NSX_MODE 0
enum {
WEBRTC_OK = 0,
WEBRTC_PARA_INV,
AEC_INIT_FAIL,
AEC_PROC_FAIL,
AGC_INIT_FAIL,
AGC_PROC_FAIL,
NSX_INIT_FAIL,
NSX_PROC_FAIL,
};
void* state_;
int32_t webrtc_resample48khzTo16khz(short *PcmIn,int pcmLen,short *out_16k)
{
int tmp_buff_size = 4096;
int32_t *tmp_buff = (int32_t*)calloc(tmp_buff_size, sizeof(int32_t));
state_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
if(pcmLen){
WebRtcSpl_ResetResample48khzTo16khz(state_);
WebRtcSpl_Resample48khzTo16khz(PcmIn,out_16k,(WebRtcSpl_State48khzTo16khz*)state_,tmp_buff);
}
return WEBRTC_OK;
}
void *aec_inst = NULL;
int32_t webrtc_aec_init(int32_t samp_freq, int32_t scsamp_freq)
{
int32_t ret;
aec_inst = WebRtcAec_Create();
if (aec_inst == 0)
{
ALOGE("WebRtcAec_Create AEC_INIT_FAIL!!!");
return -AEC_INIT_FAIL;
}
ret = WebRtcAec_Init(aec_inst, samp_freq, scsamp_freq);
if (ret != 0)
{
ALOGE("WebRtcAec_Init AEC_INIT_FAIL!!!");
return -AEC_INIT_FAIL;
}
AecConfig config;
config.skewMode = kAecFalse;
config.metricsMode = kAecFalse;
config.delay_logging = kAecFalse;
config.nlpMode = kAecNlpModerate;
ret = WebRtcAec_set_config( aec_inst, config );
ALOGE("WebRtcAec_set_config webrtc_aec_init ret:%d!!!",ret);
return WEBRTC_OK;
}
int32_t webrtc_aec_process(short *near_buf, short *far_buf, short *out_buf, int32_t delay_ms)
{
int32_t ret;
if (aec_inst == NULL || near_buf == NULL
|| far_buf == NULL || out_buf == NULL)
{
return -WEBRTC_PARA_INV;
}
ret = WebRtcAec_BufferFarend(aec_inst, (const float*)far_buf, 160);
ALOGE("WebRtcAec_BufferFarend webrtc_aec_process ret:%d!!!",ret);
if (ret > 0)
{
ALOGE("WebRtcAec_BufferFarend webrtc_aec_process error!!!");
return -AEC_PROC_FAIL;
}
int16_t *input = near_buf;
int16_t *output = out_buf;
ret = WebRtcAec_Process(aec_inst, (const float* const*)&input, 1, (float* const*)&output, 160, 0, 0);
ALOGE("WebRtcAec_Process webrtc_aec_process ret:%d!!!",ret);
if (ret < 0)
{
ALOGE("WebRtcAec_Process webrtc_aec_process!!!");
return -AEC_PROC_FAIL;
}
return WEBRTC_OK;
}
int32_t webrtc_aec_deinit()
{
WebRtcAec_Free(aec_inst);
return 0;
}
void *aecm_inst = NULL;
int32_t webrtc_aecm_init(int32_t samp_freq)
{
int32_t ret;
aecm_inst = WebRtcAecm_Create();
if (aecm_inst == 0)
{
ALOGE("WebRtcAec_Create AEC_INIT_FAIL!!!");
return -AEC_INIT_FAIL;
}
ret = WebRtcAecm_Init(aecm_inst, samp_freq);
if (ret != 0)
{
ALOGE("WebRtcAec_Init AEC_INIT_FAIL!!!");
return -AEC_INIT_FAIL;
}
AecmConfig Config;
Config.cngMode = AecmTrue;
Config.echoMode = 4;
WebRtcAecm_set_config(aecm_inst,Config);
return WEBRTC_OK;
}
int32_t webrtc_aecm_process(short *near_buf, short *far_buf, short *out_buf, int32_t delay_ms)
{
int32_t ret;
if (aecm_inst == NULL || near_buf == NULL
|| far_buf == NULL || out_buf == NULL)
{
return -WEBRTC_PARA_INV;
}
ret = WebRtcAecm_BufferFarend(aecm_inst, far_buf, 160);
ALOGE("WebRtcAec_BufferFarend webrtc_aec_process ret:%d!!!",ret);
if (ret > 0)
{
ALOGE("WebRtcAec_BufferFarend webrtc_aec_process error!!!");
return -AEC_PROC_FAIL;
}
ret = WebRtcAecm_Process(aecm_inst, near_buf, NULL, out_buf, 160, delay_ms);
ALOGE("WebRtcAec_Process webrtc_aec_process ret:%d!!!",ret);
if (ret < 0)
{
ALOGE("WebRtcAec_Process webrtc_aec_process!!!");
return -AEC_PROC_FAIL;
}
return WEBRTC_OK;
}
int32_t webrtc_aecm_deinit()
{
WebRtcAecm_Free(aecm_inst);
return 0;
}
NsxHandle *ns_inst = NULL;
int32_t webrtc_nsx_init(int32_t samp_freq)
{
int32_t ret;
ns_inst = WebRtcNsx_Create();
ret = WebRtcNsx_Init(ns_inst, (uint32_t)samp_freq);
if (ret < 0)
{
ALOGE("WebRtcNsx_Init AEC_INIT_FAIL!!!");
return -NSX_INIT_FAIL;
}
ret = WebRtcNsx_set_policy(ns_inst,3);
if (ret < 0)
{
ALOGE("WebRtcNsx_set_policy AEC_INIT_FAIL!!!");
return -NSX_INIT_FAIL;
}
return WEBRTC_OK;
}
int32_t webrtc_nsx_process(short *in_buf, short *out_buf)
{
int32_t ret;
int *input = in_buf;
int *output = out_buf;
WebRtcNsx_Process(ns_inst, (const short* const*)&input, 1, (short* const*)&output);
return WEBRTC_OK;
}
int32_t webrtc_nsx_deinit()
{
WebRtcNsx_Free(ns_inst);
return 0;
}
/*void *ns_inst = NULL;
int32_t webrtc_ns_init(int32_t samp_freq)
{
int32_t ret;
ns_inst = WebRtcNs_Create();
ret = WebRtcNs_Init(ns_inst, samp_freq);
if (ret != 0)
{
ALOGE("WebRtcNsx_Init AEC_INIT_FAIL!!!");
//return -NSX_INIT_FAIL;
}
ret = WebRtcNs_set_policy(ns_inst,2);
if (ret < 0)
{
ALOGE("WebRtcNsx_set_policy AEC_INIT_FAIL!!!");
//return -NSX_INIT_FAIL;
}
return WEBRTC_OK;
}
int32_t webrtc_ns_process(short *in_buf, short *out_buf)
{
int32_t ret;
WebRtcNs_Analyze(ns_inst,in_buf);
int32_t *input = in_buf;
int32_t *output = out_buf;
WebRtcNs_Process(ns_inst, (const float* const*)&input, 0, (float* const*)&output);
return WEBRTC_OK;
}
int32_t webrtc_ns_deinit()
{
WebRtcNs_Free(ns_inst);
return 0;
}*/
void *agc_inst = NULL;
int32_t webrtc_agc_init(uint32_t fs)
{
int32_t ret;
agc_inst = WebRtcAgc_Create();
int minLevel = 0;
int maxLevel = 255;
int agcMode = 3;
ret = WebRtcAgc_Init(agc_inst, minLevel, maxLevel, agcMode, fs);
if (ret < 0)
{
ALOGE("WebRtcAgc_Init AEC_INIT_FAIL!!!");
//return -AGC_INIT_FAIL;
}
WebRtcAgcConfig agcConfig;
agcConfig.compressionGaindB = 9;
agcConfig.limiterEnable = 1;
agcConfig.targetLevelDbfs = 3;
ret = WebRtcAgc_set_config(agc_inst, agcConfig);
if (ret < 0)
{
//return -AGC_INIT_FAIL;
}
return WEBRTC_OK;
}
//int micLevelIn = 0;
int micLevelOut;
int32_t webrtc_agc_process(const int16_t *in_near, int16_t *out)
{
int32_t ret;
if (agc_inst == NULL || in_near == NULL|| out == NULL)
{
return -WEBRTC_PARA_INV;
}
int *input = in_near;
int *output = out;
int inMicLevel = 500;
int outMicLevel = 50000;
uint8_t saturationWarning;
ret = WebRtcAgc_Process(agc_inst, (const int16_t *const *)&input, 1, FRAME_VALUE, (int16_t *const *)&output,inMicLevel, &outMicLevel, 0, &saturationWarning);
if (ret != 0)
{
ALOGE("webrtc_agc_process WebRtcAgc_Process ret == %d ",ret);
//return -AGC_PROC_FAIL;
}
//memcpy(input, out_buffer, samples * sizeof(int16_t));
return WEBRTC_OK;
}
/*int32_t webrtc_agc_config(void *agc_inst, WebRtcAgc_config_t agcConfig)
{
int32_t ret;
ret = WebRtcAgc_set_config(agc_inst, agcConfig);
if (ret < 0)
{
return -AGC_INIT_FAIL;
}
return WEBRTC_OK;
}*/
int32_t webrtc_agc_deinit()
{
WebRtcAgc_Free(agc_inst);
return 0;
}
aec_nsx_agc_preprocess.h实现如下:
可用版本:
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef AEC_NSX_AGC_PREPROCESS_H_
#define AEC_NSX_AGC_PREPROCESS_H_
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <cutils/log.h>
#include "webrtc/modules/audio_processing/agc/legacy/gain_control.h"
#include "webrtc/modules/audio_processing/aec/echo_cancellation.h"
#include "webrtc/modules/audio_processing/ns/noise_suppression.h"
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#include "webrtc/modules/audio_processing/aec/aec_core.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Initializes an AEC instance.
*
* Inputs Description
* -------------------------------------------------------------------
* int32_t samp_freq Sampling frequency of data
* int32_t scsamp_freq Soundcard sampling frequency
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* -2: error
*/
int32_t webrtc_aec_init(int32_t samp_freq, int32_t scsamp_freq);
/*
* Loading the reference audio.
*
* Inputs Description
* -------------------------------------------------------------------
* int nDataLen Size of the reference audio data
* short * szData The reference audio data
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* -3: error
*/
int32_t webrtc_aec_bufferFarend(int nDataLen, short *szData);
/*
* Loading the processing audio.
*
* Inputs Description
* -------------------------------------------------------------------
* int nDataLen Size of the processing data
* short * szInData The processing data
* short * szOutData Audio data output after processing
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* -3: error
*/
int32_t webrtc_aec_pro(int nDataLen, short *szInData, short *szOutData);
/*
* Initializes an AEC instance.
*
* Inputs Description
* -------------------------------------------------------------------
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
*/
int32_t webrtc_aec_deinit();
/*
* Initializes an ANS instance.
*
* Inputs Description
* -------------------------------------------------------------------
* int32_t samp_freq Sampling frequency of data
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* -4: error
*/
int32_t webrtc_nsx_init(int32_t samp_freq);
/*
* Loading the processing audio.
*
* Inputs Description
* -------------------------------------------------------------------
* short * in_buf The processing data
* short * out_buf Audio data output after processing
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* -5: error
*/
int32_t webrtc_nsx_process(short *in_buf, short *out_buf);
/*
* Initializes an ANS instance.
*
* Inputs Description
* -------------------------------------------------------------------
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
*/
int32_t webrtc_nsx_deinit();
/*
* Initializes an AGC instance.
*
* Inputs Description
* -------------------------------------------------------------------
* int32_t samp_freq Sampling frequency of data
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* -6: error
*/
int32_t webrtc_agc_init(uint32_t fs);
/*
* Loading the processing audio.
*
* Inputs Description
* -------------------------------------------------------------------
* short * in_buf The processing data
* short * out_buf Audio data output after processing
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* -7: error
*/
int32_t webrtc_agc_process(const int16_t *in_near, int16_t *out);
/*
* Release an AGC instance.
*
* Inputs Description
* -------------------------------------------------------------------
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
*/
int32_t webrtc_agc_deinit();
#ifdef __cplusplus
}
#endif
#endif // AEC_NSX_AGC_PREPROCESS_H_
调试版本:
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef AEC_NSX_AGC_PREPROCESS_H_
#define AEC_NSX_AGC_PREPROCESS_H_
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <cutils/log.h>
// Errors
//#include "webrtc/modules/audio_processing/aecm/echo_control_mobile.h"
//#include "webrtc/modules/audio_processing/agc/legacy/gain_control.h"
//#include "webrtc/modules/audio_processing/ns/noise_suppression_x.h"
//#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#include "webrtc/modules/audio_processing/aec/echo_cancellation.h"
#include "webrtc/modules/audio_processing/aecm/echo_control_mobile.h"
#include "webrtc/modules/audio_processing/agc/legacy/gain_control.h"
#include "webrtc/modules/audio_processing/ns/noise_suppression_x.h"
#include "webrtc/modules/audio_processing/ns/noise_suppression.h"
#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* 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.
*/
int32_t webrtc_aecm_init(int32_t samp_freq);
int32_t webrtc_aec_init(int32_t samp_freq, int32_t scsamp_freq);
/*
* This function releases the memory allocated by WebRtcAec_Create().
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecInst Pointer to the AEC instance
*/
int32_t webrtc_aecm_process(short *near_buf, short *far_buf, short *out_buf, int32_t delay_ms);
int32_t webrtc_aec_process(short *near_buf, short *far_buf, short *out_buf, int32_t delay_ms);
/*
* Initializes an AEC instance.
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecInst Pointer to the AEC instance
* int32_t sampFreq Sampling frequency of data
* int32_t scSampFreq Soundcard sampling frequency
*
* Outputs Description
* -------------------------------------------------------------------
* int32_t return 0: OK
* -1: error
*/
int32_t webrtc_aecm_deinit();
int32_t webrtc_aec_deinit();
/*
* 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 webrtc_nsx_init(int32_t samp_freq);
/*
* Runs the echo canceller on an 80 or 160 sample blocks of data.
*
* Inputs Description
* -------------------------------------------------------------------
* void* aecInst Pointer to the AEC instance
* float* const* nearend In buffer containing one frame of
* nearend+echo signal for each band
* int num_bands Number of bands in nearend buffer
* int16_t nrOfSamples Number of samples in nearend buffer
* int16_t msInSndCardBuf Delay estimate for sound card and
* system buffers
* int16_t skew Difference between number of samples played
* and recorded at the soundcard (for clock skew
* compensation)
*
* Outputs Description
* -------------------------------------------------------------------
* float* const* out Out buffer, one frame of processed nearend
* for each band
* int32_t return 0: OK
* 12000-12050: error code
*/
int32_t webrtc_nsx_process(short *in_buf, short *out_buf);
/*
* This function enables the user to set certain parameters on-the-fly.
*
* Inputs Description
* -------------------------------------------------------------------
* void* handle Pointer to the AEC instance
* AecConfig config Config instance that contains all
* properties to be set
*
* Outputs Description
* -------------------------------------------------------------------
* int return 0: OK
* 12000-12050: error code
*/
int32_t webrtc_nsx_deinit();
int32_t webrtc_agc_init(uint32_t fs);
/*
* Gets the current echo metrics for the session.
*
* Inputs Description
* -------------------------------------------------------------------
* void* handle Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* AecMetrics* metrics Struct which will be filled out with the
* current echo metrics.
* int return 0: OK
* 12000-12050: error code
*/
int32_t webrtc_agc_process(const int16_t *in_near, int16_t *out);
/*
* Gets the current delay metrics for the session.
*
* Inputs Description
* -------------------------------------------------------------------
* void* handle Pointer to the AEC instance
*
* Outputs Description
* -------------------------------------------------------------------
* int* median Delay median value.
* int* std Delay standard deviation.
* float* fraction_poor_delays Fraction of the delay estimates that may
* cause the AEC to perform poorly.
*
* int return 0: OK
* 12000-12050: error code
*/
int32_t webrtc_agc_deinit();
#ifdef __cplusplus
}
#endif
#endif // AEC_NSX_AGC_PREPROCESS_H_
以上是关于webRTC 音频3A在hal层的接口封装实现,对于音频数据的传递在调试的时候是需要值得关注的。
2、具体使用方式:
a、开启录音:
webrtc_aec_init(16000, 16000);
webrtc_nsx_init(16000);
webrtc_agc_init(16000);
b、音频流处理:
static int resampleOnechannelfrom8channel(struct stream_in *in, char *buffer,size_t bytes)
{
int ret;
int i, m, s,rd_round,byte_cnt_b;
int size_in_short = bytes/2;
char buf[bytes];
short tmp_buf[bytes];
short tmp_short1[480];
short tmp_short2[480];
//short tmp_short3[320];
short tmp_short4[160];
short tmp_short5[320];
short tmp_short6[160];
short tmp_short7[160];
char out_to_in[960];
char out_to_in_by[480];
if(debug_dump){
ALOGD("resampleOnechannelfrom8channel == %d bytes == %d", size_in_short,bytes);
}
byte_cnt_b = 0;
for (rd_round = 0; rd_round < 3; rd_round++) {
memset(buf, 0x00, bytes);
memset(tmp_buf, 0x00, bytes);
memset(tmp_short1, 0x00, 480);
memset(tmp_short2, 0x00, 480);
//memset(tmp_short3, 0x00, 320);
memset(tmp_short4, 0x00, 160);
memset(tmp_short5, 0x00, 320);
memset(tmp_short6, 0x00, 160);
memset(tmp_short7, 0x00, 160);
memset(out_to_in,0x00,960);
memset(out_to_in_by,0x00,480);
ret = pcm_read(in->pcm, buf, bytes);
if (ret) {
ALOGE("%s: pcm_read error %d", __func__, ret);
return ret;
}
memcpy((short *)tmp_buf, (short *)buf, bytes);
//fwrite(tmp_buf,bytes,1,in_debug);
if(mic_linein == 0 || mic_linein == 2){
for (i = 0, m = 0, s = 0; i < size_in_short; i++) {
if (i % 8 == 0) {
tmp_short1[m] = tmp_buf[i]>>3;
m++;
}
if(i % 8 == 6){
tmp_short2[s] = tmp_buf[i];
s++;
}
}
}else{
for (i = 0, m = 0, s = 0; i < size_in_short; i++) {
if (i % 8 == 0) {
tmp_short1[m] = tmp_buf[i];
m++;
}
if(i % 8 == 6){
tmp_short2[s] = tmp_buf[i];
s++;
}
}
}
unsigned int inlen = 240;
unsigned int outlen = 80;
speex_resampler_process_int(in->dev->resampler_mic,0, (const spx_int16_t *)tmp_short1, &inlen,(spx_int16_t *)tmp_short6, &outlen );
//fwrite(tmp_short2,480,1,in_debug_mic);
//if(speak_lineout_state){
memcpy(out_to_in,in->dev->out_to_in_buffer,960);
//fwrite(out_to_in,960,1,in_debug_speak);
OneFromTwoChannel(out_to_in,960,out_to_in_by);
speex_resampler_process_int(in->dev->resampler_speak,0, (const spx_int16_t *)out_to_in_by, &inlen,(spx_int16_t *)tmp_short7, &outlen );
//}else{
// speex_resampler_process_int(in->dev->resampler_speak,0, (const spx_int16_t *)tmp_short2, &inlen,(spx_int16_t *)tmp_short7, &outlen );
//}
webrtc_aec_bufferFarend(160,(char *)tmp_short7);
webrtc_aec_pro(160, (char *)tmp_short6,(char *)tmp_short4);
//fwrite(tmp_short4,160,1,in_debug_aec);
//speex_preprocess_run(in->dev->mSpeexState,(char *)tmp_short4);
webrtc_nsx_process((char *)tmp_short4,(char *)tmp_short5);
//fwrite(tmp_short5,160,1,in_debug_ns);
//webrtc_agc_process((char *)tmp_short4,(char *)buffer + byte_cnt_b);
//
if(mic_linein == 0 || mic_linein == 2){
memcpy((char *)buffer + byte_cnt_b, (char *)tmp_short5, 160);
}else{
//speex_preprocess_run(in->dev->mSpeexState,(char *)tmp_short5);
webrtc_agc_process((char *)tmp_short5,(char *)buffer + byte_cnt_b);
}
//webrtc_agc_process((char *)tmp_short4,(char *)buffer + byte_cnt_b);
byte_cnt_b += 160;
}
return 0;
}
c、结束录音:
webrtc_aec_deinit();
webrtc_nsx_deinit();
webrtc_agc_deinit();