Как извлечь отдельные аккорды, остатки и ноты из файла midi?
Я делаю программу, которая должна иметь возможность извлекать ноты, паузы и аккорды из определенного миди-файла и записывать соответствующую высоту (в миди-числах - они идут от 0 до 127) нот и аккордов в CSV-файл для последующего использования.
Для этого проекта я использую библиотеку Python "Music21".
from music21 import *
import pandas as pd
#SETUP
path = r"Pirates_TheCarib_midi\1225766-Pirates_of_The_Caribbean_Medley.mid"
#create a function for taking parsing and extracting the notes
def extract_notes(path):
stm = converter.parse(path)
treble = stm[0] #access the first part (if there is only one part)
bass = stm[1]
#note extraction
notes_treble = []
notes_bass = []
for thisNote in treble.getElementsByClass("Note"):
indiv_note = [thisNote.name, thisNote.pitch.midi, thisNote.offset]
notes_treble.append(indiv_note) # print's the note and the note's
offset
for thisNote in bass.getElementsByClass("Note"):
indiv_note = [thisNote.name, thisNote.pitch.midi, thisNote.offset]
notes_bass.append(indiv_note) #add the notes to the bass
return notes_treble, notes_bass
#write to csv
def to_csv(notes_array):
df = pd.DataFrame(notes_array, index=None, columns=None)
df.to_csv("attempt1_v1.csv")
#using the functions
notes_array = extract_notes(path)
#to_csv(notes_array)
#DEBUGGING
stm = converter.parse(path)
print(stm.parts)
Вот ссылка на счет, который я использую в качестве теста. https://musescore.com/user/1699036/scores/1225766
Когда я запускаю функцию extract_notes, она возвращает два пустых массива и строку:
print(stm.parts)
это возвращается
<music21.stream.iterator.StreamIterator for Score:0x1b25dead550 @:0>
Я не понимаю, почему это так. Пьеса должна состоять из двух частей: высоких и низких частот. Как я могу получить каждую ноту, аккорд и отдых в массиве, чтобы я мог поместить его в файл CSV?
1 ответ
Вот небольшой фрагмент, как я это сделал. Мне нужно было получить все ноты, аккорды и остатки для конкретного инструмента. Поэтому сначала я перебрал часть и нашел конкретный инструмент, а затем проверил, что это за типовая заметка, и добавил его.
Вы можете назвать этот метод как
notes = get_notes_chords_rests(keyboard_instruments, "Pirates_of_The_Caribbean.mid")
где keyboard_instruments - это список инструментов.
keyboard_nstrument = ["KeyboardInstrument", "Piano", "Harpsichord", "Clavichord", "Celesta", ]
def get_notes_chords_rests(instrument_type, path):
try:
midi = converter.parse(path)
parts = instrument.partitionByInstrument(midi)
note_list = []
for music_instrument in range(len(parts)):
if parts.parts[music_instrument].id in instrument_type:
for element_by_offset in stream.iterator.OffsetIterator(parts[music_instrument]):
for entry in element_by_offset:
if isinstance(entry, note.Note):
note_list.append(str(entry.pitch))
elif isinstance(entry, chord.Chord):
note_list.append('.'.join(str(n) for n in entry.normalOrder))
elif isinstance(entry, note.Rest):
note_list.append('Rest')
return note_list
except Exception as e:
print("failed on ", path)
pass
PS Важно использовать try block, потому что многие midi-файлы в Интернете повреждены.