############################################################################ # # File: midisig.icn # # Subject: Program to show signature of a MIDI file # # Author: Ralph E. Griswold # # Date: August 17, 1998 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This program displays the signature of a MIDI file. # ############################################################################ # # Links: bincvt, convert # ############################################################################ link bincvt link convert procedure main() local rest, track, tracks, width, track_segs, seg, byte, bytes, code local meta_event, event, command, channel event := table() event["8"] := "note off" event["9"] := "note on" event["a"] := "key after-touch" event["b"] := "control change" event["c"] := "program change" event["d"] := "channel after-touch" event["e"] := "pitch wheel change" event["f"] := "SysEx event" meta_event := table() meta_event["\x00"] := "track sequence number" meta_event["\x01"] := "text" meta_event["\x02"] := "copyright" meta_event["\x03"] := "sequence or track name" meta_event["\x04"] := "track instrument name" meta_event["\x05"] := "lyric" meta_event["\x06"] := "marker" meta_event["\x07"] := "cue point" meta_event["\x20"] := "channel marker" meta_event["\x2f"] := "end of track" meta_event["\x51"] := "tempo" meta_event["\x54"] := "SMPTE offset" meta_event["\x58"] := "time signature" meta_event["\x59"] := "key signature" meta_event["\x07"] := "sequencer-specific information" track_segs := [] reads(, 100000) ? { ="MThd" | stop("*** invalid header") (unsigned(move(4)) = 6) | stop("*** invalid size") write( case unsigned(move(2)) of { 0 : "single track" 1 : "multi-track, synchronous" 2 : "multi-track, asynchronous" default : stop("*** invalid track information") } | stop("*** invalid track information") ) write(tracks := unsigned(move(2)), " tracks") | stop("*** invalid track number information") write(unsigned(move(2)), " delta-ticks per quarter note") | stop("*** invalid delta-tick information") width := *tracks + 1 every track := 1 to tracks do { ="MTrk" | { write(&errout, "*** short file") break } rest := unsigned(move(4)) put(track_segs, move(rest)) } } track := 0 while seg := get(track_segs) do { write() track +:= 1 write("track", right(track, width), ": ", *seg, " bytes") seg ? { write("delta-time: ", get_time()) | stop("*** invalid delta-time") byte := move(1) if byte == "\xff" then { write( "meta-event: ", \meta_event[code := move(1)] | ("unknown code " || image(code)) ) bytes := unsigned(move(1)) if 1 <= unsigned(code) <= 7 then write(" ", move(bytes)) } else { # event byte := exbase10(ord(byte), 16) write( "event: ", \event[byte[1]] | ("unknown command " || image(byte[1])), ", channel ", byte[2] ) } next # THE NEXT THING TO DO IS GET DATA BYTES } # AND LOOP } end # Decode delta-time. procedure get_time() local delta, byte delta := "" while byte := move(1) do { if ord(byte) >= 128 then delta ||:= char(ord(byte) - 128) else { delta ||:= byte return unsigned(delta) } } fail # short data end