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.
Greetings, — one of the CELT developers here.
ReplyDeleteDid you try using the _ctl call to change the encoder complexity? The encoder does a fair amount of non-essential analysis, some of which can be deactivated to lower the complexity.
A 150MHz "486" running the encoder in realtime seems quite reasonable, so unless it's surprisingly slow. I'm certainly interested in seeing CELT running on hardware like this.
Just to be sure— you're compiling in fixed point mode, right? (There are several defines that need to be set if you're not using autoconf to build the config.h) It sounds like from your lame comment that you don't even have emulation, but I figure that it's better to ask the silly questions than to be surprised later.
Gregory, the standard setting in the toolchain for the RDC is to activate FPU-emulation.
ReplyDeleteI compiled lame and vorbis using these settings.
In the CELT package I activated FIXED_POINT.
The reason why lame and vorbis failed was the emulation slowness.
I had the same experience with my initial testing on CELT, where the slowness and resulting overruns made me think the codec was malfunctioning.
The reason for not investigating the lame/vorbis behaviour indepth, was my need for a low latency codec. If I wanted to do point to point streaming of audio, having a low latency codec would be a plus. In my second life as FM radio technician and internet DJ/broadcaster, there's one major letdown when streaming audio : latency.
Thanks for the hint.
I will give it another go on the Bifferboard. I must admit I didn't try to optimize the encoder behaviour, so I'll drop a note in the celt-dev mailinglist in case I'm stuck here.
Greetz