webRtc音频3A接口封装

在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();
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值