Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >君正T31应用开发5:回音消除

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

原创
作者头像
春江花月夜
发布于 2023-05-14 09:21:10
发布于 2023-05-14 09:21:10
1K11
代码可运行
举报
运行总次数:1
代码可运行

1.什么是回音消除?

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

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

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

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

1.2.全双工模式

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

实现原理:

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

2.君正的回音消除

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

1.1.开启回音消除

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
	ret = IMP_AI_EnableAec(devID, chnID, 0, 0);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "Audio Record enable channel failed\n");
		return NULL;
	}

1.2.结束回音消除

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
	ret = IMP_AI_DisableAec(devID, chnID);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "IMP_AI_DisableAecRefFrame\n");
		return NULL;
	}

君正完整回音消除代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 failed\n", 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: %d\n", 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: %d\n", devID, ret);
		return NULL;
	}

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

	/* enable AI device. */
	ret = IMP_AI_Enable(devID);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "enable ai %d err\n", 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: %d\n", 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: %d\n", devID, chnID, ret);
		return NULL;
	}

	IMP_LOG_INFO(TAG, "Audio In GetChnParam usrFrmDepth : %d\n", chnParam.usrFrmDepth);

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

	ret = IMP_AI_EnableAec(devID, chnID, 0, 0);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "Audio Record enable channel failed\n");
		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 failed\n");
		return NULL;
	}

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

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

	ret = IMP_AI_GetGain(devID, chnID, &aigain);
	if(ret != 0) {
		IMP_LOG_ERR(TAG, "Audio Record Get Gain failed\n");
		return NULL;
	}
	IMP_LOG_INFO(TAG, "Audio In GetGain    gain : %d\n", 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 error\n");
		}
		IMPAudioFrame frm;
		ret = IMP_AI_GetFrame(devID, chnID, &frm, BLOCK);
		if(ret != 0) {
			IMP_LOG_ERR(TAG, "Audio Get Frame Data error\n");
			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 error\n");
			return NULL;
		}

		if(++record_num >= AUDIO_RECORD_NUM)
			break;
	}

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

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

	fclose(record_file);
	pthread_exit(0);
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
1 条评论
热度
最新
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
君正T31应用开发3-音频输入
其中音频输入和音频输出存在设备和通道的概念。其中一个 MIC 认为是一个 Device,而一个 MIC 可以有多路 Channel 输入。同样的一个 SPK 认为是一个放音 Device, 而一个 SPK 也可以有多路 Channel 输出。当前版本的音频 API 一个 Device 只支持一个 Channel。 (T31只一路输入和一路输出)
春江花月夜
2023/04/01
1.9K0
君正T31应用开发3-音频输入
君正T31应用开发4-音频输出
其实手机,任何设备都有音频输出这个概念。比如你在电脑上面播放“只因你太美”这首歌曲的时候,电脑通过网易云音乐,或者别的音乐,调用电脑底层的驱动,最后把数字信号,转换成模拟信号在设备里面的喇叭这个硬件播放。
春江花月夜
2023/04/01
1.3K0
君正T31应用开发4-音频输出
君正T31应用开发6:音频编解码
前面提到的例子中,我们使用君正T31的设备都是直接使用API函数进行采集声音,然后直接播放声音的,其中涉及两组API,一组是AI,音频输入函数,一组是AO,音频输出函数。
春江花月夜
2023/05/27
1.1K0
君正T31应用开发6:音频编解码
君正T31应用开发10:智能算法检测
我们在淘宝上会看到各种各样的摄像头(IPC),有些99元包邮,有些1000元一台,比如云天励飞的摄像头。
春江花月夜
2023/06/18
1.8K0
君正T31应用开发10:智能算法检测
君正T31应用开发9:获取H265码流
和JPEG获取的码流是类似的,都是先初始化视频相关的接口,然后调用获取视频码流,最后释放视频的资源。
春江花月夜
2023/06/13
1.3K0
君正T31应用开发9:获取H265码流
君正T31开发应用12:YUV和RAW数据
是没有办法直接使用的,还要在host端做ISP,做色彩纠正,增强,HDR,插值成RGB,转成YUV,最后再使用。
春江花月夜
2023/06/22
1.4K0
君正T31开发应用12:YUV和RAW数据
君正T31应用开发8:获取JEPG码流
首先我们这个文件大部分功能是依赖于sample-common.h和sample-common.c这两个文件的,大部分demo都是调用这个common.c提供的基础库进行开发的。
春江花月夜
2023/06/11
1.7K1
君正T31应用开发8:获取JEPG码流
君正T31应用开发13:切换分辨率
一般我们买手机,电脑,只要和屏幕有关的东西的时候,都可以清晰的看到手机的参数是分辨率。
春江花月夜
2023/06/25
9371
君正T31应用开发13:切换分辨率
君正T31应用开发11:OSD应用
CSC模块主要把输入视频桢转化成硬件支持的图像,如HSV格式,NV12,NV21,RGB32,ARGB格式的任意一种格式。
春江花月夜
2023/06/22
1.5K0
君正T31应用开发11:OSD应用
AudioRecord源码解读(3)
AudioRecord可以用来采集PCM,本篇介绍下AudioRecord的创建流程。
一只小虾米
2022/10/25
1.5K0
AudioRecord源码解读(3)
SDL2库(4)-Android 端源码简要分析(AudioSubSystem)
SDL初始化 SDL_Init(): 初始化SDL。 SDL_OpenAudio(): 打开音频播放器。 SDL_PauseAudio(): 开始播放。 SDL循环渲染数据 调用callback,将正确的数据喂入
deep_sadness
2018/12/14
9020
SDL2库(4)-Android 端源码简要分析(AudioSubSystem)
GB28181设备接入端如何播放语音广播数据?
语音广播功能是GB28181设备接入端非常重要的功能属性,语音广播让终端和平台之间,有了实时双向互动,可以满足执法记录仪、智能安全帽、智能监控、智慧零售、智慧教育、远程办公、明厨亮灶、智慧交通、智慧工地、雪亮工程、平安乡村、生产运输、车载终端等场景的技术诉求。
音视频牛哥
2023/07/23
4710
GB28181设备接入端如何播放语音广播数据?
Android平台基于RTMP或RTSP的一对一音视频互动技术方案探讨
随着智能门禁等物联网产品的普及,越来越多的开发者对音视频互动体验提出了更高的要求。目前市面上大多一对一互动都是基于WebRTC,优点不再赘述,我们这里先说说可能需要面临的问题:WebRTC的服务器部署非常复杂,可以私有部署,但是非常复杂。传输基于UDP,很难保证传输质量,由于UDP是不可靠的传输协议,在复杂的公网网络环境下,各种突发流量、偶尔的传输错误、网络抖动、超时等等都会引起丢包异常,都会在一定程度上影响音视频通信的质量,难以应对复杂的互联网环境,如跨区跨运营商、低带宽、高丢包等场景,行话说的好:从demo到实用,中间还差1万个WebRTC。
音视频牛哥
2021/11/22
6970
Android国标接入端如何播放GB28181平台端语音广播数据
GB28181语音广播这块,我们依据GB/T28181-2016针对流程和实例代码,做过详细的描述,本次主要是探讨下,广播数据过来后,如何处理。
音视频牛哥
2022/10/07
2650
Android平台摄像头麦克风视音频采集录像之MediaRecorder还是SmartPublisher
在 Android 中录制摄像头采集的数据到 MP4 文件,我们可以用系统自带的MediaRecorder,也可以用第三方成熟的摄像头采集录制库,本文就两种方案,做个大概的梳理。
音视频牛哥
2024/11/21
3010
Android平台摄像头麦克风视音频采集录像之MediaRecorder还是SmartPublisher
Linux音频采集和在国产化平台中遇到的坑(二)
首先,PulseAudio跟ALSA不同的不同之处是,ALSA是内核级的,而PulseAudio则是用户层的服务,并且是作为Sound Server的形式,来管理应用程序的各种音频输入和输出,跟ALSA相同,大多数linux发行版都默认安装PulseAudio。我们这里的国产化芯片平台的银河麒麟自然也不例外。PulseAudio的结构图是这个样子的:
hbstream
2023/02/03
1.8K0
Linux音频采集和在国产化平台中遇到的坑(二)
Android平台RTMP直播推送模块技术接入说明
大牛直播SDK跨平台RTMP直播推送模块,始于2015年,支持Windows、Linux(x64_64架构|aarch64)、Android、iOS平台,支持采集推送摄像头、屏幕、麦克风、扬声器、编码前、编码后数据对接,功能强大,性能优异,配合大牛直播SDK的SmartPlayer播放器,轻松实现毫秒级的延迟体验,满足大多数行业的使用场景。
音视频牛哥
2024/08/07
4130
Android平台RTMP直播推送模块技术接入说明
Android平台GB28181设备接入侧音频采集推送示例
GB/T28181是广泛应用于视频监控行业的标准协议规范,可以在不同设备之间实现互联互通。今天我们主要探讨Android平台的Audio采集部分。
音视频牛哥
2023/07/17
4560
Android平台GB28181设备接入侧音频采集推送示例
Android平台RTSP转RTMP推送之采集麦克风音频转发
RTSP转RTMP推送,好多开发者第一想到的是采用ffmpeg命令行的形式,如果对ffmpeg比较熟,而且产品不要额外的定制和更高阶的要求,未尝不可,如果对产品稳定性、时延、断网重连等有更高的技术诉求,比较好的办法,还是采用我们的技术实现。
音视频牛哥
2024/10/30
1920
Android平台RTSP转RTMP推送之采集麦克风音频转发
PCM文件添加WAV头
在asr平台实现pcm格式录制的文件增加wav头,发现根据网上给的方法添加wav头的wav文件播放异常,播放没有声音!
呱牛笔记
2023/05/02
1.1K0
PCM文件添加WAV头
相关推荐
君正T31应用开发3-音频输入
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档