11from MidiParser import MidiParser
2+ from MidiEvents import *
23from 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 + "\n Ticks 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