用于tcp协议的基于能量阈值的语音缓冲丢包处理方法
技术领域
本发明属于计算机数字语音处理通信领域,具体来说是一种用于tcp协议的基于能量阈值的语音缓冲丢包处理方法。
背景技术
在计算机数字语音处理通信领域,比如在线教育系统、视频会议系统等,发送端从麦克风采集到的语音数据经过编码压缩后发送到服务器,服务器再将接收到的语音包转发给接收端,期间由于设备性能和网络情况不稳定造成的网络抖动现象会使得发送端、服务器端和接收端的语音处理复杂度大增,如果处理不好会出现接收端用户听到的发送端用户的语音卡顿、延迟大等现象,严重影响双方的交流,优秀的语音缓冲丢包处理可以有效缓解由于各种原因造成的语音卡顿和延迟问题,使交流双方能够顺畅的进行语音交流。
在各种语音处理通信系统中,大部分系统都有语音缓冲丢包恢复功能模块。由于语音缓冲丢包处理主要是为了解决网络传输不稳定造成的语音延迟、卡顿等问题,所以语音缓冲丢包处理方法可以基于传输协议udp和tcp进行优化。由于udp协议传输时延迟比较小,为了降低语音延迟,当前大多语音交流系统使用的语音缓冲丢包处理方法都是基于udp传输协议进行优化的。udp协议是不可靠传输协议,除了有传输速度快的优点外,也有容易丢包、数据包乱序传输等缺点。由于udp的丢包是发生在网络传输层,所以应用本身不能进行控制。在遇到网络状况不好的情况下,通过udp协议传输的语音数据包就很容易会发生数据包丢失、传输乱序等现象,如果不对语音数据丢包和乱序进行处理,听到的声音就会出现卡顿断续、前后语音混乱等现象,为了解决这些问题,语音缓冲丢包恢复处理是必须的。语音缓冲丢包处理就是要对到来的udp语音数据包进行缓冲并进行排序,然后根据播放进度对延迟到达的语音数据包进行丢弃。通过对语音数据包进行缓冲排序,增大播放延迟来缓解语音卡顿和前后语音混乱的现象。由于udp在传输过程中会丢掉一部分语音数据包,在进行语音缓冲排序时也会丢掉一部分语音数据包,为了进一步提高语音效果,可以对丢掉的语音数据包进行丢包恢复操作。丢包恢复通常用复杂的预测、插值等算法对丢掉的语音进行还原,从而来降低语音丢包对语音质量造成的影响。在使用udp协议进行传输的情况下,由于丢掉的语音数据包含有重要的语音信息,丢包恢复操作通常是很重要的一环。Tcp协议本身是可靠传输协议,优点是数据按照先后顺序进行传输,不会发生丢包和乱序现象,缺点是传输延迟会比udp协议要大。由于tcp协议的特点,语音数据在传输过程中不会丢失,也不会发生语音数据包乱序现象,但是传输延迟大小的不确定性还是存在的。使用tcp传输协议时,语音缓冲丢包处理不需要考虑乱序问题,只需要解决语音缓冲时长的动态调整,从而平衡语音延迟和断续卡顿问题。如果语音缓冲过小,则会造成卡顿,如果语音缓冲过大,则会造成延迟过大。由于tcp协议传输时,网络传输层本身不会丢包,所有的语音数据丢包都是自己控制的,所以怎么进行数据的丢包就显得尤为重要。
各种系统根据情况选择使用不同的传输协议(udp或者tcp)和语音缓冲丢包恢复方法来满足用户的语音交流需求,提高语音交流体验。总的来说,在满足需求的情况下,采取的方法越简单越好。
发明内容
本发明的目的是基于tcp传输协议和语音数据的特点,提供用于tcp协议的基于能量阈值的语音缓冲丢包处理方法。本发明的核心思想是主动丢掉不重要的音频数据包(比如背景噪音数据、音量偏小的数据)来自动降低延迟。本发明包含丢包判定模块、采集发送端、服务器转发端、接收播放端四部分,采集发送端、服务器转发端、接收播放端三部分使用相同的丢包判定算法,互相配合完成整个系统的基于tcp传输协议的语音缓冲丢包处理。本发明使用了开源的vad算法进行语音数据的判断,并不对vad算法进行讨论。下面对各个部分分别进行描述。
步骤1、针对采集发送端,具体的:
1-1、从麦克风采集音频数据帧frame(10-20毫秒);
1-2、计算frame的能量值frame_energy:先用vad算法判断frame是否含有人的语音;如果不含语音,则认为是不重要的数据(可能是噪声等),将该frame的能量值frame_energy设置为0,如果含有语音则通过能量计算公式计算该frame能量值frame_energy;
frame_energy=|sample[0]|+…+|sample[count-1]|公式(1)
其中,count是自然数,为步骤1-1中所述的一帧中含有的采样点的个数,|sample[count-1]|表示其中一个采样点的能量值;
1-3、直接获取当前发送队列中的语音缓冲长度buffer_ms1;
1-4、使用语音缓冲长度buffer_ms和能量值frame_energy,通过丢包判定模块判断该帧是否需要丢掉,如果不需要丢掉,则将该frame和frame_energy填加到发送队列,如果需要丢掉,则将该包丢掉;
1-5、发送线程每隔时间T定时检查发送队列中是否有数据,如果有数据,则从发送队列取一帧frame数据出来,将frame编码压缩后和frame_energy一起打包成音频数据包,并发送到服务器转发端;
所述的时间T是麦克风采集到的数据帧时长的一半。
步骤2、针对服务器转发端,具体的:
2-1、服务器转发端接收采集发送端发过来的音频数据包,
2-2、从接收到的音频数据包中解析出该帧能量frame_energy
2-3、取得当前转发队列中的语音缓冲长度buffer_ms2
2-4、使用buffer_ms2和frame_energy,通过通过丢包判定模块判断该音频数据包是否需要丢包,如果不需要丢包,则将该包填加到当前转发队列,如果需要丢包,则将该包丢掉;
2-5、转发线程每隔时长T1定时检查转发队列中是否有数据,如果有数据,则从转发队列取出一个从发送端接收到的音频数据包转发给接收播放端。
所述的时间T1与麦克风采集到的数据帧时长的相等。
步骤3、针对接收播放端,具体的:
3-1、接收从服务器转发端转发过来的音频数据包
3-2、从接收到的音频数据包中解析出该帧能量frame_energy
3-3、取得当前播放队列中的语音缓冲长度buffer_ms3
3-4、使用buffer_ms3和frame_energy,通过丢包判定模块判断该音频数据包是否需要丢包,如果不需要丢包,则将该包填加到播放队列,如果需要丢包,则将该包丢掉
3-5、播放线程持续时长T3定时检测是否需要向播放设备中添加音频数据包,如果需要添加,则先判断播放队列的缓冲状态isBuffering:
如果播放队列正在缓冲,即缓冲状态isBuffering==true,则判断当前播放队列中的语音缓冲长度buffer_ms3是否大于初始缓冲阈值min_ms;如果语音缓冲长度buffer_ms3大于等于初始缓冲阈值min_ms,则缓冲完成,将isBuffering设置成false,然后继续添加音频数据包;否则添加空数据包;
如果播放队列中缓冲状态isBuffering==false,且语音缓冲长度buffer_ms3大于0,则从播放队列中取出一帧frame进行解码,并将解码后的音频数据帧添加到播放,否则,则播放空数据并设置isBuffering=true
所述的时间T3是麦克风采集到的数据帧时长的一半。
所述的丢包判定模块的具体实现如下:
丢包判定模块利用tcp协议可靠传输的特点,通过丢掉相对不重要的语音数据包来控制语音数据的语音缓冲长度,平衡语音延迟和语音流畅度之间的关系。语音数据是否重要通过vad算法和语音帧的能量来判断,通过vad算法判定音频数据帧是否为语音数据,如果不是语音数据则将该音频数据帧的能量设置为0;否则对该音频数据帧进行能量计算,具体计算如下:
frame_energy=|sample[0]|+…+|sample[count-1]|公式(1)
其中,count是自然数,为步骤1-1中所述的一帧中含有的采样点的个数,|sample[count-1]|表示其中一个采样点的能量值;且该采样点的能量值大小范围为short型;该音频数据帧的时长为10毫秒的整数倍。
首先、建立语音缓冲时长和能量阈值的映射表energy_threshold_map[ms],其中ms为定义的语音缓冲时长大小,单位为毫秒;
所述的语音缓冲时长用自小到大是数组[an]表示,能量阈值用自小到大数组[bn],映射表energy_threshold_map[ms]体现了数组[an]与[bn]之间一一对应的关系,用来判断当前音频数据包是否需要丢掉。其中数组[an]与[bn]中的元素值的大小根据系统进行定义,或则根据实际情况进行判断。
例如:假设采样的音频数据帧的采样频率为48K,双声道,长度为10毫秒,映射表的大小为3,则该映射表可以定义如下:
语音缓冲时长数组[an]中a1、a2和a3的取值依次为:100毫秒,300毫秒,800毫秒;能量阈值数组[bn]中b1、b2和b3的取值依次为:10,200,500;
则energy_threshold_map[ms]对应的取值则为:
a1=100b1=10
a2=300b2=200
a3=800b3=500
可以根据实际使用情况对该表进行进一步调整。
其次、判断当前音频数据帧是否需要丢掉,丢掉输出用isCanDelete表示:为了根据映射表energy_threshold_map[ms]判断是否需要丢掉当前的音频数据帧frame,需要知道当前语音缓冲长度buffer_ms和当前音频数据帧frame的能量值frame_energy。循环查找映射表项中的数组[an],判断每项是否满足丢包条件:buffer_ms>an并且frame_energy<bn,如果满足,则判定需要丢掉当前音频数据帧frame,设置isCanDelete=true,否则判定不能丢掉当前音频数据帧frame,设置isCanDelete=false;并将输出判定结果isCanDelete给调用者;
本发明有益效果如下:
本发明从简单实用的角度出发,根据tcp协议可靠传输的特性,通过简单的语音缓冲时长和能量阈值映射表energy_threshold_map[ms]来主动控制需要丢掉的音频包,当网络延迟抖动比较大的时候,通过在播放端控制最小语音缓冲大小ms和进行丢包来平衡语音延迟和流畅度。由于用户说话交流期间总是有停顿等待时间,停顿等待期间的数据如果在网络情况不好的情况下都是可以丢掉的不重要数据,在不影响交流的情况下可以明显降低延迟。实际测试效果能够满足大多情况下的需求,在满足实用性的情况下尽量降低了算法的复杂程度。
附图说明
图1为音频丢包判定算法的流程图。
图2为采集发送端的流程图
图3为服务器转发端的流程图
图4为接收播放端的流程图
具体实施方式
下面对本发明的具体实施方式进行说明。
如图1-4所示,用于tcp协议的基于能量阈值的语音缓冲丢包处理方法,具体包括如下步骤:
如图2所示,步骤1、针对采集发送端,具体的:
1-1、从麦克风采集音频数据帧frame(10-20毫秒);
1-2、计算frame的能量值frame_energy:先用vad算法判断frame是否含有人的语音;如果不含语音,则认为是不重要的数据(可能是噪声等),将该frame的能量值frame_energy设置为0,如果含有语音则通过能量计算公式计算该frame能量值frame_energy;
frame_energy=|sample[0]|+…+|sample[count-1]|公式(1)
其中,count是自然数,为步骤1-1中所述的一帧中含有的采样点的个数,|sample[count-1]|表示其中一个采样点的能量值;
1-3、直接获取当前发送队列中的语音缓冲长度buffer_ms1;
1-4、使用语音缓冲长度buffer_ms和能量值frame_energy,通过丢包判定模块判断该帧是否需要丢掉,如果不需要丢掉,则将该frame和frame_energy填加到发送队列,如果需要丢掉,则将该包丢掉;
1-5、发送线程每隔时间T定时检查发送队列中是否有数据,如果有数据,则从发送队列取一帧frame数据出来,将frame编码压缩后和frame_energy一起打包成音频数据包,并发送到服务器转发端;
所述的时间T是麦克风采集到的数据帧时长的一半。
如图3所示,步骤2、针对服务器转发端,具体的:
2-1、服务器转发端接收采集发送端发过来的音频数据包,
2-2、从接收到的音频数据包中解析出该帧能量frame_energy
2-3、取得当前转发队列中的语音缓冲长度buffer_ms2
2-4、使用buffer_ms2和frame_energy,通过通过丢包判定模块判断该音频数据包是否需要丢包,如果不需要丢包,则将该包填加到当前转发队列,如果需要丢包,则将该包丢掉;
2-5、转发线程每隔时长T1定时检查转发队列中是否有数据,如果有数据,则从转发队列取出一个从发送端接收到的音频数据包转发给接收播放端。
所述的时间T1与麦克风采集到的数据帧时长的相等。
如图4所示,步骤3、针对接收播放端,具体的:
3-1、接收从服务器转发端转发过来的音频数据包
3-2、从接收到的音频数据包中解析出该帧能量frame_energy
3-3、取得当前播放队列中的语音缓冲长度buffer_ms3
3-4、使用buffer_ms3和frame_energy,通过丢包判定模块判断该音频数据包是否需要丢包,如果不需要丢包,则将该包填加到播放队列,如果需要丢包,则将该包丢掉
3-5、播放线程持续时长T3定时检测是否需要向播放设备中添加音频数据包,如果需要添加,则先判断播放队列的缓冲状态isBuffering:
如果播放队列正在缓冲,即缓冲状态isBuffering==true,则判断当前播放队列中的语音缓冲长度buffer_ms3是否大于初始缓冲阈值min_ms;如果语音缓冲长度buffer_ms3大于等于初始缓冲阈值min_ms,则缓冲完成,将isBuffering设置成false,然后继续添加音频数据包;否则添加空数据包;
如果播放队列中缓冲状态isBuffering==false,且语音缓冲长度buffer_ms3大于0,则从播放队列中取出一帧frame进行解码,并将解码后的音频数据帧添加到播放,否则,则播放空数据并设置isBuffering=true
所述的时间T3是麦克风采集到的数据帧时长的一半。
如图1所示,所述的丢包判定模块的具体实现如下:
丢包判定模块利用tcp协议可靠传输的特点,通过丢掉相对不重要的语音数据包来控制语音数据的语音缓冲长度,平衡语音延迟和语音流畅度之间的关系。语音数据是否重要通过vad算法和语音帧的能量来判断,通过vad算法判定音频数据帧是否为语音数据,如果不是语音数据则将该音频数据帧的能量设置为0;否则对该音频数据帧进行能量计算,具体计算如下:
frame_energy=|sample[0]|+…+|sample[count-1]|公式(1)
其中,count是自然数,为步骤1-1中所述的一帧中含有的采样点的个数,|sample[count-1]|表示其中一个采样点的能量值;且该采样点的能量值大小范围为short型;该音频数据帧的时长为10毫秒的整数倍。
首先、建立语音缓冲时长和能量阈值的映射表energy_threshold_map[ms],其中ms为定义的语音缓冲时长大小,单位为毫秒;
所述的语音缓冲时长用自小到大是数组[an]表示,能量阈值用自小到大数组[bn],映射表energy_threshold_map[ms]体现了数组[an]与[bn]之间一一对应的关系,用来判断当前音频数据包是否需要丢掉。其中数组[an]与[bn]中的元素值的大小根据系统进行定义,或则根据实际情况进行判断。
例如:假设采样的音频数据帧的采样频率为48K,双声道,长度为10毫秒,映射表的大小为3,则该映射表可以定义如下:
语音缓冲时长数组[an]中a1、a2和a3的取值依次为:100毫秒,300毫秒,800毫秒;能量阈值数组[bn]中b1、b2和b3的取值依次为:10,200,500;
则energy_threshold_map[ms]对应的取值则为:
a1=100b1=10
a2=300b2=200
a3=800b3=500
可以根据实际使用情况对该表进行进一步调整。
其次、判断当前音频数据帧是否需要丢掉,丢掉输出用isCanDelete表示:为了根据映射表energy_threshold_map[ms]判断是否需要丢掉当前的音频数据帧frame,需要知道当前语音缓冲长度buffer_ms和当前音频数据帧frame的能量值frame_energy。循环查找映射表项中的数组[an],判断每项是否满足丢包条件:buffer_ms>an并且frame_energy<bn,如果满足,则判定需要丢掉当前音频数据帧frame,设置isCanDelete=true,否则判定不能丢掉当前音频数据帧frame,设置isCanDelete=false;并将输出判定结果isCanDelete给调用者。