\subsection{Conversion functions with default settings} \seclabel{fancy-performance} {\small \begin{haskelllisting} > module Haskore.Performance.Fancy where > import qualified Haskore.Music as Music > import qualified Haskore.Performance as Performance > import qualified Haskore.Performance.Context as Context > import qualified Haskore.Performance.Player as Player > import qualified Haskore.Performance.Default as DefltPf > import Haskore.Performance (eventDur, ) > -- import qualified Data.EventList.Relative.TimeBody as TimeList > -- import qualified Data.EventList.Relative.TimeTime as TimeListPad > import qualified Data.EventList.Relative.MixedTime as TimeListPad > import qualified Data.EventList.Relative.BodyTime as BodyTimeList > import Control.Monad.Trans.State (state, evalState, ) > import Control.Monad.Trans.Reader (local, ) > > import qualified Numeric.NonNegative.Class as NonNeg > import qualified Numeric.NonNegative.Wrapper as NonNegW > import Prelude hiding (map) \end{haskelllisting} } \begin{figure} {\small \begin{haskelllisting} > player :: (NonNeg.C time, Fractional time, Real time, Fractional dyn) => > Player.T time dyn note > player = map "Fancy" > > -- a PMap that makes everything into a fancyPlayer > map :: > (NonNeg.C time, Fractional time, Real time, Fractional dyn) => > String -> Player.T time dyn note > map pname = > Performance.PlayerCons { > Performance.name = pname, > Performance.playNote = DefltPf.playNote, > Performance.interpretPhrase = fancyInterpretPhrase, > Performance.notatePlayer = DefltPf.notatePlayer () > } > > processPerformance :: (Num time) => > (time -> > (time -> time -> time, > time -> Performance.Event time dyn note -> Performance.Event time dyn note, > time)) -> > (Performance.PaddedWithRests time dyn note, time) -> > (Performance.PaddedWithRests time dyn note, time) > processPerformance f (pf, dur) = > let (fTime, fEvent, newDur) = f dur > procPf = > flip evalState 0 . > BodyTimeList.mapM > (\dt -> state $ \t -> (fTime t dt, t+dt)) > (\ev -> state $ \t -> (fmap (fEvent t) ev, t)) > in (TimeListPad.mapTimeTail procPf pf, newDur) > > fancyInterpretDynamic :: > (Fractional time, Real time, Fractional dyn) => > Music.Dynamic -> Performance.Monad time dyn note -> Performance.Monad time dyn note > fancyInterpretDynamic dyn = > let loud x = local (Performance.updateDynamics (fromRational x *)) > inflate add x dur = > let r = fromRational x / realToFrac dur > in (const id, > \t -> Player.changeVelocity (add (realToFrac t * r)), > dur) > in case dyn of > Music.Accent x -> Player.accent x > Music.Loudness x -> loud x > Music.Crescendo x -> fmap (processPerformance (inflate (+) x)) > Music.Diminuendo x -> fmap (processPerformance (inflate subtract x)) > -- Music.Crescendo x -> fmap (processPerformance (inflate x)) > -- Music.Diminuendo x -> fmap (processPerformance (inflate (-x))) > > fancyInterpretTempo :: (Fractional time, Real time) => > Music.Tempo -> Performance.Monad time dyn note -> Performance.Monad time dyn note > fancyInterpretTempo tmp = > let stretch add x dur = > let x' = fromRational x > r = x' / dur > fac t dt = add 1 (r * (2*t + dt)) > in (\t dt -> dt * fac t dt, > \t (e@Performance.Event {eventDur = d}) -> > e{eventDur = d * fac t d }, > dur * add 1 x') > in case tmp of > Music.Ritardando x -> fmap (processPerformance (stretch (+) x)) > Music.Accelerando x -> fmap (processPerformance (stretch (-) x)) > -- Music.Accelerando x -> fmap (processPerformance (stretch (\a b -> if a>=b then a-b else 0) x)) > fancyInterpretArticulation :: (NonNeg.C time, Fractional time) => > Music.Articulation -> Performance.Monad time dyn note -> Performance.Monad time dyn note > fancyInterpretArticulation art = > case art of > Music.Staccato x -> Player.staccatoAbs x > Music.Legato x -> Player.legatoAbs x > Music.Slurred x -> Player.slurredAbs x > _ -> id > {- Remaining articulations: > Tenuto | Marcato | Pedal | Fermata | FermataDown > | Breath | DownBow | UpBow | Harmonic | Pizzicato > | LeftPizz | BartokPizz | Swell | Wedge | Thumb | Stopped -} > fancyInterpretOrnament :: (Fractional time, Real time) => > Music.Ornament -> Performance.Monad time dyn note -> Performance.Monad time dyn note > fancyInterpretOrnament _orn = id > {- Remaining ornamenations: > Trill | Mordent | InvMordent | DoubleMordent | Turn > | TrilledTurn | ShortTrill | Arpeggio | ArpeggioUp > | ArpeggioDown | Instruction String | Head NoteHead -} > {- Design Problem: To do these right we need to keep the KEY SIGNATURE > around so that we can determine, for example, what the trill note is. > Alternatively, provide an argument to Trill to carry this info. -} > fancyInterpretPhrase :: > (NonNeg.C time, Fractional time, Real time, Fractional dyn) => > Performance.PhraseFun time dyn note > fancyInterpretPhrase pa = > case pa of > Music.Dyn dyn -> fancyInterpretDynamic dyn > Music.Tmp tmp -> fancyInterpretTempo tmp > Music.Art art -> fancyInterpretArticulation art > Music.Orn orn -> fancyInterpretOrnament orn > context :: > (NonNeg.C time, Fractional time, Real time, Fractional dyn) => > Context.T time dyn note > context = DefltPf.context {Performance.contextPlayer = player} \end{haskelllisting} } \caption{Definition of Player \function{Fancy.player}.} \figlabel{fancy-Player} \end{figure} {\small \begin{haskelllisting} > fromMusic :: > (Ord note, NonNeg.C time, RealFrac time, Fractional dyn, Ord dyn) => > Music.T note -> Performance.T time dyn note > fromMusic = > Performance.fromMusic map context > > fromMusicModifyContext :: > (Ord note, NonNeg.C time, RealFrac time, Fractional dyn, Ord dyn) => > (Context.T time dyn note -> Context.T time dyn note) -> > Music.T note -> > Performance.T time dyn note > fromMusicModifyContext update = > Performance.fromMusic > map > (update context) > > floatFromMusic :: (Ord note) => > Music.T note -> Performance.T NonNegW.Float Float note > floatFromMusic = fromMusic > > paddedFromMusic :: > (Ord note, NonNeg.C time, RealFrac time, Fractional dyn, Ord dyn) => > Music.T note -> Performance.Padded time dyn note > paddedFromMusic = > Performance.paddedFromMusic map context > > doublePaddedFromMusic :: > (Ord note) => > Music.T note -> Performance.Padded NonNegW.Double Double note > doublePaddedFromMusic = > Performance.paddedFromMusic map context > > paddedFromMusicModifyContext :: > (Ord note, NonNeg.C time, RealFrac time, Fractional dyn, Ord dyn) => > (Context.T time dyn note -> Context.T time dyn note) -> > Music.T note -> > Performance.T time dyn note > paddedFromMusicModifyContext update = > Performance.fromMusic > map > (update context) \end{haskelllisting} } % fromRhythmicMusic :: (Ord drum, Ord instr, RealFrac time) => % RhyMusic.T drum instr -> Performance.T time (RhyMusic.Note drum instr) % fromRhythmicMusic = % Performance.fromMusic map context % % floatFromRhythmicMusic :: (Ord drum, Ord instr) => % RhyMusic.T drum instr -> Performance.T Float (RhyMusic.Note drum instr) % floatFromRhythmicMusic = fromRhythmicMusic % % stateFromRhythmicMusic :: % (Ord drum, Ord instr, Fractional time, Real time) => % (RhyMusic.T drum instr) -> % ((Performance.T time (RhyMusic.Note drum instr), time), % Context.T time (RhyMusic.Note drum instr)) % stateFromRhythmicMusic m = % runState (Performance.monadFromMusic map m) context % monadFromMusic :: % (Ord note, RealFrac time) => % Music.T note -> % ((Performance.T time dyn note, time), % Context.T time dyn note) % monadFromMusic m = % runReader (Performance.monadFromMusic map m) context