A blog about skating and cycling, or vice versa

Giving it FLAC#

Tue, 07 Oct 2008 01:21:16 +0000

In my quest for a scriptable mixing system I tried csound (the syntax does my head in, and it won't read flac without having to convert it manually first), supercollider (doesn't work on 64 bit boxes), and ecasound (simpler than csound but requires too much base 60 arithmetic, and pitch/speed shifting for some reason sounds absolutely horrendously awful). Some time on Sunday I had the idea to write a bit of Perl that'd take a tracklist with specification of fades, pitch changes etc and turn it into an ecasound command line for me, and then I found Audio::FLAC::Decoder and decided to see if I could do it all in-house, so to speak.

From http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=501250 :

From: Daniel Barlow 
To: Debian Bug Tracking System 
Subject: libaudio-flac-decoder-perl: Does not produce same output as flac -d: data
 interleaved in weird way
Date: Sun, 05 Oct 2008 23:49:53 +0100
Package: libaudio-flac-decoder-perl
Version: 0.2-2.2+b1
Severity: important

I have rated this "important" because its effect is to make the output sound absolutely awful. On inspection of the decoded output and visual comparison with that from flac -d, it appears that each correct 16 bit word in the Audio::FLAC::Decoder output is followed by another word from elsewhere in the file.

It's the kind of code you would look at and think "how the hell did that ever work" - except of course that there's no clear evidence it did. The resulting audio is sufficiently reminiscent of the original that at first I suspected it was just my really abysmal computer speakers (then I spent an hour trying to see if it was Perl's weirdo utf8 handling, just in case) but eventually I bit the bullet and broke out od.

Having hacked it back together (there's a patch in that bug report for anyone else similarly afflicted) I find that playing two tracks at once in a no-attention-paid-to-efficiency-at-all fashion eats about 20% cpu, but there are some really stupid format conversions going on there (libflac produces 16 bit samples in the msb of 32 bit words, then A::F::D converts into 16 bit packed samples and makes it a perl string, then my perl code unpacks it into an int array again to add the values one by one to the other stream) so I think it'll be fine for more complex stuff too if we can make it a bit less stupid first. If not, we get to play linking-ECL-with-libflac just to see what happens, but that involves writing glue for the callback system and for the moment I'm just as happy using someone else's that already works. Or at least, would be if it did.

In related news, still only halfway through ripping my CD collection - the process sort of ran down as 50% of the disks I try now don't rip cleanly. I am hoping I haven't toasted my CDROM drive ...