module Mezzo.Compose.Combine
(
musicDur
, durToInt
, duration
, voices
, pad
, play
) where
import Mezzo.Model
import Mezzo.Compose.Basic
import Mezzo.Compose.Builder
import Mezzo.Compose.Types
import Mezzo.Model.Prim
import Mezzo.Model.Types
import Mezzo.Model.Music
import GHC.TypeLits
musicDur :: Primitive l => Music (m :: Partiture n l) -> Dur l
musicDur _ = Dur
durToInt :: Primitive d => Dur d -> Int
durToInt = prim
duration :: Primitive l => Music (m :: Partiture n l) -> Int
duration = durToInt . musicDur
voices :: Music m -> Int
voices (Note r d) = 1
voices (Rest d) = 1
voices (m1 :|: m2) = voices m1
voices (m1 :-: m2) = voices m1 + voices m2
voices (Chord c d) = chordVoices c
chordVoices :: forall (n :: Nat) (c :: ChordType n) . Primitive n => Cho c -> Int
chordVoices _ = prim (undefined :: ChordType n)
pad :: (HarmConstraints m (FromSilence b), Primitive b) => Music (m :: Partiture (a 1) b) -> Music ((m +-+ FromSilence b) :: Partiture a b)
pad m = m :-: rest (musicDur m)
play :: (Primitive d) => Melody m d -> Music m
play m@(ps :| p) = case ps of Melody -> mkMelNote m p ; ps' -> play ps' :|: mkMelNote m p
play m@(ps :<<< p) = case ps of Melody -> mkMelNote m p ; ps' -> play ps' :|: mkMelNote m p
play m@(ps :<< p) = case ps of Melody -> mkMelNote m p ; ps' -> play ps' :|: mkMelNote m p
play m@(ps :< p) = case ps of Melody -> mkMelNote m p ; ps' -> play ps' :|: mkMelNote m p
play m@(ps :^ p) = case ps of Melody -> mkMelNote m p ; ps' -> play ps' :|: mkMelNote m p
play m@(ps :> p) = case ps of Melody -> mkMelNote m p ; ps' -> play ps' :|: mkMelNote m p
play m@(ps :>> p) = case ps of Melody -> mkMelNote m p ; ps' -> play ps' :|: mkMelNote m p
play m@(ps :<<. p) = case ps of Melody -> mkMelNote m p ; ps' -> play ps' :|: mkMelNote m p
play m@(ps :<. p) = case ps of Melody -> mkMelNote m p ; ps' -> play ps' :|: mkMelNote m p
play m@(ps :^. p) = case ps of Melody -> mkMelNote m p ; ps' -> play ps' :|: mkMelNote m p
play m@(ps :>. p) = case ps of Melody -> mkMelNote m p ; ps' -> play ps' :|: mkMelNote m p
play m@(ps :>>. p) = case ps of Melody -> mkMelNote m p ; ps' -> play ps' :|: mkMelNote m p
play m@(ps :~| p) = case ps of Melody -> mkMelRest m ; ps' -> play ps' :|: mkMelRest m
play m@(ps :~<<< p) = case ps of Melody -> mkMelRest m ; ps' -> play ps' :|: mkMelRest m
play m@(ps :~<< p) = case ps of Melody -> mkMelRest m ; ps' -> play ps' :|: mkMelRest m
play m@(ps :~< p) = case ps of Melody -> mkMelRest m ; ps' -> play ps' :|: mkMelRest m
play m@(ps :~^ p) = case ps of Melody -> mkMelRest m ; ps' -> play ps' :|: mkMelRest m
play m@(ps :~> p) = case ps of Melody -> mkMelRest m ; ps' -> play ps' :|: mkMelRest m
play m@(ps :~>> p) = case ps of Melody -> mkMelRest m ; ps' -> play ps' :|: mkMelRest m
play m@(ps :~<<. p) = case ps of Melody -> mkMelRest m ; ps' -> play ps' :|: mkMelRest m
play m@(ps :~<. p) = case ps of Melody -> mkMelRest m ; ps' -> play ps' :|: mkMelRest m
play m@(ps :~^. p) = case ps of Melody -> mkMelRest m ; ps' -> play ps' :|: mkMelRest m
play m@(ps :~>. p) = case ps of Melody -> mkMelRest m ; ps' -> play ps' :|: mkMelRest m
play m@(ps :~>>. p) = case ps of Melody -> mkMelRest m ; ps' -> play ps' :|: mkMelRest m
mkMelNote :: (IntRep r, Primitive d) => Melody m d -> RootS r -> Music (FromRoot r d)
mkMelNote m p = p (\r -> Note r (melDur m))
mkMelRest :: Primitive d => Melody m d -> Music (FromSilence d)
mkMelRest m = r (\_ -> Rest (melDur m))
melody :: Melody (End :-- None) Quarter
melody = Melody
melDur :: Primitive d => Melody m d -> Dur d
melDur _ = Dur