# # MIDI player by MikroTourette 2017 # with enhancements by jgro 2022 # local notes section by lirion 2022 # # notes is array of MIDI notes with optional length: note/length # Length is number of ticks. If omitted, length will be set to $defaultTicks. # Use 0 for rests. :local notes 62/8,60/8,58/8,57/8,67/8,58/8,65/8,63/8,65/16,67/8,63/8,62/4,63/4,62/4,60/4,62/8,55/8,62/8,60/8,58/8,57/8,67/8,58/8,65/8,63/8,65/16,67/8,63/8,62/16,62/8,55/8,62/8,60/8,58/8,57/8,67/8,58/8,65/8,63/8,65/16,67/8,63/8,62/4,63/4,62/4,60/4,62/8,55/8,62/8,60/8,58/8,57/8,67/8,58/8,65/8,63/8,65/16,67/8,63/8,62/16,62/8,55/8,62/32,70/16,67/16,69/24,70/8,69/32,62/32,67/16,65/16,69/48,63/8,60/8,62/32,70/16,67/16,69/24,70/8,69/32,67/32,65/16,63/16,62/56,0/8; # Tempo # Because clock resolution is only 10ms, you need much longer ticks than standard MIDI :local tick 50ms; # length of a tick :local defaultTicks 4; # default number of ticks for a note :local stacc 10ms; # length of break between notes :local transpose 0; # number to add to or subtract from each note (12 is 1 octave) # MIDI player # Frequencies from C9 (MIDI 120) through B9 (beyond MIDI top note of 127) :local frqtab 8372,8869,9397,9956,10548,11175,11839,12543,13288,14080,14916,15804; :local n0; :local n; :local d0; :local d; :local l; :local midi; :local i; :local octa; :local frq; :local tones; :local durations; :for i from=0 to= ([:len $notes]-1) do={ :local entry [:pick $notes $i]; :local div [:find $entry "/"]; :if ([:typeof $div] = "nil") do={ :set tones ($tones, $entry); :set durations ($durations, $defaultTicks); } else={ :set tones ($tones, [:pick $entry 0 $div]); :set durations ($durations, [:pick $entry ($div + 1) [:len $entry]]); } } :for i from=0 to= ([:len $notes]-1) do={ :set midi [:pick $tones $i]; :set midi ($midi + $transpose); :set octa 0; :while ($midi < 120) do={:set midi ($midi + 12); :set octa ($octa + 1); }; :set midi ($midi % 12); :set frq [:tonum [:pick $frqtab $midi]]; :set frq ($frq>>($octa)); :set d0 [:pick $durations $i]; :set d ($d0 * $tick ); :set l ($d0 * ($tick - $stacc)); # :put $midi; # :put $frq; # :put $octa; if ($frq >= 20) do={ :beep frequency=$frq length=$l; } :delay $d; }