本人用的是SILK_SDK_SRC_v1.0.9进行开发.开发过程是曲折的,结果自然也是丰盛的.
SDK是从github下载的,由于这个已被整合到一个Android项目,但是文件目录结构尚完整.
所以本人就尝试直接编译整个项目,结果无法编译过去,个人认为是NDK版本不对.后来又看到有
Makefile文件,尝试用make来编译,发现不大理想,首先要生成一堆make用到的文件,这方面不
大熟悉.后来看见有一个Silk_SDK.sln文件,干脆就从这个文件入手,用vs2013打开这文件,先编
译Silk_Fix项目,再编译Dec_SDK项目,完美编译,在项目文件夹中生成Decoder_debug.exe.点
击可以直接运行.算是成功了一半.在控制台中运行,发现输出参数说明是.pcm格式的,到了这里有
点眉目了,.pcm应该是音频数据的最原始数据,声卡能够直接的数据.因为以前在开发webp图片解
码工具,就是直接生成图像的像素数据的.所以认为.pcm应该就是音频最直接的原始数据.接着就是
用Decoder_debug.exe来解码一段Sdk提供的样本.在目录test_vectors\bitstream中.
用法: 样本数据路径 输出路径
当然可以设置其他的参数,这里选择默认不输入,结果完整输出,所以认为程序的输入参数正确.那有了
解码生成的.pcm数据,怎中么检查是否正确,再回过头来想一想,既然.pcm数据是最原始数据,那应该
有程序可以播放.后来经过百度一下:java pcm 发现可以编写java应用来播放.pcm.就马上动手,打开
eclipse 复制代码编译运行,尝试播放,结果可以播放,不过听得不清楚,是不是样本数据本身就这样的?
后来就去手机QQ里找一段silk来进行尝试.为什么我会从手机QQ里找?这里面是有缘由的.
因为自从前几天升级手机QQ之后,发现里面的amr文件居然是零字节,只能在手机QQ里面找聊天
记录播放,当然也可以在里面收藏起来,但是问题来了,只能在手机QQ里播放,就算能收藏起来,谁知道
那天腾讯不再提供收藏了怎么办?里面的很多音频声音都是很动听的呀,对于程序汪汪那是很珍贵的呀!
后来在该目录下还发现有.slk文件,这个也是不能播放,发现和amr文件同名,可以断定那是音频数据,传到
电脑,用notepad++ hex方式打开,发现文件头有这么一个标识 #!SILK_V3,后来经过百度搜索,发现这
是silk文件,后来找到了相关的SDK进行编译.最开始找到的是v1.0.7版本的,里面被上传者写有一个例子,
下载下来编译不过去,其实应该还是NDK的问题吧.再找其他版本,然后就从github下载了v1.0.9版本,就
开始了上面的工作.
回到前面的话题,QQ里面的silk文件不是标准的silk文件,腾讯在文件最前面加了一个字节,后面的与
标准的silk文件格式相同.马上用java编写程序,截取QQ语言文件里面的silk文件.然后用
Decoder_debug.exe解码,生成.pcm文件,用刚才的java程序进行播放,终于传出动人的完整声音.那种
感觉大家都懂的.
接着就是想办法如何封装pcm数据了,首先想到的是无损压缩.因为在解码silk的时候都是用了最好
的参数,这样才能拥有更高保真度.搜索一番,发现都没有好的工具来封装pcm数据,convert可以实现,但
是又要下载安装,很不方便.但是发现和pcm数据有直接关系的是wav格式,写个文件头再复制pcm数据
就可以了.马上写个java程序进行尝试,果然能够完美播放.
又回到NDK的推荐编译方式上,因为咱要把Android版的应用做出来才能方便大众,毕竟不是每个
人都有电脑吧,咱程序猿就讲究奉献吧?!一定要把Android的解码工具做出来!既然不能直接编译,就老
老实实地删繁就简,提取SILK_SDK_SRC_ARM_v1.0.9里面的src和interface目录的文件到Android
项目的jni目录下,大家都知道编译原生应用很关键的一步是,如何编写Android.mk文件.可是无论怎么
写这个文件就是编译不过去.那就先编译SDK成静态库,发现能通过编译.为什么v1.0.7里面的例子就无
法编译?后来干脆删除掉,再回头看看vs2013里面的程序是可以完美运行的,那好直接将里面的
Decoder.c复制过来.先不写任何关于jni的代码,先将Decoder编译成动态库试试,结果还是不行.再回
过头看看下载下来的项目,发现里面的Android.mk文件多了些.S文件需要编译,终于明白了是怎么的
回事,原来S文件和.c文件作为源文件一起编译,当然interface里面的头文件也要添加到Android.mk
里面.Android.mk先编译SDK静态库,再编译Decoder.c成动态库,可是还是无法编译,百度后网友说,
NDK的版本不对,换了NDK版本还是不行,就想是不是ARM版本不兼容?那就舍弃ARM最低版本,直接
将ABI设置为ARMv7.这一次完美编译.接着就是怎么整合了,由于QQ语音和微信语音文件不是标准的
silk文件,一个方案是在java里面先将QQ语音截取成标准的silk文件.后来用了这样的一个方案,将main
函数改成int decode(int argc, char* argv[], int offset);前面两个参数和控制台的一样.为什么要
加offset,不在argv多添加一个字符串,原因是int 类型比字符串类型处理上方便些.再在jni.c文件中将
参数传进去.完美编译!问题又来了,ARM的虚拟机不好用,试试上X86 Android虚拟机,果然不行.那就
在Android.mk里面添加条件语句,编译X86版本的源文件变量不添加.S汇编.完美编译.再用java写封
装方法,成功运行,解码silk文件.
剩下的工作就是进行应用的修改,使得更加人性化.同时用C#编写PC端工具,PC端主要是为
Decoder.exe写一个GUI的参数输入工具,并同时实现封装.
这次就写到这里,后面有好的编程经历也会写出来和大家分享.