Lazy Sound File IO
Hannah Schroeter
uk1o@rz.uni-karlsruhe.de
Sun, 2 Dec 2001 13:17:46 +0100
Hello!
On Tue, Oct 23, 2001 at 11:01:00AM -0400, Carl McTague wrote:
> Please let me refine my question.
> Is there a general way to coerce an [Int] or [Double] etc. into a String,
> so that it may be written out to a binary file with hPutStr? There is
> toEnum, but this doesn't seem like a real solution, since it only works for
> Int values <256.
I'd write some format at least readable by programs like sox. E.g.
raw headerless 16-bit signed integers w/ a fixed sample rate. Maybe
even stereo if you are generating stereo sounds.
Now, let's do simple 16-bit integer lists, assume we have a stream
of Ints which additionally are between -2^15 and 2^15 - 1. And assume
we want network byte order (high byte first).
writeInts :: [Int] -> IO ()
writeInts = putStr . ints2Str
ints2Str :: [Int] -> String
ints2Str = concatMap int2str
where
int2str i | i >= -32768 && i <= 32767 =
map Char.chr [(i `mod` 65536) `div` 256, i `mod` 256]
That's it.
If you want to write stereo, you should interleave the Ints,
such as
nullElement :: Int -- the sample value for silence
mixStereo :: [Int] -> [Int] -> ([Int], [Int])
mixStereo [] [] = []
mixStereo l [] = zip l (repeat nullElement)
mixStereo [] l = zip (repeat nullElement) l
mixStereo (x:xs) (y:ys) = (x,y) : mixStereo xs ys
Hope that helps, even if late.
Kind regards,
Hannah.