Friday, July 20, 2007

Simplifying Spectral processing in CLAM

Current CLAM Spectrum implementation has four different internal representations: Complex array, polar array, separated magnitude and phase buffers, and separated magnitude and phase break point functions (point controled envelopes). Conversion and synchronization among such representations were handled by the Spectrum class itself and this was intended to be transparent. But processing algorithms had to know which representations were already present to trade off between doing conversion and applying different versions of a given algorithm depending on the representation.

For instance, spectrum product in polar representation is cheaper by itself than complex product, but if you have to convert incoming or outcomming spectrums it migth be not so cheap. What about having two different representations for each operand? Which one should be converted? Output format could be a discriminant but do the module has information to know which is the convenient output representation? Such decissions make the implemention of processings using spectrums really complex.

Besides that, algorithms also had to consider different cases for different scales (linear or dB). So the complexity of processing objects having to deal with spectra is very high. A lot of code dealt with querying the presence of a given representation or synchronizing them.

So, we decided to simplify all that by having several kind of spectrum for each representation and doing any representation change explicit by a converter processing. We are currently considering just two spectrum classes: MagPhaseSpectrum and ComplexSpectrum. We added also converters to the current Spectrum to enable progressive migration. The implementation of FFT and IFFT was highly simplified as we don't need to deal with conversions and prototypes configuration, just to input or output complex spectra.

This is a setup of a system which perform complex and polar products of two spectra:

The spectral product has been simplified. Now we have a product for each kind of spectrum in contrast with the previous situation where we had a single module containing implementations for every combinations of inputs.

Code is really simpler to understand and write this way. After having all that we could do a profiling on comparing which is best, conversions and cheap product or no conversions and expensive product. The option without conversions won but the situation can change on the future depending on the optimizations we could do on the conversion. Having the processing modules factored that way we could change them and doing the benchmark that easy.

In the process of takin such decission we noticed that some elementary CLAM elements such as the AudioSource, AudioSink and specially AudioMixer were taking too much CPU.

After fixing that we got a clear profile that highlights which is the proper strategy for spectrum product for our concrete case. Callgrind is a really nice tool:

So I hope we can move soon to that new way of doing spectral processing in CLAM but still a lot of code must be updated.

Monday, July 2, 2007

CLAM Plugins

One of the most interesting features of the upcomming CLAM release will be a plugin system that will allow users to add their own processings as a plugin to any CLAM based application.
Just by placing a library on a given folder.

We provide some cute tutorials on writting simple processings from scratch, and a SConstruct file that will compile and install everything in a given folder as a plugin.

It has been more easy than we thought as we were frightened by Visual 'mecatxis' and we just dropped it. A single class did the work. There is still some work to do on documenting the registration of the configuration dialogs for the processings and making the Processing Tree of the network editor to populate automatically from the factory content.

The former can be done very quick by adding the Qt4 configurator as a CLAM library, but we want to provide a more general solution not requiring users linking against Qt4. The later (processing tree population) is something Andreas Calvo is working with. And he is doing nice progresses.

Deprecating Windows as development platform

In this entry i will explain how we got ride of Windows as development platform for the CLAM project still providing Windows binaries by using the tandem mingw32 (for Linux) and Wine. We dealt with crosscompilation of most of CLAM dependencies such as Portaudio, Asio, libsndfile, liboggvorbis, pthreads, fftw3, libmad, id3lib, XercesC, libxml++, NSIS and Py2Exe.

After a very dissapointing and fustrating effort from Pau and me of trying to have a reproducible build environment for CLAM based on Visual Express 2005, we decided that the whole thing was foolish and decided give mingw a try.

I am proud of not having a Windows box available at home ;-) but that doesn't mean i cannot contribute to that part of the development so the last days i did an spike on having mingw crosscompiling CLAM from Linux! We succeeded to compile it all, the dependencies, CLAM and the applications. Because some dll conflicts when installing that could not go into the 1.1.0 version of CLAM. After a gutsy update we could compile it all,
so expect rewamped windows binaries for the next release... and maybe development binaries. You can already give a try to the latest svn snapshots.

The key point has been using Wine to install with their own windows installers some libraries and tools such as Qt4, GTK (for pkg-config, libxml++ and dependencies), and NSIS to build windows installers from Linux!

Wine and mingw are a great tandem to compile and test the binaries. Also SConstruct has been a nice tool to hack a quick build environment for third party libraries when the one provided (normally based on autotools) was too messy to get on with.

We kept a reproducible log of the mingw crosscompilation at the clam wiki. This includes how to get all the dependencies working, which may be usefull for you own project. CLAM dependencies we addressed were: Portaudio, Asio, libsndfile, liboggvorbis, pthreads, fftw3, libmad, id3lib, XercesC, libxml++, NSIS and Py2Exe.