{-# 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