君正T31应用开发5:回音消除

2023-05-14 17:21:10 浏览数 (1)

1.什么是回音消除?

1.1.单工模式&半双工模式

如果你的设备是这两种模式的话,一般都不需要考虑回音消除的困扰。

音频通过MIC头输入音频数据,然后再通过喇叭传播音频数据出去。

如果你这边只是一台设备,那么好说,就不太需要回音消除,因为你对着MIC头传音频数据的时候,你传输结束后,你才会通过喇叭传播音频数据出去,所以这时候,你一般不会有回音的困扰。

1.2.全双工模式

在即时通讯应用中,需要进行双方,或是多方的实时语音交流,在要求较高的场合,通常都是采用外置音箱放音,这样必然会产生回音,即一方说话后,通过对方的音箱放音,然后又被对方的Mic采集到回传给自己。如果不对回音进行处理,将会影响通话质量和用户体验,更严重的还会形成震荡,产生啸叫。

实现原理:

回声消除就是在Mic采集到声音之后,将本地音箱播放出来的声音从Mic采集的声音数据中消除掉,使得Mic录制的声音只有本地用户说话的声音。

2.君正的回音消除

君正的回音消除主要使用两个API函数,其中一个API函数是

1.1.开启回音消除

代码语言:javascript复制
	ret = IMP_AI_EnableAec(devID, chnID, 0, 0);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "Audio Record enable channel failedn");
		return NULL;
	}

1.2.结束回音消除

代码语言:javascript复制
	ret = IMP_AI_DisableAec(devID, chnID);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "IMP_AI_DisableAecRefFramen");
		return NULL;
	}

君正完整回音消除代码

代码语言:javascript复制
static void * IMP_Audio_Record_AEC_Thread(void *argv)
{
	int ret = -1;
	int record_num = 0;

	if(argv == NULL) {
		IMP_LOG_ERR(TAG, "Please input the record file name.n");
		return NULL;
	}

	FILE *record_file = fopen(argv, "wb");
	if(record_file == NULL) {
		IMP_LOG_ERR(TAG, "fopen %s failedn", AUDIO_RECORD_FILE);
		return NULL;
	}

	/* set public attribute of AI device. */
	int devID = 1;
	IMPAudioIOAttr attr;
	attr.samplerate = AUDIO_SAMPLE_RATE_16000;
	attr.bitwidth = AUDIO_BIT_WIDTH_16;
	attr.soundmode = AUDIO_SOUND_MODE_MONO;
	attr.frmNum = 40;
	attr.numPerFrm = 640;
	attr.chnCnt = 1;
	ret = IMP_AI_SetPubAttr(devID, &attr);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "set ai %d attr err: %dn", devID, ret);
		return NULL;
	}

	memset(&attr, 0x0, sizeof(attr));
	ret = IMP_AI_GetPubAttr(devID, &attr);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "get ai %d attr err: %dn", devID, ret);
		return NULL;
	}

	IMP_LOG_INFO(TAG, "Audio In GetPubAttr samplerate : %dn", attr.samplerate);
	IMP_LOG_INFO(TAG, "Audio In GetPubAttr   bitwidth : %dn", attr.bitwidth);
	IMP_LOG_INFO(TAG, "Audio In GetPubAttr  soundmode : %dn", attr.soundmode);
	IMP_LOG_INFO(TAG, "Audio In GetPubAttr     frmNum : %dn", attr.frmNum);
	IMP_LOG_INFO(TAG, "Audio In GetPubAttr  numPerFrm : %dn", attr.numPerFrm);
	IMP_LOG_INFO(TAG, "Audio In GetPubAttr     chnCnt : %dn", attr.chnCnt);

	/* enable AI device. */
	ret = IMP_AI_Enable(devID);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "enable ai %d errn", devID);
		return NULL;
	}

	/* set audio channel attribute of AI device. */
	int chnID = 0;
	IMPAudioIChnParam chnParam;
	chnParam.usrFrmDepth = 40;
	ret = IMP_AI_SetChnParam(devID, chnID, &chnParam);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "set ai %d channel %d attr err: %dn", devID, chnID, ret);
		return NULL;
	}

	memset(&chnParam, 0x0, sizeof(chnParam));
	ret = IMP_AI_GetChnParam(devID, chnID, &chnParam);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "get ai %d channel %d attr err: %dn", devID, chnID, ret);
		return NULL;
	}

	IMP_LOG_INFO(TAG, "Audio In GetChnParam usrFrmDepth : %dn", chnParam.usrFrmDepth);

	/* enable AI channel. */
	ret = IMP_AI_EnableChn(devID, chnID);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "Audio Record enable channel failedn");
		return NULL;
	}

	ret = IMP_AI_EnableAec(devID, chnID, 0, 0);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "Audio Record enable channel failedn");
		return NULL;
	}

	/* Set audio channel volume. */
	int chnVol = 60;
	ret = IMP_AI_SetVol(devID, chnID, chnVol);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "Audio Record set volume failedn");
		return NULL;
	}

	ret = IMP_AI_GetVol(devID, chnID, &chnVol);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "Audio Record get volume failedn");
		return NULL;
	}
	IMP_LOG_INFO(TAG, "Audio In GetVol    vol : %dn", chnVol);

	int aigain = 20;
	ret = IMP_AI_SetGain(devID, chnID, aigain);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "Audio Record Set Gain failedn");
		return NULL;
	}

	ret = IMP_AI_GetGain(devID, chnID, &aigain);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "Audio Record Get Gain failedn");
		return NULL;
	}
	IMP_LOG_INFO(TAG, "Audio In GetGain    gain : %dn", aigain);

	while(1) {
		/* get audio record frame. */

		ret = IMP_AI_PollingFrame(devID, chnID, 1000);
		if (ret != 0 ) {
			IMP_LOG_ERR(TAG, "Audio Polling Frame Data errorn");
		}
		IMPAudioFrame frm;
		ret = IMP_AI_GetFrame(devID, chnID, &frm, BLOCK);
		if(ret != 0) {
			IMP_LOG_ERR(TAG, "Audio Get Frame Data errorn");
			return NULL;
		}

		/* Save the recording data to a file. */
		fwrite(frm.virAddr, 1, frm.len, record_file);

		/* release the audio record frame. */
		ret = IMP_AI_ReleaseFrame(devID, chnID, &frm);
		if(ret != 0) {
			IMP_LOG_ERR(TAG, "Audio release frame data errorn");
			return NULL;
		}

		if(  record_num >= AUDIO_RECORD_NUM)
			break;
	}

	ret = IMP_AI_DisableAec(devID, chnID);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "IMP_AI_DisableAecRefFramen");
		return NULL;
	}
	sleep(3);
	ret = IMP_AI_DisableChn(devID, chnID);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "Audio channel disable errorn");
		return NULL;
	}

	/* disable the audio devices. */
	ret = IMP_AI_Disable(devID);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "Audio device disable errorn");
		return NULL;
	}

	fclose(record_file);
	pthread_exit(0);
}
sdk

0 人点赞