Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import midi
- #Needs MIDI module, find here: https://github.com/vishnubob/python-midi
- import sys
- import re
- readableMIDI = midi.read_midifile(sys.argv[1])
- open("MidiDataOut.txt", "w").write(str(readableMIDI))
- fghsbeepOut = open(sys.argv[2], "w")
- txt = open("MidiDataOut.txt", "r").read()
- def regexSearch(pattern, string, start=0, end=0):
- #print "Regex Start: " + str(start)
- #print "Regex Pattern: " + pattern
- if end == 0:
- return re.compile(pattern).search(string, start)
- else:
- return re.compile(pattern).search(string, end)
- def regexFindall(pattern, string):
- return re.compile(pattern).findall(string)
- def regexFirstResult(pattern, string, start=0, end=0):
- if end == 0:
- return re.compile(pattern).search(string, start).group(0)
- else:
- return re.compile(pattern).search(string, start, end).group(0)
- def noteString(noteNum):
- #45 = A2, 46=A#2
- if noteNum == None:
- return ""
- if noteNum == -1:
- return "0"
- noteList = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B",]
- return noteList[noteNum%12]+str(noteNum//12-1)
- def writeRow(trackNotes):
- writeNotes = [noteString(trackNotes[0]), noteString(trackNotes[1]), noteString(trackNotes[2]), noteString(trackNotes[3])]
- print "writeRow notes:"
- print writeNotes
- writeNotes.reverse()
- endIndex = writeNotes.index("")
- writeNotes.reverse()
- print "endIndex: "+str(endIndex)
- # if endIndex <= 2:
- # fghsbeepOut.write(writeNotes[0])
- # if endIndex <= 1:
- # fghsbeepOut.write("\t\t\t\t"+writeNotes[1])
- # if endIndex <= 0:
- # fghsbeepOut.write("\t\t\t\t"+writeNotes[2])
- # if endIndex <= -1:
- # fghsbeepOut.write("\t\t\t\t"+writeNotes[3])
- writeNotes.reverse()
- inputRes = int(re.compile(r"\d+").search(re.compile(r"resolution=\d+,").search(txt).
- group()).group())
- outputRes = input("Output resolution:")
- outputBPM = input("Output BPM:")
- includeBeginAndEnd = raw_input("Include rests before the first note? (y/n):")
- firstNoteTick = int(regexFirstResult(r"\d+",regexFirstResult(r"Note(?:On|Off)Event.tick=\d+",txt)))
- firstNotePos = regexSearch(r"Note(?:On|Off)Event.tick=\d+",txt).start()
- skipTicks = 0
- if includeBeginAndEnd == "y":
- i = 0
- while(i < firstNotePos):
- ticks = int(regexSearch(r"tick=(\d+)",txt,i).group(1))
- skipTicks = skipTicks + ticks
- i = regexSearch(r"tick=(\d+)",txt,i).end()
- fghsbeepOut.write(str(outputRes*outputBPM)+"\n#Beat 1\n")
- beatNum = 1
- currentPos = firstNotePos
- currentTick = 0
- occupiedTracks = [False, False, False, False]
- trackNotes = [None, None, None, None]
- previousNotes = [None, None, None, None]
- writeNotes = ["", "", "", ""]
- def nextNote():
- return regexSearch(r"Note(?:On|Off)Event.tick=\d+, channel=\d+, data=.(\d+)", txt, currentPos)
- def nextNoteOnOff():
- return regexSearch(r"Note(On|Off)Event", txt, currentPos).group(1)
- def nextTick():
- return int(regexSearch(r"Note(?:On|Off)Event.tick=(\d+)", txt, currentPos).group(1))
- #45 = A2, 46=A#2
- #print nextNote()
- while nextNote():
- print "- - - - - - - - - - - - - - - - - -"
- noteNum = int(nextNote().group(1))
- noteTick = int(round(float(nextTick())/float(inputRes)*float(outputRes), 0))
- print "noteTick: " + str(noteTick)
- print nextTick()
- if noteTick >= 1:
- for i in range(4):
- if (trackNotes[i] == None) | (previousNotes[i] != None) | (previousNotes != -1):
- trackNotes[i] = -1
- if (trackNotes[i] == -1) | (previousNotes[i] == -1):
- trackNotes[i] = None
- writeRow(trackNotes)
- previousNotes = trackNotes
- for i in range(noteTick):
- currentTick = currentTick + 1
- fghsbeepOut.write("\n")
- if currentTick%(2*outputRes) == 0: #The 2* should be removed in the end, it's only there so I can debug the .fghsbeep out with a file I know is correct
- beatNum = beatNum + 1
- fghsbeepOut.write("#Beat "+str(beatNum)+"\n")
- # print "\n"
- # print nextNote().group(0)
- # print currentPos
- # print nextNote().end()
- if nextNoteOnOff() == "On":
- print "\nNoteOnEvent"
- if min(occupiedTracks) == True:
- print "Too many notes on beat "+str(beatNum)+". Fix MIDI file and try again."
- break
- trackNum = occupiedTracks.index(False)
- occupiedTracks[trackNum] = True
- trackNotes[trackNum] = noteNum
- print occupiedTracks
- print trackNotes
- else:
- print "\nNoteOffEvent"
- trackNum = trackNotes.index(noteNum)
- trackNotes[trackNum] = None
- occupiedTracks[trackNum] = False
- print occupiedTracks
- print trackNotes
- print noteNum
- currentPos = nextNote().end()
- #The resolution of the MIDI files is MIDI ticks per quarter note.
- #The resolution should be lowered as much as possible without seriously sacrificing song quality. Think of it as a really good quanitizer. I recommend tending to your MIDI files before you run them through this program to make sure that nothing will get rounded poorly. Grace notes, for example, will pretty much always need some fine tuning.
- #It should pretty much always be a power of two.
- #The output BPM is quarter notes per minute.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement