首页 > 其他分享 >linphone 回声消除

linphone 回声消除

时间:2024-07-03 12:10:39浏览次数:16  
标签:插件 lc stream 回声 call linphone config 消除

声学回声消除是通过消除或者移除本地话筒中拾取到的远端的音频信号来阻止远端的声音返回去的一种处理方

法。linphone上使用speex 库实现了回声消除插件,speex库是目前开源的声学回声消除做的比较好的库。下

面总结一下,linphone上的回声消除部分。

 

第一部分--配置

linphone的声音部分,是可以配置的,初始化linphone的时候,会根据配置文件的内容来配置声音部分,包括

回声消除部分。

linphone_core_new()

|

linphone_core_init()

|

sound_config_read(lc)

{
......

#ifndef __ios
tmp=TRUE;
#else
tmp=FALSE; /* on iOS we have builtin echo cancellation.*/
#endif

/从配置文件读取ec的配置,读取失败,则为tmp的值,否则,tmp被赋值
tmp=lp_config_get_int(lc->config,"sound","echocancellation",tmp);

linphone_core_enable_echo_cancellation(lc,tmp);//保存ec

//读取ea的值,默认值为0
linphone_core_enable_echo_limiter(lc, lp_config_get_int(lc->config,"sound","echolimiter",0));

linphone_core_enable_agc(lc, lp_config_get_int(lc->config,"sound","agc",0));//读取agc的值,默认为0

......

}

这里,会从配置文件读取 echocancellation、echolimiter和agc的键值,如果配置文件里没有配置,那么用tmp

作为默认值。看看配置文件,竟然没有这几项的配置。。。那就是用tmp的值了,我是基于android平台,那么

配置的结果是:ec =1,ea=0,agc = 0;

其中一个地方要展开一下,

void linphone_call_enable_echo_limiter(LinphoneCall *call, bool_t val){
if (call!=NULL && call->audiostream!=NULL ) {
if (val) {
const char *type=lp_config_get_string(call->core->config,"sound","el_type","mic");
if (strcasecmp(type,"mic")==0)
audio_stream_enable_echo_limiter(call->audiostream,ELControlMic);
else if (strcasecmp(type,"full")==0)
audio_stream_enable_echo_limiter(call->audiostream,ELControlFull);
} else {
audio_stream_enable_echo_limiter(call->audiostream,ELInactive);
}
}
}

配置ea的时候,还会读取el_type 的配置,这是个字符串,值有三种:mic、full 和其他。

这个值用来设置什么呢?

void audio_stream_enable_echo_limiter(AudioStream *stream, EchoLimiterType type){
stream->el_type=type;
if (stream->volsend){
bool_t enable_noise_gate = stream->el_type==ELControlFull;
ms_filter_call_method(stream->volrecv,MS_VOLUME_ENABLE_NOISE_GATE,&enable_noise_gate);
ms_filter_call_method(stream->volsend,MS_VOLUME_SET_PEER,type!=ELInactive?stream->volrecv:NULL);
} else {
ms_warning("cannot set echo limiter to mode [%i] because no volume send",type);
}
}

stream->volrecv和stream->volsend都是插件MS_VOLUME_ID,可见,当键值是full的时候,会enable noise gate,

当键值是mic或full的时候,会把volsend 的peer插件设置为volrecv。

简单的说,是在VOLUME插件(声音增益插件)里处理回声。后面再细说。

 

第二部分--初始化

当接听电话时,会初始化音频流,同时会初始化回声消除插件。

call_accepted()

|

linphone_core_update_streams()

|

linphone_call_init_media_streams()

{
......

//1

call->audiostream=audiostream=audio_stream_new(md->streams[0].port,linphone_core_ipv6_enabled(lc));

//2
if (linphone_core_echo_limiter_enabled(lc)){
const char *type=lp_config_get_string(lc->config,"sound","el_type","mic");
if (strcasecmp(type,"mic")==0)
audio_stream_enable_echo_limiter(audiostream,ELControlMic);
else if (strcasecmp(type,"full")==0)
audio_stream_enable_echo_limiter(audiostream,ELControlFull);
}

//3
audio_stream_enable_gain_control(audiostream,TRUE);

//4
if (linphone_core_echo_cancellation_enabled(lc)){
int len,delay,framesize;
const char *statestr=lp_config_get_string(lc->config,"sound","ec_state",NULL);
len=lp_config_get_int(lc->config,"sound","ec_tail_len",0);
delay=lp_config_get_int(lc->config,"sound","ec_delay",0);
framesize=lp_config_get_int(lc->config,"sound","ec_framesize",0);
audio_stream_set_echo_canceller_params(audiostream,len,delay,framesize);
if (statestr && audiostream->ec){
ms_filter_call_method(audiostream->ec,MS_ECHO_CANCELLER_SET_STATE_STRING,(void*)statestr);
}
}

//5
audio_stream_enable_automatic_gain_control(audiostream,linphone_core_agc_enabled(lc));
{
int enabled=lp_config_get_int(lc->config,"sound","noisegate",0);
audio_stream_enable_noise_gate(audiostream,enabled);
}

......

}

1.在audio_stream_new函数里,会新建回声消除插件:stream->ec=ms_filter_new(MS_SPEEX_EC_ID);新建插

件时,会调用此插件的init回调。

2.根据ea的值配置VOLUME插件。

3.设置use_gc 为true。

4.根据配置文件,配置speexec插件。

5.根据agc配置use_agc,读取noisegate的键值,并配置volsend。

 

**这一部分代码都是初始化插件和配置插件,配置完了就可以启动音频流了。

顺便说下linphone 的音频插件组合:

发送:

ms_filter_link: MSAndSoundRead:0-->MSSpeexEC:1
ms_filter_link: MSSpeexEC:1-->MSVolume:0
ms_filter_link: MSVolume:0-->MSDtmfGen:0
ms_filter_link: MSDtmfGen:0-->MSAlawEnc:0
ms_filter_link: MSAlawEnc:0-->MSRtpSend:0


接收:

ms_filter_link: MSRtpRecv:0-->MSAlawDec:0
ms_filter_link: MSAlawDec:0-->MSDtmfGen:0
ms_filter_link: MSDtmfGen:0-->MSVolume:0
ms_filter_link: MSVolume:0-->MSEqualizer:0
ms_filter_link: MSEqualizer:0-->MSSpeexEC:0
ms_filter_link: MSSpeexEC:0-->MSAndSoundWrite:0

 

 

第三部分--运转

在调用init之后,马上就会开始链接发送和接收插件,并启动音频流。

call_accepted()

|

linphone_core_update_streams()

|

linphone_call_init_media_streams();

linphone_call_start_media_streams();

|

linphone_call_start_audio_stream()

|

audio_stream_start_full()

{
new rtp-send dtmf-gen,volume filter;

调用插件的方法,设置参数;

链接音频插件发送的串;

链接音频插件接收的串;

启动ticker,运行这两个插件串;

}

 

总结一下,对回声消除起作用的两个插件是speexec 和volume,下面具体看这两个插件。

 

第四部分:MS_SPEEX_EC_ID插件

前面我们看到,在音频接收和发送的插件串里都有speexec插件,但是此插件只在audio_stream_new里新建了一次,

也就是说,发送和接收的插件串里使用的speexec是同一个!没错,speexec插件有两个输入和两个输出,

/* inputs[0]= reference signal from far end (sent to soundcard)
* inputs[1]= near speech & echo signal (read from soundcard)
* outputs[0]= is a copy of inputs[0] to be sent to soundcard
* outputs[1]= near end speech, echo removed - towards far end
*/

speexec如何工作?

1.speexec插件先缓存本地录音的pcm流和远程的pcm流;

2.把远端的pcm流复制一份,交给声卡。

2.参考远端发送过来的pcm流,通过算法过滤掉本地录音pcm流的回声;

3.把得到的纯净的pcm流发给远端;

4.释放所有缓存;

5.同步本地音频流和远端音频流。

 

关于同步:我们知道,消除回声算法要做的就是从录制的声音数据中找到回声,并去除,这就需要参考正确的

远程声音数据,如果参考的内容不对,那肯定找不到回声了。所以远程的声音数据和本地声音数据的同步,就是

关键。我们本地录制的速度是均匀稳定的,而网络传输过来的远端数据的速度是不稳定的,linphone每间隔固定

的时间段,检查一次远程数据的大小,如果大于framesize,则认为积累了过多的远端数据,需要丢弃一部分。

 

 

第五部分:MS_VOLUME_ID插件

噪声抑制
————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/dxpqxb/article/details/7937106

标签:插件,lc,stream,回声,call,linphone,config,消除
From: https://www.cnblogs.com/simadi/p/18281362

相关文章

  • Linphone 配置参数(噪音调试)
    1,先找到跟语音相关的参数,其实有很多归纳一下无非就是回声消除参数、回声抑制参数、噪声处理参数、均衡器参数4个。2,要了解参数的用途。花费了一周时间还是值得的。agc=0 #这个是自动增益,试过=1会啸叫echocancellation=1#回声消除这个必须=1,否则会听到自己说话的声音ec_tail_len......
  • Java 锁粗化和锁消除
    原文:Java锁消除和锁粗化锁粗化通常情况下,为了保证多线程间的有效并发,会要求每个线程持有锁的时间尽可能短,但是某些情况下,一个程序对同一个锁不间断、高频地请求、同步与释放,会消耗掉一定的系统资源,因为锁的请求、同步与释放本身会带来性能损耗,这样高频的锁请求就反而不利于系......
  • EV代码签名——消除软件下载时的安全警告
    开发公司和软件开发人员在发布应用程序后,当用户尝试下载并安装应用程序时,被SmartScreen识别为不常见或尚未建立起良好的信誉度,系统就会发出警告,提示用户该应用程序可能对电脑构成风险。这会导致软件下载率大幅度下降。一:如何消除SmartScreen警告对于此警告,应用程序所有者......
  • 机器学习(一)——递归特征消除法实现SVM(matlab)
    机器学习方法对多维特征数据进行分类:本文用到非常经典的机器学习方法,使用递归特征消除进行特征选择,使用支持向量机构建分类模型,使用留一交叉验证的方法来评判模型的性能。构建模型:支持向量机(SupportVectorMachine,SVM);特征选择:递归特征消除(RecursiveFeatureElimination,RFE);......
  • RAG 如何消除大模型幻觉
    什么是大模型幻觉假设我们有一个基于大型生成模型(如GPT-3)的问答系统,该系统用于回答药企内部知识库中的问题。我们向其提出一个问题:“阿司匹林的主要药理作用是什么?”正确的答案应该是:“阿司匹林主要通过抑制环氧酶(COX)酶的活性,降低前列腺素和血栓素的生成,从而起到抗血小板......
  • 解放代码:识别与消除循环依赖的实战指南
    目录一、对循环依赖的基本认识(一)代码中形成循环依赖的说明(二)无环依赖的原则二、识别和消除循环依赖的方法(一)使用JDepend识别循环依赖使用Maven集成JDepend分析报告识别循环依赖(二)消除循环依赖的三大方法思考提取中介者转移业务逻辑采用回调接口三、案件实战分析......
  • BK7258--wifi音视频soc芯片,1080P H264 wifi低功耗保活,内置BLE,音频code,psram,flash,USB2.
    BK7258是上海博通推出的高度集成的Wi-Fi+BLE combo音视频芯片,支持UVC和DVP摄像头,该芯片集成音视频外设及接口,1080P,H.264,低功耗,内置flash,dsp,psram,驱屏,回声消除及降噪等,广泛适用于可视猫眼,门锁,门铃,ipc,内窥,儿童相机等应用市场。可视门铃应用:DVP接口支持720p25fps图像采集;MJPE......
  • 解答 | 怎么消除SmartScreen程序安装警告
    先导在当前的网络时代,各种功能的软件应用程序参与到人们的生活和工作中,市场规模愈来愈大,增加了许多的开发公司和软件开发人员。但在发布应用程序后,软件所有者经常会遇到一个挑战,即用户在下载时可能会遇到微软SmartScreen提示“此应用程序不太常见,可能对您的电脑构成风险”,这种......
  • Clock Switch,芯片时钟切换的毛刺是什么,如何消除
    背景芯片运行过程中需要时钟切换时,要考虑到是否会产生glitch,小小的glitch有可能导致电路运行的错误。所以时钟切换时需要特别的处理。直接使用MUX进行时钟切换或者采用如下电路结构进行时钟切换:assignoutclock=(clk1&select)|(~select&clk0);或assignoutclock=......
  • Java并发02---Synchronized的实现原理、锁的升级、锁的膨胀、对象头、锁的消除、偏向
    @目录何为synchronized前置知识:对象头锁的升级(锁的膨胀)偏向锁轻量级锁轻量级锁锁的消除何为synchronized我们知道,synchronized关键字能够将其修饰的代码块、方法、静态方法变成同步代码。我们在前文中已经介绍过了,使用volatile关键字修饰能保证变量在内存中的可见性,但不保证操作......