#!/usr/bin/python

import sys
#from mido import MidiFile
import mido

optarg     = 1
timescale  = 16.0 # Scale time to 16th of a second
extperchan = 9    # Default to standard MIDI channel  10 for extra percussion
if len(sys.argv) == 1:
    print('Usage:', sys.argv[0], '[-p extra_percussion_channel] [-t timescale] MIDI_file')
    sys.exit(0)
# Parse optional arguments
while optarg < (len(sys.argv) - 1):
    if sys.argv[optarg] == '-t': # Override tempo percentage
        timescale = float(sys.argv[optarg + 1]) * 16.0
        optarg += 2
    if sys.argv[optarg] == '-p': # Add extra percussion channel
        extperchan = int(sys.argv[optarg + 1]) - 1
        optarg += 2
mid = mido.MidiFile(sys.argv[optarg])
timeshift = timescale
totaltime = 0
eventtime = 0.0
for msg in mid:
    eventtime += msg.time * timeshift
    #print '; time = ', msg.time
    if msg.type == 'note_on' or msg.type == 'note_off':
        #if eventtime > 0.0 and eventtime < 0.5:
        #    eventtime = 0.5
        deltatime = int(round(eventtime))
        octave    = int(msg.note / 12 - 1)
        onote     = int(msg.note % 12)
        lrchan    = int(msg.channel & 1)
        vol       = int(msg.velocity >> 3)
        print('time=%.4f type=%s octave=%d onote=%d lrchan=%d vol=%d' % (msg.time, msg.type, octave, onote, lrchan, vol))
        if msg.velocity > 0 and vol == 0:
            vol = 1
        if msg.type == 'note_off':
            vol = 0
        if octave < 0:
            octave = 0
        totaltime += eventtime
        print('totaltime=%.4f scaled=%.4f' % (totaltime, totaltime*16/16.24))
        if msg.channel == 9 or msg.channel == extperchan:
            #
            # Percussion
            #
            if vol > 0:
                print('\t!BYTE\t${0:02X}, ${1:02X}, ${2:02X}\t; Percussion {3:d} Chan {4:d} Dur {5:d}'.format(deltatime, msg.note ^ 0x40, (lrchan << 7) | vol, msg.note, msg.channel + 1, vol))
                if extperchan == 9: # Play percussion on both channels if no extended percussion
                    print('\t!BYTE\t${0:02X}, ${1:02X}, ${2:02X}\t; Percussion {3:d} Chan {4:d} Dur {5:d}'.format(0, msg.note ^ 0x40, vol, msg.note, msg.channel + 1, vol))
                eventtime = 0.0
        else:
            #
            # Note
            #
            print('\t!BYTE\t${0:02X}, ${1:02X}, ${2:02X}\t; Note {3:d} Chan {4:d} Vol {5:d}'.format(deltatime, 0x80 | (octave << 4) | onote, (lrchan << 7) | vol, msg.note, msg.channel + 1, vol))
            eventtime = 0.0
    elif msg.type == 'set_tempo':
        pass
        #timeshift = msg.tempo / 500000.0 * timescale
        #print '; timescale = ', timescale
    elif msg.type == 'time_signature':
        pass
    elif msg.type == 'control_chage':
        pass
    elif msg.type == 'program_change':
        pass
print('\t!BYTE\t${0:02X}, $00, $00'.format(int(eventtime + 0.5)))
