\subsection{Haskore in Action}
\seclabel{examples}
\begin{haskelllisting}
> module Haskore.Example.Miscellaneous where
>
> import Haskore.Composition.Trill as Trill
> import Haskore.Composition.Drum as Drum
>
> import qualified Haskore.Music as Music
> import Haskore.Music (rest, delay, (/=:))
> import Haskore.Music.GeneralMIDI as MidiMusic
> import Haskore.Music.Standard as StdMusic
> import qualified Haskore.Music.Rhythmic as RhyMusic
> import qualified Haskore.Melody as Melody
> import Haskore.Melody.Standard as StdMelody
> import qualified Haskore.Performance.Context as Context
> import qualified Haskore.Interface.MIDI.InstrumentMap as InstrMap
> import qualified Haskore.Interface.MIDI.Write as WriteMidi
> import qualified Haskore.Interface.MIDI.Read as ReadMidi
> import qualified Haskore.Interface.MIDI.Render as Render
> import qualified Sound.MIDI.File.Save as SaveMidi
> import qualified Sound.MIDI.File.Load as LoadMidi
> import qualified Sound.MIDI.File as MidiFile
> import qualified Sound.MIDI.General as GeneralMidi
> import qualified Haskore.Example.SelfSim as SelfSim
> import qualified Haskore.Example.ChildSong6 as ChildSong6
> import qualified Haskore.Example.Ssf as Ssf
> import Haskore.Basic.Duration ((%+))
> import qualified Numeric.NonNegative.Wrapper as NonNeg
> import System.IO(IO)
> import Haskore.General.Utility (fst3, snd3, thd3)
> t0, t1, t2, t3, t4, t5,
> t10s, t12, t12a, t13, t13a, t13b, t13c, t13d, t13e,
> t14, t14b, t14c, t14d, cs6, ssf0 :: MidiFile.T
> piano, vibes, flute :: GeneralMidi.Instrument
> piano = GeneralMidi.AcousticGrandPiano
> vibes = GeneralMidi.Vibraphone
> flute = GeneralMidi.Flute
\end{haskelllisting}
Simple examples of Haskore in action. Note that this module also
imports modules ChildSong6, SelfSim, and Ssf.
\vspace{2ex}
\hrule{\hfill}
From the tutorial, try things such as pr12, cMajArp, cMajChd, etc. and
try applying inversions, retrogrades, etc. on the same examples. Also
try \code{ChildSong.song}. For example:
\begin{haskelllisting}
> t0 = Render.generalMidiDeflt ChildSong6.song
\end{haskelllisting}
\hrule{\hfill}
C Major scale for use in examples below:
\begin{haskelllisting}
> cms', cms :: Melody.T ()
> cms' = line (map (\n -> n en ())
> [c 0, d 0, e 0, f 0, g 0, a 0, b 0, c 1])
> cms = changeTempo 2 cms'
> drumScale :: MidiMusic.T
> drumScale =
> line (map (\n -> Drum.toMusicDefaultAttr (toEnum (n+13)) sn)
> [0,2,4,5,7,9,11,12])
\end{haskelllisting}
Test of various articulations and dynamics:
\begin{haskelllisting}
> t1 = Render.generalMidi
> (staccato (sn/10) drumScale +:+
> drumScale +:+
> legato (sn/10) drumScale )
>
> temp, mu2 :: MidiMusic.T
> temp = MidiMusic.fromMelodyNullAttr piano (crescendo 4.0 (c 0 en ()))
>
> mu2 = MidiMusic.fromMelodyNullAttr vibes
> (diminuendo 0.75 cms +:+
> crescendo 0.75 (loudness1 0.25 cms))
> t2 = Render.generalMidiDeflt mu2
>
> t3 = Render.generalMidiDeflt (MidiMusic.fromMelodyNullAttr flute
> (accelerando 0.3 cms +:+
> ritardando 0.6 cms ))
\end{haskelllisting}
\hrule{\hfill}
A function to recursively apply transformations
\code{f'} (to elements in a sequence) and
\code{g'} (to accumulated phrases):
\begin{haskelllisting}
> rep :: (Music.T note -> Music.T note)
> -> (Music.T note -> Music.T note)
> -> Int -> Music.T note -> Music.T note
> rep _ _ 0 _ = rest 0
> rep f' g' n m = m =:= g' (rep f' g' (n1) (f' m))
\end{haskelllisting}
An example using "rep" three times, recursively, to create a "cascade"
of sounds.
\begin{haskelllisting}
> run, cascade, cascades :: Melody.T ()
> run = rep (transpose 5) (delay tn) 8 (c 0 tn ())
> cascade = rep (transpose 4) (delay en) 8 run
> cascades = rep id (delay sn) 2 cascade
>
> t4' :: Melody.T () -> MidiFile.T
> t4' x = Render.generalMidiDeflt (MidiMusic.fromMelodyNullAttr piano x)
> t4 = Render.generalMidiDeflt (MidiMusic.fromMelodyNullAttr piano
> (cascades +:+ Music.reverse cascades))
\end{haskelllisting}
What happens if we simply reverse the \code{f} and \code{g} arguments?
\begin{haskelllisting}
> run', cascade', cascades' :: Melody.T ()
> run' = rep (delay tn) (transpose 5) 4 (c 0 tn ())
> cascade' = rep (delay en) (transpose 4) 6 run'
> cascades' = rep (delay sn) id 2 cascade'
> t5 = Render.generalMidiDeflt (MidiMusic.fromMelodyNullAttr piano cascades')
\end{haskelllisting}
\hrule{\hfill}
Example from the SelfSim module.
\begin{haskelllisting}
> t10s = Render.generalMidiDeflt (rep (delay SelfSim.durss) (transpose 4) 2 SelfSim.ss)
\end{haskelllisting}
\hrule{\hfill}
Example from the ChildSong6 module.
\begin{haskelllisting}
> cs6 = Render.generalMidiDeflt ChildSong6.song
\end{haskelllisting}
\hrule{\hfill}
Example from the Ssf (Stars and Stripes Forever) module.
\begin{haskelllisting}
> ssf0 = Render.generalMidiDeflt Ssf.song
\end{haskelllisting}
\hrule{\hfill}
Midi percussion test. Plays all "notes" in a range. (Requires adding
an instrument for percussion to the \code{InstrMap}.)
\begin{haskelllisting}
> drums :: GeneralMidi.Drum -> GeneralMidi.Drum -> MidiMusic.T
> drums dr0 dr1 =
> line (map (\drm -> Drum.toMusicDefaultAttr drm sn) [dr0..dr1])
>
> t11 :: GeneralMidi.Drum -> GeneralMidi.Drum -> MidiFile.T
> t11 dr0 dr1 = Render.generalMidiDeflt (drums dr0 dr1)
\end{haskelllisting}
\hrule{\hfill}
Test of \function{Music.take} and shorten.
\begin{haskelllisting}
> t12 = Render.generalMidiDeflt (Music.take 4 ChildSong6.song)
> t12a =
> Render.generalMidiDeflt
> (MidiMusic.fromMelodyNullAttr piano cms /=: ChildSong6.song)
\end{haskelllisting}
\hrule{\hfill}
Tests of the trill functions.
\begin{haskelllisting}
> t13note :: MidiMusic.T
> t13note = MidiMusic.fromMelodyNullAttr piano (c 1 qn ())
> t13 = Render.generalMidiDeflt (trill 1 sn t13note)
> t13a = Render.generalMidiDeflt (trill' 2 dqn t13note)
> t13b = Render.generalMidiDeflt (trillN 1 5 t13note)
> t13c = Render.generalMidiDeflt (trillN' 3 7 t13note)
> t13d = Render.generalMidiDeflt (roll tn t13note)
> t13e = Render.generalMidiDeflt (changeTempo (2/3) (transpose 2 (trillN' 2 7 t13note)))
\end{haskelllisting}
\hrule{\hfill}
Tests of drum.
\begin{haskelllisting}
> t14 = Render.generalMidiDeflt (Drum.toMusicDefaultAttr AcousticSnare qn)
\end{haskelllisting}
A "funk groove"
\begin{haskelllisting}
> t14b = let p1 = Drum.toMusicDefaultAttr LowTom qn
> p2 = Drum.toMusicDefaultAttr AcousticSnare en
> in Render.generalMidiDeflt (changeTempo 3 (Music.replicate 4
> (line [p1, qnr, p2, qnr, p2,
> p1, p1, qnr, p2, enr]
> =:= roll en (Drum.toMusicDefaultAttr ClosedHiHat 2))))
\end{haskelllisting}
A "jazz groove"
\begin{haskelllisting}
> t14c = let p1 = Drum.toMusicDefaultAttr CrashCymbal2 qn
> p2 = Drum.toMusicDefaultAttr AcousticSnare en
> p3 = Drum.toMusicDefaultAttr LowTom qn
> in Render.generalMidiDeflt (changeTempo 3 (Music.replicate 8
> ((p1 +:+ changeTempo (3%+2) (p2 +:+ enr +:+ p2))
> =:= (p3 +:+ qnr)) ))
> t14d = let p1 = Drum.toMusicDefaultAttr LowTom en
> p2 = Drum.toMusicDefaultAttr AcousticSnare hn
> in Render.generalMidiDeflt(line [roll tn p1,
> p1,
> p1,
> rest en,
> roll tn p1,
> p1,
> p1,
> rest qn,
> roll tn p2,
> p1,
> p1] )
\end{haskelllisting}
\hrule{\hfill}
\paragraph{Tests of the MIDI interface.}
\code{MidiMusic.T} into a MIDI file.
\begin{haskelllisting}
> tab :: MidiMusic.T -> IO ()
> tab m = SaveMidi.toFile "test.mid" (Render.generalMidiDeflt m)
\end{haskelllisting}
\code{MidiMusic.T} to a MidiFile datatype and back to Music.
\begin{haskelllisting}
> type StdContext =
> Context.T NonNeg.Float Float (RhyMusic.Note MidiMusic.Drum MidiMusic.Instr)
>
> type MidiArrange =
> (InstrMap.ChannelTable MidiMusic.Instr, StdContext, MidiMusic.T)
> tad :: MidiMusic.T -> MidiArrange
> tad = ReadMidi.toGMMusic . Render.generalMidiDeflt
\end{haskelllisting}
A MIDI file to a MidiFile datatype and back to a MIDI file.
\begin{haskelllisting}
> tcb, tc, tcd, tcdab :: FilePath -> IO ()
> tcb file = LoadMidi.fromFile file >>= SaveMidi.toFile "test.mid"
\end{haskelllisting}
MIDI file to MidiFile datatype.
\begin{haskelllisting}
> tc file = LoadMidi.fromFile file >>= print
\end{haskelllisting}
MIDI file to \code{MidiMusic.T}, a \code{InstrMap}, and a \code{Context}.
\begin{haskelllisting}
> tcd file = do
> x <- fmap ReadMidi.toGMMusic
> (LoadMidi.fromFile file)
> print $ fst3 (x::MidiArrange)
> print $ snd3 x
> print $ thd3 x
\end{haskelllisting}
A MIDI file to \code{MidiMusic.T} and back to a MIDI file.
\begin{haskelllisting}
> tcdab file =
> LoadMidi.fromFile file >>=
> (SaveMidi.toFile "test.mid" . WriteMidi.fromGMMusic .
> (id::MidiArrange -> MidiArrange) . ReadMidi.toGMMusic)
\end{haskelllisting}