Skip to content

Commit 0f8393f

Browse files
committed
Events given start times in ms
1 parent 924dcdf commit 0f8393f

File tree

3 files changed

+46
-14
lines changed

3 files changed

+46
-14
lines changed

MidiData.py

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ def __init__(self, midiFilename):
2020
self.ticksPerBeat = headerData.ticksPerBeat
2121

2222
#maps running total of delta times to microsecondsPerQuarter
23-
self.tempoChanges = TempoChanges()
23+
tempoChanges = TempoChanges()
2424
self.trackZeroEvents = []
2525
self.tracks = []
2626

27-
deltaTimeTotal = 0
27+
deltaTimeTotal = 0
28+
self.msPerBeat = 500 #default 120 bpm
2829
#should be a track header
2930
event = self.eventDecoder.nextEvent()
3031

@@ -36,7 +37,7 @@ def __init__(self, midiFilename):
3637
self.trackZeroEvents.append(event)
3738
if (event.eventClass == "Meta" and
3839
event.eventType == "SetTempo"):
39-
self.tempoChanges.addTempoChange(deltaTimeTotal, event)
40+
tempoChanges.addTempoChange(deltaTimeTotal, event)
4041

4142

4243
#read in each track
@@ -47,14 +48,42 @@ def __init__(self, midiFilename):
4748
#should be a track header
4849
event = self.eventDecoder.nextEvent()
4950
trackData = TrackData(trackName)
51+
#set up tempoChanges
52+
tempoChanges.reset()
53+
deltaTimeTotal = 0
54+
nextTotal = 0
55+
msTotal = 0 #current time in ms
56+
while (tempoChanges.hasMore() and
57+
tempoChanges.deltaTimeTotal() == 0):
58+
self.msPerBeat = tempoChanges.usPerQuarter()*.001
59+
tempoChanges.findNext()
60+
#add events
5061
while not(event.eventClass == "Meta"
5162
and event.eventType == "EndOfTrack"):
5263
event = self.eventDecoder.nextEvent()
64+
nextTotal = deltaTimeTotal + event.deltaTime
65+
#calcaute absolute start time for event in ms
66+
if self.isTicksPerBeat:
67+
while (tempoChanges.hasMore() and
68+
nextTotal > tempoChanges.deltaTimeTotal()):
69+
msTotal = msTotal + ((tempoChanges.deltaTimeTotal() -
70+
deltaTimeTotal)*self.msPerBeat/self.ticksPerBeat)
71+
deltaTimeTotal = (tempoChanges.deltaTimeTotal() -
72+
deltaTimeTotal) + deltaTimeTotal
73+
tempoChanges.findNext()
74+
self.msPerBeat = tempoChanges.usPerQuarter()*.001
75+
msTotal = (msTotal +
76+
((nextTotal-deltaTimeTotal)*self.msPerBeat/self.ticksPerBeat))
77+
else:
78+
msTotal = (event.deltaTime/self.ticksPerSecond)*.001
79+
#add event to trackData
80+
deltaTimeTotal = nextTotal
81+
event.setStartTime(msTotal)
5382
trackData.addEvent(event)
5483
self.tracks.append(trackData)
5584

5685
#this line just for testing
57-
MidiData("testMidiFile.mid")
86+
MidiData("Magic Battle.mid")
5887

5988

6089

MidiEventDecoder.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ def __init__(self, deltaTime, midiData):
6565
def __str__(self):
6666
return (self.eventClass + " " + str(self.midiData) +
6767
" deltaTime: " + str(self.deltaTime))
68+
def setStartTime(self, startTime): #set start time in ms
69+
self.startTime = startTime
6870

6971
#contains data from the header chunk
7072
class HeaderData:
@@ -117,7 +119,7 @@ def __init__(self, deltaTime, midiData):
117119
self.sequenceNumber = int.from_bytes(midiData[3:], "big")
118120
if self.eventType == "SetTempo":
119121
#micro seconds per quarter note
120-
self.usPerQuarter = int.from_bytes(midiData[4:], "big")
122+
self.usPerQuarter = int.from_bytes(midiData[3:], "big")
121123
def __str__(self):
122124
s = ("Meta " + str(self.midiData) + " deltaTime: "
123125
+ str(self.deltaTime) + " eventType: " + self.eventType)

TrackData.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,25 @@ def addEvent(self, event):
1212
self.name = event.data
1313
return
1414

15-
#this is basiclly and ordered dictionary
15+
#this is kind of like an ordered dictionary
1616
class TempoChanges:
1717
def __init__(self):
18-
self.deltaTimeTotal = []
18+
self.deltaTimeTotals = []
1919
self.tempoChangeEvents = []
2020
self.index = 0
2121
return
2222
#tempo changes need to be added in order
2323
def addTempoChange(self, deltaTimeTotal, event):
24-
self.deltaTimeTotal.append(deltaTimeTotal)
24+
self.deltaTimeTotals.append(deltaTimeTotal)
2525
self.tempoChangeEvents.append(event)
2626
#so that class can be used as a stream
27-
def current(self):
28-
return (self.deltaTimeTotal[self.index],
29-
self.tempoChangeEvets[self.index])
27+
def deltaTimeTotal(self):
28+
return self.deltaTimeTotals[self.index]
29+
def usPerQuarter(self):
30+
return self.tempoChangeEvents[self.index].usPerQuarter
3031
def findNext(self):
3132
self.index = self.index + 1
32-
def hasMoreTempoChanges(self):
33-
return self.index < len(self.tempoChangeEvents)
34-
def reset(self): #go back to first task
33+
def hasMore(self):
34+
return self.index + 1 < len(self.tempoChangeEvents)
35+
def reset(self): #go back to first tempo change
3536
self.index = 0

0 commit comments

Comments
 (0)