首先,在现在这个微信的时代,做一个IMapp,绝对不能少了语音通讯这个功能,如果没有了语音通讯功能我相信在当下已经不能算是一个IM了。
由于前段时间在忙碌一个新的项目,导致这个模块已经耽误了一个月了。终于在今天另一个项目上线之后我从新开始这个模块的研究。
在研究开始之前,我首先去市场下载了几个目前比较流行IM,然后通过强大的反编译和文件查找能力,发现即使是陌陌这个app ,他们的语音传输都是没有经过比较大的压缩的(MEWOW同样地没没有经过较大的压缩),但微信则是通过自身强大的算法,对音频文件进行了压缩处理,把音频转化为WAV格式的音频文件,大概60秒的音频文件,大小就为70K的左右,而WAV格式的文件其他机器直接可以使用API进行播放,例如在网页上。
在开始真正使用speex进行编码压缩的之前,来先了解一下音频特性。
首先音频有几个基本特性:采样率,声道,比特率。
采样率越高,声音越接近真实。
比特率越高,每帧处理的数据越多,传输的速率越快。
最好还要去了解一下窄带和宽带以及其他一些音频术语的含义,这里我 就不一一说明了,麻烦你们自行进行百度。
在理解好一通术语之后,现在要找的事就是找个列子回来参照一下。由于我们IM客户端是同时有ios和android端的,所以我要找两个系统的列子回来看看。
1.ios栗子
2.android栗子
首先,两个栗子都是可以使用,而且都是进行录音,编码,解码,播放。但是,问题来了,ios上面的经过speex处理的音频是否可以在android上面进行播放呢?答案是:不可以的,当然,是以上两个栗子的音频文件是不能给对方系统解码播放的。What are you 弄啥勒!
为了解决这个问题,必须更深入去研究两者编码和解码的差异。
1.先来翻看一下 android的编码过程。
1.1 边录边编码
1.2 录完经过OGG再次压缩格式
1.3 每帧处理160个字节,160个字节经过编码压缩为20个字节。
1.4 加入头信息
2.再去翻看一下ios的编码过程。
2.1 录制完成后,在acf录音文件中提取音频源数据pcm
2.2 每一帧编码pcm数据,每一帧160个字节。
2.3 每一帧160个源数据,经过编码压缩为38个字节
2.4 把38这个数字加入到数据头中
2.5 经过OGG压缩格式。
由上可知,两个栗子中对录音的处理相对有点差异,正是这种差异导致两个系统出来的录音不能给予彼此进行解码播放。
为了消除这种差异,我一开始进行了方案一:做一个库,让android与ios的音频处理一样。
这样的库应该是基于ios上面那个栗子的源码再写出一个jni的文件,然后给android方进行调用。
但是,这里第一步就已经把我难到了,ios系统中的char类型与java中byte有所不一样(具体自行百度)。这个方案研究了一天之后,我决定放弃,但我相信这样方案会更统一点,这样的话,两个系统对音频处理的方法就会一致了。(该方案日后再研究)
其实可以翻看以下一段ios栗子中代码发现,ios端的处理也是把一段数据分为每一帧进行编码。
由于ios也是把一个源pcm数据,拆分成每一帧160个字节进行编码,那么我只要把两个系统的编码流程统一就可以了。
方案二:统一编码流程,解码流程。
由下图看出,ios和android编码完一帧之后得到的spx加密数据长度是不一样。而这个加密后的数据长度就是spx文件下每一帧数据长度。例如:38个spx长度数据加密了160ios音频pcm数据,那么解码的时候,必须用38个spx还原出160个音频PCM数据,这样才能被播放器所播放。因此,解码播放的时候,38这个每帧加密后的数据长度必须告知解码端,否则播放失败。
因此,根据android端的情况,统一了一下编码与解码的流程:
1 . 声音录入
2. 录音器按每一帧处理,获取每一帧音频PCM数据。
3. 把每一帧音频PCM数据传给speex编码器。
4. speex编码器把每一帧PCM数据编码压缩,增溢降噪,输出每一帧编码过后的spx数据
5. 保存每一帧spx数据。
6. 录音结束,在所有spx数据前加入数据头,标示该段录音音频用了什么样的采样率,比特律,声道等。
7. 把spx数据保存到.spx文件中。
speex的处理流程如下图:
1.传输流程
2.编码流程
根据以上的阐述,可以清晰知道speex编码的整个流程如何了,关于代码方面,【明天上新】。
PS:
由于本人确实很少时间维护博客,因为平时除了上班,下班还要买菜煮饭拖地喂奶溜狗踢球跑步诳街,所以难得更新一会,不过最近时间多了,就开始更新吧。
版权声明:本文为博主原创文章,未经博主允许不得转载。