Skip to content

Commit afd694a

Browse files
committed
Created event classes for meta events
1 parent 33847f6 commit afd694a

File tree

8 files changed

+380
-179
lines changed

8 files changed

+380
-179
lines changed

MidiData.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def __init__(self, midiFilename):
4141

4242

4343
#read in each track
44-
tracknum = 0 #used to create temprary track names
44+
tracknum = 0 #used to create temporary track names
4545
while self.eventDecoder.hasMoreEvents():
4646
tracknum = tracknum + 1
4747
trackName = "Track" + str(tracknum)
@@ -82,7 +82,13 @@ def __init__(self, midiFilename):
8282
trackData.addEvent(event)
8383
self.tracks.append(trackData)
8484
#this line just for testing
85-
MidiData("testMidiFile.mid")
86-
87-
85+
''''
86+
midiData = MidiData("testMidiFile.mid")
87+
for x in midiData.trackZeroEvents:
88+
print(x)
89+
for y in midiData.tracks:
90+
print("\n\n----------------------")
91+
for x in y.events:
92+
print(x)
93+
'''
8894

MidiEventDecoder.py

Lines changed: 12 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from MidiParser import MidiParser
2+
from MidiEvents import *
23
from Util import Util
34

45
#decodes data from the MidiParser into data easier to work with in MidiData
@@ -12,11 +13,14 @@ def hasMoreEvents(self):
1213
return self.midiParser.hasMoreData()
1314
#be sure to call this once before calling nextEvent
1415
def headerData(self):
15-
return HeaderData(self.midiParser.readNextData(),
16+
data = HeaderData()
17+
data.setFromBytes(self.midiParser.readNextData(),
1618
self.midiParser.readNextData())
19+
return data
1720
#returns a MidiEvent
1821
def nextEvent(self):
1922
return self.midiEvent(self.midiParser.readNextData())
23+
#creates a MidiEvent from the midiData
2024
def midiEvent(self, midiData):
2125
#check if TrackHeader
2226
if midiData[0:4] == b'MTrk':
@@ -28,179 +32,19 @@ def midiEvent(self, midiData):
2832
temp = temp+1
2933
temp = temp + 1
3034
deltaTime = tempData[:temp]
31-
tempData = tempData[temp:]
32-
if tempData[0:1] == b'\xff':
33-
return MetaEvent(deltaTime, tempData)
35+
midiData = tempData[temp:]
36+
#Meta Event
37+
if midiData[0:1] == b'\xff':
38+
return MetaEvent(Util.varLenVal(deltaTime), midiData)
39+
#System Event
3440
if midiData[0:1] == b'\xf0' or midiData[0:1] == b'\xf7':
35-
return SystemEvemt(deltaTime, tempData)
36-
return ChannelEvent(deltaTime, tempData)
41+
return SystemEvemt(Util.varLenVal(deltaTime), midiData)
42+
return ChannelEvent(Util.varLenVal(deltaTime), midiData)
3743
def close(self):
3844
self.midiParser.close()
3945

40-
#contains all data about and event
41-
#values not used will be set to None
42-
#(it is MidiData's responsibilty to know what data is valid)
43-
class MidiEvent:
44-
#data contained:
45-
#eventType
46-
# chunkID
47-
# (midi): Note off, Note on, Note aftertouch, Controller, Program Change
48-
# Channel Aftertouch, Pitch Bend
49-
# meta
50-
# sysEx
51-
def __init__(self, deltaTime, midiData):
52-
#midi event data
53-
self.midiData = midiData
54-
self.eventClass = "Channel" #Channel, Meta, System, #TrackHeader
55-
self.eventType = None
56-
self.deltaTime = Util.varLenVal(deltaTime)
57-
self.noteNumber = None
58-
self.velocity = None
59-
self.controllerNumber = None
60-
self.programNumber = None
61-
self.aftertouchValue= None
62-
self.pitchValue = None
63-
return
64-
65-
def __str__(self):
66-
return (self.eventClass + " " + str(self.midiData) +
67-
" deltaTime: " + str(self.deltaTime))
68-
def setStartTime(self, startTime): #set start time in ms
69-
self.startTime = startTime
70-
71-
#contains data from the header chunk
72-
class HeaderData:
73-
def __init__(self, headerChunkID, headerData):
74-
self.ticksPerBeat = None
75-
self.framesPerSecond = None
76-
self.ticksPerFrame = None
77-
self.formatType = int.from_bytes(headerData[0:2], "big")
78-
self.numTracks = int.from_bytes(headerData[2:4], "big")
79-
timeDivision = headerData[4:6]
80-
if Util.msbIsOne(headerData): #frames per second
81-
self.framesPerSecond = timeDivision[0] & int('7f', 16)
82-
self.tickesPerFrame = int.from_bytes(timeDivision[1:2], "big")
83-
else: #ticks per beat
84-
self.ticksPerBeat = int.from_bytes(timeDivision, "big")
85-
return
86-
def __str__(self):
87-
s = ("Format type: " + str(self.formatType)
88-
+ " Number of tracks: " + str(self.numTracks))
89-
if self.ticksPerBeat != None:
90-
s = s + "\nTicks per Beat: " + str(self.ticksPerBeat)
91-
return s
92-
93-
class TrackHeader(MidiEvent):
94-
def __init__(self, midiData):
95-
self.midiData = midiData
96-
self.eventClass = "TrackHeader"
97-
def __str__(self):
98-
return "Track Header " + str(self.midiData)
99-
100-
class MetaEvent(MidiEvent):
101-
def __init__(self, deltaTime, midiData):
102-
self.eventClass = "Meta"
103-
self.midiData = midiData
104-
self.deltaTime = Util.varLenVal(deltaTime)
105-
self.startTime = None
106-
self.eventType = None
107-
self.dataLength = midiData[2:3]
108-
i = 2
109-
while Util.msbIsOne(midiData[i:i+1]):
110-
self.dataLength = self.dataLength + midiData[i+1:i+2]
111-
i = i+1
112-
i = i+1
113-
self.data = midiData[i:]
114-
#coverts bytes to a string
115-
self.data = str(self.data)[2:len(str(self.data))-1]
116-
if midiData[1] in Util.MetaEventDict:
117-
self.eventType = Util.MetaEventDict[midiData[1]]
118-
if self.eventType == "SequenceNumber":
119-
self.sequenceNumber = int.from_bytes(midiData[3:], "big")
120-
if self.eventType == "SetTempo":
121-
#micro seconds per quarter note
122-
self.usPerQuarter = int.from_bytes(midiData[3:], "big")
123-
def __str__(self):
124-
s = ("Meta " + str(self.midiData) + " deltaTime: "
125-
+ str(self.deltaTime) + " eventType: " + self.eventType)
126-
if self.eventType == "SetTempo":
127-
s = s + "\n\t usPerQuarter: " + str(self.usPerQuarter)
128-
return s
129-
130-
class SystemEvent(MidiEvent):
131-
def __init__(self, deltaTime, midiData):
132-
self.eventClass = "System"
133-
self.midiData = midiData
134-
self.deltaTime = Util.varLenVal(deltaTime)
135-
self.startTime = None
136-
def __str__(self):
137-
return ("System " + str(self.midiData) + " deltaTime: "
138-
+ str(self.deltaTime))
13946

140-
class ChannelEvent(MidiEvent):
141-
def __init__(self, deltaTime, midiData):
142-
self.midiData = midiData
143-
self.eventClass = "Channel"
144-
self.deltaTime = Util.varLenVal(deltaTime)
145-
self.startTime = None
146-
self.eventType = None
147-
self.noteNumber = None
148-
self.velocity = None
149-
self.aftertouchValue = None
150-
self.controllerNumber = None
151-
self.controllerValue = None
152-
self.programNumber = None #use for ProgramChange
153-
self.pitchValue = None #used for PitchBend
154-
#read eventType and channel
155-
if Util.msbIsOne(midiData):
156-
self.runningStatus = False
157-
if midiData[0] & int('f0',16) in Util.ChannelEventDict:
158-
self.eventType = Util.ChannelEventDict[midiData[0] & int('f0',16)]
159-
self.channel = midiData[0] & int('0f',16)
160-
ChannelEvent.prevEventData = (self.eventType, self.channel)
161-
else:
162-
self.eventType, self.channel = ChannelEvent.prevEventData
163-
self.runningStatus = True
164-
#set applicable values
165-
if self.runningStatus:
166-
#so that the indicies of the data are correct
167-
midiData = b'\x00' + midiData
168-
if (self.eventType == "NoteOff" or self.eventType == "NoteOn"):
169-
self.noteNumber = midiData[1]
170-
self.velocity = midiData[2]
171-
if self.eventType == "NoteAfterTouch":
172-
self.noteNumber = midiData[1]
173-
self.aftertouchValue = midiData[2]
174-
if self.eventType == "Controller":
175-
self.controllerNumber = midiData[1]
176-
self.controllerValue = midiData[2]
177-
if self.eventType == "ProgramChange":
178-
self.programNumber = midiData[1]
179-
if self.eventType == "ChannelAftertouch":
180-
self.aftertouchValue = midiData[1]
181-
if self.eventType == "PitchBend":
182-
#NOTE: this relies on Util.varLenVal not actually caring if
183-
#the format is an actual valid varaible length value
184-
#(and thus completly ignoring the msb of every byte)
185-
self.pitchValue = Util.varLenVal(midiData[2:3] + midiData[1:2])
186-
187-
def __str__(self):
188-
if self.eventType == "Controller":
189-
return ("Channel " + str(self.midiData) + " deltaTime: "
190-
+ str(self.deltaTime) + " (Controller)")
191-
return ("Channel " + str(self.midiData) + " deltaTime: "
192-
+ str(self.deltaTime) + " eventType: " + self.eventType +
193-
" channel: " + str(self.channel) + "\n\t" +
194-
"runningStatus: " + str(self.runningStatus) +
195-
" noteNumber: " + str(self.noteNumber) +
196-
" velocity: " + str(self.velocity) + "\n\t" +
197-
"aftertouchValue: " + str(self.aftertouchValue) +
198-
" controllerNumber: " + str(self.controllerNumber) +
199-
" controllerValue: " + str(self.controllerValue) + "\n\t" +
200-
"programNumber: " + str(self.programNumber))
20147

202-
#used for running status
203-
prevEventData = ()
20448

20549

20650

0 commit comments

Comments
 (0)