-- | Reader for ATS analyis data files. module Sound.SC3.UGen.External.ATS (ATS(..) ,ATSHeader(..) ,ATSFrame,atsFrames ,atsRead) where import qualified Data.ByteString.Lazy as B {- bytestring -} import Data.Int {- base -} import Data.List.Split {- split -} import Sound.OSC.Coding.Byte {- hosc -} -- | ATS analysis data. data ATS = ATS { atsHeader :: ATSHeader , atsData :: [Double] } deriving (Eq, Show) -- | ATS analysis meta-data. data ATSHeader = ATSHeader { atsSampleRate :: Double , atsFrameSize :: Int , atsWindowSize :: Int , atsNPartials :: Int , atsNFrames :: Int , atsMaxAmplitude :: Double , atsMaxFrequency :: Double , atsAnalysisDuration :: Double , atsFileType :: Int , atsFrameLength :: Int } deriving (Eq, Show) -- | ATS analysis frame data. type ATSFrame = [Double] bSep :: Int64 -> Int64 -> B.ByteString -> [B.ByteString] bSep n i d = if i == 1 then [d] else let (p,q) = B.splitAt n d in p : bSep n (i - 1) q atsParse :: FilePath -> IO [Double] atsParse fn = do d <- B.readFile fn let n = B.length d `div` 8 v = B.take 8 d f = get_decoder v return (map f (bSep 8 n d)) -- | Read an ATS data file. atsRead :: FilePath -> IO ATS atsRead fn = do d <- atsParse fn let f j = d !! j g = floor . f ft = g 9 (n, x) = ftype_n ft np = g 4 nf = g 5 fl = np * n + x hdr = ATSHeader (f 1) (g 2) (g 3) np nf (f 6) (f 7) (f 8) ft fl return (ATS hdr d) -- | Extract set of 'ATSFrame's from 'ATS'. atsFrames :: ATS -> [ATSFrame] atsFrames a = chunksOf (atsFrameLength (atsHeader a)) (atsData a) -- Determine endianess and hence decoder. get_decoder :: B.ByteString -> B.ByteString -> Double get_decoder v = if decode_f64 v == 123.0 then decode_f64 else decode_f64 . B.reverse -- Calculate partial depth and frame constant. ftype_n :: Int -> (Int, Int) ftype_n n = case n of 1 -> (2, 1) 2 -> (3, 1) 3 -> (2, 26) 4 -> (3, 26) _ -> error "ftype_n" {- -- | Analysis data in format required by the sc3 ATS UGens. atsSC3 :: ATS -> [Double] atsSC3 (ATS h d) = let f = fromIntegral td = transpose d in f (atsFileType h) : f (atsNPartials h) : f (atsNFrames h) : f (atsWindowSize h) : concatMap (td !!) (atsSC3Indices h) -- Indices for track data in the order required by sc3. atsSC3Indices :: ATSHeader -> [Int] atsSC3Indices h = let np = atsNPartials h o = 3 * (np - 1) a = [1,4 .. (1 + o)] f = map (+ 1) a p = map (+ 1) f n = map (+ (4+o)) [0..24] in if atsFileType h == 4 then a ++ f ++ p ++ n else error "atsSC3Indices: illegal ATS file type (/= 4)" -}