Example #1
0
			def read_midi_channel_prefix():
				if data[fp:fp+2] != '01':
					raise error.MidiException("Invalid MIDI Channel Prefix meta event found at position ", fp, "(expected '11' but got ", data[fp:fp+2],")")
				elif int(data[fp+2:fp+4], 16) > 15:
					raise error.MidiException("Invalid MIDI Channel Prefix meta event found at position ", fp+2, "(expected 00-0f but got ", data[fp+2:fp+4],")")
				else:
					set_channel(int(data[fp+2:fp+4], 16) + 1)
Example #2
0
			def read_midi_port():
				if data[fp:fp+2] != '01':
					raise error.MidiException("Invalid MIDI Port meta event found at position", fp, "(expected '01' but got", data[fp:fp+2],")")
				else:
					port = int(data[fp+2:fp+4], 16) + 1
					advance(4)
					return port
Example #3
0
			def read_tempo():
				if data[fp:fp+2] != "03":
					raise error.MidiException("Unrecognized Set Tempo meta event at position ", fp, "found ", data[fp:fp+2], "but expected 0x03")
				else:
					mpq = int(data[fp+2:fp+8], 16)

				print_if_verbose( "Tempo set to ", mpq, "microseconds per quarter note ", "( ", 60000000/mpq, " beats per minute)")
				advance(8)
Example #4
0
			def read_time_signature():
				if data[fp:fp+2] != "04":
					raise error.MidiException("Unrecognized Time Signature meta event at position", fp, "found", data[fp+4:fp+6], "but expected 0x04")
				else:
					numerator = int(data[fp+2:fp+4], 16)
					denominator = 2 ** int(data[fp+4:fp+6], 16)
					cpmt = int(data[fp+6:fp+8], 16)
					nonp = int(data[fp+8:fp+10], 16)
				print "Time signature:", numerator, "/", denominator
				advance(10)
Example #5
0
			def read_note_off(x):

				global channel
				#check/set key/velocity
				warnings.warn("Note off event not fully implemented")
				if int(data[fp:fp+2], 16) > 127:
					raise error.MidiException("Invalid note key at position", fp, ". Expected 0x00-0x7f, but got", b2)
				key = int(data[fp+1:fp+3], 16)
				if int(data[fp+2:fp+4], 16) > 127:
					raise error.MidiException("Invalid note velocity at position", fp, ". Expected 0x00-0x7f, but got", b3)
				velocity = int(data[fp+2:fp+4], 16)
				#set channel
				if x == None:
					set_channel(int(data[fp], 16))
					print_bytes(data[fp-2:fp+4], "Note off c nn vv")
				else:
					print_bytes(data[fp:fp+4], "nn vv")
				#print "Channel:", channel
				#find note and 
					#if in list: create note object
					#else raise error: note ended that was not started
				#print "Pop Note Command at fp:", fp
				advance(4)#pop note event is 3 bytes long
Example #6
0
			def read_key_signature():
				if data[fp:fp+2] != "02":
					raise error.MidiException("Unrecognized Key Signature meta event at position", fp, "found", data[fp+4:fp+6], "but expected 0x02")
				else:
					numsharps = int(data[fp+2:fp+4], 16)
					mode = data[fp+4:fp+6]
					majorkeys = {	249 : "C flat major",
									250 : "G flat major",
									251 : "D flat major",
									252 : "A flat major",
									253 : "E flat major",
									254 : "B flat major",
									255 : "F major",
									0  : "C major",
									1  : "G major",
									2  : "D major",
									3  : "A major",
									4  : "E major",
									5  : "B major",
									6  : "F sharp major",
									7  : "C sharp major"}
					minorkeys = {	5  : "C flat minor",
									6  : "G flat minor",
									7  : "D flat minor",
									249 : "A flat minor",
									250 : "E flat minor",
									251 : "B flat minor",
									252 : "F minor",
									253 : "C minor",
									254 : "G minor",
									255 : "D minor",
									0  : "A minor",
									1  : "E minor",
									2  : "B minor",
									3  : "F sharp minor",
									4  : "C sharp minor"}
					if mode == "00":
						print "Key signature:", majorkeys[numsharps]
					else:
						print "Key signature:", minorkeys[numsharps]
				advance(6)
Example #7
0
			def read_note_off(x):
				print_if_verbose("Note off event")
				global channel
				#check/set key/velocity
				key = int(data[fp:fp+2], 16)
				velocity = int(data[fp+2:fp+4], 16)
				print_if_verbose("\tTurning off ", key)
				#set channel
				if x == None:
					set_channel(int(data[fp-1], 16) + 1)
					print_if_verbose("Event header:")
					print_bytes(data[fp-2:fp+4], "Note off c nn vv")
				else:
					print_if_verbose("Event header:")
					print_bytes(data[fp:fp+4], "nn vv")
				print_if_verbose( "\tChannel: ", channel)
				#if in list: create note object
				found = False
				print_if_verbose("\tNotes that are on: ", list_of_notes)
				for nt in list_of_notes: 
					#create note object
					print_if_verbose(nt[0], "=? ", key, " ", nt[1], "=? ", channel)
					if nt[0] == key and nt[1] == channel and not found:
						duration = total_delta_time - nt[2]
						start = start_ticks
						note = song.add_note(start_ticks, duration, key, channel)
						print_if_verbose( "Note created: ", note.to_string(ticks_per_quarter_note))
						notes[channel].append(note)
						found = True
						list_of_notes.remove(nt) #remove from list_of_notes
						print_if_verbose("\tNotes that are on: ", list_of_notes)
					print_if_verbose("found: ", found)
				if not found:
					raise error.MidiException("Invalid note off event at position ", fp, ". No such note of pitch ", key, "is currently on")
				print_if_verbose( "Add/Pop Note Command at fp: ", fp)
				advance(4)#add note event is 3 bytes long
				print_if_verbose("\tNotes that are on: ", list_of_notes)
Example #8
0
			def read_marker():
				raise error.MidiException("Marker meta event found at position ", fp, "(Marker meta events not yet handled in program)")
Example #9
0
			def read_lyric():
				raise error.MidiException("Lyric meta event found at position ", fp, "(Lyric meta events not yet handled in program)")
Example #10
0
			def read_sequence_track_name():
				raise error.MidiException("Sequence/Track Name meta event found at position ", fp, "(Sequence/Track Name meta events not yet handled in program)")
Example #11
0
			def read_copyright_notice():
				raise error.MidiException("Copyright notice meta event found at position ", fp, "(Copyright notice meta events not yet handled in program)")
Example #12
0
			def read_time_signature():
				if data[fp:fp+2] != "04":
					raise error.MidiException("Unrecognized Time Signature meta event at position ", fp, "found ", data[fp+4:fp+6], "but expected 0x04")
Example #13
0
		for c in data:
			string += c
			if i % 2 == 1:
				string += " "
			i += 1
<<<<<<< HEAD
		#print string, "= ", explanation, value
=======
		print_if_verbose( string, "= ", explanation, value )
>>>>>>> develop

	#read header chunk:

	#check header chunk type
	if re.match(r'4d546864', data) == None:
		raise error.MidiException("File does not begin with \"MThd\"")
	fp = 8
	#check header length
	if re.match(r'00000006', data[fp:fp+8]) == None:
<<<<<<< HEAD
		raise error.MidiException("Unrecognized header length: expected \"00000006\", but got:", data[fp:fp+8])
=======
		raise error.MidiException("Unrecognized header length: expected \"00000006\", but got: ", data[fp:fp+8])
>>>>>>> develop
	fp += 8
	#check format
	midi_format = int(data[fp:fp+4], 16)
	if midi_format > 2:
<<<<<<< HEAD
		raise error.MidiException("Unrecognized format: expected 0,1, or 2, but got:", int(data[fp:fp+4], 16))
=======
Example #14
0
			def determine_event(x):
				#print "x:", x
				if x == None:
					print "fp:", fp
				global new_event_type, n1, n2, b2, b3
				if x == None:
					new_event_type = True
				#print "new_event_type:", new_event_type
				'''HANDLE MIDI EVENTS'''
				if n1 == '8':
					#pop note command
					if x == None:
						advance(2)
					read_note_off(x)
				elif n1 == '9':
					#add/pop note command
					if x == None:
						advance(2)
					read_note_on(x)
				elif n1 == 'a':
					#polyphonic note
					if x == None:
						advance(2)
					read_polyphonic()
				elif n1 == 'b':

					#MIDI Channel Mode Messages
					if b2 == '78':
						print_bytes(data[fp:fp+6], "All Sound Off")
						advance(6)
					elif b2 == '79':
						print_bytes(data[fp:fp+6], "Reset All Controllers")
						advance(6)
					elif b2 == '7a':
						print_bytes(data[fp:fp+6], "Local Control")
						advance(6)
					elif b2 == '7b':
						print_bytes(data[fp:fp+6], "All Notes Off")
						advance(6)
					elif b2 == '7c':
						print_bytes(data[fp:fp+6], "Omni Mode Off")
						advance(6)
					elif b2 == '7d':
						print_bytes(data[fp:fp+6], "Omni Mode On")
						advance(6)
					elif b2 == '7e':
						print_bytes(data[fp:fp+6], "Mono Mode On")
						advance(6)
					elif b2 == '7f':
						print_bytes(data[fp:fp+6], "Poly Mode On")
						advance(6)
					else:
						#control change
						if x == None:
							advance(2)
						read_control_change()
				elif n1 == 'c':
					#program change
					if x == None:
						advance(2)
					read_program_change()
				elif n1 == 'd':
					#channel key pressure
					if x == None:
						advance(2)
					read_channel_key_pressure()
				elif n1 == 'e':
					#pitch bend
					if x == None:
						advance(2)
					read_pitch_bend()
				elif n1 == 'f':

					'''HANDLE SYSEX EVENTS'''
					if n2 == 0:
						if x == None:
							advance(2)
						read_sysex()
					elif n2 == 7:
						if x == None:
							advance(2)
						read_sysex()
					elif n2 == 'f':
						'''HANDLE META EVENTS'''
						if b2 == '00':
							if x == None:
								advance(4)
							read_sequence_number()
						elif b2 == '01':
							if x == None:
								advance(4)
							read_text()
						elif b2 == '02':
							#Copyright notice
							if x == None:
								advance(4)
							read_copyright_notice()
						elif b2 == '03':
							#Sequence/Track Name
							if x == None:
								advance(4)
							read_sequence_track_name()
						elif b2 == '04':
							#Instrument Name
							if x == None:
								advance(4)
							read_instrument_name()
						elif b2 == '05':
							#Lyric
							if x == None:
								advance(4)
							read_lyric()
						elif b2 == '06':
							#Marker
							if x == None:
								advance(4)
							read_marker()
						elif b2 == '07':
							#Cue Point
							if x == None:
								advance(4)
							read_cue()
						elif b2 == '08':
							#Program Name
							if x == None:
								advance(4)
							name_hex = read_program_name()
							program_name = name_hex.decode("hex")
							print "Program Name:", program_name
							#print "fp is now:", fp
						elif b2 == '0a':
							#Composer Name
							#THIS IS NOT ON THE INTERNET FOR SOME REASON BUT IT'S A FREAKING THING AND I HAD TO FIGURE IT OUT FOR MYSELF
							if x == None:
								advance(4)
							program_name = read_program_name().decode("hex")
							print "Composer Name:", program_name
							#print "fp is now:", fp
						elif b2 == '20':
							#MIDI Channel Prefix
							if x == None:
								advance(4)
							channel = read_midi_channel_prefix()
							print "MIDI channel set to", channel
						elif b2 == '21':
							#MIDI Port
							if x == None:
								advance(4)
							port = read_midi_port()
							print "MIDI port set to port", port
						elif b2 == '2f':
							#End of Track
							if x == None:
								advance(4)
							read_end_of_track()
						elif b2 == '51':
							#Set Tempo
							if x == None:
								advance(4)
							read_tempo()
						elif b2 == '54':
							#SMTPE Offset
							if x == None:
								advance(4)
							read_SMTPE_offset()
						elif b2 == '58':
							#Time Signature
							if x == None:
								advance(4)
							read_time_signature()
						elif b2 == '59':
							#Key Signature
							if x == None:
								advance(4)
							read_key_signature()
						elif b2 == '7f':
							#Sequencer-Specific
							if x == None:
								advance(4)
							read_sequence_specific()
						else:
							if x != None:
								raise error.MidiException("Unrecognized Meta event at position", fp, ". Expected 00-08, 20, 2f, 51, 54, 58, 59, or 7f, but got", b2)
							n1 = last_event_type[:1]
							n2 = last_event_type[1:2]
							b2 = last_event_type[2:4]
							'''print "n1:", n1
							print "n2:", n2
							print "b2:", b2'''
							#print "Using last header (", last_event_type, ") because none identified at", fp
							new_event_type = False
							determine_event(last_event_type)
					else:
						if x != None:
							raise error.MidiException("Unrecognized event at position", fp, ". Expected 0x80-0xff, but got", data[fp:fp+2])
						n1 = last_event_type[:1]
						n2 = last_event_type[1:2]
						b2 = last_event_type[2:4]
						'''print "n1:", n1
						print "n2:", n2
						print "b2:", b2'''
						#print "Using last header (", last_event_type, ") because none identified at", fp
						new_event_type = False
						determine_event(last_event_type)
				else:
					if x != None:
						raise error.MidiException("Unrecognized event at position", fp, ". Expected 0x80-0xff, but got", data[fp:fp+2])
					n1 = last_event_type[:1]
					n2 = last_event_type[1:2]
					b2 = last_event_type[2:4]
					'''print "n1:", n1
					print "n2:", n2
					print "b2:", b2'''
					#print "Using last header (", last_event_type, ") because none identified at", fp
					new_event_type = False
					determine_event(last_event_type)
Example #15
0
			def read_end_of_track():
				if data[fp:fp+2] == '00':
					print "********************YAAAAAAY********************"
					advance(2)
				else:
					raise error.MidiException("Unrecognized End of Track meta event found at position", fp, "found", data[fp:fp+2], "but expected 0x00")
Example #16
0
			def read_cue():
				raise error.MidiException("Cue meta event found at position ", fp, "(Cue meta events not yet handled in program)")
Example #17
0
			def read_text():
				raise error.MidiException("Text meta event found at position", fp, "(Text meta events not yet handled in program)")
Example #18
0
			def read_sysex():
				raise error.MidiException("Sysex event found at position ", fp, "(sysex events not yet handled in program)")
Example #19
0
			def read_SMTPE_offset():
				raise error.MidiException("SMTPE Offset meta event found at position ", fp, "(SMTPE Offset meta events not yet handled in program)")
Example #20
0
			def read_sequence_number():
				raise error.MidiException("Sequence Number meta event found at position ", fp, "(Sequence Number meta events not yet handled in program)")
Example #21
0
			def read_sequence_specific():
				raise error.MidiException("Sequencer-Specific meta event found at position", fp, "(Sequencer-Specific meta events not yet handled in program)")
Example #22
0
def main(file_name):
	global fp,remaining_track_len, channel, n1, n2, b2, b3
	f = open(file_name, "rb")
	data = "" #string containing the data of the file in hex
	try:
		byte = f.read(1)
		while byte != "":
			data += byte
			byte = f.read(1)
	finally:
		f.close()

	data = binascii.hexlify(data) #translate binary to hex
	n1 = ""
	n2 = ""
	b2 = ""
	b3 = ""
	channel = 0
	notes = {} #a dictionary of 16 lists of Notes cooresponding to their channel number
	for i in range(0,16):
		key = i
		notes[key] = list()

	fp = 0 #file_position
	remaining_track_len = 0 #to check that the track length specified is correct

	def advance(nibbles): 
		'''updates fp and remaining_track_len
		'nibbles' is an integer representing the # of hex digits to advance
		Procedure (no return value)'''
		global fp, remaining_track_len
		fp += nibbles
		remaining_track_len -= nibbles

	def print_bytes(data, explanation = "", value = "", offset = 0):
		'''pretty-prints a small chunk of byte(s) and an explanation of what they mean in the MIDI file
		'data' is a string of hex values representing the bytes to be explained
		'explanation' is an optional string describing what the data means
		'value' is an optional string for a variable value related to the meaning of the data
		'offset' is a switch:
			odd values mean the data starts halfway through a byte
			even values means the data starts at the beginning of a byte
			there is no need to set this value to anything besides 0 or 1
		Procedure (no return value)
		'''
		i = offset
		string = ""
		for c in data:
			string += c
			if i % 2 == 1:
				string += " "
			i += 1
		print string, "= ", explanation, value

	#read header chunk:

	#check header chunk type
	if re.match(r'4d546864', data) == None:
		raise error.MidiException("File does not begin with \"MThd\"")
	else:
		print_bytes("4d546864", "\"MThd\"")
	fp = 8
	#check header length
	if re.match(r'00000006', data[fp:fp+8]) == None:
		raise error.MidiException("Unrecognized header length: expected \"00000006\", but got:", data[fp:fp+8])
	else:
		print_bytes("00000006", "Header length: 6 bytes")
	fp += 8
	#check format
	midi_format = int(data[fp:fp+4], 16)
	if midi_format > 2:
		raise error.MidiException("Unrecognized format: expected 0,1, or 2, but got:", int(data[fp:fp+4], 16))
	else:
		print_bytes(data[fp:fp+4], "Midi format:", midi_format)
	fp += 4
	#get number of tracks
	num_tracks = int(data[fp:fp+4], 16)
	fp += 4
	print_bytes(data[fp:fp+4], "Number of tracks:", num_tracks)
	#get division data 
	division = data[fp:fp+4]
	print_bytes(data[fp:fp+4], "Division:", division)
	frmt = division[0:1]
	print_bytes(division[0:1], "Format:", frmt)
	ticks_per_quarter_note = int(division[1:], 16)
	if int(frmt, 16) < 8:
		print_bytes(division[1:], "Ticks per quarter note:", ticks_per_quarter_note, 1)
	else:
		print "Negative two's compliment of", int(division[1:2], 16) - 128, "frames / second"
		print int(data[fp:fp+2],16), "ticks / frame"
	fp += 4
		
	print "READ HEADER CHUNK OF SIZE", fp, "RESTARTING fp at position", fp
	#read track chunks
	for i in range(0, num_tracks):
		'''READS EACH TRACK CHUNK'''

		total_delta_time = 0
		data = data[fp:]
		#check track chunk type
		print_bytes(data[0:8], "\"MTrk\"")
		if re.match(r'4d54726b', data) == None:
			raise error.MidiException("Track does not begin with \"MTrk\"", "at position", fp)
		fp = 8
		#get track length
		track_len = int(data[fp:fp+8], 16)
		print_bytes(data[fp:fp+8], "Track length:", track_len)
		track_len *= 2 #measure in nibbles, not bytes
		remaining_track_len = track_len
		fp += 8
		list_of_notes = []

		'''READS EACH DELTA_TIME - EVENT PAIR IN THE TRACK'''

		last_event_type = None
		no_event_head = False
		data = data[fp:]
		fp = 0
		print "RESET TRACK", i+1, "fp TO 0 AT BEGINNING OF TRACK DATA"
		def print_data(data):
			'''pretty-prints the data bytes for all events in a track chunk
			'data' is a string of hex values representing the data of the track chunk
			'''
			data_string = ""
			index_string = ""
			x = 0
			l = 100
			for i in range(0, len(data)):
				data_string += data[i]
				if (i+1) % l == 0 or i == len(data)-1:
					print data_string
					if i < 1000:
						for j in range(0,(l+3)/4):
							space = len(str(x+j*4))
							index_string += str(x+j*4)
							for z in range(0, 4-space):
								index_string += " "
					else:
						for j in range(0,(l+7)/8):
							space = len(str(x+j*8))
							index_string += str(x+j*8)
							for z in range(0, 8-space):
								index_string += " "
					print index_string
					index_string = ""
					x += l
					data_string = ""
		print_data(data)
		global new_event_type
		new_event_type = False
		while remaining_track_len > 0:
			'''READS EACH EVENT'''
			print "-------------------"
			#print "len(data):", len(data)
			if len(data) - fp <= 6:
				if data[-6:] != 'ff2f00':
					raise error.MidiException("Track does not end with end_of_track meta event")
				else:
					break

			if remaining_track_len < 0:
				raise error.MidiException("Track length does not match up with length of track data")
			j = 0
			binary_value = ""
			while int(data[fp + j:fp + j + 2], 16) >= 128:
				binary_string = bin(int(data[fp + j: fp + j + 2], 16))[2:].zfill(8)
				#print binary_string
				binary_value += binary_string[1:8]
				j += 2
			binary_string = bin(int(data[fp + j: fp + j + 2], 16))[2:].zfill(8)
			#print binary_string
			binary_value += binary_string[1:8]
			delta_time = int(binary_value, 2)
			print_bytes(data[fp:fp+j+2], "Delta time:", delta_time)
			total_delta_time += delta_time
			#print "remaining_track_len:", remaining_track_len
			#TODO adjust time position
			advance(j+2)
			#print "fp after delta_time:", fp
			#if int(first_byte, 16) < 128:
				#raise error.MidiException("Unrecognized event at position", fp, ". Expected 0x80-0xFF, but got", data[fp:fp+2])
			n1 = data[fp] #first nibble of this event's data
			n2 = data[fp+1] #second nibble of this event's data
			b2 = data[fp+2:fp+4] #second byte of this event's data
			b3 = data[fp+4:fp+6] #third byte of this event's data
			#print "This event type:", n1, n2, b2, b3
			temp_fp = fp

			def read_variable_length():
				i = 0
				binary_value = ""
				while int(data[fp + i:fp + i + 2], 16) >= 128:
					binary_string = bin(int(data[fp + i: fp + i + 2], 16))[2:].zfill(8)
					print binary_string
					binary_value += binary_string[1:8]
					i += 2
				binary_string = bin(int(data[fp + i: fp + i + 2], 16))[2:].zfill(8)
				binary_value += binary_string[1:8]
				length = int(binary_value, 2)
				advance(i+2)
				print "Variable length:", length
				return length

			def read_note_off(x):

				global channel
				#check/set key/velocity
				warnings.warn("Note off event not fully implemented")
				if int(data[fp:fp+2], 16) > 127:
					raise error.MidiException("Invalid note key at position", fp, ". Expected 0x00-0x7f, but got", b2)
				key = int(data[fp+1:fp+3], 16)
				if int(data[fp+2:fp+4], 16) > 127:
					raise error.MidiException("Invalid note velocity at position", fp, ". Expected 0x00-0x7f, but got", b3)
				velocity = int(data[fp+2:fp+4], 16)
				#set channel
				if x == None:
					channel = int(data[fp], 16)
					print_bytes(data[fp-2:fp+4], "Note off c nn vv")
				else:
					print_bytes(data[fp:fp+4], "nn vv")
				print "Channel:", channel
				#find note and 
					#if in list: create note object
					#else raise error: note ended that was not started
				print "Pop Note Command at fp:", fp
				advance(4)#pop note event is 3 bytes long

			def read_note_on(x):

				global channel
				#check/set key/velocity
				key = int(data[fp:fp+2], 16)
				velocity = int(data[fp+2:fp+4], 16)
				#set channel
				if x == None:
					channel = int(data[fp-1], 16) + 1
					print_bytes(data[fp-2:fp+4], "Note off c nn vv")
				else:
					print_bytes(data[fp:fp+4], "nn vv")
				print "Channel:", channel
				note_tuple = (key, channel, total_delta_time)
				if velocity == 0:
					#if in list: create note object
					for nt in list_of_notes: 
						#create note object
						found = False
						if nt[0] == key and nt[1] == channel:
							duration = total_delta_time - nt[2]
							note = Note.Note(total_delta_time, duration, key, channel)
							print "Note created:", note.to_string(ticks_per_quarter_note)
							notes[channel].append(note)
							found = True
							list_of_notes.remove(nt) #remove from list_of_notes
					if not found:
						print "Note created with velocity of 0 at position"
				else:
					#add note to list
					list_of_notes.append(note_tuple)
				print "Add/Pop Note Command at fp:", fp
				advance(4)#add note event is 3 bytes long

			def read_polyphonic():

				#check/set key/velocity
				#set channel
				#send message
				print "Polyphonic Note at fp:", fp
				advance(4)#polyphonic note event is 3 bytes long

			def read_control_change():

				#check control#, control_val
				#send message
				print "Control Change at fp:", fp
				print_bytes(data[fp:fp+4], "Control change")
				advance(4)#control change event is 3 bytes long

			def read_program_change():

				#check new_program_#
				#send message
				print "Program Change at fp:", fp
				print_bytes(data[fp-2:fp+2], "Program change to", int(data[fp:fp+2], 16))
				advance(2)#program change event is 2 bytes long

			def read_channel_key_pressure():

				#check channel_pressure_val
				#send message
				print "Channel Key Pressure of", data[fp:fp+2], "at fp:", fp
				advance(2)#channel key pressure event is 2 bytes long

			def read_pitch_bend():

				#check msb, lsb
				#send message
				print "Pitch Bend at fp:", fp
				advance(4)#pitch bend event is 3 bytes long



			def read_sysex():
				raise error.MidiException("Sysex event found at position", fp, "(sysex events not yet handled in program)")



			def read_sequence_number():
				warnings.warn("Sequence Number meta event found at position", fp, "(Sequence Number meta events not yet handled in program)")

			def read_text():
				raise error.MidiException("Text meta event found at position", fp, "(Text meta events not yet handled in program)")

			def read_copyright_notice():
				warnings.warn("Copyright notice meta event found at position", fp, "(Copyright notice meta events not yet handled in program)")

			def read_sequence_track_name():
				warnings.warn("Sequence/Track Name meta event found at position", fp, "(Sequence/Track Name meta events not yet handled in program)")

			def read_instrument_name():
				warnings.warn("Instrument Name meta event found at position", fp, "(Instrument Name meta events not yet handled in program)")

			def read_lyric():
				raise error.MidiException("Lyric meta event found at position", fp, "(Lyric meta events not yet handled in program)")

			def read_marker():
				raise error.MidiException("Marker meta event found at position", fp, "(Marker meta events not yet handled in program)")

			def read_cue():
				raise error.MidiException("Cue meta event found at position", fp, "(Cue meta events not yet handled in program)")

			def read_program_name():
				print "Program name meta event read at position", fp
				length = 2 * (int(data[fp:fp+2], 16))
				program_name = data[fp:fp+length]
				advance(length+2)
				return program_name
				#raise error.MidiException("Program Name meta event found at position", fp, "(Program Name meta events not yet handled in program)")

			def read_midi_channel_prefix():
				if data[fp:fp+2] != '11':
					raise error.MidiException("Invalid MIDI Channel Prefix meta event found at position", fp, "(expected '11' but got", data[fp:fp+2],")")
				elif int(data[fp+2:fp+4], 16) > 15:
					raise error.MidiException("Invalid MIDI Channel Prefix meta event found at position", fp+2, "(expected 00-0f but got", data[fp+2:fp+4],")")
				else:
					channel = data[fp+2:fp+4] + 1
					advance(4)
					return channel

			def read_midi_port():
				if data[fp:fp+2] != '01':
					raise error.MidiException("Invalid MIDI Port meta event found at position", fp, "(expected '01' but got", data[fp:fp+2],")")
				else:
					port = int(data[fp+2:fp+4], 16) + 1
					advance(4)
					return port

			def read_end_of_track():
				if data[fp:fp+2] == '00':
					print "********************YAAAAAAY********************"
					advance(2)
				else:
					raise error.MidiException("Unrecognized End of Track meta event found at position", fp, "found", data[fp:fp+2], "but expected 0x00")

			def read_tempo():
				if data[fp:fp+2] != "03":
					raise error.MidiException("Unrecognized Set Tempo meta event at position", fp, "found", data[fp:fp+2], "but expected 0x03")
				else:
					mpq = int(data[fp+2:fp+8], 16)

				print "Tempo set to", mpq, "microseconds per quarter note", "(", 60000000/mpq, " beats per minute)"
				advance(8)

			def read_SMTPE_offset():
				raise error.MidiException("SMTPE Offset meta event found at position", fp, "(SMTPE Offset meta events not yet handled in program)")

			def read_time_signature():
				if data[fp:fp+2] != "04":
					raise error.MidiException("Unrecognized Time Signature meta event at position", fp, "found", data[fp+4:fp+6], "but expected 0x04")
				else:
					numerator = int(data[fp+2:fp+4], 16)
					denominator = 2 ** int(data[fp+4:fp+6], 16)
					cpmt = int(data[fp+6:fp+8], 16)
					nonp = int(data[fp+8:fp+10], 16)
				print "Time signature:", numerator, "/", denominator
				advance(10)

			def read_key_signature():
				if data[fp:fp+2] != "02":
					raise error.MidiException("Unrecognized Key Signature meta event at position", fp, "found", data[fp+4:fp+6], "but expected 0x02")
				else:
					numsharps = int(data[fp+2:fp+4], 16)
					mode = data[fp+4:fp+6]
					majorkeys = {	249 : "C flat major",
									250 : "G flat major",
									251 : "D flat major",
									252 : "A flat major",
									253 : "E flat major",
									254 : "B flat major",
									255 : "F major",
									0  : "C major",
									1  : "G major",
									2  : "D major",
									3  : "A major",
									4  : "E major",
									5  : "B major",
									6  : "F sharp major",
									7  : "C sharp major"}
					minorkeys = {	5  : "C flat minor",
									6  : "G flat minor",
									7  : "D flat minor",
									249 : "A flat minor",
									250 : "E flat minor",
									251 : "B flat minor",
									252 : "F minor",
									253 : "C minor",
									254 : "G minor",
									255 : "D minor",
									0  : "A minor",
									1  : "E minor",
									2  : "B minor",
									3  : "F sharp minor",
									4  : "C sharp minor"}
					if mode == "00":
						print "Key signature:", majorkeys[numsharps]
					else:
						print "Key signature:", minorkeys[numsharps]
				advance(6)

			def read_sequence_specific():
				raise error.MidiException("Sequencer-Specific meta event found at position", fp, "(Sequencer-Specific meta events not yet handled in program)")

			def determine_event(x):
				#print "x:", x
				if x == None:
					print "fp:", fp
				global new_event_type, n1, n2, b2, b3
				if x == None:
					new_event_type = True
				#print "new_event_type:", new_event_type
				'''HANDLE MIDI EVENTS'''
				if n1 == '8':
					#pop note command
					if x == None:
						advance(2)
					read_note_off(x)
				elif n1 == '9':
					#add/pop note command
					if x == None:
						advance(2)
					read_note_on(x)
				elif n1 == 'a':
					#polyphonic note
					if x == None:
						advance(2)
					read_polyphonic()
				elif n1 == 'b':

					#MIDI Channel Mode Messages
					if b2 == '78':
						print_bytes(data[fp:fp+6], "All Sound Off")
						advance(6)
					elif b2 == '79':
						print_bytes(data[fp:fp+6], "Reset All Controllers")
						advance(6)
					elif b2 == '7a':
						print_bytes(data[fp:fp+6], "Local Control")
						advance(6)
					elif b2 == '7b':
						print_bytes(data[fp:fp+6], "All Notes Off")
						advance(6)
					elif b2 == '7c':
						print_bytes(data[fp:fp+6], "Omni Mode Off")
						advance(6)
					elif b2 == '7d':
						print_bytes(data[fp:fp+6], "Omni Mode On")
						advance(6)
					elif b2 == '7e':
						print_bytes(data[fp:fp+6], "Mono Mode On")
						advance(6)
					elif b2 == '7f':
						print_bytes(data[fp:fp+6], "Poly Mode On")
						advance(6)
					else:
						#control change
						if x == None:
							advance(2)
						read_control_change()
				elif n1 == 'c':
					#program change
					if x == None:
						advance(2)
					read_program_change()
				elif n1 == 'd':
					#channel key pressure
					if x == None:
						advance(2)
					read_channel_key_pressure()
				elif n1 == 'e':
					#pitch bend
					if x == None:
						advance(2)
					read_pitch_bend()
				elif n1 == 'f':

					'''HANDLE SYSEX EVENTS'''
					if n2 == 0:
						if x == None:
							advance(2)
						read_sysex()
					elif n2 == 7:
						if x == None:
							advance(2)
						read_sysex()
					elif n2 == 'f':
						'''HANDLE META EVENTS'''
						if b2 == '00':
							if x == None:
								advance(4)
							read_sequence_number()
						elif b2 == '01':
							if x == None:
								advance(4)
							read_text()
						elif b2 == '02':
							#Copyright notice
							if x == None:
								advance(4)
							read_copyright_notice()
						elif b2 == '03':
							#Sequence/Track Name
							if x == None:
								advance(4)
							read_sequence_track_name()
						elif b2 == '04':
							#Instrument Name
							if x == None:
								advance(4)
							read_instrument_name()
						elif b2 == '05':
							#Lyric
							if x == None:
								advance(4)
							read_lyric()
						elif b2 == '06':
							#Marker
							if x == None:
								advance(4)
							read_marker()
						elif b2 == '07':
							#Cue Point
							if x == None:
								advance(4)
							read_cue()
						elif b2 == '08':
							#Program Name
							if x == None:
								advance(4)
							name_hex = read_program_name()
							program_name = name_hex.decode("hex")
							print "Program Name:", program_name
							#print "fp is now:", fp
						elif b2 == '0a':
							#Composer Name
							#THIS IS NOT ON THE INTERNET FOR SOME REASON BUT IT'S A FREAKING THING AND I HAD TO FIGURE IT OUT FOR MYSELF
							if x == None:
								advance(4)
							program_name = read_program_name().decode("hex")
							print "Composer Name:", program_name
							#print "fp is now:", fp
						elif b2 == '20':
							#MIDI Channel Prefix
							if x == None:
								advance(4)
							channel = read_midi_channel_prefix()
							print "MIDI channel set to", channel
						elif b2 == '21':
							#MIDI Port
							if x == None:
								advance(4)
							port = read_midi_port()
							print "MIDI port set to port", port
						elif b2 == '2f':
							#End of Track
							if x == None:
								advance(4)
							read_end_of_track()
						elif b2 == '51':
							#Set Tempo
							if x == None:
								advance(4)
							read_tempo()
						elif b2 == '54':
							#SMTPE Offset
							if x == None:
								advance(4)
							read_SMTPE_offset()
						elif b2 == '58':
							#Time Signature
							if x == None:
								advance(4)
							read_time_signature()
						elif b2 == '59':
							#Key Signature
							if x == None:
								advance(4)
							read_key_signature()
						elif b2 == '7f':
							#Sequencer-Specific
							if x == None:
								advance(4)
							read_sequence_specific()
						else:
							if x != None:
								raise error.MidiException("Unrecognized Meta event at position", fp, ". Expected 00-08, 20, 2f, 51, 54, 58, 59, or 7f, but got", b2)
							n1 = last_event_type[:1]
							n2 = last_event_type[1:2]
							b2 = last_event_type[2:4]
							'''print "n1:", n1
							print "n2:", n2
							print "b2:", b2'''
							#print "Using last header (", last_event_type, ") because none identified at", fp
							new_event_type = False
							determine_event(last_event_type)
					else:
						if x != None:
							raise error.MidiException("Unrecognized event at position", fp, ". Expected 0x80-0xff, but got", data[fp:fp+2])
						n1 = last_event_type[:1]
						n2 = last_event_type[1:2]
						b2 = last_event_type[2:4]
						'''print "n1:", n1
						print "n2:", n2
						print "b2:", b2'''
						#print "Using last header (", last_event_type, ") because none identified at", fp
						new_event_type = False
						determine_event(last_event_type)
				else:
					if x != None:
						raise error.MidiException("Unrecognized event at position", fp, ". Expected 0x80-0xff, but got", data[fp:fp+2])
					n1 = last_event_type[:1]
					n2 = last_event_type[1:2]
					b2 = last_event_type[2:4]
					'''print "n1:", n1
					print "n2:", n2
					print "b2:", b2'''
					#print "Using last header (", last_event_type, ") because none identified at", fp
					new_event_type = False
					determine_event(last_event_type)
			determine_event(None)
			if new_event_type:
				last_event_type = data[temp_fp:temp_fp+6]

	print file_name, "is a valid MIDI file."
	number_of_notes = 0
	for c in notes:
		for n in notes[c]:
			number_of_notes += 1
			print n.to_string(ticks_per_quarter_note)
	print "Number of notes in file:", number_of_notes