module Music.Score.Articulation (
HasArticulation(..),
ArticulationT(..),
accent,
marcato,
accentLast,
marcatoLast,
accentAll,
marcatoAll,
tenuto,
separated,
staccato,
portato,
legato,
spiccato,
resetArticulation,
) where
import Control.Applicative
import Data.Foldable
import Data.Semigroup
import Data.Typeable
import Music.Dynamics.Literal
import Music.Pitch.Literal
import Music.Score.Combinators
import Music.Score.Part
import Music.Score.Score
class HasArticulation a where
setBeginSlur :: Bool -> a -> a
setContSlur :: Bool -> a -> a
setEndSlur :: Bool -> a -> a
setAccLevel :: Int -> a -> a
setStaccLevel :: Int -> a -> a
newtype ArticulationT a = ArticulationT { getArticulationT :: (((Any, Any, Any), (Sum Int, Sum Int)), a) }
deriving (Eq, Show, Ord, Functor, Foldable, Typeable, Applicative, Monad)
instance Semigroup a => Semigroup (ArticulationT a) where
ArticulationT (((es,us,bs),(al,sl)),a) <> ArticulationT (_,b) = ArticulationT (((es,us,bs),(al,sl)), a <> b)
instance (Semigroup a, Monoid a) => Monoid (ArticulationT a) where
mempty = return mempty
mappend = (<>)
instance IsPitch a => IsPitch (ArticulationT a) where
fromPitch l = return (fromPitch l)
instance IsDynamics a => IsDynamics (ArticulationT a) where
fromDynamics l = return (fromDynamics l)
instance HasArticulation (ArticulationT a) where
setEndSlur (Any -> es) (ArticulationT (((_ ,us,bs),(al,sl)),a)) = ArticulationT (((es,us,bs),(al,sl)),a)
setContSlur (Any -> us) (ArticulationT (((es,_ ,bs),(al,sl)),a)) = ArticulationT (((es,us,bs),(al,sl)),a)
setBeginSlur (Any -> bs) (ArticulationT (((es,us,_ ),(al,sl)),a)) = ArticulationT (((es,us,bs),(al,sl)),a)
setAccLevel (Sum -> al) (ArticulationT (((es,us,bs),(_ ,sl)),a)) = ArticulationT (((es,us,bs),(al,sl)),a)
setStaccLevel (Sum -> sl) (ArticulationT (((es,us,bs),(al,_ )),a)) = ArticulationT (((es,us,bs),(al,sl)),a)
instance HasArticulation b => HasArticulation (a,b) where
setEndSlur n = fmap (setEndSlur n)
setContSlur n = fmap (setContSlur n)
setBeginSlur n = fmap (setBeginSlur n)
setAccLevel n = fmap (setAccLevel n)
setStaccLevel n = fmap (setStaccLevel n)
accent :: (HasPart' a, HasArticulation a) => Score a -> Score a
accent = mapPhrase (setAccLevel 1) id id
marcato :: (HasPart' a, HasArticulation a) => Score a -> Score a
marcato = mapPhrase (setAccLevel 2) id id
accentAll :: (HasPart' a, HasArticulation a) => Score a -> Score a
accentAll = mapPhrase (setAccLevel 1) (setAccLevel 1) (setAccLevel 1)
marcatoAll :: (HasPart' a, HasArticulation a) => Score a -> Score a
marcatoAll = mapPhrase (setAccLevel 2) (setAccLevel 2) (setAccLevel 2)
accentLast :: (HasPart' a, HasArticulation a) => Score a -> Score a
accentLast = mapPhrase id id (setAccLevel 1)
marcatoLast :: (HasPart' a, HasArticulation a) => Score a -> Score a
marcatoLast = mapPhrase id id (setAccLevel 2)
tenuto :: (HasPart' a, HasArticulation a) => Score a -> Score a
tenuto = mapPhrase (setStaccLevel (2)) (setStaccLevel (2)) (setStaccLevel (2))
separated :: (HasPart' a, HasArticulation a) => Score a -> Score a
separated = mapPhrase (setStaccLevel (1)) (setStaccLevel (1)) (setStaccLevel (1))
staccato :: (HasPart' a, HasArticulation a) => Score a -> Score a
staccato = mapPhrase (setStaccLevel 1) (setStaccLevel 1) (setStaccLevel 1)
portato :: (HasPart' a, HasArticulation a) => Score a -> Score a
portato = staccato . legato
legato :: (HasPart' a, HasArticulation a) => Score a -> Score a
legato = mapPhrase (setBeginSlur True) id (setEndSlur True)
spiccato :: (HasPart' a, HasArticulation a) => Score a -> Score a
spiccato = mapPhrase (setStaccLevel 2) (setStaccLevel 2) (setStaccLevel 2)
resetArticulation :: HasArticulation c => c -> c
resetArticulation = setBeginSlur False . setContSlur False . setEndSlur False . setAccLevel 0 . setStaccLevel 0
get1 = head . toList