3. 编译和移植
通过自动配置在UNIX/Linux或其它平台支持(如Win32/cywin)编译Speex很容易,只需键入:
%./configure[options]
%make
%make install
其设置支持是通过Speex配置脚本的:
-prefix=
指定Speex安装其本路径(如 /usr)
-enable-shared/-disable-shared 是否编译共享库
-enable-static/-disable-static 是否编译静态库
-disable-wideband 取消Speex的宽带部分(典型的节省空间)
-enable-valgrind 为调试目的启用额外valgrind的命中率
-enable-sse 启用SSE指令(只在 x86/浮点)
-enable-fixed-point 编译Speex为无浮点单位(FPU)处理器
-enable-arm4-asm 启用汇编指定为ARMv4架构(只在gcc)
-enable-arm5e-asm 启用汇编指定为ARMv5E架构(只在gcc)
-enable-fixed-point-debug 只使用调试定点码(非常慢)
-enable-epic-48k 启用一个专门(不兼容)4.8kbps窄带模式(在1.1.x和1.2beta)
-enable-ti-c55x 启用支持TI C5x族
-enable-blackfin-asm 启动汇编指定为Blackfin DSP架构
-enable-vorbis-psycho 使编码器使用Vorbis心理学模型。这是非常实验性,可能在将来会被移除
3.1 平台
Speex是众所周知可在大量架构上编译和运行的,包括浮点和定点。一般只要架构能够自然地计算两个有符号16位数(32位结果)的相乘,和运行足够的时钟率,就能够运行Speex。下面是Speex知道能运行的架构(可能还可以运行于很多其它架构):
(1)x86 & x86-64
(2)Power
(3)SPARC
(4)ARM
(5)Blackfin
(6)Coldfire (68k family)
(7)TI C54xx & C55xx
(8)TI C6xxx
(9)TriMedia (experimental)
Speex知道可工作的前几个操作系统包括(它可能可工作于其它很多操作系统上):
(1)Linux
(2)uCLinux
(3)MacOS X
(4)BSD
(5)其它 UNIX/POSIX 变种
(6)塞班
源代码目录在README.xxx文件里包括了在一定的架构和操作系统编译的信息。
3.2 移植和优化
当在某一个新的或存在的平台上移植或优化Speex时,这里有一些事要思考。
3.2.1 CPU优化
影响Speex的CPU使用很多是因为是否编译它使用浮点或定点。如果你的CPU/DSP没有浮点单元(FPU),当编译使用定点将会更快。如果有FPU,测试哪个版本更快是很重要的。在x86体系,浮点一般会更快,但不总是这样子。编译Speex作为定点,你需要通过-fixed-point去配置脚本或者定义宏FIXED_POINT。作为1.2beta3,它现在可以禁用浮点兼容的API,这意味着你的代码可以连接一个没有浮点的仿真库。只要配置-disable-float-api 或者定义DISABLE_FLOAT_API宏。直到VBR功能移植到定点,不然你还需要配置-disable-vbr或定义DISABLE_VBR。
检查一些DSP构架上的其它重要事情是:
(1)确认缓存被设置为回写模式
(2)如果芯片使用SRAM代替缓存,确认有多少代码和数据是存在SRAM的,而不是RAM
如果你准备写汇编,那下面的函数是经常你首先应该考虑的:
(1)filter_mem16()
(2)iir_mem16()
(3)vq_nbest()
(4)pitch_xcorr()
(5)interp_pitch()
滤波函数filter_mem16()和iir_mem16()是实现直接形式II转(DF2T)。虽然,架构是基于乘法累加(MAC),DF2T频繁地重载加法器,这会使用代码非常的慢。在这架构(如 Blackfin 和 Coldfire), 一个更好的方法是使用DF1实现函数,这是比较容易表示的MAC。当那样做,确认DF1执行仍表现得像原来DF2T的表现是很重要的。这是很有必要的,因为滤波器是时变的和必须计算精准的相同值(不包括机四舍五入)
3.2.2 内存优化
内存优化是小嵌入平台主要需要思考的事情.在PC平台,Speex已经足够小了,不值得去做这些事情.这里有一些方法去降低Speex内存的使用,从代码大小和数据大小方面着手.优化代码大小,关键首先是删除你不需要的功能.一些例子可以很容易去禁用你不需要的项目:
(1) 宽带支持(-disable-wideband)
(2) 支持立体声(删除 stereo.c文件)
(3) VBR支持(-disable-vbr 或 宏DISABLE_VBR)
(4) 静态码本,比特率你使用的是不需要的(*_table.c 文件)
Speex也有一些方法去分配暂时数组.当使用支持C99属性的编译器(自2007年起,微软编译器不支持了,但GCC支持),最好这定义VAR_ARRAYS. 使用C99的变化长度数组时,最好定义USE_ALLOCA已致Speex能使用alloc()去分配暂时数组. 注意在很多系统, alloca()是BUG所以它可能不能工作. 如果没有定义VAR_ARRAYS和USE_ALLOCA,那Speex将回落分配一个很大的暂时空间,并让它成为自己的内部空间.这解决方案主要的缺点就是太浪费了.它需要为最坏的情况(最坏的比特率、最高的复杂度设置...)分配够的栈空间,而且默认不共享多个编码器/解码器之间的内存。如果只剩下手动分配唯一的设置,仍有一些东西能被改善的,通过重写os_support.h文件里面的speex_alloc_scratch()调用,它总是可以返回相同的内存区域。除些之外,通过重定义NB_ENC_STACK和NB_DEC_STACK(或相似宽带)可以只为已知优势的方案下分配内存。在这种情况,可以为明确的采样率,比特率和复杂度水平测量内存需要的数量。