DSP软件开发
在本文中,我描述了一个基于研究和开发DSP(数字信号处理)语音编码算法的Linux成功案例。我出于充分的理由选择了Linux而不是Windows——这些理由可能会为您提供弹药来说服老板们,Linux确实意味着商业机会。为了强调这一点,我在世界上最大的私营移动无线电制造商的总部开发了下一代数字无线电产品的软件。
幸运的是,我有一位思想开放的老板,但仍然存在困难。这些困难包括与现有系统的互操作性问题、资源共享、可访问性、文档以及某些关键Linux软件的不可用性。
一个典型的项目生命周期始于大学研究,并经历初步调查和原型设计、复杂的编码过程以及各种测试阶段,最终形成一个完整文档的软件包,以便传递给系统集成商。
我的项目是用于定点DSP的先进语音处理软件。考虑到这一点,音频功能是任何开发机器的首要需求。还需要优秀的数学处理和可视化软件以及一整套代码开发工具。最后,还需要一些DSP专用软件。
给定录制的语音文件,研究通常涉及通过听取它们来处理和评估变化。为此,声卡很有用,并且随着OSS驱动程序的可用性,声音输出对于Linux来说不是问题。生成声音的最简单方法是将声音数据文件复制到/dev/audio。传统上,此数据文件应为Sun的8位对数格式,采样率为8KHz。命令
cp audiofile.au /dev/audio
输出声音,假设一切都设置正确(有关良好的音频信息,请参阅“资源”)。
如何获得Sun格式的音频?答案是使用 sox (声音交换)。它的命令行选项起初看起来有点不友好,但以下命令将.wav文件转换为Sun格式的.au文件
sox audiofile.wav -t ul -r 8000 audiofile.au
传统的处理方法是编写C或类似的程序来读取语音文件,执行一些处理,并将输出直接写入/dev/audio(如果程序可以实时输出数据)或首先写入临时文件(如果不能)。这种方法还可以,但是 编译-链接-测试-修改 循环可能太长,无法进行有效的试错测试(有时称为研究)。
一种替代方案是 MATLAB,这是一款出色的商业数学操作软件包;但是,我找到了一个具有GPL的替代方案——Rlab。虽然Rlab没有被宣传为MATLAB的克隆,但这个高质量的软件包至少同样好用,真正实现了多平台且免费。Rlab中内置函数的范围令人印象深刻,并允许无缝添加用户函数。数据可以导入/导出、处理和图形化显示,如图1所示。有关一些有用的附加Rlab函数(包括音频播放例程),请参阅“资源”。
所有这些为我们提供了一个理想的语音算法研究平台。我们可以收听音频、进行修改并建立一个语音处理例程库,用于当前和未来的研究。可以轻松地尝试和评估这些修改。
现在,在使用Rlab进行试验后找到的算法必须手动转换为DSP代码。这实际上并不容易,原因有很多:Rlab代码使用内置库例程并且是浮点型的。而简单的DSP只是定点型的,因此通常此转换分三个步骤完成。
第一步是直接从Rlab脚本转到C——用同名的C函数复制所有Rlab函数,您编写并测试这些函数,并重写胶水代码。这将生成一个与Rlab代码位精确的可执行文件,因此使用 gdb 停止或单步执行代码可以实现C代码和Rlab脚本之间的直接比较。
第二步是用定点替代方案替换所有浮点变量和函数。对于每个数据变量,我们需要知道最大值和最小值以及截断的影响,然后适当地截断和缩放。
对于三角函数,可以使用许多成熟的技术,例如近似和查表,但是这些技术可能难以编码。雪上加霜的是,DSP内存非常有限,并且代码大小定律适用(即,代码大小将扩展到刚好大于可用空间为止)。
但是,摆弄数字可能很有趣,并且尝试手动编写定点 log 函数可能需要多次访问Rlab,以便弄清楚对数到底是什么。
最终,出现了一个没有浮点变量的C程序(使用 grep 确保);除了缩放和截断错误之外,它执行与原始Rlab代码相同的功能。同样,可以使用gdb来调查执行情况。我们可以通过选择数据并将其拖放到Rlab脚本中,将数组数据导入到Rlab以进行绘图。
一个技巧是编写一个C函数,当传递一个数组时,该函数会打印格式化的数组,以便可以选择该数组并将其粘贴到Rlab中——例如以下代码
void rprint(int length, int *array) { printf("\narray=["); for (int i=0;i<length;i++) printf("%d,",array[i]); printf("\b];\nplot(array)\n"); }
当在调试周期中频繁使用时,这可能非常有效。
关于原型设计的最后一点要提到的是使用某种形式的版本控制的好处,或者也许我应该说不使用它的愚蠢之处。有效的版本控制是UNIX/Linux成为稳定且功能强大的开发平台的主要原因之一。我们在整个开发过程中都使用了RCS。实际上,主要的RCS目录位于通过NFS挂载访问的Sun服务器上,并由许多在Solaris下工作的开发人员共享。
现在是DSP的参与——为此需要一个DSP入门套件。为了简单易用的开发,有两个主要的竞争者可用。两者都对Linux的支持参差不齐,成本在80英镑左右,并且面向业余爱好者、小型企业或大学用户。
最初的是来自德州仪器的TMS320C50 DSK(有一个更早、功能较弱的C26板),而较新的竞争者是ADI公司的ADSP2181 EZ-KIT Lite。两者都具有音频I/O——后者具有16位CD质量的立体声音频,而前者只能处理14位语音质量。在软件方面,两者都提供了一套不错的DOS可执行文件——汇编器、链接器和(对于ADI公司的套件)一个模拟器。ADSP的优势在于其汇编语言语法比TI芯片更加用户友好。我不会冒险评论哪个DSP更强大——两者都相当出色。
大多数DSP开发工具的Linux版本都在互联网上流传,但有些仍然缺失,特别是对于ADSP2181。这些缺失的是汇编器、链接器和模拟器,这很遗憾,因为我不得不使用ADSP。
免费提供的交叉汇编器 as 将很快包含ADSP21xx 兼容性。它已经处理了TMS320Cxx 代码以及其他数量惊人的处理器,并且每当作者Alfred Arnold有空闲时间时,都会添加更多。ADI公司已被接洽,要求提供汇编器和链接器的Linux版本,但他们表示目前没有支持Linux的计划。
对于DSP代码开发,我们需要一个汇编器、链接器和一个代码下载器,该下载器通过PC串行端口将可执行文件发送到DSP开发板。对于ADSP21xx,目前可用的Linux工具很少,只有下载器。
解决方案是使用DOSEMU,即Linux DOS模拟器,它有一个令人印象深刻的功能,称为 dexe(直接可执行的DOS应用程序)。这基本上是微型DOS磁盘映像中的单个DOS文件或应用程序,可以在Linux中执行,而用户不会意识到它实际上是一个DOS程序。
要使用此方法,可以将整个ADSP21xx工具集合并到单个.dexe文件中。凭借一点独创性、一些简单的shell脚本和批处理文件,用户永远不会知道他正在使用的汇编器和链接器实际上是DOS程序(有关操作指南,请参阅“资源”)。
有了新创建的dexe,我们现在就有了用于DSP代码的汇编器和链接器。ADI公司网站深处隐藏着一个UNIX(Linux/Sun)下载监视器的源代码,用于通过PC串行端口将DSP可执行文件加载到EZ-KIT Lite中。这意味着汇编器源代码可以全部(或多或少)在Linux下编译和下载。
一个令人恼火的问题是模拟器。ADI公司提供了一个DOS版本的模拟器,该模拟器无法在模拟器下运行,但这并不是放弃Linux的理由,我们稍后将看到。
ADI公司确实有一个基于经典的 gcc 的21xx C编译器,甚至发布了源代码。C代码与汇编语言完美集成,并加快了开发时间,但是它在代码大小和指令周期方面都相当低效。
我们现在有一个在DSP系统上运行的算法。这项工作生成的完整软件包包括
Rlab研究和调查脚本
来自Rlab的测试向量和语音文件
浮点C实现
定点C实现
代码的汇编语言版本
可工作的DSP可执行文件
这个列表看起来完整吗?如果是这样,那你一定像我一样是天生的程序员。任何其他人都会意识到缺少文档。
你遇到过这种情况吗?当你的管理层说文档必须采用标准格式时,你想到了 LaTeX,而他们想到了Microsoft Word。由于缺乏文本格式和图形支持,ASCII是不够的。
但是,即使您的老板也可以同意的一个无可辩驳的标准是HTML。一旦就通用标准达成一致,就该生成一组文档模板了。之后,可以使用任何编辑器来添加内容,包括Netscape composer、Emacs甚至Word。图形更成问题,但是 xfig 和 GIMP 的组合可以处理大多数情况。生成的Web文档可以在Linux、Windows、RISC OS等下读取,甚至可以在掌上电脑上访问。
为了符合公司质量控制标准,我们也使用RCS来管理文档版本。这允许将诸如 <li>RCS id: $Id$</li> 之类的构造嵌入到HTML中。当HTML文档签入RCS时,RCS标识符将插入到“$”符号之间,因此将显示在HTML页面上。
一种更漂亮的方法是在Netscape中使用JavaScript进行显示,以格式化页面并删除不需要的$符号。清单1中的HTML页面构成了某些代码文档的封面,如图2所示。
我们都知道HTML并不完美,但至少它是朝着无纸化办公室努力可以达成的妥协方案。我们合并的其他一些功能包括将RCS日志条目放置在HTML页面上的可滚动文本区域中,以及明智地使用超链接链接到注释的源代码、数据流图和流程图。
为了增强我们的文档,C原型代码使用 GCC -pg 编译,这会插入额外的代码以在程序执行期间写入性能分析信息文件。然后使用 gprof 来解释此性能分析信息。使用 xfig 手动将其转换为函数调用、图形GIF,并为其创建了一个敏感图像映射。创建并编辑了一组HTML模板来记录每个函数;可以通过单击此顶级GIF访问这些页面。
结果是一个HTML页面,以金字塔式层结构显示整个代码,从 main 开始,以及每个函数之间的调用链接,并在每个调用链接旁边写入传递的变量名。这些函数在可单击的框内命名,这些框指向该函数的说明。
此HTML文档编制过程现在正在自动化;有关更多信息,请参阅“资源”。
作为额外的奖励,我的同事们使用新的文档标准来证明购买更多Linux机器是合理的。其中一台用于使用Apache Web服务器在公司内联网上提供文档服务。该系统可以根据需要控制对文档的访问,并记录用户访问与日期和文档版本的关系。甚至可以在用户最近访问的文档发生更改时通过电子邮件自动通知受影响方。
最后,让我们考虑一下Linux的替代方案。EZ-KIT随附的ADI公司工具都在DOS下运行,并且是命令行程序。当然,它们可以在Windows DOS提示符下运行,但这并没有比Linux带来任何优势。此外,xterm比Windows DOS提示符更灵活,特别是当您想回顾闪过的错误消息页面时。此外,ADSP21xx模拟器将无法在Windows下运行,Windows必须干净地重启到DOS,就像需要运行模拟器的Linux机器一样。
这些工具的UNIX版本由ADI公司提供,但需要额外付费,并且在功能上与DOS版本相同。但是,它们仅在SunOS下运行;它们不在较新版本的Solaris下运行。
MATLAB可用于Linux、其他UNIX系统和Windows,Rlab也是如此,但我认为只有UNIX操作系统的灵活性才能充分利用这些应用程序与其他基于命令行的代码开发和调试工具进行交互。当然,调试工具适用于所有平台。它们有时可能更用户友好,但可能不如gdb功能强大,而且很少免费提供。
版本控制系统也适用于许多平台,但并非所有系统都能应对代码开发并与通过Apache提供的基于超链接HTML的文档系统集成。您选择的版本控制系统还必须具有与您喜欢的编辑器接口并在 make 层次结构中使用的能力。
显然,Linux是一个很好的DSP开发系统。您只需要购买一个DSP入门套件——其他所有内容都在您的安装CD上或可以免费下载。这个系统已经在现实世界中使用过了——它需要一些设置,但它可以工作。它可靠并且比Windows有趣得多。
将来,情况只会变得更好:更多DSP开发工具将在Linux下可用。我鼓励大家倡导在大学和企业研发中使用基于Linux的开发系统。
