Last active
November 13, 2024 17:04
-
-
Save mathigatti/fb31ef7f82b7ef822e1630c2dfea86b0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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