#!/usr/bin/env python2

import sys
import midi

CLOCK = 1000000.0
MIDIOFF = 16

print "// Music data"
print

print "uint16_t note_wl[] = {"

notes = range(0, 64)
wls = [0] + [int(CLOCK / (2 ** ((n + MIDIOFF + 1 - 69) / 12.0) * 440)) for n in notes]

print "  " + ", ".join(["0x%04x" % wl for wl in wls])

print "};"
print

mid = midi.read_midifile(sys.argv[1])

data = []

channel = [0, 0, 0]
on = set()

buf = []

for mev in mid[1]:
    if mev.tick:
        buf.sort(lambda a, b: cmp(a.name, b.name))

        for ev in buf:
            if isinstance(ev, midi.NoteOnEvent):
                note = ev.data[0] - MIDIOFF
                on.add(note)

                print "// %s on" % note
                if note <= 0 or note > 63:
                    print "// DROP"
                    continue

                for i in range(0, len(channel)):
                    if channel[i] == 0:
                        channel[i] = note
                        data.append((i + 1) << 6 | note)
                        break
                else:
                    print "// TOO MANY"
                    channel[0] = note
                    data.append(note)
            elif isinstance(ev, midi.NoteOffEvent):
                note = ev.data[0] - MIDIOFF
                on.discard(note)

                print "// %s off" % note
                if note <= 0 or note > 63:
                    print "// DROP"
                    continue

                for i in range(0, len(channel)):
                    if channel[i] == note:
                        channel[i] = 0
                        data.append((i + 1) << 6)
                        break

        tlist = list(on)
        tlist.sort()

        while len(tlist) > 4:
            del tlist[1]

        tick = mev.tick
        print "// -- %s ticks" % tick

        while tick > 63:
            data.append(63)
            tick -= 63;

        if tick > 0:
            data.append(tick)

        buf = [mev]
    else:
        buf.append(mev)

    #if len(data) > 1000:
    #    break

print
print "const uint8_t music[] __attribute__ ((section(\".text;\"))) = {"
print "  " + ", ".join(["0x%02x" % d for d in data])
print "};"
print "// " + str(len(data)) + " bytes"
