def testText(self): text = "2016(C) MCW" MyMIDI = MIDIFile(1) MyMIDI.addText(0, 0, text) MyMIDI.close() payload_encoded = text.encode("ISO-8859-1") payloadLength = len(payload_encoded) payloadLengthVar = writeVarLength(payloadLength) data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'Text') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 0xff) # Code self.assertEqual(data.unpack_into_byte(2), 0x01) # Subcode index = 3 for i in range(len(payloadLengthVar)): self.assertEqual(data.unpack_into_byte(index), payloadLengthVar[i]) index = index + 1 for i in range(len(payload_encoded)): if sys.version_info < (3, ): test_char = ord(payload_encoded[i]) else: test_char = payload_encoded[i] self.assertEqual(data.unpack_into_byte(index), test_char) index = index + 1
def testTuning(self): MyMIDI = MIDIFile(1) MyMIDI.changeNoteTuning(0, [(1, 440), (2, 880)]) MyMIDI.close() data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'UniversalSysEx') self.assertEqual(data.unpack_into_byte(0), 0x00) self.assertEqual(data.unpack_into_byte(1), 0xf0) self.assertEqual(data.unpack_into_byte(2), 15) self.assertEqual(data.unpack_into_byte(3), 0x7F) self.assertEqual(data.unpack_into_byte(4), 0x7F) self.assertEqual(data.unpack_into_byte(5), 0x08) self.assertEqual(data.unpack_into_byte(6), 0x02) self.assertEqual(data.unpack_into_byte(7), 0x00) self.assertEqual(data.unpack_into_byte(8), 0x2) self.assertEqual(data.unpack_into_byte(9), 0x1) self.assertEqual(data.unpack_into_byte(10), 69) self.assertEqual(data.unpack_into_byte(11), 0) self.assertEqual(data.unpack_into_byte(12), 0) self.assertEqual(data.unpack_into_byte(13), 0x2) self.assertEqual(data.unpack_into_byte(14), 81) self.assertEqual(data.unpack_into_byte(15), 0) self.assertEqual(data.unpack_into_byte(16), 0) self.assertEqual(data.unpack_into_byte(17), 0xf7)
def testTuningProgram(self): program = 10 channel = 0 MyMIDI = MIDIFile(1) MyMIDI.changeTuningProgram(0, 0, 0, program) MyMIDI.close() data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'ControllerEvent') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 0xB << 4 | channel) # Code self.assertEqual(data.unpack_into_byte(2), 0x65) # Controller Number self.assertEqual(data.unpack_into_byte(3), 0x0) # Controller Value self.assertEqual(data.unpack_into_byte(4), 0x00) # time self.assertEqual(data.unpack_into_byte(5), 0xB << 4 | channel) # Code self.assertEqual(data.unpack_into_byte(6), 0x64) # Controller Number self.assertEqual(data.unpack_into_byte(7), 0x03) # Controller Value self.assertEqual(data.unpack_into_byte(8), 0x00) # time self.assertEqual(data.unpack_into_byte(9), 0xB << 4 | channel) # Code self.assertEqual(data.unpack_into_byte(10), 0x06) # Bank MSB self.assertEqual(data.unpack_into_byte(11), 0x00) # Value self.assertEqual(data.unpack_into_byte(12), 0x00) # time self.assertEqual(data.unpack_into_byte(13), 0xB << 4 | channel) # Code self.assertEqual(data.unpack_into_byte(14), 0x26) # Bank LSB self.assertEqual(data.unpack_into_byte(15), program) # Bank value (bank number)
def testShiftTrack(self): track = 0 channel = 0 pitch = 100 time = 1 duration = 1 volume = 100 MyMIDI = MIDIFile(1) MyMIDI.addNote(track, channel, pitch, time, duration, volume) self.assertEqual(MyMIDI.tracks[1].eventList[0].evtname, "NoteOn") self.assertEqual(MyMIDI.tracks[1].eventList[0].pitch, pitch) self.assertEqual(MyMIDI.tracks[1].eventList[0].tick, MyMIDI.time_to_ticks(time)) self.assertEqual(MyMIDI.tracks[1].eventList[0].duration, MyMIDI.time_to_ticks(duration)) self.assertEqual(MyMIDI.tracks[1].eventList[0].volume, volume) MyMIDI.shiftTracks() self.assertEqual(MyMIDI.tracks[1].eventList[0].tick, 0)
def testMultiClose(self): track = 0 channel = 0 pitch = 69 time = 0 duration = 1.0 volume = 64 MyMIDI = MIDIFile(1) MyMIDI.addNote(track, channel, pitch, time, duration, volume) MyMIDI.close() data_length_1 = len(MyMIDI.tracks[0].MIDIdata) MyMIDI.close() data_length_2 = len(MyMIDI.tracks[0].MIDIdata) self.assertEqual(data_length_1, data_length_2) MyMIDI.tracks[0].closeTrack() data_length_3 = len(MyMIDI.tracks[0].MIDIdata) self.assertEqual(data_length_1, data_length_3)
def testLongTrackName(self): track_name = 'long track name ' * 8 MyMIDI = MIDIFile(1) MyMIDI.addTrackName(0, 0, track_name) MyMIDI.close() data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'TrackName') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 0xFF) # Code self.assertEqual(data.unpack_into_byte(2), 0x03) # subcodes
def testSysEx(self): MyMIDI = MIDIFile(1) MyMIDI.addSysEx(0, 0, 0, struct.pack('>B', 0x01)) MyMIDI.close() data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'SysEx') self.assertEqual(data.unpack_into_byte(0), 0x00) self.assertEqual(data.unpack_into_byte(1), 0xf0) self.assertEqual(data.unpack_into_byte(2), 3) self.assertEqual(data.unpack_into_byte(3), 0x00) self.assertEqual(data.unpack_into_byte(4), 0x01) self.assertEqual(data.unpack_into_byte(5), 0xf7)
def testTuningProgramWithTimeOrder(self): program = 10 MyMIDI = MIDIFile(1) MyMIDI.changeTuningProgram(0, 0, 0, program, time_order=True) MyMIDI.close() data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'ControllerEvent') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(4), 0x01) # time self.assertEqual(data.unpack_into_byte(8), 0x01) # time self.assertEqual(data.unpack_into_byte(12), 0x01) # time
def testAddNote(self): MyMIDI = MIDIFile( 1) # a format 1 file, so we increment the track number below track = 0 channel = 0 pitch = 100 time = 0 duration = 1 volume = 100 MyMIDI.addNote(track, channel, pitch, time, duration, volume) self.assertEqual(MyMIDI.tracks[1].eventList[0].evtname, "NoteOn") self.assertEqual(MyMIDI.tracks[1].eventList[0].pitch, pitch) self.assertEqual(MyMIDI.tracks[1].eventList[0].tick, MyMIDI.time_to_ticks(time)) self.assertEqual(MyMIDI.tracks[1].eventList[0].duration, MyMIDI.time_to_ticks(duration)) self.assertEqual(MyMIDI.tracks[1].eventList[0].volume, volume)
def testNRPNCallWithTimeOrder(self): track = 0 time = 0 channel = 0 controller_msb = 1 controller_lsb = 2 data_msb = 3 data_lsb = 4 MyMIDI = MIDIFile(1) MyMIDI.makeNRPNCall(track, channel, time, controller_msb, controller_lsb, data_msb, data_lsb, time_order=True) MyMIDI.close() data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'ControllerEvent') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 0xB << 4 | channel) # Code self.assertEqual(data.unpack_into_byte(2), 99) # Controller Number self.assertEqual(data.unpack_into_byte(3), controller_msb) # Controller Value self.assertEqual(data.unpack_into_byte(4), 0x01) # time self.assertEqual(data.unpack_into_byte(5), 0xB << 4 | channel) # Code self.assertEqual(data.unpack_into_byte(6), 98) # Controller Number self.assertEqual(data.unpack_into_byte(7), controller_lsb) # Controller Value self.assertEqual(data.unpack_into_byte(8), 0x01) # time self.assertEqual(data.unpack_into_byte(9), 0xB << 4 | channel) # Code self.assertEqual(data.unpack_into_byte(10), 0x06) # Bank MSB self.assertEqual(data.unpack_into_byte(11), data_msb) # Value self.assertEqual(data.unpack_into_byte(12), 0x01) # time self.assertEqual(data.unpack_into_byte(13), 0xB << 4 | channel) # Code self.assertEqual(data.unpack_into_byte(14), 0x26) # Bank LSB self.assertEqual(data.unpack_into_byte(15), data_lsb) # Bank value (bank number)
def testChannelPressure(self): pressure = 10 channel = 0 time = 0.0 tracknum = 0 realtracknum = tracknum MyMIDI = MIDIFile(1) if MyMIDI.header.numeric_format == 1: realtracknum = tracknum + 1 MyMIDI.addChannelPressure(tracknum, channel, time, pressure) MyMIDI.close() data = Decoder(MyMIDI.tracks[realtracknum].MIDIdata) self.assertEqual(MyMIDI.tracks[realtracknum].MIDIEventList[0].evtname, 'ChannelPressure') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 0xD0 | channel) # Code self.assertEqual(data.unpack_into_byte(2), pressure)
def testProgramChange(self): program = 10 channel = 0 tracknum = 0 realtracknum = tracknum time = 0.0 MyMIDI = MIDIFile(1) if MyMIDI.header.numeric_format == 1: realtracknum = tracknum + 1 MyMIDI.addProgramChange(tracknum, channel, time, program) MyMIDI.close() data = Decoder(MyMIDI.tracks[realtracknum].MIDIdata) self.assertEqual(MyMIDI.tracks[realtracknum].MIDIEventList[0].evtname, 'ProgramChange') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 0xC << 4 | channel) # Code self.assertEqual(data.unpack_into_byte(2), program)
def testNonRealTimeUniversalSysEx(self): code = 1 subcode = 2 payload_number = 42 payload = struct.pack('>B', payload_number) MyMIDI = MIDIFile(1, adjust_origin=False) # Just for fun we'll use a multi-byte time time = 1 time_bytes = writeVarLength(time * MyMIDI.ticks_per_quarternote) MyMIDI.addUniversalSysEx(0, time, code, subcode, payload, realTime=False) MyMIDI.close() data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'UniversalSysEx') self.assertEqual(data.unpack_into_byte(0), time_bytes[0]) # Time self.assertEqual(data.unpack_into_byte(1), time_bytes[1]) # Time self.assertEqual(data.unpack_into_byte(2), 0xf0) # UniversalSysEx == 0xF0 self.assertEqual(data.unpack_into_byte(3), 5 + len(payload)) # Payload length = 5+actual pyayload self.assertEqual(data.unpack_into_byte(4), 0x7E) # 0x7E == non-realtime self.assertEqual(data.unpack_into_byte(5), 0x7F) # Sysex channel (always 0x7F) self.assertEqual(data.unpack_into_byte(6), code) self.assertEqual(data.unpack_into_byte(7), subcode) self.assertEqual(data.unpack_into_byte(8), payload_number) # Data self.assertEqual(data.unpack_into_byte(9), 0xf7) # End of message
def testAddControllerEvent(self): track = 0 time = 0 channel = 3 controller_number = 1 parameter = 2 MyMIDI = MIDIFile(1) MyMIDI.addControllerEvent(track, channel, time, controller_number, parameter) MyMIDI.close() data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'ControllerEvent') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 0xB << 4 | channel) # Code self.assertEqual(data.unpack_into_byte(2), controller_number) # Controller Number self.assertEqual(data.unpack_into_byte(3), parameter) # Controller Value
def testKeySignature(self): time = 0 track = 0 accidentals = 3 accidental_type = MINOR mode = MAJOR MyMIDI = MIDIFile(1) MyMIDI.addKeySignature(track, time, accidentals, accidental_type, mode) MyMIDI.close() data = Decoder(MyMIDI.tracks[0].MIDIdata) self.assertEqual(MyMIDI.tracks[0].MIDIEventList[0].evtname, 'KeySignature') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 0xFF) # Code self.assertEqual(data.unpack_into_byte(2), 0x59) # subcode self.assertEqual(data.unpack_into_byte(3), 0x02) # Event subtype self.assertEqual(data.unpack_into_byte(4), accidentals * accidental_type) self.assertEqual(data.unpack_into_byte(5), mode)
def testRealTimeUniversalSysEx(self): code = 1 subcode = 2 payload_number = 47 payload = struct.pack('>B', payload_number) MyMIDI = MIDIFile(1) MyMIDI.addUniversalSysEx(0, 0, code, subcode, payload, realTime=True) MyMIDI.close() data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'UniversalSysEx') self.assertEqual(data.unpack_into_byte(0), 0x00) self.assertEqual(data.unpack_into_byte(1), 0xf0) self.assertEqual(data.unpack_into_byte(2), 5 + len(payload)) self.assertEqual(data.unpack_into_byte(3), 0x7F) # 0x7F == real-time self.assertEqual(data.unpack_into_byte(4), 0x7F) self.assertEqual(data.unpack_into_byte(5), code) self.assertEqual(data.unpack_into_byte(6), subcode) self.assertEqual(data.unpack_into_byte(7), payload_number) self.assertEqual(data.unpack_into_byte(8), 0xf7)
def testEmptyEventList(self): MyMIDI = MIDIFile(1) MyMIDI.close() data_length = len(MyMIDI.tracks[0].MIDIdata) self.assertEqual(data_length, 4) # Header length 4
def testPitchWheel(self): val = 1000 MyMIDI = MIDIFile(1) MyMIDI.addPitchWheelEvent(0, 0, 0, val) MyMIDI.close() MSB = (val + 8192) >> 7 LSB = (val + 8192) & 0x7F data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 224) # Code self.assertEqual(data.unpack_into_byte(2), LSB) self.assertEqual(data.unpack_into_byte(3), MSB) val = -1000 MyMIDI = MIDIFile(1) MyMIDI.addPitchWheelEvent(0, 0, 0, val) MyMIDI.close() MSB = (val + 8192) >> 7 LSB = (val + 8192) & 0x7F data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 224) # Code self.assertEqual(data.unpack_into_byte(2), LSB) self.assertEqual(data.unpack_into_byte(3), MSB)
def testAdjustOrigin(self): track = 0 channel = 0 pitch = 69 time = 1 duration = 0.1 volume = 64 MyMIDI = MIDIFile(1, adjust_origin=True) MyMIDI.addNote(track, channel, pitch, time, duration, volume) time = 1.1 MyMIDI.addNote(track, channel, pitch, time, duration, volume) MyMIDI.close() data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(data.unpack_into_byte(0), 0x00) # first time self.assertEqual(data.unpack_into_byte(8), 0x00) # seconds time MyMIDI = MIDIFile(1, adjust_origin=False) time = 0.1 MyMIDI.addNote(track, channel, pitch, time, duration, volume) time = 0.2 MyMIDI.addNote(track, channel, pitch, time, duration, volume) MyMIDI.close() data = Decoder(MyMIDI.tracks[1].MIDIdata) self.assertEqual(data.unpack_into_byte(0), MyMIDI.ticks_per_quarternote / 10) # first time, should be an integer < 127 self.assertEqual(data.unpack_into_byte(8), 0x00) # first time
def testWriteFile(self): # Just to make sure the stream can be written without throwing an error. MyMIDI = MIDIFile(1) MyMIDI.addNote(0, 0, 100, 0, 1, 100) with open("/tmp/test.mid", "wb") as output_file: MyMIDI.writeFile(output_file)
def testTempo(self): tempo = 60 MyMIDI = MIDIFile(1, file_format=2) MyMIDI.addTempo(0, 0, tempo) MyMIDI.close() data = Decoder(MyMIDI.tracks[0].MIDIdata) self.assertEqual(MyMIDI.tracks[0].MIDIEventList[0].evtname, 'Tempo') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 0xff) # Code self.assertEqual(data.unpack_into_byte(2), 0x51) self.assertEqual(data.unpack_into_byte(3), 0x03) self.assertEqual(data[4:7], struct.pack('>L', int(60000000 / tempo))[1:4]) # Also check the format 1 file tempo = 60 MyMIDI = MIDIFile(2, file_format=1) MyMIDI.addTempo(1, 0, tempo) MyMIDI.close() data = Decoder(MyMIDI.tracks[0].MIDIdata) self.assertEqual(MyMIDI.tracks[0].MIDIEventList[0].evtname, 'Tempo') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 0xff) # Code self.assertEqual(data.unpack_into_byte(2), 0x51) self.assertEqual(data.unpack_into_byte(3), 0x03) self.assertEqual(data[4:7], struct.pack('>L', int(60000000 / tempo))[1:4])
def testTimeSignature(self): time = 0 track = 0 numerator = 4 denominator = 2 clocks_per_tick = 24 MyMIDI = MIDIFile(1, file_format=2) MyMIDI.addTimeSignature(track, time, numerator, denominator, clocks_per_tick) MyMIDI.close() data = Decoder(MyMIDI.tracks[0].MIDIdata) self.assertEqual(MyMIDI.tracks[0].MIDIEventList[0].evtname, 'TimeSignature') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 0xFF) # Code self.assertEqual(data.unpack_into_byte(2), 0x58) # subcode self.assertEqual(data.unpack_into_byte(3), 0x04) # Data length self.assertEqual(data.unpack_into_byte(4), numerator) self.assertEqual(data.unpack_into_byte(5), denominator) self.assertEqual(data.unpack_into_byte(6), clocks_per_tick) # Data length self.assertEqual(data.unpack_into_byte(7), 0x08) # 32nd notes per quarter note # We also want to check with a format 1 file, make sure it ends up in # the tempo track time = 0 track = 1 numerator = 4 denominator = 2 clocks_per_tick = 24 MyMIDI = MIDIFile(2, file_format=1) MyMIDI.addTimeSignature(track, time, numerator, denominator, clocks_per_tick) MyMIDI.close() data = Decoder(MyMIDI.tracks[0].MIDIdata) self.assertEqual(MyMIDI.tracks[0].MIDIEventList[0].evtname, 'TimeSignature') self.assertEqual(data.unpack_into_byte(0), 0x00) # time self.assertEqual(data.unpack_into_byte(1), 0xFF) # Code self.assertEqual(data.unpack_into_byte(2), 0x58) # subcode self.assertEqual(data.unpack_into_byte(3), 0x04) # Data length self.assertEqual(data.unpack_into_byte(4), numerator) self.assertEqual(data.unpack_into_byte(5), denominator) self.assertEqual(data.unpack_into_byte(6), clocks_per_tick) # Data length self.assertEqual(data.unpack_into_byte(7), 0x08) # 32nd notes per quarter note
def testTimeShift(self): # With one track MyMIDI = MIDIFile(1, adjust_origin=True) track = 0 channel = 0 pitch = 100 time1 = 5 duration = 1 volume = 100 MyMIDI.addNote(track, channel, pitch, time1, duration, volume) MyMIDI.close() self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].tick, MyMIDI.time_to_ticks(0)) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].tick, MyMIDI.time_to_ticks(duration)) # With two tracks track2 = 1 MyMIDI = MIDIFile(2, adjust_origin=True) MyMIDI.addNote(track, channel, pitch, time1, duration, volume) time2 = 6 MyMIDI.addNote(track2, channel, pitch, time2, duration, volume) MyMIDI.close() # ticks have already been converted to delta ticks self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].tick, MyMIDI.time_to_ticks(0)) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].tick, MyMIDI.time_to_ticks(duration)) self.assertEqual(MyMIDI.tracks[2].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[2].MIDIEventList[0].tick, MyMIDI.time_to_ticks(0 + duration)) self.assertEqual(MyMIDI.tracks[2].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[2].MIDIEventList[1].tick, MyMIDI.time_to_ticks(0 + duration)) # Negative Time MyMIDI = MIDIFile(1, adjust_origin=True) track = 0 channel = 0 pitch = 100 time = -5 duration = 1 volume = 100 MyMIDI.addNote(track, channel, pitch, time, duration, volume) MyMIDI.close() self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].tick, MyMIDI.time_to_ticks(0)) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].tick, MyMIDI.time_to_ticks(0 + duration)) # Negative time, two tracks MyMIDI = MIDIFile(2, adjust_origin=True) track = 0 channel = 0 pitch = 100 time = -1 duration = 1 volume = 100 MyMIDI.addNote(track, channel, pitch, time, duration, volume) track2 = 1 time2 = 0 MyMIDI.addNote(track2, channel, pitch, time2, duration, volume) MyMIDI.close() self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].tick, MyMIDI.time_to_ticks(0)) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].tick, MyMIDI.time_to_ticks(1)) self.assertEqual(MyMIDI.tracks[2].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[2].MIDIEventList[0].tick, MyMIDI.time_to_ticks(1)) self.assertEqual(MyMIDI.tracks[2].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[2].MIDIEventList[1].tick, MyMIDI.time_to_ticks(1))
def testDeinterleaveNotes(self): MyMIDI = MIDIFile(1, adjust_origin=False) track = 0 channel = 0 pitch = 100 time1 = 0 time2 = 1 duration = 2 volume = 100 MyMIDI.addNote(track, channel, pitch, time1, duration, volume) # on at 0 off at 2 MyMIDI.addNote(track, channel, pitch, time2, duration, volume + 1) # on at 1 off at 3 MyMIDI.close() # ticks have already been converted to delta ticks self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[0].tick, MyMIDI.time_to_ticks(time1)) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[1].tick, MyMIDI.time_to_ticks(time2)) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[2].evtname, 'NoteOn') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[2].tick, MyMIDI.time_to_ticks(time2 - time2)) self.assertEqual(MyMIDI.tracks[1].MIDIEventList[3].evtname, 'NoteOff') self.assertEqual(MyMIDI.tracks[1].MIDIEventList[3].tick, MyMIDI.time_to_ticks(time2 - time2 + duration))
def testRemoveDuplicates(self): # First notes track = 0 channel = 0 pitch = 69 time = 0 duration = 1 volume = 64 MyMIDI = MIDIFile(1) MyMIDI.addNote(track, channel, pitch, time, duration, volume) # also adds a corresponding NoteOff MyMIDI.addNote(track, channel, pitch, time, duration, volume) # also adds a corresponding NoteOff MyMIDI.close() self.assertEqual(2, len( MyMIDI.tracks[1].eventList)) # One NoteOn event, one NoteOff event MyMIDI = MIDIFile(1) MyMIDI.addNote(track, channel, pitch, time, duration, volume) pitch = 70 MyMIDI.addNote(track, channel, pitch, time, duration, volume) MyMIDI.close() self.assertEqual(4, len(MyMIDI.tracks[1].eventList) ) # Two NoteOn events, two NoteOff events # Next tempo tempo = 60 track = 0 time = 0 MyMIDI = MIDIFile(1) MyMIDI.addTempo(track, time, tempo) MyMIDI.addTempo(track, time, tempo) MyMIDI.close() self.assertEqual(1, len(MyMIDI.tracks[0].eventList)) MyMIDI = MIDIFile(1) MyMIDI.addTempo(track, time, tempo) tempo = 80 MyMIDI.addTempo(track, time, tempo) MyMIDI.close() self.assertEqual(2, len(MyMIDI.tracks[0].eventList)) # Program Number time = 0 track = 0 program = 10 channel = 0 MyMIDI = MIDIFile(1) MyMIDI.addProgramChange(track, channel, time, program) MyMIDI.addProgramChange(track, channel, time, program) MyMIDI.close() self.assertEqual(1, len(MyMIDI.tracks[track + 1].eventList)) MyMIDI = MIDIFile(1) MyMIDI.addProgramChange(track, channel, time, program) program = 11 MyMIDI.addProgramChange(track, channel, time, program) MyMIDI.close() self.assertEqual(2, len(MyMIDI.tracks[track + 1].eventList)) # Track Name track = 0 time = 0 track_name = "track" MyMIDI = MIDIFile(1) MyMIDI.addTrackName(track, time, track_name) MyMIDI.addTrackName(track, time, track_name) MyMIDI.close() self.assertEqual(1, len(MyMIDI.tracks[1].eventList)) MyMIDI = MIDIFile(1) MyMIDI.addTrackName(track, time, track_name) track_name = "track 2" MyMIDI.addTrackName(track, time, track_name) MyMIDI.close() self.assertEqual(2, len(MyMIDI.tracks[1].eventList)) # SysEx. These are never removed track = 0 time = 0 manufacturer = 10 MyMIDI = MIDIFile(1) MyMIDI.addSysEx(track, time, manufacturer, struct.pack('>B', 0x01)) MyMIDI.addSysEx(track, time, manufacturer, struct.pack('>B', 0x01)) MyMIDI.close() self.assertEqual(2, len(MyMIDI.tracks[1].eventList)) # UniversalSysEx. Same thing -- never remove track = 0 time = 0 code = 1 subcode = 2 payload_number = 47 payload = struct.pack('>B', payload_number) MyMIDI = MIDIFile(1) MyMIDI.addUniversalSysEx(track, time, code, subcode, payload, realTime=True) MyMIDI.addUniversalSysEx(track, time, code, subcode, payload, realTime=True) MyMIDI.close() self.assertEqual(2, len(MyMIDI.tracks[1].eventList))
def testEndOfTrack(self): MyMIDI = MIDIFile(1, ticks_per_quarternote=480) MyMIDI.addTimeSignature(0, 0, 4, 2, 8) MyMIDI.addNote(0, 0, 60, 0, 0.75, 55) MyMIDI.addNote(0, 0, 64, 1, 0.75, 55) MyMIDI.addNote(0, 0, 67, 2, 0.75, 55) MyMIDI.addNote(0, 0, 60, 4, 0.75, 55) MyMIDI.addNote(0, 0, 64, 5, 0.75, 55) MyMIDI.addNote(0, 0, 67, 6, 0.75, 55) with open(os.path.join(gettempdir(), "TestEndOfTrack_1.mid"), "wb") as f_midi: MyMIDI.writeFile(f_midi) MyMIDI = MIDIFile(1, ticks_per_quarternote=480) MyMIDI.addTimeSignature(0, 0, 4, 2, 8) MyMIDI.addNote(0, 0, 60, 0, 0.75, 55) MyMIDI.addNote(0, 0, 64, 1, 0.75, 55) MyMIDI.addNote(0, 0, 67, 2, 0.75, 55) MyMIDI.addNote(0, 0, 60, 4, 0.75, 55) MyMIDI.addNote(0, 0, 64, 5, 0.75, 55) MyMIDI.addNote(0, 0, 67, 6, 0.75, 55) MyMIDI.addEndOfTrack(0, 6.65) with open(os.path.join(gettempdir(), "TestEndOfTrack_2.mid"), "wb") as f_midi: MyMIDI.writeFile(f_midi) # No "End-Of-Track" and "End-Of-Track" placed before the final note event # should give the same result # --- Actually, not correct. The system track end comes at a different # time. This test is commented for now. #self.assertTrue(filecmp.cmp(os.path.join(gettempdir(), "TestEndOfTrack_1.mid"), os.path.join(gettempdir(), "TestEndOfTrack_2.mid"))) MyMIDI = MIDIFile(1, ticks_per_quarternote=480) MyMIDI.addTimeSignature(0, 0, 4, 2, 8) MyMIDI.addNote(0, 0, 60, 0, 0.75, 55) MyMIDI.addNote(0, 0, 64, 1, 0.75, 55) MyMIDI.addNote(0, 0, 67, 2, 0.75, 55) MyMIDI.addNote(0, 0, 60, 4, 0.75, 55) MyMIDI.addNote(0, 0, 64, 5, 0.75, 55) MyMIDI.addNote(0, 0, 67, 6, 0.75, 55) MyMIDI.addEndOfTrack(0, 8) with open(os.path.join(gettempdir(), "TestEndOfTrack_3.mid"), "wb") as f_midi: MyMIDI.writeFile(f_midi) # No "End-Of-Track" and "End-Of-Track" placed after the final note event # should give a different result self.assertFalse( filecmp.cmp(os.path.join(gettempdir(), "TestEndOfTrack_1.mid"), os.path.join(gettempdir(), "TestEndOfTrack_3.mid"))) os.remove(os.path.join(gettempdir(), "TestEndOfTrack_1.mid")) os.remove(os.path.join(gettempdir(), "TestEndOfTrack_2.mid")) os.remove(os.path.join(gettempdir(), "TestEndOfTrack_3.mid"))