{-# LANGUAGE RebindableSyntax #-}
module Durations where
import qualified ClassRecord
import qualified Class
import qualified Sound.Audacity.LabelTrack as LabelTrack
import Control.DeepSeq (NFData, rnf, force)
import Control.Applicative (Applicative, liftA2, pure, (<*>))
import qualified Data.Traversable as Trav
import qualified Data.Foldable as Fold
import Data.Traversable (Traversable, traverse)
import Data.Foldable (Foldable, foldMap)
import qualified Algebra.Additive as Additive
import NumericPrelude.Numeric hiding (sum)
import NumericPrelude.Base hiding (readFile, writeFile)
data T a =
Cons {
total :: a,
classes :: ClassRecord.T a
}
names :: T String
names = Cons "Total" ClassRecord.names
instance NFData a => NFData (T a) where
rnf (Cons totalDur classDurs) = rnf (totalDur, classDurs)
instance Functor T where
fmap = Trav.fmapDefault
instance Foldable T where
foldMap = Trav.foldMapDefault
instance Traversable T where
traverse f (Cons totalDur classDurs) =
liftA2 Cons (f totalDur) (traverse f classDurs)
instance Applicative T where
pure a = Cons a $ pure a
Cons fTotal fClasses <*> Cons totalDur classDurs =
Cons (fTotal totalDur) (fClasses <*> classDurs)
class Track f where
intervalSizes :: (Additive.C t) => f t a -> f t (t, a)
-- ToDo: move to audacity
instance Track LabelTrack.T where
intervalSizes =
LabelTrack.mapWithTime (\bnds lab -> (uncurry subtract bnds, lab))
sum ::
(Track f, Foldable (f Double)) =>
f Double (Class.Abstract advert rasping chirping ticking growling) ->
T Double
sum =
Fold.foldl'
(\(Cons totalDur acc) (dur,cls) ->
let add r select set = set r $ select r + dur
in force $ Cons (totalDur+dur) $
case cls of
Class.Advertisement _ _ _ ->
add acc ClassRecord.advertisement
(\r d -> r{ClassRecord.advertisement = d})
Class.NoAdvertisement (Class.Rasping _) ->
add acc ClassRecord.rasping
(\r d -> r{ClassRecord.rasping = d})
Class.NoAdvertisement (Class.Chirping _) ->
add acc ClassRecord.chirping
(\r d -> r{ClassRecord.chirping = d})
Class.NoAdvertisement (Class.Ticking _) ->
add acc ClassRecord.ticking
(\r d -> r{ClassRecord.ticking = d})
Class.NoAdvertisement (Class.Growling _) ->
add acc ClassRecord.growling
(\r d -> r{ClassRecord.growling = d})
Class.NoAdvertisement (Class.Other _) -> acc)
(pure 0) .
intervalSizes