python-3.x 如何从MIDI文件中提取单独的和弦,休止符和音符?

ijnw1ujt  于 2023-04-08  发布在  Python
关注(0)|答案(1)|浏览(122)

我正在做一个程序,应该能够从某个midi文件中提取音符,休止符和和弦,并将音符和和弦的各自音高(以midi音调数字为单位-它们从0-127)写到csv文件中供以后使用。
对于这个项目,我使用Python库“Music 21”。

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文件中了?

2g32fytz

2g32fytz1#

这里是我是如何做到这一点的小片段.我需要得到所有的音符,和弦和休息的具体文书.所以在第一次我迭代通过部分,并找到具体的文书,然后检查它是什么样的注意,并添加它.
你可以这样调用这个方法:

notes = get_notes_chords_rests(keyboard_instruments, "Pirates_of_The_Caribbean.mid")

其中keyboard_instruments是乐器列表:
keyboard_instruments = ["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

P.S.使用try block很重要,因为网络上很多midi文件都被损坏了。

相关问题