Tuesday, January 4, 2011

AudioStreamer - CeltStreamer

I must admit that chosing the Edimax 6104 router wasn't the easiest path to OpenWRT hacking, but it was very rewarding in terms of the learning curve. After some minor tweaking I decided to dig deeper into the wonders of Embedded micro-architectures. One of the uses of the Openwrt system was to be able to distribute audio without the hassle of audio cables. But what about capturing and broadcasting audio directly from my router or similar machine ?

So a new project was born : audiostreamer

Objective : find the smallest, cheapest machine to capture 22Khz audio and broadcast it to a corresponding receiver. Budget : 50 €

After reading some forums, I stumbled on the Bifferboard (S3282@150Mhz, 8MB ROM, 32MB RAM).
It has sufficient space for all my programming needs and measures only 68x28x21 mm ! That's tiny !

  • Bifferboard : 35 GBP
  • Housing : 5 GBP
  • USB Soundcard : 1.8 GBP

Streaming PCM from and to the device didn't pose any major difficulty :
[Streaming] arecord -D plughw:0,0 -r 48000 -c 2 -f S16_LE | nc 192.168.2.10 6666
[Receiving] nc 192.168.2.9 6666 | aplay -D plughw:0,0

Playing some MP3 audio worked too, using mpc and mpd, combined with a shoutcast-server on my desktop.

The next hurdle was to produce compressed audio in order to minimize bandwidth use ...

  • LAME : failed (lack of FPU on the S3282)
  • IVORBIS (Fixed Point version of Vorbis) : failed

Then I did some research and found another Fixed Point codec .... CELT - Constrained Energy Lapped Transform.

After some fiddling with the 'tools' sources, I managed to compile the celtencoder and celtdecoder.
They work fine ... but they don't seem to be compatible with the aplay / arecord PCM netcatting.
The result is a working encoding/decoding environment, but unfortunately not realtime !

Nicely tucked away in the GIT-repository, I found the celtclient demo and tried to implement it.
I stripped out the streaming part and reduced the main loop to the following activities :



do { alsa_read(pcm1) ; celt_encode(pcm1,celt) ; celt_decode(celt,pcm2) ; alsa_write(pcm2) } loop

Massive overruns and underruns in the ALSA part ....

My Bifferboard running at approximately 50 BogoMips could only handle following testcase @ 8Khz, mono:
do { alsa_read(pcm) ; celt_encode(pcm,celt) ; alsa_write(pcm) } loop

In order to estimate the needed processing power for celt_encode@22Khz I ported the sources to my Edimax environment.
The Adm5120 runs at approx 170BogoMips and should at least on paper provide 3x more processing power.

After implementing the ALSA-sound subsystem I couldn't get the USB Audio to play a standard WAV-file without being completely choppy and slowed down.
Turns out the USB-host on the ADM5120 isn't completely following the USB specifications and is lacking Isochronuous transfer mode.

I'm left no other solution than to get myself a different board to test on. I'm not sure if I would strip down one of the latest routers (TP-LINK 1043 - Atheros AR9132@400Mhz - 266 BogoMips) or maybe look at one of the Marvel boards.