Skip to content

Instantly share code, notes, and snippets.

@mathigatti
Last active December 3, 2022 04:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mathigatti/fb31ef7f82b7ef822e1630c2dfea86b0 to your computer and use it in GitHub Desktop.
Save mathigatti/fb31ef7f82b7ef822e1630c2dfea86b0 to your computer and use it in GitHub Desktop.
import glob
from music21 import converter, instrument, note, chord, interval, pitch
import sys
from tqdm import tqdm
def valid_note(note_number):
return -12*5 <= note_number <= 12*5
def first_note(notes_to_parse):
for element in notes_to_parse:
try:
if isinstance(element, note.Note):
return int(element.pitch.ps)
if isinstance(element, chord.Chord):
return int(element.notes[-1].pitch.ps)
except:
pass
return 60
def midi2text(midis_folder):
""" Get all the notes and chords from the midi files in the ./midi_songs directory """
notes = []
midis = sorted(glob.glob(f"{midis_folder}/*.mid"))
for file in tqdm(midis):
try:
midi = converter.parse(file)
# Transpose to C
k = midi.analyze('key')
i = interval.Interval(k.tonic, pitch.Pitch('C4'))
midi = midi.transpose(i)
mode = str(k.mode)
#print("Parsing %s" % file)
notes_to_parse = None
try: # file has instrument parts
s2 = instrument.partitionByInstrument(midi)
notes_to_parse = s2.parts[0].recurse()
except: # file has notes in a flat structure
notes_to_parse = midi.flat.notes
notes.append(f"{mode} =>")
last_note = first_note(notes_to_parse)
for element in notes_to_parse:
try:
#print(last_note)
if isinstance(element, note.Note):
duration = element.duration.quarterLength
new_note = int(element.pitch.ps)
if duration > 0 and valid_note(new_note - last_note):
notes.append(f"{str(new_note - last_note)}|{duration}")
last_note = new_note
elif isinstance(element, note.Rest):
duration = element.duration.quarterLength
if 0 < duration < 32:
notes.append(f"R|{duration}")
elif isinstance(element, chord.Chord):
duration = element.duration.quarterLength
chord_notes = [int(new_note.pitch.ps)-last_note for new_note in element.notes if valid_note(int(new_note.pitch.ps)-last_note)]
if duration > 0 and len(chord_notes) > 0:
notes.append('.'.join(map(str,chord_notes)) + "|" + str(duration))
last_note = int(element.notes[0].pitch.ps)
except:
pass
notes.append("\n")
except:
pass
with open('notes.txt', 'w') as filepath:
filepath.write(" ".join(notes).replace("\n ","\n").strip())
if __name__ == '__main__':
midis_folder = sys.argv[1]
midi2text(midis_folder)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment