packages feed

temporal-media 0.1.1 → 0.2.0

raw patch · 3 files changed

+653/−804 lines, 3 filesdep +dlistdep +mtldep −containersPVP ok

version bump matches the API change (PVP)

Dependencies added: dlist, mtl

Dependencies removed: containers

API changes (from Hackage documentation)

- Temporal.Media: (:+:) :: Media c a -> Media c a -> Media c a
- Temporal.Media: (:=:) :: Media c a -> Media c a -> Media c a
- Temporal.Media: Control :: c -> (Media c a) -> Media c a
- Temporal.Media: MediaUnit :: t -> (Media c (Unit t a)) -> MediaUnit t c a
- Temporal.Media: Prim :: a -> Media c a
- Temporal.Media: Unit :: t -> (Maybe a) -> Unit t a
- Temporal.Media: class Arrangeable a
- Temporal.Media: class Construct m
- Temporal.Media: class Controlable c a
- Temporal.Media: class Reversible a
- Temporal.Media: class Temporal t a => Sliceable t a
- Temporal.Media: class Temporal t a => Stretchable t a
- Temporal.Media: class Dur t => Sustainable t f
- Temporal.Media: class Dur t => Temporal t a
- Temporal.Media: class Dur t => TemporalFunctor t f
- Temporal.Media: class Stretchable t a => TemporalStretchable t a
- Temporal.Media: class ToMaybe m
- Temporal.Media: control :: Controlable c a => c -> a -> a
- Temporal.Media: cut :: (Reversible a, Sliceable t a) => t -> t -> a -> a
- Temporal.Media: data Dur t => MediaUnit t c a
- Temporal.Media: data Dur t => Unit t a
- Temporal.Media: drop :: Sliceable t a => t -> a -> a
- Temporal.Media: fold :: (a -> b) -> (b -> b -> b) -> (b -> b -> b) -> (c -> b -> b) -> Media c a -> b
- Temporal.Media: foldU :: Dur t => (t -> a -> b) -> (b -> b -> b) -> (b -> b -> b) -> (c -> b -> b) -> MediaUnit t c a -> Maybe b
- Temporal.Media: fromMedia :: Arrangeable b => (a -> b) -> (c -> b -> b) -> Media c a -> b
- Temporal.Media: fromMediaUnit :: Dur t => (c -> EventList t a -> EventList t a) -> MediaUnit t c a -> EventList t a
- Temporal.Media: instance (Dur t, Stretchable t a) => Stretchable t (EventList t a)
- Temporal.Media: instance (Eq a, Dur t) => Eq (Unit t a)
- Temporal.Media: instance (Eq c, Eq a) => Eq (Media c a)
- Temporal.Media: instance (Show a, Dur t) => Show (Unit t a)
- Temporal.Media: instance (Show c, Show a) => Show (Media c a)
- Temporal.Media: instance Applicative (Media c)
- Temporal.Media: instance Arrangeable (Media c a)
- Temporal.Media: instance Construct (Media c)
- Temporal.Media: instance Controlable c (Media c a)
- Temporal.Media: instance Dur t => Applicative (MediaUnit t c)
- Temporal.Media: instance Dur t => Applicative (Unit t)
- Temporal.Media: instance Dur t => Arrangeable (EventList t a)
- Temporal.Media: instance Dur t => Arrangeable (MediaUnit t c a)
- Temporal.Media: instance Dur t => Construct (EventList t)
- Temporal.Media: instance Dur t => Construct (MediaUnit t c)
- Temporal.Media: instance Dur t => Construct (Unit t)
- Temporal.Media: instance Dur t => Controlable () (EventList t a)
- Temporal.Media: instance Dur t => Controlable c (MediaUnit t c a)
- Temporal.Media: instance Dur t => Functor (EventList t)
- Temporal.Media: instance Dur t => Functor (MediaUnit t c)
- Temporal.Media: instance Dur t => Functor (Unit t)
- Temporal.Media: instance Dur t => Monad (MediaUnit t c)
- Temporal.Media: instance Dur t => Monad (Unit t)
- Temporal.Media: instance Dur t => Reversible (MediaUnit t c a)
- Temporal.Media: instance Dur t => Reversible (Unit t a)
- Temporal.Media: instance Dur t => Sliceable t (MediaUnit t c a)
- Temporal.Media: instance Dur t => Sliceable t (Unit t a)
- Temporal.Media: instance Dur t => Stretchable t (MediaUnit t c a)
- Temporal.Media: instance Dur t => Stretchable t (Unit t a)
- Temporal.Media: instance Dur t => Sustainable t (EventList t)
- Temporal.Media: instance Dur t => Sustainable t (MediaUnit t c)
- Temporal.Media: instance Dur t => Temporal t (EventList t a)
- Temporal.Media: instance Dur t => Temporal t (MediaUnit t c a)
- Temporal.Media: instance Dur t => Temporal t (Unit t a)
- Temporal.Media: instance Dur t => TemporalFunctor t (EventList t)
- Temporal.Media: instance Dur t => TemporalFunctor t (MediaUnit t c)
- Temporal.Media: instance Dur t => TemporalFunctor t (Unit t)
- Temporal.Media: instance Dur t => TemporalStretchable t (MediaUnit t c a)
- Temporal.Media: instance Dur t => ToMaybe (Unit t)
- Temporal.Media: instance Functor (Media c)
- Temporal.Media: instance Monad (Media c)
- Temporal.Media: instance Reversible a => Reversible (Media c a)
- Temporal.Media: instance Sliceable t a => Sliceable t (Media c a)
- Temporal.Media: instance Stretchable t a => Stretchable t (Media c a)
- Temporal.Media: instance Stretchable t a => TemporalStretchable t (Media c a)
- Temporal.Media: instance Temporal t a => Temporal t (Media c a)
- Temporal.Media: mapEvent :: Dur t => (a -> b) -> Event t a -> Event t b
- Temporal.Media: prim :: Construct m => a -> m a
- Temporal.Media: reverse :: Reversible a => a -> a
- Temporal.Media: sustain :: (Dur t, Sustainable t f) => t -> f a -> f a
- Temporal.Media: sustainBy :: Sustainable t f => (t -> t -> a -> (b, t)) -> f a -> f b
- Temporal.Media: take :: Sliceable t a => t -> a -> a
- Temporal.Media: toEvent :: (Temporal t (m a), ToMaybe m) => m a -> EventList t a
- Temporal.Media: toEventList :: (Temporal t (m a), ToMaybe m) => (c -> EventList t a -> EventList t a) -> Media c (m a) -> EventList t a
- Temporal.Media: toMaybe :: ToMaybe m => m a -> Maybe a
- Temporal.Media: tstretch :: TemporalStretchable t a => (t -> t) -> a -> a
- Temporal.Media: tstretchRel :: (Temporal t a, TemporalStretchable t a) => (t -> t) -> a -> a
- Temporal.Media: type Event t a = (t, t, a)
- Temporal.Media: unMediaUnit :: Dur t => MediaUnit t c a -> Media c (Unit t a)
- Temporal.Media.Double: (+:+) :: Arrangeable a => a -> a -> a
- Temporal.Media.Double: (:+:) :: Media c a -> Media c a -> Media c a
- Temporal.Media.Double: (:=:) :: Media c a -> Media c a -> Media c a
- Temporal.Media.Double: (=:=) :: Arrangeable a => a -> a -> a
- Temporal.Media.Double: Control :: c -> (Media c a) -> Media c a
- Temporal.Media.Double: Prim :: a -> Media c a
- Temporal.Media.Double: class Arrangeable a
- Temporal.Media.Double: class Construct m
- Temporal.Media.Double: class Controlable c a
- Temporal.Media.Double: class Reversible a
- Temporal.Media.Double: class ToMaybe m
- Temporal.Media.Double: control :: Controlable c a => c -> a -> a
- Temporal.Media.Double: cut :: (Reversible a, Sliceable Dur a) => Dur -> Dur -> a -> a
- Temporal.Media.Double: data Media c a
- Temporal.Media.Double: delay :: (Temporal Dur a, Arrangeable a) => Dur -> a -> a
- Temporal.Media.Double: dmap :: TemporalFunctor Dur f => (Dur -> a -> b) -> (f a -> f b)
- Temporal.Media.Double: dmapRel :: (Temporal Dur (f a), TemporalFunctor Dur f) => (Dur -> a -> b) -> (f a -> f b)
- Temporal.Media.Double: drop :: Sliceable Dur a => Dur -> a -> a
- Temporal.Media.Double: dur :: Temporal Dur a => a -> Dur
- Temporal.Media.Double: fold :: (a -> b) -> (b -> b -> b) -> (b -> b -> b) -> (c -> b -> b) -> Media c a -> b
- Temporal.Media.Double: foldU :: (Dur -> a -> b) -> (b -> b -> b) -> (b -> b -> b) -> (c -> b -> b) -> MediaUnit c a -> Maybe b
- Temporal.Media.Double: fromMedia :: Arrangeable b => (a -> b) -> (c -> b -> b) -> Media c a -> b
- Temporal.Media.Double: fromMediaUnit :: (c -> EventList a -> EventList a) -> MediaUnit c a -> EventList a
- Temporal.Media.Double: linseg :: (Ord t, Fractional t) => [t] -> t -> t
- Temporal.Media.Double: loop :: Arrangeable a => Int -> a -> a
- Temporal.Media.Double: mapEvent :: (a -> b) -> Event a -> Event b
- Temporal.Media.Double: none :: Temporal Dur a => Dur -> a
- Temporal.Media.Double: parallel :: Arrangeable a => [a] -> a
- Temporal.Media.Double: prim :: Construct m => a -> m a
- Temporal.Media.Double: reverse :: Reversible a => a -> a
- Temporal.Media.Double: sequent :: Arrangeable a => [a] -> a
- Temporal.Media.Double: slice :: Sliceable Dur a => Dur -> Dur -> a -> a
- Temporal.Media.Double: stretch :: Stretchable Dur a => Dur -> a -> a
- Temporal.Media.Double: sustain :: Sustainable Dur f => Dur -> f a -> f a
- Temporal.Media.Double: sustainBy :: Sustainable Dur f => (Dur -> Dur -> a -> (b, Dur)) -> f a -> f b
- Temporal.Media.Double: take :: Sliceable Dur a => Dur -> a -> a
- Temporal.Media.Double: tdmap :: TemporalFunctor Dur f => (Time -> Dur -> a -> b) -> (f a -> f b)
- Temporal.Media.Double: tdmapRel :: (Temporal Dur (f a), TemporalFunctor Dur f) => (Time -> Dur -> a -> b) -> (f a -> f b)
- Temporal.Media.Double: temp :: (Construct m, Temporal Dur (m a), Stretchable Dur (m a)) => Dur -> a -> m a
- Temporal.Media.Double: tmap :: TemporalFunctor Dur f => (Time -> a -> b) -> (f a -> f b)
- Temporal.Media.Double: tmapRel :: (Temporal Dur (f a), TemporalFunctor Dur f) => (Time -> a -> b) -> (f a -> f b)
- Temporal.Media.Double: toEvent :: (Temporal Dur (m a), ToMaybe m) => m a -> EventList a
- Temporal.Media.Double: toEventList :: (Temporal Dur (m a), ToMaybe m) => (c -> EventList a -> EventList a) -> Media c (m a) -> EventList a
- Temporal.Media.Double: toMaybe :: ToMaybe m => m a -> Maybe a
- Temporal.Media.Double: tstretch :: TemporalStretchable Dur a => (Time -> Dur) -> a -> a
- Temporal.Media.Double: tstretchRel :: TemporalStretchable Dur a => (Time -> Dur) -> a -> a
- Temporal.Media.Double: type Dur = Double
- Temporal.Media.Double: type Event a = Event Dur a
- Temporal.Media.Double: type EventList a = EventList Dur a
- Temporal.Media.Double: type MediaUnit c a = MediaUnit Dur c a
- Temporal.Media.Double: type Unit a = Unit Dur a
- Temporal.Media.Double: unMediaUnit :: MediaUnit c a -> Media c (Unit a)
+ Temporal.Media: (=:/) :: Dur t => Media t a -> Media t a -> Media t a
+ Temporal.Media: Event :: t -> t -> a -> Event t a
+ Temporal.Media: data Event t a
+ Temporal.Media: dropM :: Dur t => t -> Media t a -> Media t a
+ Temporal.Media: eventContent :: Event t a -> a
+ Temporal.Media: eventDur :: Event t a -> t
+ Temporal.Media: eventMap :: (Event t a -> Event t a') -> (Media t a -> Media t a')
+ Temporal.Media: eventStart :: Event t a -> t
+ Temporal.Media: instance (Eq t, Eq a) => Eq (Event t a)
+ Temporal.Media: instance (Show t, Show a) => Show (Event t a)
+ Temporal.Media: instance Dur Float
+ Temporal.Media: instance Functor (Event t)
+ Temporal.Media: instance Functor (EventList t)
+ Temporal.Media: instance Functor (Media t)
+ Temporal.Media: parallelT :: Dur t => [Media t a] -> Media t a
+ Temporal.Media: renderMedia :: Dur t => Media t a -> EventList t a
+ Temporal.Media: reverseM :: Media t a -> Media t a
+ Temporal.Media: takeM :: Dur t => t -> Media t a -> Media t a
- Temporal.Media: (+:+) :: Arrangeable a => a -> a -> a
+ Temporal.Media: (+:+) :: Dur t => Media t a -> Media t a -> Media t a
- Temporal.Media: (=:=) :: Arrangeable a => a -> a -> a
+ Temporal.Media: (=:=) :: Dur t => Media t a -> Media t a -> Media t a
- Temporal.Media: class (Num t, Ord t, Fractional t) => Dur t
+ Temporal.Media: class (Ord a, Num a, Fractional a) => Dur a
- Temporal.Media: data Media c a
+ Temporal.Media: data Media t a
- Temporal.Media: delay :: (Temporal t a, Arrangeable a) => t -> a -> a
+ Temporal.Media: delay :: Dur t => t -> Media t a -> Media t a
- Temporal.Media: dmap :: TemporalFunctor t f => (t -> a -> b) -> f a -> f b
+ Temporal.Media: dmap :: (t -> a -> b) -> Media t a -> Media t b
- Temporal.Media: dmapRel :: (TemporalFunctor t f, Temporal t (f a)) => (t -> a -> b) -> f a -> f b
+ Temporal.Media: dmapRel :: Dur t => (t -> a -> b) -> Media t a -> Media t b
- Temporal.Media: dur :: Temporal t a => a -> t
+ Temporal.Media: dur :: Media t a -> t
- Temporal.Media: loop :: Arrangeable a => Int -> a -> a
+ Temporal.Media: loop :: Dur t => Int -> Media t a -> Media t a
- Temporal.Media: none :: Temporal t a => t -> a
+ Temporal.Media: none :: Dur t => t -> Media t a
- Temporal.Media: parallel :: Arrangeable a => [a] -> a
+ Temporal.Media: parallel :: Dur t => [Media t a] -> Media t a
- Temporal.Media: sequent :: Arrangeable a => [a] -> a
+ Temporal.Media: sequent :: Dur t => [Media t a] -> Media t a
- Temporal.Media: slice :: Sliceable t a => t -> t -> a -> a
+ Temporal.Media: slice :: Dur t => t -> t -> Media t a -> Media t a
- Temporal.Media: stretch :: Stretchable t a => t -> a -> a
+ Temporal.Media: stretch :: Dur t => t -> Media t a -> Media t a
- Temporal.Media: tdmap :: TemporalFunctor t f => (t -> t -> a -> b) -> f a -> f b
+ Temporal.Media: tdmap :: (t -> t -> a -> b) -> Media t a -> Media t b
- Temporal.Media: tdmapRel :: (TemporalFunctor t f, Temporal t (f a)) => (t -> t -> a -> b) -> f a -> f b
+ Temporal.Media: tdmapRel :: Dur t => (t -> t -> a -> b) -> Media t a -> Media t b
- Temporal.Media: temp :: (Construct m, Temporal t (m a), Stretchable t (m a)) => t -> a -> m a
+ Temporal.Media: temp :: Dur t => t -> a -> Media t a
- Temporal.Media: tmap :: TemporalFunctor t f => (t -> a -> b) -> f a -> f b
+ Temporal.Media: tmap :: (t -> a -> b) -> Media t a -> Media t b
- Temporal.Media: tmapRel :: (TemporalFunctor t f, Temporal t (f a)) => (t -> a -> b) -> f a -> f b
+ Temporal.Media: tmapRel :: Dur t => (t -> a -> b) -> Media t a -> Media t b

Files

src/Temporal/Media.hs view
@@ -1,650 +1,646 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}-module Temporal.Media (-	-- * Time classes-	Dur(..), Temporal(..), Stretchable(..), -	ToMaybe(..), TemporalFunctor(..), -    Sustainable(..), sustain,-    TemporalStretchable(..),-    -- * Transformers-	Reversible(..), Sliceable(..), cut, -	-- * Structure -	Construct(..), Arrangeable(..),	Controlable(..),-	sequent, parallel, loop, delay, temp,-	-- * Media-	Media(..), fold, fromMedia,-	-- * Simple interperetation-	-- ** Event list-	Event, EventList(..), -	mapEvent, toEvent, toEventList,-	-- ** Unit Temporal Media-	MediaUnit(..), unMediaUnit, foldU, fromMediaUnit,-	Unit(..),-    -- ** Misc-     tmapRel, dmapRel, tdmapRel,  tstretchRel, linseg-)-where--import Control.Applicative-import Control.Monad--import Data.Function-import Data.Ratio-import Data.Tree--import Prelude hiding (reverse, take, drop)-import qualified Prelude as P (reverse)--import Debug.Trace--debug msg x = trace (msg ++ " : " ++ show x) x------------------------------------------------------ Classes-------------------------------------------------------- Time classes---- | time class-class (Num t, Ord t, Fractional t) => Dur t--instance Dur Double-instance Integral a => Dur (Ratio a)---- | Temporal structures-class Dur t => Temporal t a where-	none    :: t -> a        -- ^ absence of value-	dur     :: a -> t        -- ^ duration of value            ---- | Stretching values by given time-factor-class Temporal t a => Stretchable t a where-	stretch :: t -> a -> a       ---- | Values covertible to 'Maybe'	------  auxiliary class for conversion to 'EventList'-class ToMaybe m where-	toMaybe :: m a -> Maybe a---- | temporal map------ minimal complete defenition : @tdmap@-class Dur t => TemporalFunctor t f where-    -- | map with time-    tmap :: (t -> a -> b) -> f a -> f b   -    -- | map with duration-    dmap :: (t -> a -> b) -> f a -> f b --    -- | map with time and duration-    tdmap  :: (t -> t -> a -> b) -> f a -> f b--    tmap f = tdmap (flip $ const f)-    dmap f = tdmap (const f)--class Dur t => Sustainable t f where    -    -- | map with time and duration and transform duration time-    sustainBy :: (t -> t -> a -> (b, t)) -> f a -> f b---- | adds constant amount of duration to all notes-sustain :: (Dur t, Sustainable t f) => t -> f a -> f a-sustain dt' = sustainBy $ \t dt x -> (x, dt + dt')---class Stretchable t a => TemporalStretchable t a where-    tstretch :: (t -> t) -> a -> a---------------------------------------------------------- transformers-----class Reversible a where-	reverse :: a -> a---- | extracting parts, minimal complete definition:  'slice'.-class Temporal t a => Sliceable t a where-	slice :: t -> t -> a -> a   -- ^ @slice t0 t1 v@ extracts part of @v@ inside @[t0, t1]@-	take  :: t -> a -> a        -	drop  :: t -> a -> a--	take t   = slice 0 t-	drop t x = slice t (dur x) x--sliceErrorMessage = error "should be t0 <= t1, for slice t0 t1" ---- | mixing slice and reverse. ------ @cut t0 t1 v@ - if @t1 < t0@ reverses result of 'slice'-cut :: (Reversible a, Sliceable t a) => t -> t -> a -> a-cut t0 t1 m-	| t0 <= t1  = slice t0 t1 m-	| otherwise = slice (tm - t0) (tm - t1) $ reverse m-	where tm = dur m--------------------------------------------------------- Structure------- | constructor for generic structures-class Construct m where-	prim :: a -> m a---- | composing structures in sequent and parallel ways -class Arrangeable a where-	(+:+) :: a -> a -> a-	(=:=) :: a -> a -> a---- | modifer-class Controlable c a where-	control :: c -> a -> a-	--sequent, parallel :: Arrangeable a => [a] -> a--sequent  = foldl1 (+:+)-parallel = foldl1 (=:=)--loop :: Arrangeable a => Int -> a -> a-loop n = sequent . replicate n --delay :: (Temporal t a, Arrangeable a) => t -> a -> a-delay t x = none t +:+ x----- | constructs generic temporal structure @m a@ form time @t@ and initial value @a@-temp :: (Construct m, Temporal t (m a), Stretchable t (m a))-	=> t -> a -> m a-temp t = stretch t . prim---------------------------------------------------------- Media---- | Data type to represent temporal media-data Media c a = Prim a                        -- ^ single value-	       | Media c a :+: Media c a       -- ^ sequential composition-	       | Media c a :=: Media c a       -- ^ parallel composition-	       | Control c (Media c a)         -- ^ specific environment modifier-		deriving (Show, Eq)----- | Folding Media------ > fold prim seq par mod x------ * prim - responds to 'Prim'------ * seq  - responds to ':+:'------ * par  - responds to ':=:'------ * mod  - responds to 'Control'-fold :: (a -> b) -> (b -> b -> b) -> (b -> b -> b) -> (c -> b -> b) -	-> Media c a -> b-fold prim seq par mod m = -	case m of-		Prim a      -> prim a-		a :+: b     -> (seq `on` f) a b-		a :=: b     -> (par `on` f) a b-		Control c a -> mod c $ f a -	where f = fold prim seq par mod-	---instance Functor (Media c) where-	fmap f x = case x of-			Prim a      -> Prim $ f a-			a :+: b     -> fmap f a :+: fmap f b-			a :=: b     -> fmap f a :=: fmap f b-			Control c a -> Control c $ fmap f a--instance Monad (Media c) where-	return   = Prim-	ma >>= f = case ma of-			Prim a      -> f a-			a :+: b     -> (a >>= f) :+: (b >>= f)-			a :=: b     -> (a >>= f) :=: (b >>= f)-			Control c a -> Control c $ a >>= f--instance Applicative (Media c) where-	pure  = return-	(<*>) = ap----- time--instance Temporal t a => Temporal t (Media c a) where-	none      = Prim . none-	dur       = fold dur (+) max (const id)--instance Stretchable t a => Stretchable t (Media c a) where-	stretch d = fmap $ stretch d--instance Stretchable t a => TemporalStretchable t (Media c a) where-    tstretch f m = tdmapM (\t _ -> stretch $ f t) m-    --- transformers--instance Reversible a => Reversible (Media c a) where-	reverse x = case x of-			Prim a      -> Prim $ reverse a-			a :+: b     -> ((:+:) `on` reverse) b a-			a :=: b     -> ((:=:) `on` reverse) a b-			Control c a -> Control c $ reverse a---instance Sliceable t a => Sliceable t (Media c a) where-	slice t0 t1 m -	    | t1 < t0   = sliceErrorMessage-	    | t1 <= 0   = none $ (t1 - t0)-	    | t0 >= tm  = none $ (t1 - t0)-	    | t0 < 0    = none (abs t0) :+: slice 0 t1 m-	    | t1 > tm   = slice t0 tm m :+: none (t1 - tm)-	    | otherwise = case m of-                        Prim a      -> Prim $ slice t0 t1 a-                        a :+: b     -> sliceSeq t0 t1 a b -                        a :=: b     -> ((:=:) `on` slice t0 t1) a b-                        Control c a -> Control c $ slice t0 t1 a-		where tm = dur m--sliceSeq :: Sliceable t a => t -> t -> Media c a -> Media c a -> Media c a-sliceSeq t0 t1 a b-	| t1 <= ta  = slice t0 t1 a-	| t0 >= ta  = slice (t0 - ta) (t1 - ta) b-	| otherwise = slice t0 ta a :+: slice 0 (t1 - ta) b-	where ta = dur a--	--- Structure--instance Construct (Media c) where-	prim = Prim--instance Arrangeable (Media c a) where-	(+:+) = (:+:)-	(=:=) = (:=:)--instance Controlable c (Media c a) where-	control = Control--------------------------------------------------------- Meaning---- | Media interpretation------ given two functions (to convert elementary value @(a -> b)@, --- and to convert modifiers @(c -> b -> b)@) `fromMedia` interprets 'Media' structure-fromMedia :: Arrangeable b => (a -> b) -> (c -> b -> b) -> Media c a -> b-fromMedia prim mod = fold prim (+:+) (=:=) mod-	---------------------------------------------------------------------------------------	--- | Event type------ @(t, dt, a)@ - value @a@ starts at @t@ and lasts for @dt@-type Event t a = (t, t, a)---- | list of events with given total time-data EventList t a = EventList t [Event t a]-	deriving (Show, Eq)---toEvent :: (Temporal t (m a), ToMaybe m) => m a -> EventList t a-toEvent a = EventList (dur a) $ maybe [] (return . singleEvent) $ toMaybe a-	where singleEvent x = (0, dur a, x)--mapEvent :: Dur t => (a -> b) -> Event t a -> Event t b-mapEvent f (t, dt, a) = (t, dt, f a)--instance Dur t => Functor (EventList t) where-	fmap f (EventList t es) = EventList t $ fmap (mapEvent f) es---- time--instance Dur t => Temporal t (EventList t a) where-	none t = EventList t []-	dur (EventList t _) = t--instance (Dur t, Stretchable t a) => Stretchable t (EventList t a) where-	stretch d (EventList t es) = EventList (d * t) $ map (stretchEvent d) es-		where stretchEvent d (t, dt, a) = (d * t, d * dt, stretch d a)--instance Dur t => TemporalFunctor t (EventList t) where-	tdmap f (EventList t es) = EventList t $ map (tmapEvent f) es-		where tmapEvent f (t, dt, a) = (t, dt, a') where a' = f t dt a--instance Dur t => Sustainable t (EventList t) where-	sustainBy f (EventList t es) = EventList t $ map (tmapEvent f) es-		where tmapEvent f (t, dt, a) = (t, dt', a') where (a', dt') = f t dt a------ structure--instance Dur t => Construct (EventList t) where-	prim a = EventList 1 [(0, 1, a)]--instance Dur t => Arrangeable (EventList t a) where-	(EventList t es) +:+ (EventList t' es') = -		EventList (t + t') (es ++ map (delayEvent t) es')-		where delayEvent d (t, dt, a) = (t + d, dt, a)-	(EventList t es) =:= (EventList t' es') =-		EventList (max t t') $ merge es es'-		where merge []  x = x-		      merge x  [] = x-                      merge (a@(ta, _, _):as) (b@(tb, _, _):bs) -			| ta < tb   = a : merge as     (b:bs)-			| otherwise = b : merge (a:as) bs--instance Dur t => Controlable () (EventList t a) where-	control = const id---- meaning---- | converting to 'EventList'------ 'toEventList' mapps generic temporal value @(m a)@ that can be --- represented with @(t, Maybe a)@ to 'EventList' -toEventList :: (Temporal t (m a), ToMaybe m) -	=> (c -> EventList t a -> EventList t a) -	-> Media c (m a) -> EventList t a-toEventList = fromMedia toEvent-------------------------------------------------------------------------------------------------------------------------------------------------- Special case : Media with explicit time. Value is unit ------- | Media with explicit time------ Value is unit (undividable, invariant to reverse and time stretching) --- O(1) 'dur'-data Dur t => MediaUnit t c a = MediaUnit t (Media c (Unit t a))--unMediaUnit :: Dur t => MediaUnit t c a -> Media c (Unit t a)-unMediaUnit (MediaUnit _ m) = m---instance Dur t => Functor (MediaUnit t c) where-	fmap f (MediaUnit t m) = MediaUnit t $ fmap (fmap f) m---instance Dur t => Monad (MediaUnit t c) where-	return = MediaUnit 1 . return . return-	(MediaUnit t ma) >>= f = MediaUnit (dur ma') ma'-		where ma' = ft =<< ma-                      ft ta = case unMediaUnit . f <$> ta of-				(Unit t (Just a)) -> stretch t a-				(Unit t Nothing)  -> none t --instance Dur t => Applicative (MediaUnit t c) where-	pure  = return-	(<*>) = ap----- time --instance Dur t => Temporal t (MediaUnit t c a) where-	none t              = MediaUnit t $ none t     -	dur (MediaUnit t _) = t--instance Dur t => Stretchable t (MediaUnit t c a) where-	stretch d (MediaUnit t m) = MediaUnit (t * d) $ stretch d m---instance Dur t => TemporalFunctor t (MediaUnit t c) where-    dmap f (MediaUnit t m) = MediaUnit t $ fmap (tmap f) m-    tdmap f (MediaUnit t m) = MediaUnit t $ tdmapM (\t dt -> fmap (f t dt)) m--instance Dur t => TemporalStretchable t (MediaUnit t c a) where-    tstretch f (MediaUnit _ m) = liftA2 MediaUnit dur id $ tstretch f m--instance Dur t => Sustainable t (MediaUnit t c) where-    sustainBy f (MediaUnit t m) = uncurry MediaUnit $ sustainByM f' m-        where f' t dt = liftA2 (,) (fu t dt) (ft t dt)-              ft t dt (Unit d a) = maybe dt (snd . f t dt) a  -              fu t dt = fmap (fst . f t dt) ---tdmapM :: Temporal t a => (t -> t -> a -> b) -> Media c a -> Media c b-tdmapM f m = fmap (\(t, dt, a) -> f t dt a) $ setEvents m--sustainByM :: (Stretchable t a, Stretchable t b) -    => (t -> t -> a -> (b, t)) -> Media c a -> (t, Media c b)-sustainByM f m = (newDur t', rearrangeSustain t' m')-    where t' = setSustainDurs m'  -          m' = tdmapM (\t dt a -> (dt, f t dt a)) m----------------------------------------------------------------- time dependent mapping tools--setEvents :: Temporal t a => Media c a -> Media c (Event t a)-setEvents m = setTimes 0 (setDurs m) m--setDurs :: Temporal t a => Media c a -> Tree t-setDurs = fold prim seq par contr-    where prim  a   = Node (dur a) []-          seq   a b = Node (on (+) rootLabel a b) [a, b]-          par   a b = Node (on max rootLabel a b) [a, b]-          contr c a = Node (rootLabel a) [a]-         --setTimes :: Dur t => t -> Tree t -> Media c a -> Media c (Event t a)-setTimes t0 durTree m = -    case m of-        Prim a  -> Prim (t0, rootLabel durTree, a)-        a :+: b -> setTimes t0 ta a :+: setTimes (t0 + rootLabel ta) tb b-        a :=: b -> on (:=:) (uncurry $ setTimes t0) (ta, a) (tb, b)-        Control c a -> Control c $ setTimes t0 ta a-    where sf = subForest durTree-          ta = sf !! 0-          tb = sf !! 1-    --rearrangeSustain :: Stretchable t a => Tree (t, t) -> Media c (t, (a, t)) -> Media c a-rearrangeSustain tr m = -    case m of-        Prim a  -> Prim $ stretch (newDur tr / oldDur tr) $ fst $ snd a-        a :+: b -> (rearrangeSustainSeq dta dta' dtb dtb') (ra a) (rb b)-        a :=: b -> (rearrangeSustainPar dta dta' dtb dtb') (ra a) (rb b)-        Control c a -> Control c $ ra a-    where sf   = subForest tr-          dta  = oldDur $ sf !! 0-          dtb  = oldDur $ sf !! 1-          dta' = newDur $ sf !! 0-          dtb' = newDur $ sf !! 1-          ra   = rearrangeSustain $ sf !! 0-          rb   = rearrangeSustain $ sf !! 1--rearrangeSustainSeq :: Stretchable t a =>-    t -> t -> t -> t ->-    Media c a -> Media c a -> Media c a-rearrangeSustainSeq dta dta' dtb dtb' a b-    | dta' < dta = sequent [a, none (dta - dta'), b]-    | dta' > dta && dtab  > 0 = parallel [sequent [a, none dtab], delay dta b]-    | dta' > dta && dtab <= 0 = parallel [a, sequent [delay dta b, none (abs $ dtab)]]-    | otherwise  = sequent[a, b]-    where dtab = dta + dtb' - dta' ---rearrangeSustainPar :: Stretchable t a =>-    t -> t -> t -> t ->-    Media c a -> Media c a -> Media c a-rearrangeSustainPar dta dta' dtb dtb' a b  -    | dtab < 0  = parallel [sequent [a, none (abs dtab)], b]-    | otherwise = parallel [a, sequent [b, none (abs dtab)]]-    where dtab = dta' - dtb'----setSustainDurs :: Dur t => Media c (t, (a, t)) -> Tree (t, t)-setSustainDurs = fold prim seq par contr-    where prim  a   = Node (fst a, snd $ snd a) []-          seq   a b = Node (on (+) oldDur a b, oldDur a + newDur b) [a, b]-          par   a b = Node (on max oldDur a b, on max newDur a b)   [a, b]-          contr c a = Node (oldDur a, newDur a) [a]-         --oldDur = fst . rootLabel-newDur = snd . rootLabel--    --- transformers---- | 'fold' replica for MediaUnit-foldU :: Dur t => (t -> a -> b) -> (b -> b -> b) -> (b -> b -> b) -> (c -> b -> b)-	       -> MediaUnit t c a -> Maybe b-foldU prim seq par mod = fold prim' (liftA2 seq) (liftA2 par) mod' . unMediaUnit-	where prim' (Unit t a) = prim t <$> a-	      mod' c = fmap (mod c)-	     	--instance Dur t => Reversible (MediaUnit t c a) where-    reverse (MediaUnit t m) = MediaUnit t $ snd $ fold prim seq par contr m-            where prim u@(Unit dt a) = (dt, Prim u)-                  seq (da, a) (db, b) = (da + db, b :+: a)-                  par (da, a) (db, b) = (\x -> (max da db, x)) $ -                        (if (da < db) -                         then delay (db - da) a =:= b-                         else a =:= delay (da - db) b)-                  contr c (da, a) = (da, Control c a)-                    --instance Dur t => Sliceable t (MediaUnit t c a) where-	slice t0 t1 (MediaUnit t a) = MediaUnit (t1 - t0) $ slice t0 t1 a---- Structure--instance Dur t => Construct (MediaUnit t c) where-	prim = MediaUnit 1 . prim . prim--instance Dur t => Arrangeable (MediaUnit t c a) where-	a +:+ b = MediaUnit (on (+) dur a b) $ on (+:+) unMediaUnit a b-	a =:= b = MediaUnit (on max dur a b) $ on (=:=) unMediaUnit a b-	--instance Dur t => Controlable c (MediaUnit t c a) where-	control c (MediaUnit t a) = MediaUnit t $ control c a---- meaning---- | Interpretation of 'MediaUnit'------ it relies on properties of 'Unit' (it's temporal and covertible to 'Maybe')-fromMediaUnit :: Dur t => (c -> EventList t a -> EventList t a) -	-> MediaUnit t c a -> EventList t a-fromMediaUnit f = toEventList f . unMediaUnit----------------------------------------------------------------- Unit---- | unit values that can happen and lasts for some time-data Dur t => Unit t a = Unit t (Maybe a)-	deriving (Show, Eq)--instance Dur t => Functor (Unit t) where-	fmap f (Unit t a) = Unit t $ fmap f a--instance Dur t => Monad (Unit t) where-	return   = prim -	(Unit t a) >>= f = case fmap f a of-				Nothing         -> none t-				Just (Unit t' b) -> Unit (t * t') b--instance Dur t => Applicative (Unit t) where-	pure  = return-	(<*>) = ap---- time --instance Dur t => Temporal t (Unit t a) where-	none t = Unit t Nothing-	dur (Unit t _) = t--instance Dur t => Stretchable t (Unit t a) where-	stretch d (Unit t a) = Unit (d * t) a--instance Dur t => ToMaybe (Unit t) where-	toMaybe (Unit _ a) = a--instance Dur t => TemporalFunctor t (Unit t) where-    dmap f (Unit t a) = Unit t $ fmap (f t) a-    -    tdmap f (Unit dt a) = -          case a of-            Just x  -> phi dt x-            Nothing -> Unit dt Nothing-         where phi t x = Unit t $ Just $ f 0 t x---- Unit transformers--instance Dur t => Reversible (Unit t a) where-	reverse = id--instance Dur t => Sliceable t (Unit t a) where-	slice t0 t1 u@(Unit t a) -		| t1 < t0          = sliceErrorMessage-		| t1 < (t - eps) || t0 > eps = none $ t1 - t0 -		| otherwise        = u-		where eps = 1e-6 ---- structure--instance Dur t => Construct (Unit t) where-	prim a = Unit 1 $ Just a---------------------------------------------------------------------------------------------------------------------------- Misc------- | relative tmap------ time values are normalized by argument duration.------ @Dur t => t inside [0, 1]@ where 1 is total duration of second argument-tmapRel :: (TemporalFunctor t f, Temporal t (f a)) => (t -> a -> b) -> f a -> f b-tmapRel f x = tmap (f . ( / dur x)) x---- | relative dmap------ time values are normalized by argument duration.------ @Dur t => t inside [0, 1]@ where 1 is total duration of second argument-dmapRel :: (TemporalFunctor t f, Temporal t (f a)) => (t -> a -> b) -> f a -> f b-dmapRel f x = dmap (f . ( / dur x)) x---- | relative tdmap------ time values are normalized by argument duration.------ @Dur t => t inside [0, 1]@ where 1 is total duration of second argument-tdmapRel :: (TemporalFunctor t f, Temporal t (f a)) => (t -> t -> a -> b) -> f a -> f b-tdmapRel f x = tdmap (on f ( / dur x)) x---- | relative tstretch-tstretchRel :: (Temporal t a, TemporalStretchable t a) => (t -> t) -> a -> a-tstretchRel f x = tstretch (f . (/ dur x)) x---- linear interpolation--linseg1 :: (Num t, Ord t, Fractional t) => (t, t, t) -> (t -> t)-linseg1 (a, dur, b) x = a + (b - a) * x / dur---- | linear interpolation------ linseg [a, da, b, db, c, ... ]------ @a, b, c ...@ - values------ @da, db, ...@ - duration of segments-linseg :: (Ord t, Fractional t) => [t] -> t -> t-linseg xs t = -    case xs of-        (a:dur:b:[])      -> seg a dur b t-        (a:dur:b:(x:xs')) -> if t < dur -                             then seg a dur b t-                             else linseg (b:x:xs') (t - dur)-    where seg a dur b t -                | t < 0     = a-                | t >= dur  = b-                | otherwise = a + (b - a)*(t/dur)+{-# LANGUAGE GADTs, FlexibleInstances #-}++-- | An embedded domain-specific language (EDSL) for +-- creating lists of constant time events related in time.+-- Combinators are optimized in fusion style.++module Temporal.Media(+    -- * Introduction++    -- | "Temporal.Media" is an embedded domain-specific +    -- language (EDSL) for creating lists of constant time +    -- events related in time. Constant time event is value+    -- that starts at some fixed time and lasts for some +    -- fixed time. Library provides functions to build lists+    -- of such events with time-relations like sequent,  +    -- parallel or delayed. +    --+    -- Core type of library is 'Media'. It provides interface+    -- to compose list of events. There is optimization that +    -- goes on behind the scene. +    --+    -- * Fusion +    --+    -- >fmap f . fmap g +    --+    -- is trasformed to+    --+    -- >fmap (f . g) +    --+    -- same holds for more general 'eventMap'.+    --+    -- * Loops+    --+    -- Transformations on 'loop' 's are  executed only for +    -- one cycle.+    --+    -- * Structure functions+    --+    -- Structure functions ('sequent', 'parallel', +    -- 'stretch', 'reverseM') are rendered as linear +    -- transformations of time and duration of an event.+    --+    -- Example of usage can be found in package 'temporal-music-notation' [1].+    -- Score module is based on this library.+    --+    -- \[1\] <http://hackage.haskell.org/package/temporal-music-notation>+    +    -- * Types+    +    Dur(..), Media, Event(..), EventList(..),++    -- * Constructors+        +    none, temp,++    -- * Composition++    (+:+), (=:=), (=:/),+    sequent, parallel, parallelT,+    delay, loop,++    -- * Transformations+    +    stretch, +    reverseM,+    slice, takeM, dropM,++    -- * Mappings++    eventMap,+    tmap, dmap, tdmap,+    tmapRel, dmapRel, tdmapRel,++    -- * Rendering+    dur, renderMedia,++    -- * Miscellaneous++    linseg+    )+where    ++++import Data.List(foldl')+import Data.Maybe(catMaybes)+import Data.Ratio(Ratio)+import Data.Function(on)++import Control.Arrow(first, second, (***))++import Control.Monad.State(State, state, runState)+import Control.Monad (foldM, liftM2)++import Data.DList(DList, empty, singleton, append, fromList, toList)++--import Debug.Trace++--debug :: Show a => String -> a -> a+--debug str x = trace (str ++ " : " ++ show x) x++-- | class of 'time' values+class (Ord a, Num a, Fractional a) => Dur a++instance Dur Double+instance Dur Float+instance Integral a => Dur (Ratio a)++-- | 'Media' is core data type. Essentially 'Media' provides +-- functional interface to 'EventList' construction.+data Media t a = Media t (M t a) ++-- | Media operations+data M t a where+-- constructors+    None :: t -> M t a+    Prim :: t -> a -> M t a++-- composition+    Seq  :: [(t, M t a)] -> M t a+    Par  :: [(t, M t a)] -> M t a++    Loop :: Int -> (t, M t a) -> M t a++-- transformation+    Stretch :: t -> (t, M t a) -> M t a++    Slice :: Interval t -> (t, M t a) -> M t a+    Reverse :: M t a -> M t a++-- mappings+    Fmap :: (a' -> a) -> M t a' -> M t a+    Emap :: (Event t a' -> Event t a) -> M t a' -> M t a++-- | Constant time events. Value @a@ starts at some time +-- and lasts for some time.+data Event t a = Event+    { eventStart    :: t+    , eventDur      :: t+    , eventContent  :: a+    } deriving (Show, Eq)+++instance Functor (Event t) where+    fmap f (Event t d a) = Event t d $ f a++-- | List of 'Event' s. First argument stands for total duration+-- of 'EventList'.+data EventList t a = EventList t [Event t a]+    deriving (Show, Eq)++instance Functor (EventList t) where+    fmap f (EventList t es) = EventList t $ map (fmap f) es+++------------------------------------------------------------+------------------------------------------------------------++-- constructors+++-- | 'none' constructs an empty event. +-- Nothing is going on for a given time.+none :: Dur t => t -> Media t a +none d +    | d >= 0    = Media d $ None d+    | otherwise = msgDurErr++-- | 'temp' constructs just an event. Value of type a+-- lasts for some time.+temp :: Dur t => t -> a -> Media t a+temp d a  +    | d >= 0    = Media d $ Prim d a+    | otherwise = msgDurErr++msgDurErr = error "duration must be non-negative"++-- duration querry++-- | Duration querry.+dur :: Media t a -> t+dur (Media t _) = t++unM :: Media t a -> M t a+unM (Media _ x) = x++-- composition++-- | Binary sequent composition. +-- In @(a+:+b)@ @a@ happens first and then @b@ goes.+(+:+) :: Dur t => Media t a -> Media t a -> Media t a+Media t a +:+ Media t' a' = Media (t + t') $ +    case (a, a') of+        (None d, None d') -> None $ d + d'+        _                 -> Seq [(t, a), (t', a')]++-- | Binary parallel composition. +-- In @(a=:=b)@ @a@ and @b@ happen simultaneously.+(=:=) :: Dur t => Media t a -> Media t a -> Media t a+Media t a =:= Media t' a' = Media (max t t') $+    case (a, a') of+        (None d, None d') -> None $ max d d'+        _                 -> Par [(t, a), (t', a')] ++-- | Truncating binary composition. +-- In @(a=:/b)@, @a@ and @b@ happen simultaneously but+-- whole result lasts only for @min ('dur' a) ('dur' b)@ time. +(=:/) :: Dur t => Media t a -> Media t a -> Media t a+a =:/ b = parallelT [a, b]++-- | 'delay' appends block of nothing of given duration +-- to the begging of value (if duration is positive)+-- or to the end of value (if duration is negative).+delay :: Dur t => t -> Media t a -> Media t a+delay d a +    | d > 0     = none d +:+ a+    | d < 0     = a +:+ (none $ abs d)+    | otherwise = a++-- | Sequent composition on lists.+sequent :: Dur t => [Media t a] -> Media t a+sequent xs = Media (sum $ map fst ds) $ Seq ds+    where ds = map (\x -> (dur x, unM x)) xs++-- | Parallel composition on lists.+parallel :: Dur t => [Media t a] -> Media t a+parallel xs = Media (maximum $ map fst ds) $ Par ds+    where ds = map (\x -> (dur x, unM x)) xs++-- | Truncating parallel composition on lists.+parallelT :: Dur t => [Media t a] -> Media t a+parallelT xs = slice 0 d $ parallel xs+    where d = minimum $ map dur xs++-- | 'loop' repeats sequentially given value.+loop :: Dur t => Int -> Media t a -> Media t a+loop n (Media t a)+    | n <= 0    = none 0+    | otherwise = Media (t * fromIntegral n) $+            case a of+                Loop n' a' -> Loop (n * n') a'+                _          -> Loop n (t, a)++--loop n = sequent . replicate n++-- transformation++-- | Stretching values by factor.+stretch :: Dur t => t -> Media t a -> Media t a+stretch k m@(Media t a)  +    | k < 0     = reverseM $ stretch (abs k) m +    | otherwise = Media (k * t) $ +            case a of+                Stretch k' x -> Stretch (k * k') x+                _            -> Stretch k (t, a)+++-- | 'slice' cuts piece of value within given time interval.+-- for @('slice' t0 t1 m)@, if @t1 < t0@ result is reversed.+-- If @t0@ is negative or @t1@ goes beyond @'dur' m@ blocks of+-- nothing inserted so that duration of result equals to +-- @'abs' (t0 - t1)@.+slice :: Dur t => t -> t -> Media t a -> Media t a+slice t0 t1 m@(Media t a)     +    | t0 == t1  = none 0+    | t0 <  t1  = Media (t1 - t0) $ Slice (t0, t1) (t, a)+    | otherwise = slice (t - t0) (t - t1) $ reverseM m++-- | @('takeM' t)@ is equivalent to @('slice' 0 t)@.+takeM :: Dur t => t -> Media t a -> Media t a+takeM t = slice 0 t +++-- | @('dropM' t m)@ is equivalent to @('slice' t (dur m) m)@.+dropM :: Dur t => t -> Media t a -> Media t a+dropM t x = slice t (dur x) x+++-- | Reverses input.+reverseM :: Media t a -> Media t a+reverseM (Media t a) = Media t $+    case a of+        Reverse x -> x+        _         -> Reverse a++-- mappings ++instance Functor (Media t) where+    fmap f (Media t a) = Media t $ +            case a of+                Fmap f' a' -> Fmap (f . f') a'+                _          -> Fmap f a ++-- | General mapping. In the end all values of type 'Media' +-- are to be converted to 'EventList' wich is list of 'Event' s +-- and function 'eventMap' allows mapping on 'Media' subvalues as if +-- they are events already.+--+-- Warning : It is possible to change start time position with +-- 'eventMap' but it can lead to unexpected outcome when used +-- with 'slice' function. 'slice' operates on structure of +-- type 'Media' (how value was built with 'sequent', 'parallel'+-- or 'stretch' and other functions), but 'eventMap' operates +-- on 'Media' subvalues as if they are converted to 'Event' s +-- and some shifted events can slip through 'slice' 's fingers.+eventMap ::    +       (Event t a -> Event t a') +    -> (Media t a -> Media t a')+eventMap f (Media t a) = Media t $ +    case a of+        Emap f' a' -> Emap (f . f') a'+        _          -> Emap f a++-- | map with time+tmap :: (t -> a -> b) -> Media t a -> Media t b+tmap f = tdmap (flip $ const f)++-- | map with duration+dmap :: (t -> a -> b) -> Media t a -> Media t b+dmap f = tdmap (const f)++-- | map with time and duration +tdmap :: (t -> t -> a -> b) -> Media t a -> Media t b+tdmap f = eventMap $ \(Event t d a) -> Event t d $ f t d a++-- | Relative 'tmap'. Time values are normalized by argument's duration.   +tmapRel :: Dur t => (t -> a -> b) -> Media t a -> Media t b+tmapRel f x = tmap (f . ( / dur x)) x++-- | Relative 'dmap'.+dmapRel :: Dur t => (t -> a -> b) -> Media t a -> Media t b+dmapRel f x = dmap (f . ( / dur x)) x++-- | Relative 'tdmap'. +tdmapRel :: Dur t => (t -> t -> a -> b) -> Media t a -> Media t b+tdmapRel f x = tdmap (on f ( / dur x)) x++---------------------------------------------------------------+-- Misc++-- | Linear interpolation. Can be useful with 'eventMap' for +-- envelope changes.+--+-- linseg [a, da, b, db, c, ... ]+--+-- @a, b, c ...@ - values+--+-- @da, db, ...@ - duration of segments+linseg :: (Ord t, Fractional t) => [t] -> t -> t+linseg xs t = +    case xs of+        (a:dur:b:[])      -> seg a dur b t+        (a:dur:b:(x:xs')) -> if t < dur +                             then seg a dur b t+                             else linseg (b:x:xs') (t - dur)+    where seg a dur b t +                | t < 0     = a+                | t >= dur  = b+                | otherwise = a + (b - a)*(t/dur)++----------------------------------------------------------------+----------------------------------------------------------------+-- interpretation++-- | 'renderMedia' converts values of type 'Media' to+-- values of type 'EventList'. If some values have negative+-- time (it is possible through 'eventMap') all events are +-- shifted so that first event has zero start time. Events+-- are unsorted by start time.+renderMedia :: Dur t => Media t a -> EventList t a+renderMedia (Media totalDur m) = formEventList dt es+    where (es, dt) = runState (renderM totalDur initCtx m) dt0+          dt0 = (0, totalDur)  ++++formEventList :: Dur t +    => Interval t -> DList (Event t a) -> EventList t a+formEventList (t0, t1) es = +    EventList (t1 - t0) $ shiftEs $ toList es+    where shiftEs+            | t0 < 0    = map shiftEvent+            | otherwise = id+          shiftEvent e = e{eventStart = eventStart e - t0}   +                +++type MList t a = State (Interval t) (DList (Event t a))++renderM :: Dur t => t -> Ctx t a b -> M t a -> MList t b+renderM totalDur ctx m = +    case m of+     -- constructors+        None d   -> return empty+        Prim d x -> if isSlicePrim (ctxSlice ctx) (0, totalDur)+                        then return empty+                        else renderPrim (ctxTfm ctx) d x++        _        -> if isSliceComp (ctxSlice ctx) (0, totalDur)+                        then return empty+                        else +            case m of+           -- composition+                Seq xs   -> renderSeq ctx xs+                Par xs   -> renderPar ctx xs++                Loop n x -> renderLoop totalDur ctx n x++        -- transformation +                Stretch d x -> renderStretch ctx d x++                Slice dt x  -> renderSlice dt ctx x+                Reverse x   -> renderReverse totalDur ctx x++        -- mappings+                Fmap f m' -> renderFmap totalDur ctx f m'+                Emap f m' -> renderEmap totalDur ctx f m' ++   +renderPrim :: Dur t => Tfm t a b -> t -> a -> MList t b+renderPrim tfm d x = state $ +    \(t0, t1) -> let t0' = min t0 $ eventStart e+                     t1' = max t1 $ eventStart e + eventDur e+                 in  (singleton e, (t0', t1')) +    where e = appTfm tfm $ Event 0 d x+++renderSeq :: Dur t => Ctx t a b -> [(t, M t a)] -> MList t b+renderSeq ctx = fmap fst . foldM phi (empty, 0)+    where phi (res, d') (d, x) = fmap (\x -> (append res x, d' + d)) $ +                    renderM d (shiftCtx d' ctx) x++renderPar :: Dur t => Ctx t a b -> [(t, M t a)] -> MList t b+renderPar ctx = fmap (foldl' append empty) . mapM phi+    where phi (d, x) = renderM d ctx x+++renderLoop :: Dur t+    => t -> Ctx t a b -> Int -> (t, M t a) -> MList t b+renderLoop totalDur ctx n (d, x) = +    fmap (foldl' append empty) $ mapM phi ids +    where e   = renderM d initCtx x+          ids = loopIds (ctxSlice ctx) n d +          phi (segType, ds) =                +                case segType of+                    Part  -> renderM d ctx' x+                    Whole -> fmap (fmap (appTfm $ ctxTfm ctx')) e+                where ctx' = shiftCtx ds ctx++data LoopSeg = Part | Whole++-- ineffective / consider better solution++loopIds :: Dur t => [SliceSeg t] -> Int -> t -> [(LoopSeg, t)] +loopIds f n d = catMaybes $ map phi [0 .. n-1]+    where phi i+            | not $ isSlicePrim f dt = Just (Whole, fst dt)+            | not $ isSliceComp f dt = Just (Part,  fst dt)+            | otherwise              = Nothing+            where dt = (d * fromIntegral i, d)+                    ++++renderStretch :: Dur t+    => Ctx t a b -> t -> (t, M t a) -> MList t b+renderStretch ctx k (d, x) = +    renderM d (stretchCtx k ctx) x++renderSlice :: Dur t+    => Interval t -> Ctx t a b -> (t, M t a) -> MList t b+renderSlice (t0, t1) ctx (d, m) = +    renderM d (sliceCtx (t0, t1) ctx) m++renderReverse :: Dur t+    => t -> Ctx t a b ->  M t a -> MList t b+renderReverse totalDur ctx x = +    renderM totalDur (reverseCtx totalDur ctx) x++renderFmap :: Dur t+    => t -> Ctx t a b -> (a' -> a) -> M t a' -> MList t b+renderFmap totalDur ctx f m = +    renderM totalDur (appendFmapCtx f ctx) m++renderEmap :: Dur t+    => t -> Ctx t a b +    -> (Event t a' -> Event t a) -> M t a' -> MList t b+renderEmap totalDur ctx f m = +    renderM totalDur (appendEmapCtx f ctx) m+++------------------------------------------------------+-- utils++-- Types++data LinTfm t = LinTfm+    { linTfmStart :: (t, t, t)+    , linTfmDur   :: (t, t, t)+    }++type Tfm t a b = (LinTfm t, Event t a -> Event t b)++type Interval t = (t, t)++type SliceSeg t = (t, LinTfm t)++data Ctx t a b = Ctx+    { ctxSlice :: [SliceSeg t]+    , ctxTfm   :: (Tfm t a b)+    }++-----------------------------------------------------------+-- funs on++-- LinTfm++appLinTfm :: Num t => LinTfm t -> (t, t) -> (t, t)+appLinTfm lt (t, d) = (x11*t + x12*d + b1, x21*t + x22*d + b2)+    where (x11, x12, b1) = linTfmStart lt+          (x21, x22, b2) = linTfmDur   lt++idLinTfm :: Num t => LinTfm t+idLinTfm = LinTfm (1, 0, 0) (0, 1, 0)++shiftLinTfm :: Num t => t -> LinTfm t -> LinTfm t+shiftLinTfm k (LinTfm (x11, x12, b1) (x21, x22, b2)) =+    LinTfm (x11, x12, b1')+           (x21, x22, b2') +    where !b1' = k*x11 + b1+          !b2' = k*x21 + b2  ++stretchLinTfm :: Num t => t -> LinTfm t -> LinTfm t+stretchLinTfm k (LinTfm (x11, x12, b1) (x21, x22, b2)) = +    LinTfm (k*x11, k*x12, b1)+           (k*x21, k*x22, b2) ++reverseLinTfm :: Num t => t -> LinTfm t -> LinTfm t +reverseLinTfm totalDur (LinTfm (x11, x12, b1) (x21, x22, b2)) =+    LinTfm (-x11, x12 - x11, totalDur * x11 + b1)+           (-x21, x22 - x21, totalDur * x21 + b2) +            +-- Tfm++idTfm :: Num t => Tfm t a a+idTfm = (idLinTfm, id)++appTfm :: Dur t => Tfm t a b -> Event t a -> Event t b+appTfm (linTfm, f) = f . liftEv linTfm++liftEv :: Dur t => LinTfm t -> Event t a -> Event t a+liftEv lt (Event t d a) = Event t' d' a+    where (t', d') = appLinTfm lt (t, d)+ +appendFmap :: (a' -> a) -> Tfm t a b -> Tfm t a' b+appendFmap f = second ( . fmap f)++appendEmap :: Dur t => +       (Event t a' -> Event t a) +    -> (Tfm t a b  -> Tfm t a' b)+appendEmap f (linTfm, g) = (linTfm', resTfm)+    where linTfm' = idLinTfm+          resTfm  = g . liftEv linTfm . f  ++-- Interval++within :: Dur t => Interval t -> Interval t -> Bool+within (a', b') (a, b) =+       a' >= aEps && a' <= bEps +    && b' >= aEps && b' <= bEps+    where (aEps, bEps) = epsInterval (a, b)++outside :: Dur t => Interval t -> Interval t -> Bool+outside (a', b') (a, b) = b' < aEps || a' > bEps+    where (aEps, bEps) = epsInterval (a, b)        ++epsInterval :: Dur t => Interval t -> Interval t+epsInterval (a, b) = (a - eps, b + eps)+    where eps  = 1e-9++toInterval :: Dur t => (t, t) -> Interval t+toInterval (t, d) = (t, t + d)++-- SliceSeg++isSlicePrim, isSliceComp :: Dur t +    => [SliceSeg t] -> (t, t) -> Bool++isSlicePrim = isSlice (\a b -> not $ within a b)+isSliceComp = isSlice outside++isSlice :: Dur t +    => (Interval t -> Interval t -> Bool)+    -> [SliceSeg t] -> (t, t) -> Bool+isSlice pred xs dt = +    case xs of+        []           -> False+        (d, lt) : ts -> +            let dt' = appLinTfm lt dt+            in  if toInterval dt' `pred` (0, d)+                    then True+                    else isSlice pred ts dt'++-- Ctx++initCtx :: Dur t => Ctx t a a+initCtx = Ctx [] idTfm++shiftCtx :: Dur t => t -> Ctx t a b -> Ctx t a b+shiftCtx t = appendLinTfmCtx $ shiftLinTfm t++stretchCtx :: Dur t => t -> Ctx t a b -> Ctx t a b+stretchCtx t = appendLinTfmCtx $ stretchLinTfm t++sliceCtx :: Dur t => Interval t -> Ctx t a b -> Ctx t a b+sliceCtx (t0, t1) x = shiftCtx (-t0) $ x{+    ctxSlice = (totalDur, idLinTfm) : ctxSlice x}+    where totalDur = t1 - t0++reverseCtx :: Dur t => t -> Ctx t a b -> Ctx t a b+reverseCtx t = appendLinTfmCtx $ reverseLinTfm t++appendLinTfmCtx :: Dur t +    => (LinTfm t -> LinTfm t) +    -> Ctx t a b -> Ctx t a b+appendLinTfmCtx m x = appendSlice m $ x{ +    ctxTfm = first m $ ctxTfm x }+    where appendSlice m x+            | null $ ctxSlice x = x+            | otherwise         = x{ +                ctxSlice = onSeg m $ ctxSlice x}+          onSeg f (x:xs) = second f x : xs++appendFmapCtx :: Dur t => (a' -> a) -> Ctx t a b -> Ctx t a' b+appendFmapCtx = appendMapCtx . appendFmap++appendEmapCtx :: Dur t +    => (Event t a' -> Event t a) +    -> Ctx t a b -> Ctx t a' b+appendEmapCtx = appendMapCtx . appendEmap++appendMapCtx :: Dur t+    => (Tfm t a b -> Tfm t a' b)+    -> (Ctx t a b -> Ctx t a' b)+appendMapCtx f x = x{ ctxTfm = f $ ctxTfm x }+
− src/Temporal/Media/Double.hs
@@ -1,149 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}--- | Special case of "Temporal.Media". Time is @Double@-module Temporal.Media.Double (-	-- * Time classes-	Dur, none, dur, stretch, ToMaybe(..), -    tmap, dmap, tdmap, -    sustain, sustainBy,-    tstretch, -    -- * Transformers-	Reversible(..), slice, take, drop, cut, -	-- * Structure -	Construct(..), Arrangeable(..), Controlable(..),-	sequent, parallel, loop, delay, temp,-	-- * Media-	Media(..), fold, fromMedia,-	-- * Simple interperetation-	-- ** Event list-	Event, EventList(..), -	mapEvent, toEvent, toEventList,-	-- ** Unit Media-	MediaUnit(..), unMediaUnit, foldU, fromMediaUnit,-	Unit(..),-    -- * Misc-    tmapRel, dmapRel, tdmapRel, tstretchRel, linseg-) -where--import Prelude hiding (take, drop, reverse)-import Control.Applicative--import qualified Temporal.Media as M-import Temporal.Media (-	ToMaybe(..),-	Reversible(..), -	Construct(..), Arrangeable(..), Controlable(..), -	sequent, parallel, loop,-	Media(..), fold, fromMedia, linseg)--------------------------------------------- Time -----type Time = Double-type Dur  = Double--none :: M.Temporal Dur a => Dur -> a-none = M.none--dur :: M.Temporal Dur a => a -> Dur-dur = M.dur--stretch :: M.Stretchable Dur a => Dur -> a -> a-stretch = M.stretch---- | temporal stretch-tstretch :: M.TemporalStretchable Dur a => (Time -> Dur) -> a -> a-tstretch = M.tstretch--tstretchRel :: M.TemporalStretchable Dur a => (Time -> Dur) -> a -> a-tstretchRel = M.tstretchRel--tmap :: M.TemporalFunctor Dur f => (Time -> a -> b) -> (f a -> f b)-tmap = M.tmap--dmap :: M.TemporalFunctor Dur f => (Dur -> a -> b) -> (f a -> f b)-dmap = M.dmap--tdmap :: M.TemporalFunctor Dur f => (Time -> Dur -> a -> b) -> (f a -> f b)-tdmap = M.tdmap---tmapRel :: (M.Temporal Dur (f a), M.TemporalFunctor Dur f) => (Time -> a -> b) -> (f a -> f b)-tmapRel = M.tmapRel--dmapRel :: (M.Temporal Dur (f a), M.TemporalFunctor Dur f) => (Dur -> a -> b) -> (f a -> f b)-dmapRel = M.dmapRel--tdmapRel :: (M.Temporal Dur (f a), M.TemporalFunctor Dur f) => (Time -> Dur -> a -> b) -> (f a -> f b)-tdmapRel = M.tdmapRel--sustain :: M.Sustainable Dur f => Dur -> f a -> f a-sustain = M.sustain--sustainBy :: M.Sustainable Dur f => (Dur -> Dur -> a -> (b, Dur)) -> f a -> f b-sustainBy = M.sustainBy------------------------------------------------- transformers--slice :: M.Sliceable Dur a => Dur -> Dur -> a -> a-slice = M.slice--take :: M.Sliceable Dur a => Dur -> a -> a-take = M.take--drop :: M.Sliceable Dur a => Dur -> a -> a-drop = M.drop--cut :: (Reversible a, M.Sliceable Dur a) => Dur -> Dur -> a -> a-cut = M.cut------------------------------------------------- Structure--delay :: (M.Temporal Dur a, Arrangeable a) => Dur -> a -> a-delay = M.delay--temp :: (Construct m, M.Temporal Dur (m a), M.Stretchable Dur (m a)) -	=> Dur -> a -> m a-temp = M.temp-	---------------------------------------------- --- EventList--type Event a     = M.Event Dur a-type EventList a = M.EventList Dur a--mapEvent :: (a -> b) -> Event a -> Event b-mapEvent = M.mapEvent--toEvent :: (M.Temporal Dur (m a), ToMaybe m) => m a -> EventList a-toEvent = M.toEvent--toEventList :: (M.Temporal Dur (m a), ToMaybe m) -	=> (c -> EventList a -> EventList a) -	-> Media c (m a) -> EventList a-toEventList = M.toEventList------------------------------------------------- MediaUnit--type MediaUnit c a = M.MediaUnit Dur c a--unMediaUnit :: MediaUnit c a -> Media c (Unit a)-unMediaUnit = M.unMediaUnit--foldU :: (Dur -> a -> b) -> (b -> b -> b) -> (b -> b -> b) -> (c -> b -> b)-	-> MediaUnit c a -> Maybe b-foldU = M.foldU--fromMediaUnit :: (c -> EventList a -> EventList a) -> MediaUnit c a -> EventList a-fromMediaUnit = M.fromMediaUnit------------------------------------------------- Temp--type Unit a = M.Unit Dur a-
temporal-media.cabal view
@@ -1,12 +1,16 @@ Name:          temporal-media-Version:       0.1.1+Version:       0.2.0 License-file:  LICENSE Cabal-Version: >= 1.2 License:       BSD3 Author:	       Anton Kholomiov Maintainer:    <anton.kholomiov@gmail.com> Synopsis:      data types for temporal media-Description:   +Description:  +      An embedded domain-specific language (EDSL) for +      creating lists of constant time events related in time.+      Combinators are optimized in fusion style.+       Ispired by the paper /An Algebraic Theory of Polymorphic Temporal Media/,        Paul Hudak        <http://haskell.cs.yale.edu/yale/papers/polymedia/hudak-RR-1259.pdf>, @@ -20,9 +24,7 @@  Library   Build-Depends:-        base >= 4, base < 5, containers >= 0.3+        base >= 4, base < 5, mtl >= 2, dlist >= 0.5   Hs-Source-Dirs:      src/   Exposed-Modules:         Temporal.Media-        Temporal.Media.Double-