module Sound.Analysis.Meapsoft ( Frame(..), Segment
, features
, read_file
, segments) where
import Control.Monad
import System.IO
data Frame = Frame {
onset_time :: Double
, duration :: Double
, avg_mel_spec :: [Double]
, avg_chroma :: [Double]
, avg_chunk_power :: Double
, avg_chroma_scalar :: Double
, avg_freq_simple :: Double
, avg_mfcc :: [Double]
, avg_pitch_simple :: Double
, avg_spec_centroid :: Double
, avg_spec_flatness :: Double
, avg_spec :: [Double]
, chunk_length :: Double
, chunk_start_time :: Double
, spectral_stability :: Double
, raw_data :: (Double, Double, [[Double]]) }
deriving (Show, Read)
type Segment = (Double, Double)
segments :: [Frame] -> [Segment]
segments = map (\c -> (onset_time c, duration c))
features :: [(String, Int)]
features = [ ("AvgMelSpec", 40)
, ("AvgChroma", 12)
, ("AvgFramePower", 1)
, ("AvgChromaScalar", 1)
, ("AvgFreqSimple", 1)
, ("AvgMFCC", 13)
, ("AvgPitchSimple", 1)
, ("AvgSpecCentroid", 1)
, ("AvgSpecFlatness", 1)
, ("AvgSpec", 513)
, ("FrameLength", 1)
, ("FrameStartTime", 1)
, ("SpectralStability", 1) ]
read_file :: FilePath -> IO [Frame]
read_file f =
do h <- openFile f ReadMode
t <- hGetContents h
let l = drop 2 (lines t)
return (map parse_frame l)
form_groups :: [Int] -> [a] -> [[a]]
form_groups [] _ = []
form_groups (n:ns) l = a : form_groups ns b
where (a, b) = splitAt n l
type Chunk = (Double, Double, [[Double]])
make_chunk :: [Double] -> Chunk
make_chunk (o:t:f) = (o, t, form_groups (map snd features) f)
make_chunk _ = error "misformed data"
make_frame :: Chunk -> Frame
make_frame c@(o, t, [ f1, f2, [f3], [f4], [f5]
, f6, [f7], [f8], [f9], f10
, [f11], [f12], [f13] ]) =
Frame o t f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 c
make_frame _ = error "make_frame"
split_on :: (Eq a) => a -> [a] -> [[a]]
split_on x xs = l' ++ r'
where (l, r) = span (/= x) xs
l' = if null l then [] else [l]
r' = if null r then [] else split_on x (tail r)
to_f :: String -> Double
to_f = read
parse_frame :: String -> Frame
parse_frame = make_frame . make_chunk . map to_f . drop 1 . split_on ' '