Advertisement
glitchdetector

MIDI

Oct 10th, 2018
260
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 67.24 KB | None | 0 0
  1. #!/usr/bin/lua
  2. --require 'DataDumper'   -- http://lua-users.org/wiki/DataDumper
  3. local M = {} -- public interface
  4. M.Version = 'VERSION'
  5. M.VersionDate = 'DATESTAMP'
  6. -- 20170917 6.8 fix 153: bad argument #1 to 'char' and round dtime
  7. -- 20160702 6.7 to_millisecs() now handles set_tempo across multiple Tracks
  8. -- 20150921 6.5 segment restores controllers as well as patch and tempo
  9. -- 20150920 6.4 segment respects a set_tempo exactly on the start time
  10. -- 20150628 6.3 absent any set_tempo, default is 120bpm (see MIDI filespec 1.1)
  11. -- 20150422 6.2 works with lua5.3
  12. -- 20140609 6.1 switch pod and doc over to using moonrocks
  13. -- 20140108 6.0 in lua5.2 require('posix') returns the posix table
  14. -- 20120504 5.9 add the contents of mid_opus_tracks()
  15. -- 20111129 5.7 _encode handles empty tracks; score2stats num_notes_by_channel
  16. -- 20111111 5.6 fix patch 45 and 46 in Number2patch, should be Pizz and Harp
  17. -- 20110115 5.5 add mix_opus_tracks()
  18. -- 20110126 5.4 "previous message repeated N times" to save space on stderr
  19. -- 20110126 5.3 robustness fix if one note_on and multiple note_offs
  20. -- 20110125 5.2 opus2score terminates unended notes at the end of the track
  21. -- 20110124 5.1 the warnings in midi2opus display track_num
  22. -- 20110122 5.0 sysex2midimode.get pythonism eliminated
  23. -- 20110119 4.9 copyright_text_event "time" item was missing
  24. -- 20110110 4.8 note_on with velocity=0 treated as a note-off
  25. -- 20110109 4.7 many global vars localised, passes lualint :-)
  26. -- 20110108 4.6 duplicate int2sevenbits removed, passes lualint -r
  27. -- 20110108 4.5 related end_track bugs fixed around line 516
  28. -- 20110108 4.4 null text_event bug fixed
  29. -- 20101026 4.3 segment() remembers all patch_changes, not just the list values
  30. -- 20101010 4.2 play_score() uses posix.fork if available
  31. -- 20101009 4.2 merge_scores() moves aside conflicting channels correctly
  32. -- 20101006 4.1 concatenate_scores() deepcopys also its 1st score
  33. -- 20101006 4.1 segment() uses start_time and end_time named arguments
  34. -- 20101005 4.1 timeshift() must not pad the set_tempo command
  35. -- 20101003 4.0 pitch2note_event must be chapitch2note_event
  36. -- 20100918 3.9 set_sequence_number supported, FWIW
  37. -- 20100918 3.8 timeshift and segment accept named args
  38. -- 20100913 3.7 first released version
  39.  
  40. ---------------------------- private -----------------------------
  41. local sysex2midimode = {
  42.     ["\126\127\09\01\247"] = 1,
  43.     ["\126\127\09\02\247"] = 0,
  44.     ["\126\127\09\03\247"] = 2,
  45. }
  46.  
  47. local previous_warning = '' -- 5.4
  48. local previous_times = 0    -- 5.4
  49. local function clean_up_warnings() -- 5.4
  50.     -- Call this before returning from any publicly callable function
  51.     -- whenever there's a possibility that a warning might have been printed
  52.     -- by the function, or by any private functions it might have called.
  53.     if previous_times > 1 then
  54.         io.stderr:write('  previous message repeated '
  55.          ..previous_times..' times\n')
  56.     elseif previous_times > 0 then
  57.         io.stderr:write('  previous message repeated\n')
  58.     end
  59.     previous_times = 0
  60.     previous_warning = ''
  61. end
  62. local function warn(str)
  63.     if str == previous_warning then -- 5.4
  64.         previous_times = previous_times + 1
  65.     else
  66.         clean_up_warnings()
  67.         io.stderr:write(str,'\n')
  68.         previous_warning = str
  69.     end
  70. end
  71. local function die(str)
  72.     clean_up_warnings()
  73.     io.stderr:write(str,'\n')
  74.     os.exit(1)
  75. end
  76. local function round(x) return math.floor(x+0.5) end
  77.  
  78. local function readOnly(t)  -- Programming in Lua, page 127
  79.     local proxy = {}
  80.     local mt = {
  81.         __index = t,
  82.         __newindex = function (t, k, v)
  83.             die("attempt to update a read-only table")
  84.         end
  85.     }
  86.     setmetatable(proxy, mt)
  87.     return proxy
  88. end
  89.  
  90. local function dict(a)
  91.     local d = {}
  92.     if a == nil then return d end
  93.     for k,v in ipairs(a) do d[v] = true end
  94.     return d
  95. end
  96.  
  97. local function sorted_keys(t)
  98.     local a = {}
  99.     for k,v in pairs(t) do a[#a+1] = k end
  100.     table.sort(a)
  101.     return  a
  102. end
  103.  
  104. local function int2byte(i)
  105.     return string.char(math.floor((i+0.5) % 256))
  106. end
  107.  
  108. local function int2sevenbits(i)
  109.     return string.char(math.floor((i+0.5) % 128))
  110. end
  111.  
  112. local function int2twobytes(i)
  113.     local b1 = math.floor(i/256) % 256
  114.     local b2 = i % 256
  115.     return string.char(b1,b2)
  116. end
  117.  
  118. local function twobytes2int(s)
  119.     return 256*string.byte(string.sub(s,1)) + string.byte(string.sub(s,2))
  120. end
  121.  
  122. local function int2fourbytes(i)
  123.     local b1 = math.floor(i/16777216) % 256
  124.     local b2 = math.floor(i/65536) % 256
  125.     local b3 = math.floor(i/256) % 256
  126.     local b4 = i % 256
  127.     return string.char(b1,b2,b3,b4)
  128. end
  129.  
  130. local function fourbytes2int(s)
  131.     return 16777216*string.byte(string.sub(s,1)) +
  132.      65536 * string.byte(string.sub(s,2)) +
  133.      256*string.byte(string.sub(s,3)) + string.byte(string.sub(s,4))
  134. end
  135.  
  136. local function read_14_bit(byte_a)
  137.     -- decode a 14 bit quantity from two bytes,
  138.     return string.byte(byte_a,1) + 128 * string.byte(byte_a,2)
  139. end
  140.  
  141. local function write_14_bit(integer)
  142.     -- encode a 14 bit quantity into two bytes,
  143.     return string.char(integer % 128, math.floor(integer/128) % 128)
  144.     -- return string.char((integer/128) % 128, integer % 128)
  145. end
  146.  
  147. local function ber_compressed_int(integer)
  148. --[[BER compressed integer (not an ASN.1 BER, see perlpacktut for
  149. details).  Its bytes represent an unsigned integer in base 128,
  150. most significant digit first, with as few digits as possible.
  151. Bit eight (the high bit) is set on each byte except the last.
  152. ]]
  153. -- stderr.write('integer = ..',integer)
  154.     -- warn('integer = '..tostring(integer)..' type '..type(integer))
  155.     if integer == 0 then return '\000' end
  156.     local ber = { string.char(integer % 128) }
  157.     while integer > 127 do
  158.         integer = math.floor(integer/128)
  159.         local seven_bits = integer % 128
  160.         table.insert(ber, 1, string.char(128+seven_bits))
  161.     end
  162.     return table.concat(ber)
  163. end
  164.  
  165. local function str2ber_int(s, start)
  166. --[[Given (a string, and a position within it), returns
  167. (the ber_integer at that position, and the position after the ber_integer).
  168. ]]
  169.     local i = start
  170.     local integer = 0
  171.     while true do
  172.         local byte = string.byte(s, i)
  173.         integer = integer + (byte%128)
  174.         if byte < 127.5 then
  175.             return integer, i+1
  176.         end
  177.         if i >= #s then
  178.             warn('str2ber_int: no end-of-integer found')
  179.             return 0, start
  180.         end
  181.         i = i + 1
  182.         integer = integer * 128
  183.     end
  184. end
  185.  
  186. local function some_text_event(which_kind, text)
  187.     if not which_kind then which_kind = 1 end
  188.     if not text then text = 'some_text' end
  189.     return '\255'..int2sevenbits(which_kind)..ber_compressed_int(text:len())..text
  190. end
  191.  
  192. local function copy(t)
  193.     local new_table = {}
  194.     for k, v in pairs(t) do new_table[k] = v end
  195.     return new_table
  196. end
  197.  
  198. local function deepcopy(object)  -- http://lua-users.org/wiki/CopyTable
  199.     local lookup_table = {}
  200.     local function _copy(object)
  201.         if type(object) ~= "table" then
  202.             return object
  203.         elseif lookup_table[object] then
  204.             return lookup_table[object]
  205.         end
  206.         local new_table = {}
  207.         lookup_table[object] = new_table
  208.         for index, value in pairs(object) do
  209.             new_table[_copy(index)] = _copy(value)
  210.         end
  211.         return setmetatable(new_table, getmetatable(object))
  212.     end
  213.     return _copy(object)
  214. end
  215.  
  216. local function _decode(trackdata, exclude, include, event_callback, exclusive_event_callback, no_eot_magic)
  217. --[[Decodes MIDI track data into an opus-style list of events.
  218. The options:
  219.   'exclude' is a dictionary-table of event types which will be ignored
  220.   'include' (and no exclude), makes exclude an array of all
  221.       possible events, /minus/ what include specifies
  222.   'event_callback' is a function
  223.   'exclusive_event_callback' is a function
  224. ]]
  225.  
  226.     if not trackdata then trackdata= '' end
  227.     if not exclude then exclude = {} end
  228.     if not include then include = {} end
  229.     if include and not exclude then exclude = M.All_events end  -- 4.6
  230.  
  231.     local event_code = -1 -- used for running status
  232.     local event_count = 0
  233.     local events = {}
  234.  
  235.     local i = 1     -- in Lua, i is the pointer to within the trackdata
  236.     while i < #trackdata do   -- loop while there's anything to analyze
  237.         local eot = false -- when True event registrar aborts this loop 4.6,4.7
  238.         event_count = event_count + 1
  239.  
  240.         local E = {} -- event; feed it to the event registrar at the end. 4.7
  241.  
  242.         -- Slice off the delta time code, and analyze it
  243.         local time
  244.         time, i = str2ber_int(trackdata, i)
  245.  
  246.         -- Now let's see what we can make of the command
  247.         local first_byte = string.byte(trackdata,i); i = i+1
  248.  
  249.         if first_byte < 240 then  -- It's a MIDI event
  250.             if first_byte % 256 > 127 then
  251.                 event_code = first_byte
  252.             else
  253.                 -- It wants running status; use last event_code value
  254.                 i = i-1
  255.                 if event_code == -1 then
  256.                     warn("Running status not set; Aborting track.")
  257.                     return {}
  258.                 end
  259.             end
  260.  
  261.             local command = math.floor(event_code / 16) * 16
  262.             local channel = event_code % 16
  263.             local parameter
  264.             local param1
  265.             local param2
  266.  
  267.             if command == 246 then  --  0-byte argument
  268.                 --pass
  269.             elseif command == 192 or command == 208 then  --  1-byte arg
  270.                 parameter = string.byte(trackdata, i); i = i+1
  271.             else -- 2-byte argument could be BB or 14-bit
  272.                 param1 = string.byte(trackdata, i); i = i+1
  273.                 param2 = string.byte(trackdata, i); i = i+1
  274.             end
  275.  
  276.             ----------------- MIDI events -----------------------
  277.  
  278.             local continue = false
  279.             if command      == 128 then
  280.                 if exclude['note_off'] then
  281.                     continue = true
  282.                 else
  283.                     E = {'note_off', time, channel, param1, param2}
  284.                 end
  285.             elseif command == 144 then
  286.                 if exclude['note_on'] then
  287.                     continue = true
  288.                 else
  289.                     E = {'note_on', time, channel, param1, param2}
  290.                 end
  291.             elseif command == 160 then
  292.                 if exclude['key_after_touch'] then
  293.                     continue = true
  294.                 else
  295.                     E = {'key_after_touch',time,channel,param1,param2}
  296.                 end
  297.             elseif command == 176 then
  298.                 if exclude['control_change'] then
  299.                     continue = true
  300.                 else
  301.                     E = {'control_change',time,channel,param1,param2}
  302.                 end
  303.             elseif command == 192 then
  304.                 if exclude['patch_change'] then
  305.                     continue = true
  306.                 else
  307.                     E = {'patch_change', time, channel, parameter}
  308.                 end
  309.             elseif command == 208 then
  310.                 if exclude['channel_after_touch'] then
  311.                     continue = true
  312.                 else
  313.                     E = {'channel_after_touch', time, channel, parameter}
  314.                 end
  315.             elseif command == 224 then
  316.                 if exclude['pitch_wheel_change'] then
  317.                     continue = true
  318.                 else -- the 2 param bytes are a 14-bit int
  319.                     E = {'pitch_wheel_change', time, channel,
  320.                      128*param2+param1-8192}
  321.                 end
  322.             else
  323.                 warn("Shouldn't get here; command="..tostring(command))
  324.             end
  325.  
  326.         elseif first_byte == 255 then  -- It's a Meta-Event!
  327.             local command = string.byte(trackdata, i); i = i+1
  328.             local length
  329.             length, i = str2ber_int(trackdata, i)
  330.             if (command      == 0) then
  331.                 if length == 2 then  -- 3.9
  332.                     E = {'set_sequence_number', time,
  333.                      twobytes2int(string.sub(trackdata,i,i+1)) }
  334.                 else
  335.                     warn('set_sequence_number: length must be 2, not '
  336.                      .. tostring(length))
  337.                     E = {'set_sequence_number', time, 0}
  338.                 end
  339.  
  340.             -- Defined text events ------
  341.             elseif command == 1 then
  342.                 E = {'text_event', time, string.sub(trackdata,i,i+length-1)}
  343.             elseif command == 2 then  -- 4.9
  344.                 E = {'copyright_text_event', time, string.sub(trackdata,i,i+length-1)}
  345.             elseif command == 3 then
  346.                 E = {'track_name',time, string.sub(trackdata,i,i+length-1)}
  347.             elseif command == 4 then
  348.                 E = {'instrument_name',time, string.sub(trackdata,i,i+length-1)}
  349.             elseif command == 5 then
  350.                 E = {'lyric',time, string.sub(trackdata,i,i+length-1)}
  351.             elseif command == 6 then
  352.                 E = {'marker',time, string.sub(trackdata,i,i+length-1)}
  353.             elseif command == 7 then
  354.                 E = {'cue_point',time, string.sub(trackdata,i,i+length-1)}
  355.  
  356.             -- Reserved but apparently unassigned text events -------------
  357.             elseif command == 8 then
  358.                 E = {'text_event_08',time, string.sub(trackdata,i,i+length-1)}
  359.             elseif command == 9 then
  360.                 E = {'text_event_09',time, string.sub(trackdata,i,i+length-1)}
  361.             elseif command == 10 then
  362.                 E = {'text_event_0a',time, string.sub(trackdata,i,i+length-1)}
  363.             elseif command == 11 then
  364.                 E = {'text_event_0b',time, string.sub(trackdata,i,i+length-1)}
  365.             elseif command == 12 then
  366.                 E = {'text_event_0c',time, string.sub(trackdata,i,i+length-1)}
  367.             elseif command == 13 then
  368.                 E = {'text_event_0d',time, string.sub(trackdata,i,i+length-1)}
  369.             elseif command == 14 then
  370.                 E = {'text_event_0e',time, string.sub(trackdata,i,i+length-1)}
  371.             elseif command == 15 then
  372.                 E = {'text_event_0f',time, string.sub(trackdata,i,i+length-1)}
  373.            
  374.             -- Now the sticky events -------------------------------------
  375.             elseif command == 47 then
  376.                 E = {'end_track', time}
  377.                 -- The code for handling this, oddly, comes LATER,
  378.                 -- in the event registrar.
  379.             elseif command == 81 then -- DTime, Microseconds/Crochet
  380.                 if length ~= 3 then
  381.                     warn('set_tempo event, but length='..length)
  382.                 end
  383.                 E = {'set_tempo', time,
  384.                     string.byte(trackdata,i) * 65536
  385.                     + string.byte(trackdata,i+1) * 256
  386.                     + string.byte(trackdata,i+2)
  387.                 }
  388.             elseif command == 84 then
  389.                 if length ~= 5 then   -- DTime, HR, MN, SE, FR, FF
  390.                     warn('smpte_offset event, but length='..length)
  391.                 end
  392.                 E = {'smpte_offset', time,
  393.                     string.byte(trackdata,i),
  394.                     string.byte(trackdata,i+1),
  395.                     string.byte(trackdata,i+2),
  396.                     string.byte(trackdata,i+3),
  397.                     string.byte(trackdata,i+4)
  398.                 }
  399.             elseif command == 88 then
  400.                 if length ~= 4 then   -- DTime, NN, DD, CC, BB
  401.                     warn('time_signature event, but length='..length)
  402.                 end
  403.                 E = {'time_signature', time,
  404.                     string.byte(trackdata,i),
  405.                     string.byte(trackdata,i+1),
  406.                     string.byte(trackdata,i+2),
  407.                     string.byte(trackdata,i+3)
  408.                 }
  409.             elseif command == 89 then
  410.                 if length ~= 2 then   -- DTime, SF(signed), MI
  411.                     warn('key_signature event, but length='..length)
  412.                 end
  413.                 local b1 = string.byte(trackdata,i)
  414.                 if b1 > 127 then b1 = b1 - 256 end   -- signed byte :-(
  415.                 local b2 = string.byte(trackdata,i+1)
  416.                 -- list(struct.unpack(">bB",trackdata[0:2]))}
  417.                 E = {'key_signature', time, b1, b2 }
  418.             elseif (command == 127) then
  419.                 E = {'sequencer_specific',time,
  420.                     string.sub(trackdata,i,i+length-1)}
  421.             else
  422.                 E = {'raw_meta_event', time, command,
  423.                     string.sub(trackdata,i,i+length-1)}
  424.                 --"[uninterpretable meta-event command of length length]"
  425.                 -- DTime, Command, Binary Data
  426.                 -- It's uninterpretable; record it as raw_data.
  427.             end
  428.  
  429.             -- Pointer += length; --  Now move Pointer
  430.             i = i + length
  431.             -- Hmm... in lua, we should be using Pointer again....
  432.             -- trackdata =  string.sub(trackdata, length+1)
  433.  
  434.         --#####################################################################
  435.         elseif first_byte == 240 or first_byte == 247 then
  436.             -- Note that sysexes in MIDI /files/ are different than sysexes
  437.             -- in MIDI transmissions!! The vast majority of system exclusive
  438.             -- messages will just use the F0 format. For instance, the
  439.             -- transmitted message F0 43 12 00 07 F7 would be stored in a
  440.             -- MIDI file as F0 05 43 12 00 07 F7. As mentioned above, it is
  441.             -- required to include the F7 at the end so that the reader of the
  442.             -- MIDI file knows that it has read the entire message. (But the F7
  443.             -- is omitted if this is a non-final block in a multiblock sysex;
  444.             -- but the F7 (if there) is counted in the message's declared
  445.             -- length, so we don't have to think about it anyway.)
  446.             --command = trackdata.pop(0)
  447.             local length
  448.             length, i = str2ber_int(trackdata, i)
  449.             if first_byte == 240 then
  450.                 -- 20091008 added ISO-8859-1 to get an 8-bit str
  451.                 E = {'sysex_f0', time, string.sub(trackdata,i,i+length-1)}
  452.             else
  453.                 E = {'sysex_f7', time, string.sub(trackdata,i,i+length-1)}
  454.             end
  455.             i = i + length
  456.             -- trackdata =  string.sub(trackdata, length+1)
  457.  
  458.         --#####################################################################
  459.         -- Now, the MIDI file spec says:
  460.         --  <track data> = <MTrk event>+
  461.         --  <MTrk event> = <delta-time> <event>
  462.         --  <event> = <MIDI event> | <sysex event> | <meta-event>
  463.         -- I know that, on the wire, <MIDI event> can include note_on,
  464.         -- note_off, and all the other 8x to Ex events, AND Fx events
  465.         -- other than F0, F7, and FF -- namely, <song position msg>,
  466.         -- <song select msg>, and <tune request>.
  467.         --
  468.         -- Whether these can occur in MIDI files is not clear specified
  469.         -- from the MIDI file spec.  So, I'm going to assume that
  470.         -- they CAN, in practice, occur.  I don't know whether it's
  471.         -- proper for you to actually emit these into a MIDI file.
  472.        
  473.         elseif first_byte == 242 then   -- DTime, Beats
  474.             --  <song position msg> ::=     F2 <data pair>
  475.             E = {'song_position', time, read_14_bit(string.sub(trackdata,i))}
  476.             trackdata = string.sub(trackdata,3)
  477.  
  478.         elseif first_byte == 243 then -- <song select> ::= F3 <data singlet>
  479.             -- E=['song_select', time, struct.unpack('>B',trackdata.pop(0))[0]]
  480.             E = {'song_select', time, string.byte(trackdata,i)}
  481.             -- trackdata = trackdata[1:]
  482.             trackdata = string.sub(trackdata,2)
  483.             -- DTime, Thing (what?! song number?  whatever ...)
  484.  
  485.         elseif first_byte == 246 then   -- DTime
  486.             E = {'tune_request', time}
  487.             -- What would a tune request be doing in a MIDI /file/?
  488.  
  489.         --########################################################
  490.         -- ADD MORE META-EVENTS HERE.  TODO:
  491.         -- f1 -- MTC Quarter Frame Message. One data byte follows
  492.         --     the Status; it's the time code value, from 0 to 127.
  493.         -- f8 -- MIDI clock.    no data.
  494.         -- fa -- MIDI start.    no data.
  495.         -- fb -- MIDI continue. no data.
  496.         -- fc -- MIDI stop.     no data.
  497.         -- fe -- Active sense.  no data.
  498.         -- f4 f5 f9 fd -- unallocated
  499.  
  500. --[[
  501.         elseif (first_byte > 240) { -- Some unknown kinda F-series event ####
  502.             -- Here we only produce a one-byte piece of raw data.
  503.             -- But the encoder for 'raw_data' accepts any length of it.
  504.             E = [ 'raw_data', time, substr(trackdata,Pointer,1) ]
  505.             -- DTime and the Data (in this case, the one Event-byte)
  506.             ++Pointer;  -- itself
  507.  
  508. ]]
  509.         elseif first_byte > 240 then  -- Some unknown F-series event
  510.             -- Here we only produce a one-byte piece of raw data.
  511.             E = {'raw_data', time, string.byte(trackdata,i)}  -- 4.6
  512.             trackdata = string.sub(trackdata,2)  -- 4.6
  513.         else  -- Fallthru.
  514.             warn(string.format("Aborting track.  Command-byte first_byte=0x%x",first_byte)) --4.6
  515.             break
  516.         end
  517.         -- End of the big if-group
  518.  
  519.  
  520.         --#####################################################################
  521.         --  THE EVENT REGISTRAR...
  522.         -- warn('3: E='+str(E))
  523.         if E and  E[1] == 'end_track' then
  524.             -- This is the code for exceptional handling of the EOT event.
  525.             eot = true
  526.             if not no_eot_magic then
  527.                 if E[2] > 0 then  -- a null text-event to carry the delta-time
  528.                     E = {'text_event', E[2], ''}  -- 4.4
  529.                 else
  530.                     E = nil   -- EOT with a delta-time of 0; ignore it.
  531.                 end
  532.             end
  533.         end
  534.  
  535.         if E and not exclude[E[1]] then
  536.             --if ( $exclusive_event_callback ):
  537.             --    &{ $exclusive_event_callback }( @E );
  538.             --else
  539.             --    &{ $event_callback }( @E ) if $event_callback;
  540.             events[#events+1] = E
  541.         end
  542.         if eot then break end
  543.     end
  544.     -- End of the big "Event" while-block
  545.  
  546.     return events
  547. end
  548.  
  549. local function _encode(events_lol)
  550.     local no_running_status = false
  551.     local no_eot_magic      = false   -- 4.6
  552.     local never_add_eot     = false   -- 4.6
  553.     local unknown_callback  = false   -- 4.6
  554.     local data = {} -- what I'll store the chunks of byte-data in
  555.  
  556.     -- This is so my end_track magic won't corrupt the original
  557.     local events = deepcopy(events_lol)
  558.  
  559.     if not never_add_eot then -- One way or another, tack on an 'end_track'
  560.         if #events > 0 then   -- 5.7
  561.             local last = events[#events] -- 4.5, 4.7
  562.             if not (last[1] == 'end_track') then  -- no end_track already
  563.                 if (last[1] == 'text_event' and last[3] == '') then -- 4.5,4.6
  564.                     -- 0-length text event at track-end.
  565.                     if no_eot_magic then
  566.                         -- Exceptional case: don't mess with track-final
  567.                         -- 0-length text_events; just peg on an end_track
  568.                         events.append({'end_track', 0})
  569.                     else
  570.                         -- NORMAL CASE: replace with an end_track, leaving DTime
  571.                         last[1] = 'end_track'
  572.                     end
  573.                 else
  574.                     -- last event was neither 0-length text_event nor end_track
  575.                     events[#events+1] = {'end_track', 0}
  576.                 end
  577.             end
  578.         else  -- an eventless track!
  579.             events = { {'end_track', 0},}
  580.         end
  581.     end
  582.  
  583.     -- maybe_running_status = not no_running_status  -- unused? 4.7
  584.     local last_status = -1 -- 4.7
  585.  
  586.     for k,E in ipairs(events) do
  587.         -- get rid of the two pop's and increase the other E[] indices by two
  588.         if not E then break end
  589.  
  590.         local event = E[1] -- 4.7
  591.         if #event < 1 then break end
  592.  
  593.         local dtime = round(E[2]) -- 4.7 6.8
  594.         -- print('event='..event..' dtime='..dtime)
  595.  
  596.         local event_data = '' -- 4.7
  597.  
  598.         if    -- MIDI events -- eligible for running status
  599.              event  == 'note_on'
  600.              or event == 'note_off'
  601.              or event == 'control_change'
  602.              or event == 'key_after_touch'
  603.              or event == 'patch_change'
  604.              or event == 'channel_after_touch'
  605.              or event == 'pitch_wheel_change'   then
  606.  
  607.             -- This block is where we spend most of the time.  Gotta be tight.
  608.             local status = nil     -- 4.7
  609.             local parameters = nil -- 4.7
  610.             if (event == 'note_off') then
  611.                 status = 128 + (E[3] % 16)
  612.                 parameters = int2sevenbits(E[4]%128)..int2sevenbits(E[5]%128)
  613.             elseif event == 'note_on' then
  614.                 status = 144 + (E[3] % 16)
  615.                 parameters = int2sevenbits(E[4]) .. int2sevenbits(E[5])
  616.             elseif event == 'key_after_touch' then
  617.                 status = 160 + (E[3] % 16)
  618.                 parameters = int2sevenbits(E[4]) .. int2sevenbits(E[5])
  619.             elseif event == 'control_change' then
  620.                 status = 176 + (E[3] % 16)
  621.                 parameters = int2sevenbits(E[4]) .. int2sevenbits(E[5])
  622.             elseif event == 'patch_change' then
  623.                 status = 192 + (E[3] % 16)
  624.                 parameters = int2sevenbits(E[4])
  625.             elseif event == 'channel_after_touch' then
  626.                 status = 208 + (E[3] % 16)
  627.                 parameters = int2sevenbits(E[4])
  628.             elseif event == 'pitch_wheel_change' then
  629.                 status = 224 + (E[3] % 16)
  630.                 parameters =  write_14_bit(E[4] + 8192)
  631.             else
  632.                 warn("BADASS FREAKOUT ERROR 31415!")
  633.             end
  634.  
  635.             -- And now the encoding
  636.  
  637.             data[#data+1] = ber_compressed_int(dtime)
  638.             if (status ~= last_status) or no_running_status then
  639.                 data[#data+1] = int2byte(status)
  640.             end
  641.             data[#data+1] = parameters
  642.             last_status = status
  643.             -- break
  644.         else
  645.             -- Not a MIDI event.
  646.             last_status = -1
  647.  
  648.             if event == 'raw_meta_event' then
  649.                 event_data = some_text_event(E[3], E[4])
  650.             elseif (event == 'set_sequence_number') then  -- 3.9
  651.                 event_data = some_text_event(0, int2twobytes(E[3]))
  652.  
  653.             -- Text Meta-events...
  654.             -- a case for a dict, I think (pjb) ...
  655.             elseif (event == 'text_event') then
  656.                 event_data = some_text_event(1, E[3])
  657.             elseif (event == 'copyright_text_event') then
  658.                 event_data = some_text_event(2, E[3])
  659.             elseif (event == 'track_name') then
  660.                 event_data = some_text_event(3, E[3])
  661.             elseif (event == 'instrument_name') then
  662.                 event_data = some_text_event(4, E[3])
  663.             elseif (event == 'lyric') then
  664.                 event_data = some_text_event(5, E[3])
  665.             elseif (event == 'marker') then
  666.                 event_data = some_text_event(6, E[3])
  667.             elseif (event == 'cue_point') then
  668.                 event_data = some_text_event(7, E[3])
  669.             elseif (event == 'text_event_08') then
  670.                 event_data = some_text_event(8, E[3])
  671.             elseif (event == 'text_event_09') then
  672.                 event_data = some_text_event(9, E[3])
  673.             elseif (event == 'text_event_0a') then
  674.                 event_data = some_text_event(10, E[3])
  675.             elseif (event == 'text_event_0b') then
  676.                 event_data = some_text_event(11, E[3])
  677.             elseif (event == 'text_event_0c') then
  678.                 event_data = some_text_event(12, E[3])
  679.             elseif (event == 'text_event_0d') then
  680.                 event_data = some_text_event(13, E[3])
  681.             elseif (event == 'text_event_0e') then
  682.                 event_data = some_text_event(14, E[3])
  683.             elseif (event == 'text_event_0f') then
  684.                 event_data = some_text_event(15, E[3])
  685.             -- End of text meta-events
  686.  
  687.             elseif (event == 'end_track') then
  688.                 event_data = '\255\47\0'
  689.             elseif (event == 'set_tempo') then
  690.                 --event_data = struct.pack(">BBwa*", 0xFF, 0x51, 3,
  691.                 --            substr( struct.pack('>I', E[0]), 1, 3))
  692.                 event_data = '\255\81\03' .. string.sub(int2fourbytes(E[3]),2)
  693.                 -- XXX don't understand that ?!
  694.             elseif (event == 'smpte_offset') then
  695.                 event_data = '\255\84\05' ..
  696.                     string.char(E[3],E[4],E[5],E[6],E[7])
  697.             elseif (event == 'time_signature') then
  698.                 event_data = '\255\88\04' .. string.char(E[3],E[4],E[5],E[6])
  699.             elseif (event == 'key_signature') then
  700.                 local e3 = E[3]; if e3<0 then e3 = 256+e3 end  -- signed byte
  701.                 event_data = '\255\89\02' .. string.char(e3,E[4])
  702.             elseif (event == 'sequencer_specific') then
  703.                 event_data = some_text_event(127, E[3])
  704.             -- End of Meta-events
  705.  
  706.             -- Other Things...
  707.             elseif (event == 'sysex_f0') then
  708.                 event_data =
  709.                  "\240"..ber_compressed_int(string.len(E[3]))..E[3]
  710.             elseif (event == 'sysex_f7') then
  711.                 event_data =
  712.                  "\247"..ber_compressed_int(string.len(E[3]))..E[3]
  713.             elseif (event == 'song_position') then
  714.                  event_data = "\242"..write_14_bit( E[3] )
  715.             elseif (event == 'song_select') then
  716.                  event_data = "\243"..string.char(E[3])
  717.             elseif (event == 'tune_request') then
  718.                  event_data = "\246"
  719.             elseif (event == 'raw_data') then
  720.                 warn("_encode: raw_data event not supported")
  721.                 break
  722.             -- End of Other Stuff
  723.  
  724.             -- The Big Fallthru
  725.             else
  726.                 if not unknown_callback then
  727.                     warn("Unknown event: "..tostring(event))
  728.                 end
  729.                 break
  730.             end
  731.  
  732.             --print "Event $event encoded part 2\n"
  733.             --if str(type(event_data)).find('str') >= 0 then
  734.             --  event_data = bytearray(event_data.encode('Latin1', 'ignore'))
  735.             --end
  736.             if event_data and (#event_data > 0) then -- how could it be empty?
  737.                 -- data.append(struct.pack('>wa*', dtime, event_data))
  738.                 -- print(' event_data='+str(event_data))
  739.                 data[#data+1] = ber_compressed_int(dtime)
  740.                 data[#data+1] = event_data
  741.             end
  742.         end
  743.     end
  744.     return table.concat(data)
  745. end
  746.  
  747. local function consistentise_ticks(scores) -- 3.6
  748.     -- used by mix_scores, merge_scores, concatenate_scores
  749.     if #scores == 1 then return deepcopy(scores) end
  750.     local are_consistent = true
  751.     local ticks = scores[1][1]
  752.     for iscore = 2,#scores do
  753.         if scores[iscore][1] ~= ticks then
  754.             are_consistent = false
  755.             break
  756.         end
  757.     end
  758.     if are_consistent then return deepcopy(scores) end
  759.     local new_scores = {}
  760.     for ks,score in ipairs(scores) do
  761.         new_scores[ks] = M.opus2score(M.to_millisecs(M.score2opus(score)))
  762.     end
  763.     return new_scores
  764. end
  765.  
  766. -------------------------- public ------------------------------
  767. M.All_events = readOnly{
  768.     note_off=true, note_on=true, key_after_touch=true, control_change=true,
  769.     patch_change=true, channel_after_touch=true, pitch_wheel_change=true,
  770.     text_event=true, copyright_text_event=true, track_name=true,
  771.     instrument_name=true, lyric=true, marker=true, cue_point=true,
  772.     text_event_08=true, text_event_09=true, text_event_0a=true,
  773.     text_event_0b=true, text_event_0c=true, text_event_0d=true,
  774.     text_event_0e=true, text_event_0f=true,
  775.     end_track=true, set_tempo=true, smpte_offset=true,
  776.     time_signature=true, key_signature=true,
  777.     sequencer_specific=true, raw_meta_event=true,
  778.     sysex_f0=true, sysex_f7=true,
  779.     song_position=true, song_select=true, tune_request=true,
  780. }
  781. -- And three dictionaries:
  782. M.Number2patch = readOnly{   -- General MIDI patch numbers:
  783. [0]='Acoustic Grand',
  784. [1]='Bright Acoustic',
  785. [2]='Electric Grand',
  786. [3]='Honky-Tonk',
  787. [4]='Electric Piano 1',
  788. [5]='Electric Piano 2',
  789. [6]='Harpsichord',
  790. [7]='Clav',
  791. [8]='Celesta',
  792. [9]='Glockenspiel',
  793. [10]='Music Box',
  794. [11]='Vibraphone',
  795. [12]='Marimba',
  796. [13]='Xylophone',
  797. [14]='Tubular Bells',
  798. [15]='Dulcimer',
  799. [16]='Drawbar Organ',
  800. [17]='Percussive Organ',
  801. [18]='Rock Organ',
  802. [19]='Church Organ',
  803. [20]='Reed Organ',
  804. [21]='Accordion',
  805. [22]='Harmonica',
  806. [23]='Tango Accordion',
  807. [24]='Acoustic Guitar(nylon)',
  808. [25]='Acoustic Guitar(steel)',
  809. [26]='Electric Guitar(jazz)',
  810. [27]='Electric Guitar(clean)',
  811. [28]='Electric Guitar(muted)',
  812. [29]='Overdriven Guitar',
  813. [30]='Distortion Guitar',
  814. [31]='Guitar Harmonics',
  815. [32]='Acoustic Bass',
  816. [33]='Electric Bass(finger)',
  817. [34]='Electric Bass(pick)',
  818. [35]='Fretless Bass',
  819. [36]='Slap Bass 1',
  820. [37]='Slap Bass 2',
  821. [38]='Synth Bass 1',
  822. [39]='Synth Bass 2',
  823. [40]='Violin',
  824. [41]='Viola',
  825. [42]='Cello',
  826. [43]='Contrabass',
  827. [44]='Tremolo Strings',
  828. [45]='Pizzicato Strings',
  829. [46]='Orchestral Harp',
  830. [47]='Timpani',
  831. [48]='String Ensemble 1',
  832. [49]='String Ensemble 2',
  833. [50]='SynthStrings 1',
  834. [51]='SynthStrings 2',
  835. [52]='Choir Aahs',
  836. [53]='Voice Oohs',
  837. [54]='Synth Voice',
  838. [55]='Orchestra Hit',
  839. [56]='Trumpet',
  840. [57]='Trombone',
  841. [58]='Tuba',
  842. [59]='Muted Trumpet',
  843. [60]='French Horn',
  844. [61]='Brass Section',
  845. [62]='SynthBrass 1',
  846. [63]='SynthBrass 2',
  847. [64]='Soprano Sax',
  848. [65]='Alto Sax',
  849. [66]='Tenor Sax',
  850. [67]='Baritone Sax',
  851. [68]='Oboe',
  852. [69]='English Horn',
  853. [70]='Bassoon',
  854. [71]='Clarinet',
  855. [72]='Piccolo',
  856. [73]='Flute',
  857. [74]='Recorder',
  858. [75]='Pan Flute',
  859. [76]='Blown Bottle',
  860. [77]='Skakuhachi',
  861. [78]='Whistle',
  862. [79]='Ocarina',
  863. [80]='Lead 1 (square)',
  864. [81]='Lead 2 (sawtooth)',
  865. [82]='Lead 3 (calliope)',
  866. [83]='Lead 4 (chiff)',
  867. [84]='Lead 5 (charang)',
  868. [85]='Lead 6 (voice)',
  869. [86]='Lead 7 (fifths)',
  870. [87]='Lead 8 (bass+lead)',
  871. [88]='Pad 1 (new age)',
  872. [89]='Pad 2 (warm)',
  873. [90]='Pad 3 (polysynth)',
  874. [91]='Pad 4 (choir)',
  875. [92]='Pad 5 (bowed)',
  876. [93]='Pad 6 (metallic)',
  877. [94]='Pad 7 (halo)',
  878. [95]='Pad 8 (sweep)',
  879. [96]='FX 1 (rain)',
  880. [97]='FX 2 (soundtrack)',
  881. [98]='FX 3 (crystal)',
  882. [99]='FX 4 (atmosphere)',
  883. [100]='FX 5 (brightness)',
  884. [101]='FX 6 (goblins)',
  885. [102]='FX 7 (echoes)',
  886. [103]='FX 8 (sci-fi)',
  887. [104]='Sitar',
  888. [105]='Banjo',
  889. [106]='Shamisen',
  890. [107]='Koto',
  891. [108]='Kalimba',
  892. [109]='Bagpipe',
  893. [110]='Fiddle',
  894. [111]='Shanai',
  895. [112]='Tinkle Bell',
  896. [113]='Agogo',
  897. [114]='Steel Drums',
  898. [115]='Woodblock',
  899. [116]='Taiko Drum',
  900. [117]='Melodic Tom',
  901. [118]='Synth Drum',
  902. [119]='Reverse Cymbal',
  903. [120]='Guitar Fret Noise',
  904. [121]='Breath Noise',
  905. [122]='Seashore',
  906. [123]='Bird Tweet',
  907. [124]='Telephone Ring',
  908. [125]='Helicopter',
  909. [126]='Applause',
  910. [127]='Gunshot',
  911. }
  912.  
  913. M.Notenum2percussion = readOnly{   -- General MIDI Percussion (on Channel 9):
  914. [33]='Metronome Click',
  915. [34]='Metronome Bell',
  916. [35]='Acoustic Bass Drum',
  917. [36]='Bass Drum 1',
  918. [37]='Side Stick',
  919. [38]='Acoustic Snare',
  920. [39]='Hand Clap',
  921. [40]='Electric Snare',
  922. [41]='Low Floor Tom',
  923. [42]='Closed Hi-Hat',
  924. [43]='High Floor Tom',
  925. [44]='Pedal Hi-Hat',
  926. [45]='Low Tom',
  927. [46]='Open Hi-Hat',
  928. [47]='Low-Mid Tom',
  929. [48]='Hi-Mid Tom',
  930. [49]='Crash Cymbal 1',
  931. [50]='High Tom',
  932. [51]='Ride Cymbal 1',
  933. [52]='Chinese Cymbal',
  934. [53]='Ride Bell',
  935. [54]='Tambourine',
  936. [55]='Splash Cymbal',
  937. [56]='Cowbell',
  938. [57]='Crash Cymbal 2',
  939. [58]='Vibraslap',
  940. [59]='Ride Cymbal 2',
  941. [60]='Hi Bongo',
  942. [61]='Low Bongo',
  943. [62]='Mute Hi Conga',
  944. [63]='Open Hi Conga',
  945. [64]='Low Conga',
  946. [65]='High Timbale',
  947. [66]='Low Timbale',
  948. [67]='High Agogo',
  949. [68]='Low Agogo',
  950. [69]='Cabasa',
  951. [70]='Maracas',
  952. [71]='Short Whistle',
  953. [72]='Long Whistle',
  954. [73]='Short Guiro',
  955. [74]='Long Guiro',
  956. [75]='Claves',
  957. [76]='Hi Wood Block',
  958. [77]='Low Wood Block',
  959. [78]='Mute Cuica',
  960. [79]='Open Cuica',
  961. [80]='Mute Triangle',
  962. [81]='Open Triangle',
  963. }
  964.  
  965. M.Event2channelindex = readOnly{ ['note']=4, ['note_off']=3, ['note_on']=3,
  966.  ['key_after_touch']=3, ['control_change']=3, ['patch_change']=3,
  967.  ['channel_after_touch']=3, ['pitch_wheel_change']=3,
  968. }
  969.  
  970. function M.concatenate_scores(scores)
  971.     -- the deepcopys are needed if input_scores are refs to the same table
  972.     -- e.g. if invoked by midisox's repeat()
  973.     local input_scores = consistentise_ticks(scores) -- 3.6
  974.     local output_score = deepcopy(input_scores[1])   -- 4.2
  975.     for i = 2,#input_scores do
  976.         local input_score = input_scores[i]
  977.         local output_stats = M.score2stats(output_score)
  978.         local delta_ticks = output_stats['nticks']
  979.         for itrack = 2,#input_score do
  980.             if itrack > #output_score then -- new output track if doesn't exist
  981.                 output_score[#output_score+1] = {}
  982.             end
  983.             for k,event in ipairs(input_score[itrack]) do
  984.                 local new_event = copy(event)
  985.                 new_event[2] = new_event[2] + delta_ticks
  986.                 table.insert(output_score[itrack], new_event)
  987.                 -- output_score[itrack][-1][1] += delta_ticks  -- hmm...
  988.             end
  989.         end
  990.     end
  991.     return output_score
  992. end
  993.  
  994. function M.grep(score, t)
  995.     if score == nil then return {1000,{},} end
  996.     local ticks = score[1]
  997.     local new_score = {ticks,{},}
  998.     if not t or type(t) ~= 'table' then return new_score end
  999.     local channels = dict(t)
  1000.     local itrack = 2 while itrack <= #score do
  1001.         new_score[itrack] = {}
  1002.         for k,event in ipairs(score[itrack]) do
  1003.             local channel_index = M.Event2channelindex[event[1]]
  1004.             if channel_index then
  1005.                 if channels[event[channel_index]] then
  1006.                     table.insert(new_score[itrack], event)
  1007.                 end
  1008.             else
  1009.                 table.insert(new_score[itrack], event)
  1010.             end
  1011.         end
  1012.         itrack = itrack + 1
  1013.     end
  1014.     return new_score
  1015. end
  1016.  
  1017. function M.merge_scores(scores)
  1018.     local output_score = {1000,}
  1019.     local channels_so_far = {}
  1020.     local all_channels = dict{0,1,2,3,4,5,6,7,8,10,11,12,13,14,15}
  1021.     for ks,input_score in ipairs(consistentise_ticks(scores)) do -- 3.6
  1022.         local new_stats = M.score2stats(input_score)
  1023.         local new_channels = dict(new_stats['channels_total']) -- 4.2 dict
  1024.         new_channels[9] = nil  -- 2.8 cha9 must remain cha9 (in GM)
  1025.         for j,channel in ipairs(sorted_keys(new_channels)) do  -- 4.2 to catch 0
  1026.             if channels_so_far[channel] then
  1027.                 local free_channels = copy(all_channels)
  1028.                 for k,v in pairs(channels_so_far) do
  1029.                     if v then free_channels[k] = nil end
  1030.                 end
  1031.                 for k,v in pairs(new_channels) do
  1032.                     if v then free_channels[k] = nil end
  1033.                 end
  1034.                 -- consistently choose lowest avaiable, to ease testing
  1035.                 local free_channel = nil
  1036.                 local fcs = sorted_keys(free_channels)
  1037.                 if #fcs > 0 then
  1038.                     free_channel = fcs[1]
  1039.                 else
  1040.                     break
  1041.                 end
  1042.                 for itrack = 2,#input_score do
  1043.                     for k3,input_event in ipairs(input_score[itrack]) do
  1044.                         local ci = M.Event2channelindex[input_event[1]]
  1045.                         if ci and input_event[ci]==channel then
  1046.                             input_event[ci] = free_channel
  1047.                         end
  1048.                     end
  1049.                 end
  1050.                 channels_so_far[free_channel] = true
  1051.             end
  1052.             channels_so_far[channel] = true
  1053.         end
  1054.         for itrack = 2,#input_score do
  1055.             output_score[#output_score+1] = input_score[itrack]
  1056.         end
  1057.     end
  1058.     return output_score
  1059. end
  1060.  
  1061. function M.mix_opus_tracks(input_tracks) -- 5.5
  1062.     -- must convert each track to absolute times !
  1063.     local output_score = {1000, {}}
  1064.     for ks,input_track in ipairs(input_tracks) do -- 5.8
  1065.         local input_score = M.opus2score({1000, input_track})
  1066.         for k,event in ipairs(input_score[2]) do
  1067.             table.insert(output_score[2], event)
  1068.         end
  1069.     end
  1070.     table.sort(output_score[2], function (e1,e2) return e1[2]<e2[2] end)
  1071.     local output_opus = M.score2opus(output_score)
  1072.     return output_opus[2]
  1073. end
  1074.  
  1075. function M.mix_scores(input_scores)
  1076.     local output_score = {1000, {}}
  1077.     for ks,input_score in ipairs(consistentise_ticks(input_scores)) do -- 3.6
  1078.         for itrack = 2,#input_score do
  1079.             for k,event in ipairs(input_score[itrack]) do
  1080.                 table.insert(output_score[2], event)
  1081.             end
  1082.         end
  1083.     end
  1084.     return output_score
  1085. end
  1086.  
  1087. function M.midi2ms_score(midi)
  1088.     return M.opus2score(M.to_millisecs(M.midi2opus(midi)))
  1089. end
  1090.  
  1091. function M.midi2opus(s)
  1092.     if not s then s = '' end
  1093.     --my_midi=bytearray(midi)
  1094.     if #s < 4 then return {1000,{},} end
  1095.     local i = 1
  1096.     local id = string.sub(s, i, i+3); i = i+4
  1097.     if id ~= 'MThd' then
  1098.         warn("midi2opus: midi starts with "..id.." instead of 'MThd'")
  1099.         clean_up_warnings()
  1100.         return {1000,{},}
  1101.     end
  1102.     -- h:short; H:unsigned short; i:int; I:unsigned int;
  1103.     -- l:long; L:unsigned long; f:float; d:double.
  1104.     -- [length, format, tracks_expected, ticks] = struct.unpack(
  1105.     --  '>IHHH', bytes(my_midi[4:14]))  is this 10 bytes or 14 ?
  1106.     -- NOT 2+4+4+4 grrr...   'MHhd'+4+2+2+2 !
  1107.     local length          = fourbytes2int(string.sub(s,i,i+3)); i = i+4
  1108.     local format          = twobytes2int(string.sub(s,i,i+1)); i = i+2
  1109.     local tracks_expected = twobytes2int(string.sub(s,i,i+1)); i = i+2
  1110.     local ticks           = twobytes2int(string.sub(s,i,i+1)); i = i+2
  1111.     if length ~= 6 then
  1112.         warn("midi2opus: midi header length was "..tostring(length).." instead of 6")
  1113.         clean_up_warnings()
  1114.         return {1000,{},}
  1115.     end
  1116.     local my_opus = {ticks,}
  1117.     local track_num = 1   -- 5.1
  1118.     while i < #s-8 do
  1119.         local track_type   = string.sub(s, i, i+3); i = i+4
  1120.         if track_type ~= 'MTrk' then
  1121.             warn('midi2opus: Warning: track #'..track_num..' type is '..track_type.." instead of 'MTrk'")
  1122.         end
  1123.         local track_length = fourbytes2int(string.sub(s,i,i+3)); i = i+4
  1124.         if track_length > #s then
  1125.             warn('midi2opus: track #'..track_num..' length '..track_length..' is too large')
  1126.             clean_up_warnings()
  1127.             return my_opus  -- 4.9
  1128.         end
  1129.         local my_midi_track = string.sub(s, i, i+track_length-1) -- 4.7
  1130.         i = i+track_length
  1131.         local my_track = _decode(my_midi_track) -- 4.7
  1132.         my_opus[#my_opus+1] = my_track
  1133.         track_num = track_num + 1   -- 5.1
  1134.     end
  1135.     clean_up_warnings()
  1136.     return my_opus
  1137. end
  1138.  
  1139. function M.midi2score(midi)
  1140.     return M.opus2score(M.midi2opus(midi))
  1141. end
  1142.  
  1143. function M.play_score(score)
  1144.     if not score then return end
  1145.     local midi
  1146.     if M.score_type(score) == 'opus' then
  1147.         midi = M.opus2midi(score)
  1148.     else
  1149.         midi = M.score2midi(score)
  1150.     end
  1151.     local posix  -- 6.0 in lua5.2 require posix returns the posix table
  1152.     pcall(function() posix = require 'posix' end)
  1153.     if posix and posix.fork then   -- 4.2
  1154.         local pid = posix.fork()
  1155.         if pid == 0 then
  1156.             local p = assert(io.popen("aplaymidi -", 'w'))  -- background
  1157.             p:write(midi) ; p:close() ; os.exit(0)
  1158.         end
  1159.     else
  1160.         local fn = os.tmpname()
  1161.         local fh = assert(io.open(fn, 'w'));  fh:write(midi);  fh:close()
  1162.         os.execute("aplaymidi "..fn..' ; rm '..fn..' &')
  1163.     end
  1164. end
  1165.  
  1166. function M.opus2midi(opus)
  1167.     if #opus < 2 then opus = {1000, {},} end
  1168.     -- tracks = copy.deepcopy(opus)
  1169.     local ntracks = #opus - 1
  1170.     local ticks = opus[1]
  1171.     local format
  1172.     if ntracks == 1 then format = 0 else format = 1 end
  1173.     local my_midi = "MThd\00\00\00\06" ..
  1174.      int2twobytes(format) .. int2twobytes(ntracks) .. int2twobytes(ticks)
  1175.     -- struct.pack('>HHH',format,ntracks,ticks)
  1176.     --for track in tracks:
  1177.     for i = 2, #opus do
  1178.         local events = _encode(opus[i])
  1179.         -- should really do an array and then concat...
  1180.         my_midi = my_midi .. 'MTrk' .. int2fourbytes(#events) .. events
  1181.     end
  1182.     clean_up_warnings()
  1183.     return my_midi
  1184. end
  1185.  
  1186. function M.opus2score(opus)
  1187.     if opus == nil or #opus < 2 then return {1000,{},} end
  1188.     local ticks = opus[1]
  1189.     local score = {ticks,}
  1190.     local itrack = 2; while itrack <= #opus do
  1191.         local opus_track = opus[itrack]
  1192.         local ticks_so_far = 0
  1193.         local score_track = {}
  1194.         local chapitch2note_on_events = {}   -- 4.0
  1195.         local k; for k,opus_event in ipairs(opus_track) do
  1196.             ticks_so_far = ticks_so_far + opus_event[2]
  1197.             if opus_event[1] == 'note_off' or
  1198.              (opus_event[1] == 'note_on' and opus_event[5] == 0) then -- 4.8
  1199.                 local cha = opus_event[3]  -- 4.0
  1200.                 local pitch = opus_event[4]
  1201.                 local key = cha*128 + pitch  -- 4.0
  1202.                 local pending_notes = chapitch2note_on_events[key] -- 5.3
  1203.                 if pending_notes and #pending_notes > 0 then
  1204.                     local new_e = table.remove(pending_notes, 1)
  1205.                     new_e[3] = ticks_so_far - new_e[2]
  1206.                     score_track[#score_track+1] = new_e
  1207.                 elseif pitch > 127 then
  1208.                     warn('opus2score: note_off with no note_on, bad pitch='
  1209.                      ..tostring(pitch))
  1210.                 else
  1211.                     warn('opus2score: note_off with no note_on cha='
  1212.                      ..tostring(cha)..' pitch='..tostring(pitch))
  1213.                 end
  1214.             elseif opus_event[1] == 'note_on' then
  1215.                 local cha = opus_event[3]  -- 4.0
  1216.                 local pitch = opus_event[4]
  1217.                 local new_e = {'note',ticks_so_far,0,cha,pitch,opus_event[5]}
  1218.                 local key = cha*128 + pitch  -- 4.0
  1219.                 if chapitch2note_on_events[key] then
  1220.                     table.insert(chapitch2note_on_events[key], new_e)
  1221.                 else
  1222.                     chapitch2note_on_events[key] = {new_e,}
  1223.                 end
  1224.             else
  1225.                 local new_e = copy(opus_event)
  1226.                 new_e[2] = ticks_so_far
  1227.                 score_track[#score_track+1] = new_e
  1228.             end
  1229.         end
  1230.         -- check for unterminated notes (Oisín) -- 5.2
  1231.         for chapitch,note_on_events in pairs(chapitch2note_on_events) do
  1232.             for k,new_e in ipairs(note_on_events) do
  1233.                 new_e[3] = ticks_so_far - new_e[2]
  1234.                 score_track[#score_track+1] = new_e
  1235.                 --warn("adding unterminated note: {'"..new_e[1].."', "..new_e[2]
  1236.                 -- ..', '..new_e[3]..', '..new_e[4]..', '..new_e[5]..'}')
  1237.                 warn("opus2score: note_on with no note_off cha="..new_e[4]
  1238.                  ..' pitch='..new_e[5]..'; adding note_off at end')
  1239.             end
  1240.         end
  1241.         score[#score+1] = score_track
  1242.         itrack = itrack + 1
  1243.     end
  1244.     clean_up_warnings()
  1245.     return score
  1246. end
  1247.  
  1248. function M.score2opus(score)
  1249.     if score == nil or #score < 2 then return {1000,{},} end
  1250.     local ticks = score[1]
  1251.     local opus = {ticks,}
  1252.     local itrack = 2; while itrack <= #score do
  1253.         local score_track = score[itrack]
  1254.         local time2events = {}
  1255.         local k,scoreevent; for k,scoreevent in ipairs(score_track) do
  1256.             local continue = false
  1257.             if scoreevent[1] == 'note' then
  1258.                 local note_on_event = {'note_on',scoreevent[2],
  1259.                  scoreevent[4],scoreevent[5],scoreevent[6]}
  1260.                 local note_off_event = {'note_off',scoreevent[2]+scoreevent[3],
  1261.                  scoreevent[4],scoreevent[5],scoreevent[6]}
  1262.                 if time2events[note_on_event[2]] then
  1263.                    table.insert(time2events[note_on_event[2]], note_on_event)
  1264.                 else
  1265.                    time2events[note_on_event[2]] = {note_on_event,}
  1266.                 end
  1267.                 if time2events[note_off_event[2]] then
  1268.                    table.insert(time2events[note_off_event[2]], note_off_event)
  1269.                 else
  1270.                    time2events[note_off_event[2]] = {note_off_event,}
  1271.                 end
  1272.                 continue = true
  1273.             end
  1274.             if not continue then
  1275.                 if time2events[scoreevent[2]] then
  1276.                     table.insert(time2events[scoreevent[2]], scoreevent)
  1277.                 else
  1278.                     time2events[scoreevent[2]] = {scoreevent, }
  1279.                 end
  1280.             end
  1281.         end
  1282.         local sorted_times = {}  -- list of keys
  1283.         for k,v in pairs(time2events) do
  1284.             sorted_times[#sorted_times+1] = k
  1285.         end
  1286.         table.sort(sorted_times)
  1287.         local sorted_events = {} -- once-flattened list of values sorted by key
  1288.         for k,time in ipairs(sorted_times) do
  1289.             for k2,v in ipairs(time2events[time]) do
  1290.                 --sorted_events[#sorted_events+1] = v NOPE, must copy!
  1291.                 sorted_events[#sorted_events+1] = {}
  1292.                 for k3,v3 in ipairs(v) do
  1293.                     table.insert(sorted_events[#sorted_events],v3)
  1294.                 end
  1295.             end
  1296.         end
  1297.         local abs_time = 0
  1298.         for k,event in ipairs(sorted_events) do  -- abs times => delta times
  1299.             local delta_time = event[2] - abs_time
  1300.             abs_time = event[2]
  1301.             event[2] = delta_time
  1302.         end
  1303.         opus[#opus+1] = sorted_events
  1304.         itrack = itrack + 1
  1305.     end
  1306.     clean_up_warnings()
  1307.     return opus
  1308. end
  1309.  
  1310. function M.score_type(t)
  1311.     if t == nil or type(t) ~= 'table' or #t < 2 then return '' end
  1312.     local i = 2   -- ignore first element  -- 4.7
  1313.     while i <= #t do
  1314.         local k,event; for k,event in ipairs(t[i]) do
  1315.             if event[1] == 'note' then
  1316.                 return 'score'
  1317.             elseif event[1] == 'note_on' then
  1318.                 return 'opus'
  1319.             end
  1320.         end
  1321.         i = i + 1
  1322.     end
  1323.     return ''
  1324. end
  1325.  
  1326. function M.score2midi(score)
  1327.     return M.opus2midi(M.score2opus(score))
  1328. end
  1329.  
  1330. function M.score2stats(opus_or_score)
  1331. --[[ returns a table:
  1332.  bank_select (array of 2-element arrays {msb,lsb}),
  1333.  channels_by_track (table, by track, of arrays),
  1334.  channels_total (array),
  1335.  general_midi_mode (array),
  1336.  ntracks,
  1337.  nticks,
  1338.  num_notes_by_channel (table of numbers),
  1339.  patch_changes_by_track (table of tables),
  1340.  patch_changes_total (array),
  1341.  percussion (a dictionary histogram of channel-9 events),
  1342.  pitches (dict histogram of pitches on channels other than 9),
  1343.  pitch_range_by_track (table, by track, of two-member-arrays),
  1344.  pitch_range_sum (sum over tracks of the pitch_ranges)
  1345. ]]
  1346.     local bank_select_msb = -1
  1347.     local bank_select_lsb = -1
  1348.     local bank_select = {}
  1349.     local channels_by_track = {}
  1350.     local channels_total    = {}
  1351.     local general_midi_mode = {}
  1352.     local num_notes_by_channel = {} -- 5.7
  1353.     local patches_used_by_track  = {}
  1354.     local patches_used_total     = {}
  1355.     local patch_changes_by_track = {}
  1356.     local patch_changes_total    = {}
  1357.     local percussion = {} -- histogram of channel 9 "pitches"
  1358.     local pitches    = {} -- histogram of pitch-occurrences channels 0-8,10-15
  1359.     local pitch_range_sum = 0   -- u pitch-ranges of each track
  1360.     local pitch_range_by_track = {}
  1361.     local is_a_score = true
  1362.     if opus_or_score == nil then
  1363.         return {bank_select={}, channels_by_track={}, channels_total={},
  1364.          general_midi_mode={}, ntracks=0, nticks=0,
  1365.          num_notes_by_channel={},
  1366.          patch_changes_by_track={}, patch_changes_total={},
  1367.          percussion={}, pitches={}, pitch_range_by_track={},
  1368.          ticks_per_quarter=0, pitch_range_sum=0
  1369.         }
  1370.     end
  1371.     local ticks_per_quarter = opus_or_score[1]
  1372.     local nticks = 0 -- 4.7
  1373.     for i = 2,#opus_or_score do  -- ignore first element, which is ticks
  1374.         local highest_pitch = 0  -- 4.7
  1375.         local lowest_pitch = 128 -- 4.7
  1376.         local channels_this_track = {}      -- 4.7
  1377.         local patch_changes_this_track = {} -- 4.7
  1378.         for k,event in ipairs(opus_or_score[i]) do
  1379.             if event[1] == 'note' then
  1380.                 num_notes_by_channel[event[4]] = (num_notes_by_channel[event[4]] or 0) + 1
  1381.                 if event[4] == 9 then
  1382.                     percussion[event[5]] = (percussion[event[5]] or 0) + 1
  1383.                 else
  1384.                     pitches[event[5]]    = (pitches[event[5]] or 0) + 1
  1385.                     if event[5] > highest_pitch then
  1386.                         highest_pitch = event[5]
  1387.                     end
  1388.                     if event[5] < lowest_pitch then
  1389.                         lowest_pitch = event[5]
  1390.                     end
  1391.                 end
  1392.                 channels_this_track[event[4]] = true
  1393.                 channels_total[event[4]] = true
  1394.                 local finish_time = event[2] + event[3] -- 4.7
  1395.                 if finish_time > nticks then
  1396.                     nticks = finish_time
  1397.                 end
  1398.             elseif event[1] == 'note_on' then
  1399.                 is_a_score = false   -- 4.6
  1400.                 num_notes_by_channel[event[3]] = (num_notes_by_channel[event[3]] or 0) + 1
  1401.                 if event[3] == 9 then
  1402.                     percussion[event[4]] = (percussion[event[4]] or 0) + 1
  1403.                 else
  1404.                     pitches[event[4]]    = (pitches[event[4]] or 0) + 1
  1405.                     if event[4] > highest_pitch then
  1406.                         highest_pitch = event[4]
  1407.                     end
  1408.                     if event[4] < lowest_pitch then
  1409.                         lowest_pitch = event[4]
  1410.                     end
  1411.                 end
  1412.                 channels_this_track[event[3]] = true
  1413.                 channels_total[event[3]] = true
  1414.             elseif event[1] == 'note_off' then
  1415.                 local finish_time = event[2] -- 4.7
  1416.                 if finish_time > nticks then
  1417.                     nticks = finish_time
  1418.                 end
  1419.             elseif event[1] == 'patch_change' then
  1420.                 patch_changes_this_track[event[3]] = event[4]
  1421.                 patch_changes_total[event[4]] = true
  1422.             elseif event[1] == 'control_change' then
  1423.                 if event[4] == 0 then  -- bank select MSB
  1424.                     bank_select_msb = event[5]
  1425.                 elseif event[4] == 32 then  -- bank select LSB
  1426.                     bank_select_lsb = event[5]
  1427.                 end
  1428.                 if bank_select_msb >= 0 and bank_select_lsb >= 0 then
  1429.                     table.insert(bank_select,{bank_select_msb,bank_select_lsb})
  1430.                     bank_select_msb = -1
  1431.                     bank_select_lsb = -1
  1432.                 end
  1433.             elseif event[1] == 'sysex_f0' then
  1434.                 if sysex2midimode[event[3]] then
  1435.                 table.insert(general_midi_mode,sysex2midimode[event[3]]) -- 5.0
  1436.                 end
  1437.             end
  1438.             if is_a_score then
  1439.                 if event[2] > nticks then
  1440.                     nticks = event[2]
  1441.                 end
  1442.             else
  1443.                 nticks = nticks + event[2]
  1444.             end
  1445.         end
  1446.         if lowest_pitch == 128 then
  1447.             lowest_pitch = 0
  1448.         end
  1449.         table.insert(channels_by_track, sorted_keys(channels_this_track))
  1450.         table.insert(patch_changes_by_track, patch_changes_this_track) -- 4.2
  1451.         table.insert(pitch_range_by_track, {lowest_pitch,highest_pitch})
  1452.         pitch_range_sum = pitch_range_sum + highest_pitch - lowest_pitch
  1453.         i = i + 1
  1454.     end
  1455.  
  1456.     return {
  1457.         bank_select=bank_select,
  1458.         channels_by_track=channels_by_track,
  1459.         channels_total=sorted_keys(channels_total),
  1460.         general_midi_mode=general_midi_mode,
  1461.         ntracks=#opus_or_score-1,
  1462.         nticks=nticks,
  1463.         num_notes_by_channel=num_notes_by_channel,
  1464.         patch_changes_by_track=patch_changes_by_track,
  1465.         patch_changes_total=sorted_keys(patch_changes_total),
  1466.         percussion=percussion,
  1467.         pitches=pitches,
  1468.         pitch_range_by_track=pitch_range_by_track,
  1469.         pitch_range_sum=pitch_range_sum,
  1470.         ticks_per_quarter=ticks_per_quarter
  1471.     }
  1472. end
  1473.  
  1474. function M.segment(...)
  1475.     local args = {...}  -- 3.8
  1476.     local score, start, endt, tracks = ...
  1477.     if #args == 1 and type(args[1][1]) == 'table' then
  1478.         score = args[1][1]
  1479.         start = args[1]['start_time'] -- 4.1
  1480.         endt = args[1]['end_time']    -- 4.1
  1481.         tracks = args[1]['tracks']
  1482.     end
  1483.     if not score == nil or type(score) ~= 'table' or #score < 2 then
  1484.         return {1000, {},}
  1485.     end
  1486.     if not start then start = 0 end -- 4.1
  1487.     if not endt  then endt  = 1000000000 end
  1488.     if not tracks then tracks = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} end
  1489.     local new_score = {score[1],}
  1490.     local my_type = M.score_type(score)
  1491.     if my_type == '' then
  1492.         return new_score
  1493.     end
  1494.     if my_type == 'opus' then
  1495.         -- more difficult (disconnecting note_on's from their note_off's)...
  1496.         warn("segment: opus format is not supported\n")
  1497.         clean_up_warnings()
  1498.         return new_score
  1499.     end
  1500.     tracks = dict(tracks)  -- convert list to lookup
  1501.     for i = 2,#score do   -- ignore ticks; we count in ticks anyway
  1502.         if tracks[i-1] then
  1503.             local new_track = {}
  1504.             local channel2cc_num  = {} -- recentest controlchange before start
  1505.             local channel2cc_val  = {}
  1506.             local channel2cc_time = {}
  1507.             local channel2patch_num = {} -- recentest patchchange before start
  1508.             local channel2patch_time = {}
  1509.             local set_tempo_num = 500000 -- recentest tempochange 6.3
  1510.             local set_tempo_time = 0
  1511.             local earliest_note_time = endt
  1512.             for k,event in ipairs(score[i]) do
  1513.                 if event[1] == 'control_change' then  -- 6.5
  1514.                     local cc_time = channel2cc_time[event[3]] or 0
  1515.                     if event[2]<=start and event[2]>=cc_time then
  1516.                         channel2cc_num[event[3]]  = event[4]
  1517.                         channel2cc_val[event[3]]  = event[5]
  1518.                         channel2cc_time[event[3]] = event[2]
  1519.                     end
  1520.                 elseif event[1] == 'patch_change' then
  1521.                     local patch_time = channel2patch_time[event[3]] or 0 -- 4.7
  1522.                     if event[2]<=start and event[2]>=patch_time then  -- 2.0
  1523.                         channel2patch_num[event[3]]  = event[4]
  1524.                         channel2patch_time[event[3]] = event[2]
  1525.                     end
  1526.                 elseif event[1] == 'set_tempo' then   -- 6.4 <=start not <start
  1527.                     if (event[2]<=start) and (event[2]>=set_tempo_time) then
  1528.                         set_tempo_num  = event[3]
  1529.                         set_tempo_time = event[2]
  1530.                     end
  1531.                 end
  1532.                 if event[2] >= start and event[2] <= endt then
  1533.                     new_track[#new_track+1]= event
  1534.                     if event[1] == 'note' and event[2]<earliest_note_time then
  1535.                         earliest_note_time = event[2]
  1536.                     end
  1537.                 end
  1538.             end
  1539.             if #new_track > 0 then
  1540.                 new_track[#new_track+1] = ({'set_tempo', start, set_tempo_num})
  1541.                 for k,c in ipairs(sorted_keys(channel2patch_num)) do -- 4.3
  1542.                     new_track[#new_track+1] =
  1543.                      ({'patch_change', start, c, channel2patch_num[c]})
  1544.                 end
  1545.                 for k,c in ipairs(sorted_keys(channel2cc_num)) do -- 6.5
  1546.                     new_track[#new_track+1] = ({'control_change', start, c,
  1547.                       channel2cc_num[c],  channel2cc_val[c]})
  1548.                 end
  1549.                 new_score[#new_score+1] = (new_track)
  1550.             end
  1551.         end
  1552.     end
  1553.     clean_up_warnings()
  1554.     return new_score
  1555. end
  1556.  
  1557. function M.timeshift(...)
  1558.     local args = {...}  -- 3.8
  1559.     local score, shift, start_time, from_time, tracks_array = ...
  1560.     if #args == 1 and type(args[1][1]) == 'table' then
  1561.         score = args[1][1]
  1562.         shift = args[1]['shift']
  1563.         start_time = args[1]['start_time']
  1564.         from_time = args[1]['from_time']
  1565.         tracks_array = args[1]['tracks']
  1566.     end
  1567.     if score == nil or #score < 2 then return {1000, {},} end
  1568.     if from_time == nil then from_time = 0 end
  1569.     if not tracks_array then
  1570.         tracks_array = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
  1571.     end
  1572.     local new_score = {score[1],}
  1573.     local my_type = M.score_type(score)
  1574.     if my_type == '' then return new_score end
  1575.     if my_type == 'opus' then
  1576.         warn("timeshift: opus format is not supported\n")
  1577.         clean_up_warnings()
  1578.         return new_score
  1579.     end
  1580.     if shift ~= nil and start_time ~= nil then
  1581.         warn("timeshift: shift and start_time specified: ignoring shift\n")
  1582.         shift = nil
  1583.     end
  1584.     if shift == nil then
  1585.         if start_time == nil or start_time < 0 then
  1586.             start_time = 0
  1587.         end
  1588.         -- shift = start_time - from_time
  1589.     end
  1590.  
  1591.     local tracks = dict(tracks_array)  -- convert list to lookup
  1592.     local earliest = 1000000000
  1593.     if start_time ~= nil or shift < 0 then -- find the earliest event
  1594.         for i = 2,#score do   -- ignore first element (ticks)
  1595.             if tracks[i-1] then
  1596.                 for k,event in ipairs(score[i]) do
  1597.                     local continue2 = false
  1598.                     if event[2] < from_time then
  1599.                         -- just inspect the to_be_shifted events
  1600.                         continue2 = true
  1601.                     end
  1602.                     if not continue2 then
  1603.                         if event[2] < earliest then
  1604.                             earliest = event[2]
  1605.                         end
  1606.                     end
  1607.                 end
  1608.             end
  1609.         end
  1610.     end
  1611.     if earliest > 999999999 then
  1612.         earliest = 0
  1613.     end
  1614.     if shift == nil then
  1615.         shift = start_time - earliest
  1616.     elseif (earliest + shift) < 0 then
  1617.         start_time = 0
  1618.         shift = 0 - earliest
  1619.     end
  1620.  
  1621.     local i = 2   -- ignore first element (ticks) -- 4.7
  1622.     while i <= #score do
  1623.         if not tracks[i-1] then
  1624.             new_score[#new_score+1] = deepcopy(score[i])
  1625.             i = i + 1
  1626.         else
  1627.             local new_track = {} -- 4.7
  1628.             for k,event in ipairs(score[i]) do
  1629.                 local continue = false
  1630.                 local new_event = copy(event) -- 4.7
  1631.                 if new_event[2] >= from_time then
  1632.                     -- 4.1 must not rightshift set_tempo
  1633.                     if new_event[1] ~= 'set_tempo' or shift<0 then
  1634.                         new_event[2] = new_event[2] + shift
  1635.                     end
  1636.                 elseif (shift < 0) and (new_event[2] >= (from_time+shift)) then
  1637.                     continue = true
  1638.                 end
  1639.                 if not continue then
  1640.                     new_track[#new_track+1] = new_event
  1641.                 end
  1642.             end
  1643.             if #new_track > 0 then
  1644.                 new_score[#new_score+1] = new_track
  1645.             end
  1646.             i = i + 1
  1647.         end
  1648.     end
  1649.     clean_up_warnings()
  1650.     return new_score
  1651. end
  1652.  
  1653. function M.to_millisecs(old_opus)   -- 6.7
  1654.     if old_opus == nil then return {1000,{},}; end
  1655.     local old_tpq  = old_opus[1]
  1656.     local new_opus = {1000,}
  1657.     -- 6.7 first go through building a dict of set_tempos by absolute-tick
  1658.     local ticks2tempo = {}
  1659.     local itrack = 2
  1660.     while itrack <= #old_opus do
  1661.         local ticks_so_far = 0
  1662.         local k; for k,old_event in ipairs(old_opus[itrack]) do
  1663.             if old_event[1] == 'note' then
  1664.                 warn('to_millisecs needs an opus, not a score')
  1665.                 clean_up_warnings()
  1666.                 return {1000,{},}
  1667.             end
  1668.             ticks_so_far = ticks_so_far + old_event[2]
  1669.             if old_event[1] == 'set_tempo' then
  1670.                 ticks2tempo[ticks_so_far] = old_event[3]
  1671.             end
  1672.         end
  1673.         itrack = itrack + 1
  1674.     end
  1675.     --  then get the sorted-array of their keys
  1676.     local tempo_ticks = sorted_keys(ticks2tempo)
  1677.     --  then go through converting to millisec, testing if the next
  1678.     --  set_tempo lies before the next track-event, and using it if so.
  1679.     local itrack = 2
  1680.     while itrack <= #old_opus do
  1681.         local ms_per_old_tick = 500.0 / old_tpq -- will be rounded later 6.3
  1682.         local i_tempo_ticks = 1
  1683.         local ticks_so_far = 0
  1684.         local ms_so_far = 0.0
  1685.         local previous_ms_so_far = 0.0
  1686.         local new_track = {{'set_tempo',0,1000000},}  -- new "crochet" is 1 sec
  1687.         local k; for k,old_event in ipairs(old_opus[itrack]) do
  1688.             -- detect if ticks2tempo has something before this event
  1689.             -- If ticks2tempo is at the same time, don't handle it yet.
  1690.             local event_delta_ticks = old_event[2]
  1691.             if i_tempo_ticks <= #tempo_ticks and
  1692.               tempo_ticks[i_tempo_ticks] < (ticks_so_far + old_event[2]) then
  1693.                 local delta_ticks = tempo_ticks[i_tempo_ticks] - ticks_so_far
  1694.                 ms_so_far = ms_so_far + (ms_per_old_tick * delta_ticks)
  1695.                 ticks_so_far = tempo_ticks[i_tempo_ticks]
  1696.                 ms_per_old_tick = ticks2tempo[ticks_so_far] / (1000.0*old_tpq)
  1697.                 i_tempo_ticks = i_tempo_ticks + 1
  1698.                 event_delta_ticks = event_delta_ticks - delta_ticks
  1699.             end  -- now handle the new event
  1700.             local new_event = copy(old_event) -- 4.7
  1701.             ms_so_far = ms_so_far + (ms_per_old_tick * old_event[2])  -- NO!
  1702.             new_event[2] = math.floor(0.5 + ms_so_far - previous_ms_so_far)
  1703.             if old_event[1] ~= 'set_tempo' then -- set_tempos are already known
  1704.                 previous_ms_so_far = ms_so_far
  1705.                 new_track[#new_track+1] = new_event
  1706.             end
  1707.             ticks_so_far = ticks_so_far + event_delta_ticks
  1708.         end
  1709.         new_opus[#new_opus+1] = new_track
  1710.         itrack = itrack + 1
  1711.     end
  1712.     clean_up_warnings()
  1713.     return new_opus
  1714. end
  1715.  
  1716. return M
  1717.  
  1718. -- http://lua-users.org/wiki/ModuleDefinition
  1719. -- http://lua-users.org/wiki/LuaModuleFunctionCritiqued
  1720. --[=[
  1721.  
  1722. =pod
  1723.  
  1724. =head1 NAME
  1725.  
  1726. MIDI.lua - Reading, writing and manipulating MIDI data
  1727.  
  1728. =head1 SYNOPSIS
  1729.  
  1730.  local MIDI = require 'MIDI'
  1731.  
  1732.  local my_score = {
  1733.     96,  -- ticks per beat
  1734.     {    -- first track
  1735.         {'patch_change', 0, 1, 8},
  1736.         {'note', 5, 96, 1, 25, 96},
  1737.         {'note', 101, 96, 1, 29, 96},
  1738.     },  -- end of first track
  1739.  }
  1740.  
  1741.  -- Going through a score within a Lua program...
  1742.  channels = {[2]=true, [3]=true, [5]=true, [8]=true, [13]=true}
  1743.  for itrack = 2,#my_score do  -- skip 1st element, which is ticks
  1744.     for k,event in ipairs(my_score[itrack]) do
  1745.        if event[1] == 'note' then
  1746.           -- for example, do something to all notes
  1747.        end
  1748.        -- to work on events in only particular channels...
  1749.        channelindex = MIDI.Event2channelindex[event[1]]
  1750.        if channelindex and channels[event[channelindex]] then
  1751.           -- do something to channels 2,3,5,8 and 13
  1752.        end
  1753.     end
  1754.  end
  1755.  
  1756.  local midifile = assert(io.open('f.mid','w'))
  1757.  midifile:write(MIDI.score2midi(my_score))
  1758.  midifile:close()
  1759.  
  1760. =head1 DESCRIPTION
  1761.  
  1762. This module offers functions:  concatenate_scores(), grep(),
  1763. merge_scores(), mix_scores(), midi2opus(), midi2score(), opus2midi(),
  1764. opus2score(), play_score(), score2midi(), score2opus(), score2stats(),
  1765. score_type(), segment(), timeshift() and to_millisecs(),
  1766. where "midi" means the MIDI-file bytes (as can be put in a .mid file,
  1767. or piped into aplaymidi), and "opus" and "score" are list-structures
  1768. as inspired by Sean Burke's MIDI-Perl CPAN module.
  1769.  
  1770. The "opus" is a direct translation of the midi-file-events, where
  1771. the times are delta-times, in ticks, since the previous event:
  1772.  
  1773.  {'note_on',  dtime, channel, note, velocity}       -- in an "opus"
  1774.  {'note_off', dtime, channel, note, velocity}       -- in an "opus"
  1775.  
  1776. The "score" is more human-centric; it uses absolute times, and
  1777. combines the separate note_on and note_off events into one "note"
  1778. event, with a duration:
  1779.  
  1780.  {'note', start_time, duration, channel, note, velocity} -- in a "score"
  1781.  
  1782. MIDI.lua is a call-compatible translation into Lua of the Python module
  1783. http://www.pjb.com.au/midi/free/MIDI.py ;
  1784. see http://www.pjb.com.au/midi/MIDI.html
  1785.  
  1786. =head1 FUNCTIONS
  1787.  
  1788. =over 3
  1789.  
  1790. =item I<concatenate_scores> (array_of_scores)
  1791.  
  1792. Concatenates an array of scores into one score.
  1793. If the scores differ in their "ticks" parameter,
  1794. they will all get converted to millisecond-tick format.
  1795.  
  1796. =item I<grep> (score, channels)
  1797.  
  1798. Returns a "score" containing only the channels specified.
  1799. (It also works on an "opus", but because of the
  1800. incremental times the result will usually be useless.)
  1801. The second parameter is an array of the wanted channel numbers,
  1802. for example:
  1803.  
  1804.  channels = {0, 4,}
  1805.  
  1806. =item I<merge_scores> (array_of_scores)
  1807.  
  1808. Merges an array of scores into one score.  A merged score comprises
  1809. all of the tracks from all of the input scores; un-merging is possible
  1810. by selecting just some of the tracks.
  1811. If the scores differ in their "ticks" parameter,
  1812. they will all get converted to millisecond-tick format.
  1813. merge_scores attempts to resolve channel-conflicts,
  1814. but there are of course only 15 available channels...
  1815.  
  1816. =item I<mix_opus_tracks> (tracks)
  1817.  
  1818. Mixes an array of opus tracks into one track.
  1819. A mixed track cannot be un-mixed.
  1820. It is assumed that the tracks share the same I<ticks> parameter
  1821. and the same tempo.
  1822. Mixing score-tracks is trivial (just insert all the events into one array).
  1823. Mixing opus-tracks is only slightly harder,
  1824. but it's common enough that a dedicated function is useful.
  1825.  
  1826. =item I<mix_scores> (array_of_scores)
  1827.  
  1828. Mixes an array of scores into one one-track score.
  1829. A mixed score cannot be un-mixed.
  1830. Hopefully the scores have no undesirable channel conflicts between them...
  1831. If the scores differ in their "ticks" parameter,
  1832. they will all get converted to millisecond-tick format.
  1833.  
  1834.  
  1835. =item I<midi2ms_score> (midi_in_string_form)
  1836.  
  1837. Translates MIDI into a "score" with one beat per second and one
  1838. tick per millisecond, using midi2opus() then to_millisecs()
  1839. then opus2score()
  1840.  
  1841. =item I<midi2opus> (midi_in_string_form)
  1842.  
  1843. Translates MIDI into an "opus".  For a description of the
  1844. "opus" format, see opus2midi()
  1845.  
  1846. =item I<midi2score> (midi_in_string_form)
  1847.  
  1848. Translates MIDI into a "score", using midi2opus() then opus2score()
  1849.  
  1850.  
  1851. =item I<opus2midi> (an_opus)
  1852.  
  1853. The argument is an array: the first item in the list is the "ticks"
  1854. parameter, the others are the tracks. Each track is an array of
  1855. midi-events, and each event is itself an array; see EVENTS below.
  1856. opus2midi() returns a string of the MIDI, which can then be
  1857. written to a .mid file, or to stdout.
  1858.  
  1859.  local MIDI = require 'MIDI'
  1860.  my_opus = {
  1861.     96, -- MIDI-ticks per beat
  1862.     {   -- first track:
  1863.         {'patch_change', 0, 1, 8},   -- and these are the events...
  1864.         {'set_tempo', 0, 750000},    -- microseconds per beat
  1865.         {'note_on', 5, 1, 25, 96},
  1866.         {'note_off', 96, 1, 25, 0},
  1867.         {'note_on', 0, 1, 29, 96},
  1868.         {'note_off', 96, 1, 29, 0},
  1869.     },  -- end of first track
  1870.  }
  1871.  local my_midi = MIDI.opus2midi(my_opus)
  1872.  io.write(my_midi)  -- can be saved in o.mid or piped into "aplaymidi -"
  1873.  
  1874. =item I<opus2score> (an_opus)
  1875.  
  1876. For a description of the "opus" and "score" formats,
  1877. see opus2midi() and score2opus().
  1878.  
  1879. The score track is returned sorted by the end-times of the notes,
  1880. so if you need it sorted by their start-times you have to do that yourself:
  1881.  
  1882.   table.sort(score[itrack], function (e1,e2) return e1[2]<e2[2] end)
  1883.  
  1884. =item I<play_score> (opus_or_score)
  1885.  
  1886. Converts the "score" to midi, and feeds it into 'aplaymidi -'.
  1887. If Lua's I<posix> module is installed, the aplaymidi process will
  1888. be run in the background.
  1889.  
  1890. =item I<score_type> (opus_or_score)
  1891.  
  1892. Returns a string, either 'opus' or 'score' or ''
  1893.  
  1894. =item I<score2midi> (a_score)
  1895.  
  1896. Translates a "score" into MIDI, using score2opus() then opus2midi()
  1897.  
  1898. =item I<score2opus> (a_score)
  1899.  
  1900. The argument is an array: the first item in the list is the "ticks"
  1901. parameter, the others are the tracks. Each track is an array
  1902. of score-events, and each event is itself an array.
  1903. score2opus() returns an array specifying the equivalent "opus".
  1904. A score-event is similar to an opus-event (see above),
  1905. except that in a score:
  1906.  
  1907. 1) all times are expressed as an absolute number of ticks
  1908.     from the track's start time
  1909.  
  1910. 2) the pairs of 'note_on' and 'note_off' events in an "opus"
  1911.     are abstracted into a single 'note' event in a "score"
  1912.  
  1913.  {'note', start_time, duration, channel, pitch, velocity}
  1914.  
  1915.  my_score = {
  1916.     96,
  1917.     {   -- first track
  1918.         {'patch_change', 0, 1, 8},
  1919.         {'note', 5, 96, 1, 25, 96},
  1920.         {'note', 101, 96, 1, 29, 96},
  1921.     },  -- end of first track
  1922.  }
  1923.  my_opus = score2opus(my_score)
  1924.  
  1925. =item I<score2stats> (opus_or_score)
  1926.  
  1927. Returns a table of some basic stats about the score, like:
  1928.  
  1929.  bank_select (array of 2-element arrays {msb,lsb}),
  1930.  channels_by_track (table, by track, of arrays),
  1931.  channels_total (array),
  1932.  general_midi_mode (array),
  1933.  ntracks,
  1934.  nticks,
  1935.  num_notes_by_channel (table of numbers)
  1936.  patch_changes_by_track (table of arrays),
  1937.  patch_changes_total (array),
  1938.  percussion (a dictionary histogram of channel-9 events),
  1939.  pitches (dict histogram of pitches on channels other than 9),
  1940.  pitch_range_by_track (table, by track, of two-member-arrays),
  1941.  pitch_range_sum (sum over tracks of the pitch_ranges)
  1942.  
  1943. =item I<segment> (score, start_time, end_time, tracks)
  1944.  
  1945. =item I<segment> {score, start_time=100, end_time=2000, tracks={3,4,5}}
  1946.  
  1947. Returns a "score" which is a segment of the one supplied
  1948. as the argument, beginning at "start_time" ticks and ending
  1949. at "end_time" ticks (or at the end if "end_time" is not supplied).
  1950. If the array "tracks" is specified, only those tracks will be returned.
  1951.  
  1952. =item I<timeshift> (score, shift, start_time, from_time, tracks)
  1953.  
  1954. =item I<timeshift> {score, shift=50, start_time=nil, from_time=2000, tracks={2,3}}
  1955.  
  1956. Returns a "score" shifted in time by "shift" ticks, or shifted
  1957. so that the first event starts at "start_time" ticks.
  1958.  
  1959. If "from_time" is specified, only those events in the score
  1960. that begin after it are shifted. If "start_time" is less than
  1961. "from_time" (or "shift" is negative), then the intermediate
  1962. notes are deleted, though patch-change events are preserved.
  1963.  
  1964. If "tracks" are specified, then only those tracks (0 to 15) get shifted.
  1965. "tracks" should be an array.
  1966.  
  1967. It is deprecated to specify both "shift" and "start_time".
  1968. If this does happen, timeshift() will print a warning to
  1969. stderr and ignore the "shift" argument.
  1970.  
  1971. If "shift" is negative and sufficiently large that it would
  1972. leave some event with a negative tick-value, then the score
  1973. is shifted so that the first event occurs at time 0. This
  1974. also occurs if "start_time" is negative, and is also the
  1975. default if neither "shift" nor "start_time" are specified.
  1976.  
  1977. =item I<to_millisecs> (an_opus)
  1978.  
  1979. Recallibrates all the times in an "opus" to use one beat
  1980. per second and one tick per millisecond.  This makes it
  1981. hard to retrieve any information about beats or barlines,
  1982. but it does make it easy to mix different scores together.
  1983.  
  1984. =back
  1985.  
  1986. =head1 EVENTS
  1987.  
  1988. The "opus" is a direct translation of the midi-file-events, where
  1989. the times are delta-times, in ticks, since the previous event.
  1990.  
  1991.  {'note_on',  dtime, channel, note, velocity}       -- in an "opus"
  1992.  {'note_off', dtime, channel, note, velocity}       -- in an "opus"
  1993.  
  1994. The "score" is more human-centric; it uses absolute times, and
  1995. combines the separate note_on and note_off events into one "note"
  1996. event, with a duration:
  1997.  
  1998.  {'note', start_time, duration, channel, note, velocity} -- in a "score"
  1999.  
  2000. Events (in an "opus" structure):
  2001.  
  2002.  {'note_off', dtime, channel, note, velocity}       -- in an "opus"
  2003.  {'note_on',  dtime, channel, note, velocity}       -- in an "opus"
  2004.  {'key_after_touch', dtime, channel, note, velocity}
  2005.  {'control_change', dtime, channel, controller(0-127), value(0-127)}
  2006.  {'patch_change', dtime, channel, patch}
  2007.  {'channel_after_touch', dtime, channel, velocity}
  2008.  {'pitch_wheel_change', dtime, channel, pitch_wheel}
  2009.  {'text_event', dtime, text}
  2010.  {'copyright_text_event', dtime, text}
  2011.  {'track_name', dtime, text}
  2012.  {'instrument_name', dtime, text}
  2013.  {'lyric', dtime, text}
  2014.  {'marker', dtime, text}
  2015.  {'cue_point', dtime, text}
  2016.  {'text_event_08', dtime, text}
  2017.  {'text_event_09', dtime, text}
  2018.  {'text_event_0a', dtime, text}
  2019.  {'text_event_0b', dtime, text}
  2020.  {'text_event_0c', dtime, text}
  2021.  {'text_event_0d', dtime, text}
  2022.  {'text_event_0e', dtime, text}
  2023.  {'text_event_0f', dtime, text}
  2024.  {'end_track', dtime}
  2025.  {'set_tempo', dtime, tempo}
  2026.  {'smpte_offset', dtime, hr, mn, se, fr, ff}
  2027.  {'time_signature', dtime, nn, dd, cc, bb}
  2028.  {'key_signature', dtime, sf, mi}
  2029.  {'sequencer_specific', dtime, raw}
  2030.  {'raw_meta_event', dtime, command(0-255), raw}
  2031.  {'sysex_f0', dtime, raw}
  2032.  {'sysex_f7', dtime, raw}
  2033.  {'song_position', dtime, song_pos}
  2034.  {'song_select', dtime, song_number}
  2035.  {'tune_request', dtime}
  2036.  
  2037. =head1 DATA TYPES
  2038.  
  2039.  channel = a value 0 to 15
  2040.  controller = 0 to 127 (see http://www.pjb.com.au/muscript/gm.html#cc)
  2041.  dtime = time measured in "ticks", 0 to 268435455
  2042.  velocity = a value 0 (soft) to 127 (loud)
  2043.  note = a value 0 to 127  (middle-C is 60)
  2044.  patch = 0 to 127 (see http://www.pjb.com.au/muscript/gm.html )
  2045.  pitch_wheel = a value -8192 to 8191 (0x1FFF)
  2046.  raw = 0 or more bytes of binary data
  2047.  sequence_number = a value 0 to 65,535 (0xFFFF)
  2048.  song_pos = a value 0 to 16,383 (0x3FFF)
  2049.  song_number = a value 0 to 127
  2050.  tempo = microseconds per crochet (quarter-note), 0 to 16777215
  2051.  text = a string of 0 or more bytes of of ASCII text
  2052.  ticks = the number of ticks per crochet (quarter-note)
  2053.  
  2054. In I<sysex_f0> events, the I<raw> data must not start with a \xF0
  2055. byte, since this gets added automatically;
  2056. but it must end with an explicit \xF7 byte!
  2057. In the very unlikely case that you ever need to split I<sysex> data
  2058. into one I<sysex_f0> followed by one or more I<sysex_f7>s, then
  2059. only the last of those I<sysex_f7> events must end with the explicit \xF7
  2060. byte (again, the I<raw> data of individual I<sysex_f7> events
  2061. must not start with any \xF7 byte, since this gets added automatically).
  2062.  
  2063. =head1 PUBLIC-ACCESS TABLES
  2064.  
  2065. =over 3
  2066.  
  2067. =item I<Number2patch>
  2068.  
  2069. In this table the index is the patch-number (0 to 127),
  2070. and the value is its corresponding General-MIDI Patch
  2071. (on Channels other than 9).
  2072. See: http://www.pjb.com.au/muscript/gm.html#patch
  2073.  
  2074. =item I<Notenum2percussion>
  2075.  
  2076. In this table the index is the note-number (35 to 81),
  2077. and the value is its corresponding General-MIDI Percussion instrument
  2078. (on Channel 9).  See: http://www.pjb.com.au/muscript/gm.html#perc
  2079.  
  2080. =item I<Event2channelindex>
  2081.  
  2082. In this table the index is the event-name (see EVENTS),
  2083. and the value is the position within the event-array
  2084. at which the I<Channel-number> occurs.
  2085. It is very useful for manipulating particular channels
  2086. within a score (see SYNOPSIS)
  2087.  
  2088. =back
  2089.  
  2090. =head1 DOWNLOAD
  2091.  
  2092. This module is available as a LuaRock in
  2093. http://luarocks.org/modules/peterbillam
  2094. so you should be able to install it with the command:
  2095. B<sudo luarocks install midi>
  2096.  
  2097. The source is in
  2098. http://www.pjb.com.au/comp/lua/MIDI.lua
  2099. for you to install by hand in your LUA_PATH
  2100.  
  2101. The test script used during development is
  2102. http://www.pjb.com.au/comp/lua/test_mi.lua
  2103. which requires the DataDumper module.
  2104.  
  2105. You should be able to install the luaposix module with:
  2106. B<sudo luarocks install luaposix>
  2107.  
  2108. =head1 AUTHOR
  2109.  
  2110. Peter J Billam, http://www.pjb.com.au/comp/contact.html
  2111.  
  2112. =head1 SEE ALSO
  2113.  
  2114.  http://www.pjb.com.au/
  2115.  http://www.pjb.com.au/comp/index.html#lua
  2116.  http://www.pjb.com.au/comp/lua/MIDI.html
  2117.  http://www.pjb.com.au/midi/MIDI.html
  2118.  http://www.pjb.com.au/muscript/gm.html
  2119.  
  2120. =cut
  2121.  
  2122. ]=]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement