module Sound.File.NeXT ( Header(..)
, header
, read
, write
, module Sound.File.Encoding ) where
import Prelude hiding (read)
import qualified Data.ByteString.Lazy as B
import Data.Int
import Data.Maybe
import Sound.OpenSoundControl.Byte
import Sound.File.Decode
import Sound.File.Encode
import Sound.File.Encoding
type Offset = Int64
type SampleRate = Int
type FrameCount = Int
type ChannelCount = Int
data Header = Header { frameCount :: FrameCount
, encoding :: Encoding
, sampleRate :: SampleRate
, channelCount :: ChannelCount }
deriving (Eq, Show)
toEncoding :: Int -> Encoding
toEncoding 2 = Linear8
toEncoding 3 = Linear16
toEncoding 5 = Linear32
toEncoding 6 = Float
toEncoding 7 = Double
toEncoding _ = undefined
fromEncoding :: Encoding -> Int
fromEncoding Linear8 = 2
fromEncoding Linear16 = 3
fromEncoding Linear32 = 5
fromEncoding Float = 6
fromEncoding Double = 7
magic :: Int
magic = 0x2e736e64
encodeHeader :: Header -> B.ByteString
encodeHeader (Header nf enc sr nc) =
let nb = nf * nc * sizeOf enc
h = [magic, 28, nb, (fromEncoding enc), sr, nc, 0]
in B.concat (map encode_i32 h)
decodeHeader :: B.ByteString -> Maybe (Offset, Header)
decodeHeader u =
let f n = decode_i32 (B.drop n u)
m = f 0
off = fromIntegral (f 4)
nb = f 8
enc = toEncoding (f 12)
sr = f 16
nc = f 20
nf = nb `div` (nc * sizeOf enc)
in if m == magic
then Just (off, Header nf enc sr nc)
else Nothing
writeB :: FilePath -> Header -> B.ByteString -> IO ()
writeB fn (Header nf enc sr nc) d =
let h = encodeHeader (Header nf enc sr nc)
b = B.append h d
in B.writeFile fn b
write :: FilePath -> Header -> [[Double]] -> IO ()
write fn (Header nf enc sr nc) d =
let b = encode enc d
in writeB fn (Header nf enc sr nc) b
readB :: FilePath -> IO (Header, B.ByteString)
readB fn = do
b <- B.readFile fn
let (off, h) = fromMaybe undefined (decodeHeader b)
return (h, B.drop off b)
header :: FilePath -> IO Header
header fn = do
(h, _) <- read fn
return h
read :: FilePath -> IO (Header, [[Double]])
read fn = do
(Header nf enc sr nc, b) <- readB fn
let d = decode enc nc b
return (Header nf enc sr nc, d)