\section{Convenient Functions for Getting Started With Haskore} \label{test-functions} {\small \begin{verbatim}
> module Haskore.Test where
> import Haskore.Basics  
> import Haskore.Performance
> import Haskore.ToMidi 
> -- import System.Process( system )
> import Haskore.GeneralMidi
> import Haskore.OutputMidi
>
> ----------------------------------------------------------------------------
> -- Given a PMap, Context, UserPatchMap, and file name, we can 
> -- write a Music value into a midi file:
> ----------------------------------------------------------------------------
> mToMF :: PMap -> Context -> UserPatchMap -> String -> Music -> IO ()
> mToMF pmap c upm fn m =
>       let pf = perform pmap c m
>           mf = performToMidi pf upm
>       in outputMidiFile fn mf
>
> ----------------------------------------------------------------------------
> -- Convenient default values and test routines
> ----------------------------------------------------------------------------
> -- a default UserPatchMap
> -- Note: the PC sound card I'm using is limited to 9 instruments
> defUpm :: UserPatchMap
> defUpm = [("piano","Acoustic Grand Piano",1),
>           ("vibes","Vibraphone",2),
>           ("bass","Acoustic Bass",3),
>           ("flute","Flute",4),
>           ("sax","Tenor Sax",5),
>           ("guitar","Acoustic Guitar (steel)",6),
>           ("violin","Viola",7),
>           ("violins","String Ensemble 1",8),
>           ("drums","Acoustic Grand Piano",9)]  
>             -- the GM name for drums is unimportant, only channel 9
>
> -- a default PMap that makes everything into a fancyPlayer
> defPMap :: String -> Player
> defPMap pname =
>   MkPlayer pname nf pf sf
>   where MkPlayer _ nf pf sf = fancyPlayer
> 
> -- a default Context
> defCon :: Context
> defCon = Context { cTime   = 0,
>		     cPlayer = fancyPlayer,
>		     cInst   = "piano",
>		     cDur    = metro 120 qn,
>		     cKey    = 0,
>		     cVol    = 127 }
> 
> -- Using the defaults above, from a Music object, we can:
> -- a) generate a performance
> testPerf  :: Music -> Performance
> testPerf m = perform defPMap defCon m
> testPerfDur  :: Music -> (Performance, DurT)
> testPerfDur m = perf defPMap defCon m
> 
> -- b) generate a midifile datatype
> testMidi :: Music -> MidiFile
> testMidi m = performToMidi (testPerf m) defUpm
> 
> -- c) generate a midifile
> test     :: Music -> IO ()
> test     m = outputMidiFile "test.mid" (testMidi m)
> 
> {-
> -- d) generate and play a midifile on Windows 95, Windows NT, or Linux 
> testWin95, testNT, testLinux :: Music -> IO ()
> testWin95 m = do
>                 test m
>                 system "mplayer test.mid"
>                 return ()
> testNT    m = do
>                 test m
>                 system "mplay32 test.mid"
>                 return ()
> testLinux m = do
>                 test m
>                 system "playmidi -rf test.mid"
>                 return ()
> -}
Alternatively, just run "test m" manually, and then invoke the midi player on your system using "play", defined below for NT:
> {-
> play = do
>          system "mplay32 test.mid"
>          return ()
> -}
A more general function in the tradition of testMidi, makeMidi also takes a Context and a UserPatchMap.
> makeMidi :: (Music, Context, UserPatchMap) -> MidiFile
> makeMidi (m,c,upm) = performToMidi (perform defPMap c m) upm
> ----------------------------------------------------------------------------
> -- Some General Midi test functions (use with caution)
> ----------------------------------------------------------------------------
> -- a General Midi user patch map; i.e. one that maps GM instrument names
> -- to themselves, using a channel that is the patch number modulo 16.
> -- This is for use ONLY in the code that follows, o/w channel duplication
> -- is possible, which will screw things up in general.
> gmUpm :: UserPatchMap
> gmUpm = map (\(gmn,n) -> (gmn, gmn, mod n 16 + 1)) genMidiMap
> 
> -- Something to play each "instrument group" of 8 GM instruments;
> -- this function will play a C major arpeggio on each instrument.
> gmTest :: Int -> IO()
> gmTest i =  let gMM = take 8 (drop (i*8) genMidiMap)
>                 mu  = line (map simple gMM)
>                 simple (inm,_) = Instr inm cMajArp
>             in  mToMF defPMap defCon gmUpm "test.mid" mu
\end{verbatim} }