236 lines
11 KiB
Python
236 lines
11 KiB
Python
#-----------------------------------------------------------------------------
|
|
# Name: miditest.py
|
|
# Purpose: Unit testing harness for midiutil
|
|
#
|
|
# Author: Mark Conway Wirt <emergentmusics) at (gmail . com>
|
|
#
|
|
# Created: 2008/04/17
|
|
# Copyright: (c) 2009, Mark Conway Wirt
|
|
# License: Please see License.txt for the terms under which this
|
|
# software is distributed.
|
|
#-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
# Next few lines are necessary owing to limitations of the IDE and the
|
|
# directory structure of the project.
|
|
|
|
import sys, struct
|
|
sys.path.append('..')
|
|
|
|
import unittest
|
|
from midiutil.MidiFile import MIDIFile, MIDIHeader, MIDITrack, writeVarLength, \
|
|
frequencyTransform, returnFrequency
|
|
import sys
|
|
|
|
class TestMIDIUtils(unittest.TestCase):
|
|
|
|
def testWriteVarLength(self):
|
|
self.assertEquals(writeVarLength(0x70), [0x70])
|
|
self.assertEquals(writeVarLength(0x80), [0x81, 0x00])
|
|
self.assertEquals(writeVarLength(0x1FFFFF), [0xFF, 0xFF, 0x7F])
|
|
self.assertEquals(writeVarLength(0x08000000), [0xC0, 0x80, 0x80, 0x00])
|
|
|
|
def testAddNote(self):
|
|
MyMIDI = MIDIFile(1)
|
|
MyMIDI.addNote(0, 0, 100,0,1,100)
|
|
self.assertEquals(MyMIDI.tracks[0].eventList[0].type, "note")
|
|
self.assertEquals(MyMIDI.tracks[0].eventList[0].pitch, 100)
|
|
self.assertEquals(MyMIDI.tracks[0].eventList[0].time, 0)
|
|
self.assertEquals(MyMIDI.tracks[0].eventList[0].duration, 1)
|
|
self.assertEquals(MyMIDI.tracks[0].eventList[0].volume, 100)
|
|
|
|
def testDeinterleaveNotes(self):
|
|
MyMIDI = MIDIFile(1)
|
|
MyMIDI.addNote(0, 0, 100, 0, 2, 100)
|
|
MyMIDI.addNote(0, 0, 100, 1, 2, 100)
|
|
MyMIDI.close()
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, 'NoteOn')
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].time, 0)
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].type, 'NoteOff')
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].time, 128)
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[2].type, 'NoteOn')
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[2].time, 0)
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[3].type, 'NoteOff')
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[3].time, 256)
|
|
|
|
def testTimeShift(self):
|
|
|
|
# With one track
|
|
MyMIDI = MIDIFile(1)
|
|
MyMIDI.addNote(0, 0, 100, 5, 1, 100)
|
|
MyMIDI.close()
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, 'NoteOn')
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].time, 0)
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].type, 'NoteOff')
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].time, 128)
|
|
|
|
# With two tracks
|
|
MyMIDI = MIDIFile(2)
|
|
MyMIDI.addNote(0, 0, 100, 5, 1, 100)
|
|
MyMIDI.addNote(1, 0, 100, 6, 1, 100)
|
|
MyMIDI.close()
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, 'NoteOn')
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].time, 0)
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].type, 'NoteOff')
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].time, 128)
|
|
self.assertEquals(MyMIDI.tracks[1].MIDIEventList[0].type, 'NoteOn')
|
|
self.assertEquals(MyMIDI.tracks[1].MIDIEventList[0].time, 128)
|
|
self.assertEquals(MyMIDI.tracks[1].MIDIEventList[1].type, 'NoteOff')
|
|
self.assertEquals(MyMIDI.tracks[1].MIDIEventList[1].time, 128)
|
|
|
|
# Negative Time
|
|
MyMIDI = MIDIFile(1)
|
|
MyMIDI.addNote(0, 0, 100, -5, 1, 100)
|
|
MyMIDI.close()
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, 'NoteOn')
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].time, 0)
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].type, 'NoteOff')
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].time, 128)
|
|
|
|
# Negative time, two tracks
|
|
|
|
MyMIDI = MIDIFile(2)
|
|
MyMIDI.addNote(0, 0, 100, -1, 1, 100)
|
|
MyMIDI.addNote(1, 0, 100, 0, 1, 100)
|
|
MyMIDI.close()
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, 'NoteOn')
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].time, 0)
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].type, 'NoteOff')
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[1].time, 128)
|
|
self.assertEquals(MyMIDI.tracks[1].MIDIEventList[0].type, 'NoteOn')
|
|
self.assertEquals(MyMIDI.tracks[1].MIDIEventList[0].time, 128)
|
|
self.assertEquals(MyMIDI.tracks[1].MIDIEventList[1].type, 'NoteOff')
|
|
self.assertEquals(MyMIDI.tracks[1].MIDIEventList[1].time, 128)
|
|
|
|
def testFrequency(self):
|
|
freq = frequencyTransform(8.1758)
|
|
self.assertEquals(freq[0], 0x00)
|
|
self.assertEquals(freq[1], 0x00)
|
|
self.assertEquals(freq[2], 0x00)
|
|
freq = frequencyTransform(8.66196) # 8.6620 in MIDI documentation
|
|
self.assertEquals(freq[0], 0x01)
|
|
self.assertEquals(freq[1], 0x00)
|
|
self.assertEquals(freq[2], 0x00)
|
|
freq = frequencyTransform(440.00)
|
|
self.assertEquals(freq[0], 0x45)
|
|
self.assertEquals(freq[1], 0x00)
|
|
self.assertEquals(freq[2], 0x00)
|
|
freq = frequencyTransform(440.0016)
|
|
self.assertEquals(freq[0], 0x45)
|
|
self.assertEquals(freq[1], 0x00)
|
|
self.assertEquals(freq[2], 0x01)
|
|
freq = frequencyTransform(439.9984)
|
|
self.assertEquals(freq[0], 0x44)
|
|
self.assertEquals(freq[1], 0x7f)
|
|
self.assertEquals(freq[2], 0x7f)
|
|
freq = frequencyTransform(8372.0190)
|
|
self.assertEquals(freq[0], 0x78)
|
|
self.assertEquals(freq[1], 0x00)
|
|
self.assertEquals(freq[2], 0x00)
|
|
freq = frequencyTransform(8372.062) #8372.0630 in MIDI documentation
|
|
self.assertEquals(freq[0], 0x78)
|
|
self.assertEquals(freq[1], 0x00)
|
|
self.assertEquals(freq[2], 0x01)
|
|
freq = frequencyTransform(13289.7300)
|
|
self.assertEquals(freq[0], 0x7F)
|
|
self.assertEquals(freq[1], 0x7F)
|
|
self.assertEquals(freq[2], 0x7E)
|
|
freq = frequencyTransform(12543.8760)
|
|
self.assertEquals(freq[0], 0x7F)
|
|
self.assertEquals(freq[1], 0x00)
|
|
self.assertEquals(freq[2], 0x00)
|
|
freq = frequencyTransform(8.2104) # Just plain wrong in documentation, as far as I can tell.
|
|
#self.assertEquals(freq[0], 0x0)
|
|
#self.assertEquals(freq[1], 0x0)
|
|
#self.assertEquals(freq[2], 0x1)
|
|
|
|
# Test the inverse
|
|
testFreq = 15.0
|
|
accuracy = 0.00001
|
|
x = returnFrequency(frequencyTransform(testFreq))
|
|
delta = abs(testFreq - x)
|
|
self.assertEquals(delta < (accuracy*testFreq), True)
|
|
testFreq = 200.0
|
|
x = returnFrequency(frequencyTransform(testFreq))
|
|
delta = abs(testFreq - x)
|
|
self.assertEquals(delta < (accuracy*testFreq), True)
|
|
testFreq = 400.0
|
|
x = returnFrequency(frequencyTransform(testFreq))
|
|
delta = abs(testFreq - x)
|
|
self.assertEquals(delta < (accuracy*testFreq), True)
|
|
testFreq = 440.0
|
|
x = returnFrequency(frequencyTransform(testFreq))
|
|
delta = abs(testFreq - x)
|
|
self.assertEquals(delta < (accuracy*testFreq), True)
|
|
testFreq = 1200.0
|
|
x = returnFrequency(frequencyTransform(testFreq))
|
|
delta = abs(testFreq - x)
|
|
self.assertEquals(delta < (accuracy*testFreq), True)
|
|
testFreq = 5000.0
|
|
x = returnFrequency(frequencyTransform(testFreq))
|
|
delta = abs(testFreq - x)
|
|
self.assertEquals(delta < (accuracy*testFreq), True)
|
|
testFreq = 12000.0
|
|
x = returnFrequency(frequencyTransform(testFreq))
|
|
delta = abs(testFreq - x)
|
|
self.assertEquals(delta < (accuracy*testFreq), True)
|
|
|
|
|
|
def testSysEx(self):
|
|
MyMIDI = MIDIFile(1)
|
|
MyMIDI.addSysEx(0,0, 0, struct.pack('>B', 0x01))
|
|
MyMIDI.close()
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, 'SysEx')
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[0])[0], 0x00)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[1])[0], 0xf0)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[2])[0], 3)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[3])[0], 0x00)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[4])[0], 0x01)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[5])[0], 0xf7)
|
|
|
|
def testUniversalSysEx(self):
|
|
MyMIDI = MIDIFile(1)
|
|
MyMIDI.addUniversalSysEx(0,0, 1, 2, struct.pack('>B', 0x01))
|
|
MyMIDI.close()
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, 'UniversalSysEx')
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[0])[0], 0x00)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[1])[0], 0xf0)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[2])[0], 6)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[3])[0], 0x7E)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[4])[0], 0x7F)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[5])[0], 0x01)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[6])[0], 0x02)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[7])[0], 0x01)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[8])[0], 0xf7)
|
|
|
|
def testTuning(self):
|
|
MyMIDI = MIDIFile(1)
|
|
MyMIDI.changeNoteTuning(0, [(1, 440), (2, 880)])
|
|
MyMIDI.close()
|
|
self.assertEquals(MyMIDI.tracks[0].MIDIEventList[0].type, 'UniversalSysEx')
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[0])[0], 0x00)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[1])[0], 0xf0)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[2])[0], 15)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[3])[0], 0x7E)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[4])[0], 0x7F)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[5])[0], 0x08)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[6])[0], 0x02)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[7])[0], 0x00)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[8])[0], 0x2)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[9])[0], 0x1)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[10])[0], 69)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[11])[0], 0)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[12])[0], 0)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[13])[0], 0x2)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[14])[0], 81)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[15])[0], 0)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[16])[0], 0)
|
|
self.assertEquals(struct.unpack('>B', MyMIDI.tracks[0].MIDIdata[17])[0], 0xf7)
|
|
|
|
MIDISuite = unittest.TestLoader().loadTestsFromTestCase(TestMIDIUtils)
|
|
|
|
if __name__ == '__main__':
|
|
unittest.TextTestRunner(verbosity=1).run(MIDISuite)
|
|
|