\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} }