{-# Language DeriveFunctor, DeriveFoldable, DeriveTraversable #-} module Csound.Dynamic.Types.EventList( CsdSco(..), CsdEvent, csdEventStart, csdEventDur, csdEventContent, CsdEventList(..), delayCsdEventList, rescaleCsdEventList ) where import Data.Traversable import Data.Foldable -- | The Csound note. It's a triple of -- -- > (startTime, duration, parameters) type CsdEvent a = (Double, Double, a) csdEventStart :: CsdEvent a -> Double csdEventDur :: CsdEvent a -> Double csdEventContent :: CsdEvent a -> a csdEventStart (a, _, _) = a csdEventDur (_, a, _) = a csdEventContent (_, _, a) = a csdEventTotalDur :: CsdEvent a -> Double csdEventTotalDur (start, dur, _) = start + dur -- | A class that represents Csound scores. All functions that use score are defined -- in terms of this class. If you want to use your own score representation, just define -- two methods of the class. -- -- The properties: -- -- > forall a . toCsdEventList (singleCsdEvent a) === CsdEventList 1 [(0, 1, a)] class Functor f => CsdSco f where -- | Converts a given score representation to the canonical one. toCsdEventList :: f a -> CsdEventList a -- | Constructs a scores that contains only one event. The event happens immediately and lasts for 1 second. singleCsdEvent :: CsdEvent a -> f a -- | 'Csound.Base.CsdEventList' is a canonical representation of the Csound scores. -- A scores is a list of events and we should know the total duration of the scores. -- It's not meant to be used directly. We can use a better alternative. More convenient -- type that belongs to 'Csound.Base.CsdSco' type class (see temporal-csound package). data CsdEventList a = CsdEventList { csdEventListDur :: Double , csdEventListNotes :: [CsdEvent a] } deriving (Eq, Show, Functor, Foldable, Traversable) instance CsdSco CsdEventList where toCsdEventList = id singleCsdEvent evt = CsdEventList (csdEventTotalDur evt) [evt] delayCsdEventList :: Double -> CsdEventList a -> CsdEventList a delayCsdEventList k (CsdEventList totalDur events) = CsdEventList (k + totalDur) (fmap (delayCsdEvent k) events) delayCsdEvent :: Double -> CsdEvent a -> CsdEvent a delayCsdEvent k (start, dur, a) = (k + start, dur, a) rescaleCsdEventList :: Double -> CsdEventList a -> CsdEventList a rescaleCsdEventList k (CsdEventList totalDur events) = CsdEventList (k * totalDur) (fmap (rescaleCsdEvent k) events) rescaleCsdEvent :: Double -> CsdEvent a -> CsdEvent a rescaleCsdEvent k (start, dur, a) = (k * start, k * dur, a)