资源预览内容
第1页 / 共10页
第2页 / 共10页
第3页 / 共10页
第4页 / 共10页
第5页 / 共10页
第6页 / 共10页
第7页 / 共10页
第8页 / 共10页
第9页 / 共10页
第10页 / 共10页
亲,该文档总共10页全部预览完了,如果喜欢就下载吧!
资源描述
多核平台下声音采集与播放并发互斥技术研究摘要:在要求时延较小的仿真系统中,声音采集与播放是一个并发互斥过程。就单核cpu下的并发互斥技术,特别是当前国内虚拟电台系统中应用的并发互斥技术进行了分析研究,针对其在多核cpu下可能存在的问题进行了讨论,在此基础上提出了一种基于录音优先算法的改进算法,并从技术对比和算法复杂度方面进行了论证。关键词:多核cpu;多线程编程;并发互斥0引言多核cpu已经成为当前cpu市场上的主流产品,部份在单核cpu平台下运行良好的基于多线程的软件程序在多核cpu平台下出现了问题,如数据同步、线程并发、状态互斥等,因此设计适应多核cpu环境的算法与软件势在必行。坦克通信装备模拟仿真诸多技术要点之一即为声音的采集与播放并发执行,该技术背景是当车内通话器1号盒工作方式开关处于“车通”位时,电台需要对车内乘员话音数据采集并实时播放,电台侧音播放原理亦是如此。因此,对多核平台下声音采集与播放并发互斥研究十分必要。1通信控制原理分析为了提高仿真系统的实时性,在仿真电台启动的同时,系统语音采集线程和网络接收线程跟随启动并执行实时语音采集和网络信号接收任务,但是其语音(侧音)信号播放与否要根据通信状态匹配来确定。为此,需要设置两个状态标志m_txon和m_rxon。当m_txon为true时,模拟电台处于发信状态,此时需要播放侧音。当m_rxon为true时,模拟电台处于收信状态,如车通标志位为true,则需要播放一路或多路语音。当模拟系统设置成发信状态时(m_txon为true,m_rxon为false),语音数据包的发送与接收处于互斥状态。首先停止接收网络数据包,停止播放接收到的语音数据,尔后转入通话发信状态,此后,录音、播放侧音、发送语音数据处于并发状态,这里仅对录音和播音并发互斥进行研究。这种并发的实现,通过发送消息方式进行。当录满一个缓冲区后,通过windows系统发送消息,执行回调函数。在回调程序中,将录满数据的缓冲区进行拷贝,拷贝至播音缓冲区队列中和发送缓冲区中,激活播音和发送处理。在播音的同时,将本地模拟电台系统参数和发送缓冲区中数据打包并发送。windows操作系统中的消息因其传递方式不同可区分为发送消息(sendmessage)和寄送消息(postmessage),二者最主要的区别是消息被接收对象收到后是否立即被处理。鼠标和键盘消息通常都是寄送的,即消息被发送到窗口应用程序的消息队列中,应用程序只有在空闲时,才会去搜索消息队列,并在消息队列中处理该消息,通信可能会延迟。实装电台收信、发信转换恰恰是通过点击鼠标实现的,属于寄送消息,难以满足实时通信需要,特别是如果出现与其他应用程序窗口切换的状况,则通信将会被中断,这是绝对不能允许的。坦克通信训练系统仿真中,巧妙采用了文本框消息处理机制,变点击鼠标的寄送消息为文本框内容改变的发送消息机制,其并发处理的方法是:向模拟电台系统中特定文本框发送字符,以激发文本框onchange事件,在文本框onchange事件的处理中进行语音的播放、压缩、发送,使得录音、播放、压缩、发送等线程并发进行。2声音采集与播放并发控制模型如果对一个交互式应用程序采用多线程编程,单核cpu下该线程的并发执行,是在一个时间片内只有一个线程在执行。多核cpu使得计算机可以真正地在同一时间片内运行多个线程,从微观上真正实现并行化。因此,如果采用传统单核环境下并发处理技术,如互锁操作、临界区、事件、互斥器、信号量等等,会出现许多预料之外的效果,甚至导致程序混乱或失控。如欲令声音采集与播放线程并发执行,在单核下其实质为交替并发,在多核下为交替并发或并行化执行,结果其播放语音会出现间歇性的噪声影响。究其根本原因,是在多核状态下,由于线程执行序列的不确定性,使得某些时刻播放线程进度先于采集线程,导致其播放的声音数据为乱码,产生乱码噪声影响。因此,需要采取合适的解决方案或者设计新的并发控制模型。2.1点对点消息队列解决方案visual c+2005及以上版本支持进程间通信方法,即点对点消息队列,用以提供数据队列,用于在进程间交换数据。因此,可以创建一个读队列和一个写队列,并且对该队列只能指定其为读权限或者写权限,不能同时拥有读写权限。同时,其消息队列为经典的先入先出队列(fifo)。如果队列已经填满,写函数将被阻塞(等待队列中出现空位),可能立即返回失败或者等待指定时长后返回。同样原理,读函数也可能被阻塞,直至队列中出现新的未读消息或者等待指定时长后返回。该方法较好的解决了声音采集与播放线程的并发与互斥问题,但是其应用模式为向上兼容,如使用visual c+6.0及其以下版本无法使用该方案,因此,本仿真中不宜采用该方案。2.2命名内存映射对象解决方案该方案是在内存中使用命名内存映射对象并为其分配一块共享内存空间,授予句柄,其他进程通过句柄可直接读取这块内存数据。实际工程中的系统往往需要在多个进程之间共享数据,如果共享数据量少,处理方法是灵活多变的,如果共享数据容量巨大,那么就需要借助于内存映射文件来进行。实际上,内存映射文件正是解决本地多个进程间数据共享的最有效方法之一。其特点如下:在管理大型数据流以及要在单机上的进程数据共享等情形下,最合适使用内存映射方式,不仅速度快,还能有效地节省内存;多个进程共享内存时,如果各进程需要频繁地对共享内存读写,为确保程序运行正确,应该在各进程中创建同步信号,使得这些进程有序地访问共享内存。本系统仿真中所需内存数据较少,仅为1.5m左右,并且需要频繁进行声音数据的采集、播放,特别是基于单核同步方案在多核下难以奏效,因此该方案也不是本仿真的最佳方案。2.3录音优先解决方案该方案是目前国内虚拟电台系统模拟仿真所采用的。其基本原理是:采用环形缓冲区,在录放同步的前提下,使录音线程在录满2个缓冲区后播放线程方启动运行,其目的是使录音数据始终有一定的裕量。通过实验得知,在双核cpu环境下,当优先1个逻辑区位启动时,乱码噪声仍明显存在,优先2个逻辑区位时,乱码噪声基本消失,优先3个以上逻辑区位时乱码噪声消失,但是其声音延迟明显(大于500ms)。出现该结果的原因是:无法保证声音采集工作缓冲区始终领先于播放缓冲区的1至2个逻辑区位,有时是12个逻辑区位,有时是34个逻辑区位,更有甚者是负逻辑区位。在多核条件下,领先逻辑区位更加无法确定,随机现象更加突出。因此,该方案尽管能够满足单核或双核状态下的模拟仿真需求,但是稳定性不好,仅属权宜解决方案。2.4录放同步解决方案对多线程的录音开始后,如果录音设备只有一个缓冲区,且该缓冲区录满之后没有加入新的缓冲区,则声音录制将停止。因此在开始录音之前必须将多个(本系统为10个)录制缓冲区通过waveinprepareheader和waveinaddbuffer加入到录音设备中。在一个缓冲区被录满后,windows就会通过在waveinopen中指定的方式进行回调,在回调处理程序中首先将当前缓冲区用waveinunprepareheader从录音设备中撤出,将其中录好的语音数据取出来。然后再将该缓冲区通过waveinprepareheader和waveinaddbuffer加入到录音设备中。这样就可以保证所录的音频中不会有断开的间隔。只有当模拟电台处于发信状态时,才播放耳机侧音、压缩和发送并使它们并发进行以减少延时。因此为提高语音实时组播系统的效率,在录音的回调程序中,判断模拟电台状态标志:当为接收状态时,录音数据不播放,也不压缩发送;当为发信状态时,将语音数据从缓冲区中拷贝至播音缓冲区队列中和发送缓冲区中,并通过向模拟电台系统中特定文本框发送字符,以激发文本框onchange事件,进行并发处理。在模拟系统设置成接收状态时(m_txon为false,m_rxon为true),首先停止发送网络数据包,停止播放已录的语音数据,转入接收状态。接收数据包并根据相应策略播放数据包语音。在对上述多线程任务执行进行分析的基础上,重点就录放同步算法进行研究,同时考虑到利用系统api实现录音播音的通用性,代码列举部份不对其作过多介绍。本方案是录音优先解决方案的改进方案,即录音和放音线程同步启动,并发执行。该方案需要定义2路缓冲区,1路用来记录声卡采集到的语音数据,1路用来填充标志位,标记该路语音数据是否填充完毕,如图1所示:图1双路缓冲区示意图该算法采用双缓冲区机制(声音缓冲区和标志缓冲区),其算法流程如下:(1)定义双路缓冲区、缓冲区头部结构体初始化。(2)录音设备参数结构体初始化并打开录音设备,指定录音内存。(3)启动录音线程,开始采集声音。(4)放音设备参数结构体初始化并打开放音设备,指定放音内存。(5)启动放音线程,开始播放声音。(6)当录满一个缓冲区的语音数据后,触发wim_data事件,将采集到的语音数据压入录音缓存,设置标志缓冲区相应位为true,对下一缓冲区序号模maxwaveblock操作,确保其始终为环形缓冲区,恢复录音设备结构体参数设置,并加入新的缓存以继续录音操作。(7)当播放完一个缓冲区后,触发wom_done事件,通过标志缓冲区布尔值判断下一缓冲区是否填充数据完毕,如果完毕则将录音缓冲区首地址压入到播放缓冲区,准备并播放缓冲区,否则等待直到该缓冲区填充完毕并播放。播放完毕后,设置标志缓冲区相应位为false,对下一缓冲区序号模maxwaveblock操作,确保其始终为环形缓冲区。(8)录(放)音线程持续运行,(6)和(7)并发执行。(9)接收到系统退出消息后,停止录(放)音,清空录(放)音缓存,关闭录(放)音设备。在上述算法中,核心操作是对语音数据缓冲区和标志缓冲区的数据同步操作,现将该算法的部分关键代码列举如下:void crecorderdlg:onmm_wim_data(uint wparam, long lparam)/录满一个缓冲区的数据量时回调该函数waveinflagwim_bufw_index_0=true;/标志位置真,标识对应缓冲区填满数据wim_bufw_index_0 = (wim_bufw_index_0+1)%maxwaveblock;void crecorderdlg:onmm_wom_done(uint wparam, long lparam)/播放完一个缓冲区后回调该函数int loop = 0;while (!waveinflagwom_bufw_index_0 & loop 10)/如果欲读缓冲区未填满,则继续等待直至填满或超时退出sleep(1);loop+;waveinflagwom_bufw_index_0=false;/标志位置假,标识对应缓冲区数据读完wom_bufw_index_0 = (wom_bufw_index_0+1)%maxwaveblock;3结束语将该算法与录音优先算法进行实验对比可以看出,录放同步算法性能稳定,并发及互斥效果良好,完全能够满足系统仿真需求。从空间复杂度来看,该算法仅利用了很小的辅助空间(10bytes),即实现了对录音缓冲区状态的判断;从时间复杂度来看,该算法在最坏情况下,亦即循环等待直至超时,其延时仅为10ms左右,对实现录音播音的并发处理影响不大。因此,该算法简洁扼要,切中要害,很好解决了录音与放音并发执行问题。参考文献:1路锦正,周冬梅.visual c+音频/视频处理技术及工程实践m.北京:电子工业出版社.2009.2reinders j.programming for parallelismeb/ol.2007.http:/www.cajc
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号