|
3 | 3 | from TrackData import TempoChanges |
4 | 4 | from MidiEvents import * |
5 | 5 |
|
6 | | -#contains the finalized data after anylisis |
| 6 | + |
| 7 | +# contains the finalized data after analysis |
7 | 8 | class MidiData: |
8 | 9 | def __init__(self, midiFilename): |
9 | 10 | self.eventDecoder = MidiEventDecoder(midiFilename) |
10 | 11 | headerData = self.eventDecoder.headerData() |
11 | | - #variables |
| 12 | + # variables |
12 | 13 | self.format = headerData.formatType |
13 | 14 | self.numTracks = headerData.numTracks |
14 | 15 | self.isTicksPerBeat = False |
15 | | - if headerData.ticksPerBeat == None: |
| 16 | + if headerData.ticksPerBeat is None: |
16 | 17 | self.isTicksPerBeat = False |
17 | 18 | self.ticksPerSecond = (headerData.framesPerSecond * |
18 | 19 | headerData.ticksPerFrame) |
19 | 20 | else: |
20 | 21 | self.isTicksPerBeat = True |
21 | 22 | self.ticksPerBeat = headerData.ticksPerBeat |
22 | 23 |
|
23 | | - #maps running total of delta times to microsecondsPerQuarter |
| 24 | + if headerData.formatType != 1: |
| 25 | + raise NotSupportedException("Midi files of format " + str(headerData.formatType) |
| 26 | + + " are not supported") |
| 27 | + |
| 28 | + # maps running total of delta times to microsecondsPerQuarter |
24 | 29 | tempoChanges = TempoChanges() |
25 | 30 | self.tracks = [] |
26 | 31 |
|
27 | | - deltaTimeTotal = 0 |
28 | | - self.msPerBeat = 500 #default 120 bpm |
| 32 | + self.msPerBeat = 500 # default 120 bpm |
29 | 33 |
|
30 | | - #read in each track |
31 | | - tracknum = 0 #used to create temporary track names |
| 34 | + # read in each track |
| 35 | + tracknum = 0 # used to create temporary track names |
32 | 36 | while self.eventDecoder.hasMoreEvents(): |
33 | 37 | trackName = "Track" + str(tracknum) |
34 | | - tracknum = tracknum + 1 |
35 | | - #should be a track header |
| 38 | + tracknum += 1 |
36 | 39 | trackData = TrackData(trackName) |
| 40 | + # should be a track header |
37 | 41 | event = self.eventDecoder.nextEvent() |
38 | | - #set up tempoChanges |
| 42 | + if not(isinstance(event, TrackHeader)): |
| 43 | + raise UnexpectedEventException(event, TrackHeader()) |
| 44 | + # set up tempoChanges |
39 | 45 | tempoChanges.reset() |
40 | | - self.msPerBeat = 500 #default 120 bpm |
| 46 | + self.msPerBeat = 500 # default 120 bpm |
41 | 47 | deltaTimeTotal = 0 |
42 | | - nextTotal = 0 |
43 | | - msTotal = 0 #current time in ms |
44 | | - #add events |
| 48 | + msTotal = 0 # current time in ms |
| 49 | + # add events |
45 | 50 | while not(isinstance(event, EndOfTrackEvent)): |
46 | 51 | event = self.eventDecoder.nextEvent() |
47 | | - if (isinstance(event, SetTempoEvent)): |
| 52 | + if isinstance(event, SetTempoEvent): |
48 | 53 | tempoChanges.addTempoChange(deltaTimeTotal, event.tempo) |
49 | 54 | nextTotal = deltaTimeTotal + event.deltaTime |
50 | | - #calcaute absolute start time for event in ms |
| 55 | + # calculate absolute start time for event in ms |
51 | 56 | if self.isTicksPerBeat: |
52 | 57 | while (tempoChanges.hasMore() and |
53 | 58 | nextTotal >= tempoChanges.deltaTimeTotal()): |
54 | | - msTotal = msTotal + ((tempoChanges.deltaTimeTotal() - |
55 | | - deltaTimeTotal)*self.msPerBeat/self.ticksPerBeat) |
| 59 | + msTotal += ((tempoChanges.deltaTimeTotal() - deltaTimeTotal)*self.msPerBeat/self.ticksPerBeat) |
56 | 60 | deltaTimeTotal = tempoChanges.deltaTimeTotal() |
57 | 61 | self.msPerBeat = tempoChanges.usPerQuarter()*.001 |
58 | 62 | tempoChanges.findNext() |
59 | | - msTotal = (msTotal + |
60 | | - ((nextTotal-deltaTimeTotal)*self.msPerBeat/self.ticksPerBeat)) |
| 63 | + msTotal += ((nextTotal-deltaTimeTotal)*self.msPerBeat/self.ticksPerBeat) |
61 | 64 | else: |
62 | 65 | msTotal = (event.deltaTime/self.ticksPerSecond)*.001 |
63 | | - #add event to trackData |
| 66 | + # add event to trackData |
64 | 67 | deltaTimeTotal = nextTotal |
65 | 68 | event.setStartTime(msTotal) |
66 | 69 | trackData.addEvent(event) |
67 | 70 | self.tracks.append(trackData) |
68 | 71 |
|
69 | 72 | def getNumTracks(self): |
70 | 73 | return len(self.tracks) |
| 74 | + |
71 | 75 | def getTrack(self, index): |
72 | 76 | return self.tracks[index] |
| 77 | + |
| 78 | + |
| 79 | +class UnexpectedEventException(Exception): |
| 80 | + def __init__(self, event, expectedEvent): |
| 81 | + self.event = event |
| 82 | + self.expectedEvent = expectedEvent |
| 83 | + |
| 84 | + def __str__(self): |
| 85 | + return str("MidiData expected event of type " + str(type(self.expectedEvent)) |
| 86 | + + ", got event of type " + str(type(self.event))) |
| 87 | + |
| 88 | + |
| 89 | +class NotSupportedException(Exception): |
| 90 | + def __init__(self, value): |
| 91 | + self.value = value |
| 92 | + |
| 93 | + def __str__(self): |
| 94 | + return str(self.value) |
0 commit comments