Lazy Sound File IO
Sun, 2 Dec 2001 13:17:46 +0100
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
int2str i | i >= -32768 && i <= 32767 =
map Char.chr [(i `mod` 65536) `div` 256, i `mod` 256]
If you want to write stereo, you should interleave the Ints,
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.