def writeMidiTrack(self, out): """ Create/write the MIDI track. We convert timing offsets to midi-deltas. """ tr = self.miditrk """ If the -1 flag is set we need to add a terminate to the end of each track. This is done to make looping software like seq24 happy. We do this by truncating all data in the file past the current tick pointer and inserting an all-notes-off at that position. """ if gbl.endsync and self.channel>=0: eof = gbl.tickOffset for offset in tr.keys(): if offset > eof: del tr[offset] self.addToTrack(eof, chr(0xb0 | self.channel) + chr(0x7b) + chr(0)) """ To every MIDI track we generate we add (if the -0 flag was set) an on/off beep at offset 0. This makes for easier sync in multi-tracks. """ if gbl.synctick and self.channel >= 0: t,v = syncTone self.addToTrack(0, chr(0x90 | self.channel) + chr(t) + chr(v) ) self.addToTrack(1, chr(0x90 | self.channel) + chr(t) + chr(0) ) if gbl.debug: ttl = 0 lg=1 for t in tr: a=len(tr[t]) if a > lg: lg = a ttl += a print "Unique ts: %s; Ttl events %s; Average ev/ts %.2f" % \ (len(tr), ttl, float(ttl)/len(tr) ) last = 0 # Convert all events to MIDI deltas and store in # the track array/list tdata = [] # empty track container lastSts = None # Running status tracker for a in sorted(tr.keys()): delta = a-last if not tr[a]: continue # this skips the delta offset update! for d in tr[a]: """ Running status check. For each packet compare the first byte with the first byte of the previous packet. If it is can be converted to running status we strip out byte 0. Note that valid running status byte are 0x80..0xef. 0xfx are system messages and are note suitable for running status. """ if len(d) > 1: if d[0] == lastSts: d=d[1:] else: lastSts = d[0] s=ord(lastSts) if s < 0x80 or s > 0xef or not gbl.runningStatus: lastSts = None tdata.extend( [ intToVarNumber(delta) , d ] ) delta = 0 last = a # Add an EOF to the track (included in total track size) tdata.append( intToVarNumber(0)) tdata.append( chr(0xff) + chr(0x2f) + chr(0x00) ) tdata = ''.join(tdata) totsize = len(tdata) out.write("MTrk") out.write(intToLong(totsize)) out.write( tdata )
def mkHeader(count, tempo, Mtype): return "MThd" + intToLong(6) + intToWord(Mtype) + intToWord(count) + intToWord(tempo)
def mkHeader(count, tempo, Mtype): return packBytes("MThd", intToLong(6), intToWord(Mtype), intToWord(count), intToWord(tempo))
def writeMidiTrack(self, out): """ Create/write the MIDI track. We convert timing offsets to midi-deltas. """ tr=self.miditrk """ To every MIDI track we generate we add (if the -0 flag was set) an on/off beep at offset 0. This makes for easier sync in multi-tracks. """ if gbl.synctick and self.channel >= 0: self.addToTrack(0, chr(0x90 | self.channel) + chr(80) + chr(90) ) self.addToTrack(1, chr(0x90 | self.channel) + chr(80) + chr(0) ) if gbl.debug: ttl = 0 lg=1 for t in tr: a=len(tr[t]) if a > lg: lg = a ttl += a print "Unique ts: %s; Ttl events %s; Average ev/ts %.2f" % \ (len(tr), ttl, float(ttl)/len(tr) ) last = 0 # Convert all events to MIDI deltas and store in # the track array/list tdata=[] # empty track container lastSts=None # Running status tracker for a in sorted(tr.keys()): delta = a-last for d in tr[a]: """ Running status check. For each packet compare the first byte with the first byte of the previous packet. If it is can be converted to running status we strip out byte 0. Note that valid running status byte are 0x80..0xef. 0xfx are system messages and are note suitable for running status. """ if len(d) > 1: if d[0] == lastSts: d=d[1:] else: lastSts = d[0] s=ord(lastSts) if s < 0x80 or s > 0xef or not gbl.runningStatus: lastSts = None tdata.extend( [ intToVarNumber(delta) , d ] ) delta = 0 last = a # Add an EOF to the track (included in total track size) tdata.append( intToVarNumber(0)) tdata.append( chr(0xff) + chr(0x2f) + chr(0x00) ) tdata = ''.join(tdata) totsize = len(tdata) out.write("MTrk") out.write(intToLong(totsize)) out.write( tdata )