我如何读取 music21 中的 midi / musicxml 文件以供独奏钢琴使用,其中声音中可以同时存在多个音符?
How do I read midi / musicxml files in music21 for solo piano where there can be multiple notes in a voice simultaneously?
我写了一个python脚本来用music21处理midi文件,然后再写一个midi文件。如果独奏钢琴在某种意义上是“简单”的,即一个声音中没有同时演奏多个音高/音符,那么这将起作用。
https://github.com/githubuser1983/algorithmic_python_music/blob/main/12RootOf2.py
上面的相关部分是:
def parseMidi(fp,part=0):
import os
from music21 import converter
print(fp)
score = converter.parse(fp,quantizePost=True)
print(list(score.elements[0].notesAndRests))
#print([e.partAbbreviation for e in score.elements][0])
from music21 import chord
durs = []
ll0 = []
vols = []
isPauses = []
for p in score.elements[part].notesAndRests:
#print(p)
if type(p)==chord.Chord:
pitches = median([e.pitch.midi-21 for e in p]) # todo: think about chords
vol = median([e.volume.velocity for e in p])
dur = float(p.duration.quarterLength)
#print(pitches)
ll0.append(pitches)
isPause = False
elif (p.name=="rest"):
pitches = 89
vol = 1
dur = float(p.duration.quarterLength)
ll0.append(pitches)
isPause = True
else:
pitches = p.pitch.midi-21
vol = p.volume.velocity
dur = float(p.duration.quarterLength)
ll0.append(pitches)
isPause = False
durs.append(dur/(12*4.0))
vols.append(vol*1.0/127.0)
isPauses.append(isPause)
#print(p.name,p.octave,p.duration.quarterLength)
#print(dir(score))
#print(ll0)
#print(durs)
return ll0,durs,vols,isPauses
另一种选择是读取 musicxml 而不是 midi。我需要让算法工作的是每个声音的音符列表 = (pitch, duration, volume, isPause)。
感谢您的帮助。
目前,在 music21 中,stream.Voice
对象更多的是显示概念而非逻辑概念。声音和和弦都是同时发生的,这就是 MIDI 文件捕获的全部内容。 (事实上 ,本周发布的第 7 版 pending changes 除了制作小节外,还可以从 MIDI 文件中制作更少的声音和更多的和弦。如果混响或录制的演奏有小的重叠你可能会得到雕刻师永远不会在 sheet 音乐中打印的“声音”。)
在你的情况下,我可能只需要 Part
对象的 .flat
来去除声音(最终去除 v.7 中的测量),然后 运行 chordify()
如果您想确保没有重叠。否则,如果您根本不需要和弦,您仍然可以获取 chordify() 的输出并找到每个和弦的根音。几种可能性都取决于您的来源。
我写了一个python脚本来用music21处理midi文件,然后再写一个midi文件。如果独奏钢琴在某种意义上是“简单”的,即一个声音中没有同时演奏多个音高/音符,那么这将起作用。
https://github.com/githubuser1983/algorithmic_python_music/blob/main/12RootOf2.py
上面的相关部分是:
def parseMidi(fp,part=0):
import os
from music21 import converter
print(fp)
score = converter.parse(fp,quantizePost=True)
print(list(score.elements[0].notesAndRests))
#print([e.partAbbreviation for e in score.elements][0])
from music21 import chord
durs = []
ll0 = []
vols = []
isPauses = []
for p in score.elements[part].notesAndRests:
#print(p)
if type(p)==chord.Chord:
pitches = median([e.pitch.midi-21 for e in p]) # todo: think about chords
vol = median([e.volume.velocity for e in p])
dur = float(p.duration.quarterLength)
#print(pitches)
ll0.append(pitches)
isPause = False
elif (p.name=="rest"):
pitches = 89
vol = 1
dur = float(p.duration.quarterLength)
ll0.append(pitches)
isPause = True
else:
pitches = p.pitch.midi-21
vol = p.volume.velocity
dur = float(p.duration.quarterLength)
ll0.append(pitches)
isPause = False
durs.append(dur/(12*4.0))
vols.append(vol*1.0/127.0)
isPauses.append(isPause)
#print(p.name,p.octave,p.duration.quarterLength)
#print(dir(score))
#print(ll0)
#print(durs)
return ll0,durs,vols,isPauses
另一种选择是读取 musicxml 而不是 midi。我需要让算法工作的是每个声音的音符列表 = (pitch, duration, volume, isPause)。
感谢您的帮助。
目前,在 music21 中,stream.Voice
对象更多的是显示概念而非逻辑概念。声音和和弦都是同时发生的,这就是 MIDI 文件捕获的全部内容。 (事实上 ,本周发布的第 7 版 pending changes 除了制作小节外,还可以从 MIDI 文件中制作更少的声音和更多的和弦。如果混响或录制的演奏有小的重叠你可能会得到雕刻师永远不会在 sheet 音乐中打印的“声音”。)
在你的情况下,我可能只需要 Part
对象的 .flat
来去除声音(最终去除 v.7 中的测量),然后 运行 chordify()
如果您想确保没有重叠。否则,如果您根本不需要和弦,您仍然可以获取 chordify() 的输出并找到每个和弦的根音。几种可能性都取决于您的来源。