module Music.Score.Articulation (
Articulation,
SetArticulation,
Accentuation,
Separation,
Articulated(..),
HasArticulations(..),
HasArticulation(..),
HasArticulations',
HasArticulation',
articulation',
articulations',
accent,
marcato,
accentLast,
marcatoLast,
accentAll,
marcatoAll,
staccatissimo,
staccato,
separated,
portato,
legato,
legatissimo,
tenuto,
spiccato,
ArticulationT(..),
varticulation,
addArtCon,
) where
import Control.Applicative
import Control.Comonad
import Control.Lens hiding (above, below, transform)
import Data.AffineSpace
import Data.Foldable
import Data.Functor.Couple
import Data.Semigroup
import Data.Typeable
import Data.VectorSpace hiding (Sum)
import Data.Functor.Context
import Music.Score.Part
import Music.Time
import Music.Time.Internal.Transform
import Music.Dynamics.Literal
import Music.Pitch.Literal
import Music.Score.Harmonics
import Music.Score.Part
import Music.Score.Phrases
import Music.Score.Slide
import Music.Score.Text
import Music.Score.Ties
type family Articulation (s :: *) :: *
type family SetArticulation (b :: *) (s :: *) :: *
type ArticulationLensLaws' s t a b = (
Articulation (SetArticulation a s) ~ a,
SetArticulation (Articulation t) s ~ t,
SetArticulation a (SetArticulation b s) ~ SetArticulation a s
)
type ArticulationLensLaws s t = ArticulationLensLaws' s t (Articulation s) (Articulation t)
class (HasArticulations s t) => HasArticulation s t where
articulation :: Lens s t (Articulation s) (Articulation t)
class (Transformable (Articulation s),
Transformable (Articulation t),
ArticulationLensLaws s t) => HasArticulations s t where
articulations :: Traversal s t (Articulation s) (Articulation t)
type HasArticulation' a = HasArticulation a a
type HasArticulations' a = HasArticulations a a
articulation' :: (HasArticulation s t, s ~ t) => Lens' s (Articulation s)
articulation' = articulation
articulations' :: (HasArticulations s t, s ~ t) => Traversal' s (Articulation s)
articulations' = articulations
#define PRIM_ARTICULATION_INSTANCE(TYPE) \
\
type instance Articulation TYPE = TYPE; \
type instance SetArticulation a TYPE = a; \
\
instance (Transformable a, a ~ Articulation a, SetArticulation TYPE a ~ TYPE) \
=> HasArticulation TYPE a where { \
articulation = ($) } ; \
\
instance (Transformable a, a ~ Articulation a, SetArticulation TYPE a ~ TYPE) \
=> HasArticulations TYPE a where { \
articulations = ($) } ; \
PRIM_ARTICULATION_INSTANCE(())
PRIM_ARTICULATION_INSTANCE(Bool)
PRIM_ARTICULATION_INSTANCE(Ordering)
PRIM_ARTICULATION_INSTANCE(Char)
PRIM_ARTICULATION_INSTANCE(Int)
PRIM_ARTICULATION_INSTANCE(Integer)
PRIM_ARTICULATION_INSTANCE(Float)
PRIM_ARTICULATION_INSTANCE(Double)
type instance Articulation (c,a) = Articulation a
type instance SetArticulation b (c,a) = (c,SetArticulation b a)
type instance Articulation [a] = Articulation a
type instance SetArticulation b [a] = [SetArticulation b a]
type instance Articulation (Maybe a) = Articulation a
type instance SetArticulation b (Maybe a) = Maybe (SetArticulation b a)
type instance Articulation (Either c a) = Articulation a
type instance SetArticulation b (Either c a) = Either c (SetArticulation b a)
type instance Articulation (Event a) = Articulation a
type instance SetArticulation g (Event a) = Event (SetArticulation g a)
type instance Articulation (Placed a) = Articulation a
type instance SetArticulation g (Placed a) = Placed (SetArticulation g a)
type instance Articulation (Note a) = Articulation a
type instance SetArticulation g (Note a) = Note (SetArticulation g a)
type instance Articulation (Voice a) = Articulation a
type instance SetArticulation b (Voice a) = Voice (SetArticulation b a)
type instance Articulation (Track a) = Articulation a
type instance SetArticulation b (Track a) = Track (SetArticulation b a)
type instance Articulation (Score a) = Articulation a
type instance SetArticulation b (Score a) = Score (SetArticulation b a)
instance HasArticulation a b => HasArticulation (c, a) (c, b) where
articulation = _2 . articulation
instance HasArticulations a b => HasArticulations (c, a) (c, b) where
articulations = traverse . articulations
instance HasArticulations a b => HasArticulations [a] [b] where
articulations = traverse . articulations
instance HasArticulations a b => HasArticulations (Maybe a) (Maybe b) where
articulations = traverse . articulations
instance HasArticulations a b => HasArticulations (Either c a) (Either c b) where
articulations = traverse . articulations
instance (HasArticulations a b) => HasArticulations (Event a) (Event b) where
articulations = from event . whilstL articulations
instance (HasArticulation a b) => HasArticulation (Event a) (Event b) where
articulation = from event . whilstL articulation
instance (HasArticulations a b) => HasArticulations (Placed a) (Placed b) where
articulations = _Wrapped . whilstLT articulations
instance (HasArticulation a b) => HasArticulation (Placed a) (Placed b) where
articulation = _Wrapped . whilstLT articulation
instance (HasArticulations a b) => HasArticulations (Note a) (Note b) where
articulations = _Wrapped . whilstLD articulations
instance (HasArticulation a b) => HasArticulation (Note a) (Note b) where
articulation = _Wrapped . whilstLD articulation
instance HasArticulations a b => HasArticulations (Voice a) (Voice b) where
articulations = traverse . articulations
instance HasArticulations a b => HasArticulations (Track a) (Track b) where
articulations = traverse . articulations
instance HasArticulations a b => HasArticulations (Score a) (Score b) where
articulations =
_Wrapped . _2
. _Wrapped
. traverse
. from event
. whilstL articulations
type instance Articulation (Couple c a) = Articulation a
type instance SetArticulation g (Couple c a) = Couple c (SetArticulation g a)
type instance Articulation (TextT a) = Articulation a
type instance SetArticulation g (TextT a) = TextT (SetArticulation g a)
type instance Articulation (HarmonicT a) = Articulation a
type instance SetArticulation g (HarmonicT a) = HarmonicT (SetArticulation g a)
type instance Articulation (TieT a) = Articulation a
type instance SetArticulation g (TieT a) = TieT (SetArticulation g a)
type instance Articulation (SlideT a) = Articulation a
type instance SetArticulation g (SlideT a) = SlideT (SetArticulation g a)
instance (HasArticulations a b) => HasArticulations (Couple c a) (Couple c b) where
articulations = _Wrapped . articulations
instance (HasArticulation a b) => HasArticulation (Couple c a) (Couple c b) where
articulation = _Wrapped . articulation
instance (HasArticulations a b) => HasArticulations (TextT a) (TextT b) where
articulations = _Wrapped . articulations
instance (HasArticulation a b) => HasArticulation (TextT a) (TextT b) where
articulation = _Wrapped . articulation
instance (HasArticulations a b) => HasArticulations (HarmonicT a) (HarmonicT b) where
articulations = _Wrapped . articulations
instance (HasArticulation a b) => HasArticulation (HarmonicT a) (HarmonicT b) where
articulation = _Wrapped . articulation
instance (HasArticulations a b) => HasArticulations (TieT a) (TieT b) where
articulations = _Wrapped . articulations
instance (HasArticulation a b) => HasArticulation (TieT a) (TieT b) where
articulation = _Wrapped . articulation
instance (HasArticulations a b) => HasArticulations (SlideT a) (SlideT b) where
articulations = _Wrapped . articulations
instance (HasArticulation a b) => HasArticulation (SlideT a) (SlideT b) where
articulation = _Wrapped . articulation
type family Accentuation (a :: *) :: *
type family Separation (a :: *) :: *
type instance Accentuation () = ()
type instance Separation () = ()
type instance Accentuation (a, b) = a
type instance Separation (a, b) = b
class (
Fractional (Accentuation a),
Fractional (Separation a),
AffineSpace (Accentuation a),
AffineSpace (Separation a)
) => Articulated a where
accentuation :: Lens' a (Accentuation a)
separation :: Lens' a (Separation a)
instance (AffineSpace a, AffineSpace b, Fractional a, Fractional b) => Articulated (a, b) where
accentuation = _1
separation = _2
accent :: (HasPhrases' s b, HasArticulations' b, Articulation b ~ a, Articulated a) => s -> s
accent = set (phrases . _head . articulations . accentuation) 1
marcato :: (HasPhrases' s b, HasArticulations' b, Articulation b ~ a, Articulated a) => s -> s
marcato = set (phrases . _head . articulations . accentuation) 2
accentLast :: (HasPhrases' s b, HasArticulations' b, Articulation b ~ a, Articulated a) => s -> s
accentLast = set (phrases . _last . articulations . accentuation) 1
marcatoLast :: (HasPhrases' s b, HasArticulations' b, Articulation b ~ a, Articulated a) => s -> s
marcatoLast = set (phrases . _last . articulations . accentuation) 2
accentAll :: (HasArticulations' s, Articulation s ~ a, Articulated a) => s -> s
accentAll = set (articulations . accentuation) 1
marcatoAll :: (HasArticulations' s, Articulation s ~ a, Articulated a) => s -> s
marcatoAll = set (articulations . accentuation) 2
tenuto :: (HasArticulations' s, Articulation s ~ a, Articulated a) => s -> s
tenuto = id
spiccato :: (HasArticulations' s, Articulation s ~ a, Articulated a) => s -> s
spiccato = id
legatissimo :: (HasArticulations' s, Articulation s ~ a, Articulated a) => s -> s
legatissimo = set (articulations . separation) (2)
legato :: (HasArticulations' s, Articulation s ~ a, Articulated a) => s -> s
legato = set (articulations . separation) (1)
separated :: (HasArticulations' s, Articulation s ~ a, Articulated a) => s -> s
separated = set (articulations . separation) 0
portato :: (HasArticulations' s, Articulation s ~ a, Articulated a) => s -> s
portato = set (articulations . separation) 0.5
staccato :: (HasArticulations' s, Articulation s ~ a, Articulated a) => s -> s
staccato = set (articulations . separation) 1
staccatissimo :: (HasArticulations' s, Articulation s ~ a, Articulated a) => s -> s
staccatissimo = set (articulations . separation) 2
newtype ArticulationT n a = ArticulationT { getArticulationT :: (n, a) }
deriving (
Eq, Ord, Show, Typeable, Functor, Applicative, Monad,
Comonad, Transformable, Monoid, Semigroup
)
instance (Monoid n, Num a) => Num (ArticulationT n a) where
(+) = liftA2 (+)
(*) = liftA2 (*)
() = liftA2 ()
abs = fmap abs
signum = fmap signum
fromInteger = pure . fromInteger
instance (Monoid n, Fractional a) => Fractional (ArticulationT n a) where
recip = fmap recip
fromRational = pure . fromRational
instance (Monoid n, Floating a) => Floating (ArticulationT n a) where
pi = pure pi
sqrt = fmap sqrt
exp = fmap exp
log = fmap log
sin = fmap sin
cos = fmap cos
asin = fmap asin
atan = fmap atan
acos = fmap acos
sinh = fmap sinh
cosh = fmap cosh
asinh = fmap asinh
atanh = fmap atanh
acosh = fmap acos
instance (Monoid n, Enum a) => Enum (ArticulationT n a) where
toEnum = pure . toEnum
fromEnum = fromEnum . extract
instance (Monoid n, Bounded a) => Bounded (ArticulationT n a) where
minBound = pure minBound
maxBound = pure maxBound
instance Wrapped (ArticulationT p a) where
type Unwrapped (ArticulationT p a) = (p, a)
_Wrapped' = iso getArticulationT ArticulationT
instance Rewrapped (ArticulationT p a) (ArticulationT p' b)
type instance Articulation (ArticulationT p a) = p
type instance SetArticulation p' (ArticulationT p a) = ArticulationT p' a
instance (Transformable p, Transformable p')
=> HasArticulation (ArticulationT p a) (ArticulationT p' a) where
articulation = _Wrapped . _1
instance (Transformable p, Transformable p')
=> HasArticulations (ArticulationT p a) (ArticulationT p' a) where
articulations = _Wrapped . _1
deriving instance (IsPitch a, Monoid n) => IsPitch (ArticulationT n a)
deriving instance (IsInterval a, Monoid n) => IsInterval (ArticulationT n a)
deriving instance Reversible a => Reversible (ArticulationT p a)
instance (Tiable n, Tiable a) => Tiable (ArticulationT n a) where
isTieEndBeginning (ArticulationT (_,a)) = isTieEndBeginning a
toTied (ArticulationT (d,a)) = (ArticulationT (d1,a1), ArticulationT (d2,a2))
where
(a1,a2) = toTied a
(d1,d2) = toTied d
addArtCon :: (
HasPhrases s t a b, HasArticulation' a, HasArticulation a b, Articulation a ~ d, Articulation b ~ Ctxt d
) => s -> t
addArtCon = over (phrases.varticulation) withContext
varticulation = lens (fmap $ view articulation) (flip $ zipVoiceWithNoScale (set articulation))