DSP Software Development

Follow the development of speech algorithms for digital radios through the complete project life cycle.

In this article, I describe a Linux success story based on researching and developing DSP (Digital Signal Processing) speech coding algorithms. I chose Linux over Windows for good reasons—reasons that may provide you with ammunition to persuade the bosses that Linux really does mean business. To emphasize this, I developed the software for the next generation of digital radio products in the headquarters of the world's largest private mobile radio manufacturer.

Luckily, I had an open-minded boss, but there were still difficulties. These included interoperability issues with existing systems, resource sharing, accessibility, documentation and the non-availability of some crucial software for Linux.

Project Life Cycle

A typical project life cycle begins with university research and proceeds through initial investigation and prototyping, a complex coding route and various testing stages to a fully documented software package for passing on to system integrators.

My project was advanced speech processing software for fixed-point DSP. Bearing this in mind, audio capabilities topped the list of requirements for any development machine. Also needed were good mathematical processing and visualization software and a whole set of code-development tools. Finally, some DSP-specific software was required.


Given recorded speech files, research often involves processing and evaluating the changes by listening to them. For this, a sound card is useful, and with the availability of the OSS drivers, sound output is no problem for Linux. The easiest way to generate sound is to copy a sound data file to /dev/audio. Tradition specifies this data file should be in Sun's 8-bit logarithmic format, sampled at 8KHz. The command

cp audiofile.au /dev/audio

outputs sound, assuming everything is set up properly (see Resources for good audio information).

How do you get Sun format audio? The answer is to use sox (SOund eXchange). Its command-line options seem a bit unfriendly at first, but the following command converts a .wav file into a Sun format .au file:

sox audiofile.wav -t ul -r 8000 audiofile.au

Traditional processing is done by writing a C or similar program to read in the speech file, perform some processing and write the output either directly to /dev/audio (if the program can output the data in real time) or to a temporary file first (if it cannot). This works okay, but the compile-link-test-modify cycle can be too lengthy to permit efficient trial-and-error testing (sometimes called research).

One alternative is MATLAB, the excellent commercial mathematical manipulation package; however, I found an alternative with a GPL—Rlab. Although not promoted as a MATLAB clone, this high-quality suite of software is at least as usable, truly multi-platform and free. The range of built-in functions in Rlab is impressive and allows the seamless addition of user functions. Data can be imported/exported, processed and displayed graphically, as shown in Figure 1. See Resources for some useful additional Rlab functions, including an audio playback routine.

Figure 1. Using Rlab to Modify and Plot Speech Waveforms

All this gives us an ideal platform for speech algorithm research. We can listen to audio, make modifications and build up a library of speech processing routines to use in current and future investigations. The modifications can be tried and evaluated with little effort.


Now the algorithms found after playing with Rlab must be converted manually to DSP code. This isn't actually easy for a number of reasons: the Rlab code makes use of built-in library routines and is floating-point. The humble DSP is only fixed-point, so normally this conversion is done in three steps.

The first is to go directly from the Rlab script to C—replicating all the Rlab functions with C functions of the same name, which you write and test, and rewriting the glue code. This produces an executable that is bit-exact with the Rlab code, so halting or single-stepping the code with gdb can allow direct comparisons between the C and the Rlab script.

The second step is to replace all the floating-point variables and functions with fixed-point alternatives. For each data variable, we need to know maximum and minimum values and the effect of truncation, then truncate and scale appropriately.

For trigonometric functions, a number of established techniques such as approximation and table lookup may be used, but these can be difficult to code. It doesn't help that DSP memory is extremely limited and the law of code size applies (i.e., code size will expand until it's just larger than the available space).

However, fiddling with numbers can be good fun, and trying to write a fixed-point log function by hand may require a few more visits to Rlab in order to work out exactly what a logarithm does.

Eventually, a C program emerges that has no floating-point variables (use grep to make sure); other than scaling and truncation errors, it performs the same function as the original Rlab code. Again, gdb can be used to investigate execution. We can import array data to Rlab for plotting by selecting the data and dropping it into an Rlab script.

One trick is to write a C function that, when passed an array, prints the array formatted so that it can be selected and pasted into Rlab—code such as:

void rprint(int length, int *array) {
   for (int i=0;i<length;i++)
   printf("\b];\nplot(array)\n"); }

When used frequently in the debugging cycle, this can be very effective.

The last point to mention under prototyping is the benefit of using some form of version control, or perhaps I should say the foolishness of not using it. Effective version control is one of the major reasons UNIX/Linux is a stable and capable development platform. We used RCS throughout the development process. In fact, the main RCS directory was on a Sun accessed via an NFS mount and shared by a number of developers working under Solaris.