module Music.Time.Aligned (
Aligned,
aligned,
renderAligned,
renderAlignedVoice,
renderAlignedNote,
renderAlignedDuration,
) where
import Control.Applicative
import Control.Comonad
import Control.Lens hiding (Indexable, Level, above, below,
index, inside, parts, reversed,
transform, (<|), (|>))
import Data.AffineSpace
import Data.AffineSpace.Point
import Data.Bifunctor
import Data.Foldable (Foldable)
import qualified Data.Foldable as Foldable
import Data.Functor.Adjunction (unzipR)
import Data.Functor.Couple
import Data.String
import Data.Typeable
import Data.VectorSpace
import Music.Dynamics.Literal
import Music.Pitch.Literal
import Music.Time.Reverse
import Music.Time.Juxtapose
import Music.Time.Split
import Music.Time.Note
import Music.Time.Event
import Music.Time.Voice
import Music.Time.Score
newtype Aligned v = Aligned { getAligned :: (Time, LocalDuration, v) }
aligned :: Time -> LocalDuration -> v -> Aligned v
aligned t d a = Aligned (t, d, a)
instance Show a => Show (Aligned a) where
show (Aligned (t,d,v)) = "aligned ("++show t++") ("++show d++") ("++ show v++")"
instance Transformable v => Transformable (Aligned v) where
transform s (Aligned (t, d, v)) = Aligned (transform s t, d, transform s v)
instance HasDuration v => HasDuration (Aligned v) where
_duration (Aligned (_, _, v)) = _duration v
instance HasDuration v => HasPosition (Aligned v) where
_era (Aligned (position, alignment, v)) =
(position .-^ (size * alignment)) <-> (position .+^ (size * (1alignment)))
where
size = _duration v
renderAligned :: HasDuration a => (Span -> a -> b) -> Aligned a -> b
renderAligned f a@(Aligned (_, _, v)) = f (_era a) v
voiceToScoreInEra :: Span -> Voice a -> Score a
voiceToScoreInEra e = set era e . scat . map (uncurry stretch) . view pairs . fmap pure
noteToEventInEra :: Span -> Note a -> Event a
noteToEventInEra e = set era e . view notee . fmap pure
durationToSpanInEra :: Span -> Duration -> Span
durationToSpanInEra = const
renderAlignedVoice :: Aligned (Voice a) -> Score a
renderAlignedVoice = renderAligned voiceToScoreInEra
renderAlignedNote :: Aligned (Note a) -> Event a
renderAlignedNote = renderAligned noteToEventInEra
renderAlignedDuration :: Aligned Duration -> Span
renderAlignedDuration = renderAligned durationToSpanInEra