music21 :给定 midi 输入,输出正确拼写的音高和八度数

Posted

技术标签:

【中文标题】music21 :给定 midi 输入,输出正确拼写的音高和八度数【英文标题】:music21 : given midi input, output correctly-spelled pitches with octave numbers 【发布时间】:2021-09-29 22:04:38 【问题描述】:

请参阅下面的编辑了解正在进行的 MRE

我正在尝试将music21 的text 输出转换为包含八度音阶数字和正确的等音拼写。

作为背景,我是一名 javascript 程序员,对 music21 和 python 不熟悉。

以下

myMusic = converter.parse("midi")
myMusic.show("text")

产量

Time      Actual output      Desired Output 
0.0 <music21.note.Note C>      C4
0.1 <music21.note.Note D#>     E-4
0.2 <music21.note.Note G>      G4
0.3 <music21.note.Note G>      G4

这里有两个问题:

    如何在文本输出中包含八度音阶? (有趣的是,当有和弦时,每个音符的八度都会出现。

    D# 应该是 Eb,即应该在音调上下文中解释。我想在整个解析的midi文件上运行EnharmonicSimplifier.bestPitches()来纠正这个问题,但是from the docs,它似乎只能在note list上运行。

我做错了吗?我应该输出到不同的格式来获取这些信息吗?我需要时间点(偏移量可以)、八度数和正确拼写的音高。也许我缺少中间处理?

任何指导表示赞赏。

编辑:正在进行的 MRE,解决了问题 1.(严重吗?),但不是 2.

from music21 import *
environment.set('autoDownload', 'allow')

stream1 = converter.parse("https://upload.wikimedia.org/wikipedia/commons/5/55/MIDI_sample.mid")

for n in stream1.recurse().notes:
  try: 
    print(n.offset, n.nameWithOctave)
  except Exception as e: 
    print(n.offset, *n.pitches)

产量(摘录)

237.5 C2
238.0 F#2
238.2 F#2
238.5 C2 F#2
238.7 B-2

【问题讨论】:

【参考方案1】:

1

.show() 在调试时一目了然,但不适合结构化输出。看看recurse()。 music21 有一个容器本体:对象是“in”声音、“in”小节、“in”声部、“in”乐谱。因此,如果您从分数开始自上而下并想要遍历每个嵌套容器,只需使用 recurse():

for n in myStream.recurse().notes:
   print(n.offset, ' '.join(p.nameWithOctave for p in n.pitches))

备注属性:http://web.mit.edu/music21/doc/moduleReference/moduleNote.html

2

simplifyMultipleEnharmonics() 接受一个可迭代的音高(或可以转换为音高的东西,但如果你有它们,可以更快地给它音高)。每个 Note 或 Chord 对象都有一个 pitches 属性,因此您可以安全地在 Notes 或 Chords 上调用 .pitches,同时遍历您的解析文件,并将该音高元组连同您的 Key 对象一起发送到 simplifyMultipleEnharmonics

for n in myStream.recurse().notes:
  closest_key = n.getContextByClass(key.Key)
  n.pitches = pitch.simplifyMultipleEnharmonics(n.pitches, keyContext=closest_key)

【讨论】:

文字解释给了我一个高层次的理解——谢谢! - 但我遇到了实施问题。 (粗体是为了清楚起见,而不是大喊大叫)Re: 1.nameWithOctave 和弦失败。我添加了except Try ... Exception as e: print(n.offset, *n.pitches),它解决了这个问题,但可能不是最好的方法。 Re: 2. 尝试过,但考虑到我第一次接触 Python,太抽象了。您的答案能否包含一个实际为 .mid 文件生成所需输出的代码示例?这是来自***的示例:upload.wikimedia.org/wikipedia/commons/5/55/MIDI_sample.mid 是的,很好的调用,nameWithOctave 只对单个对象有意义,所以我的示例现在打印一个名称列表。以及#2 的代码示例。 我收到 1 的语法错误。将检查 2。当我有机会时,但有道理! 已编辑,抱歉!! 现在说得通了!如果您是 music21 的开发人员,可能值得考虑在文档中包含这样的示例,因为我认为带有时间点的音高是一个非常常见的用例。无论如何,我感谢您的帮助!

以上是关于music21 :给定 midi 输入,输出正确拼写的音高和八度数的主要内容,如果未能解决你的问题,请参考以下文章

music21:从平面乐谱中获取 midi 声音的声音/程序/乐器?

使用 music21 显示 Mid 文件中的 midi 音高数字

music21:写入midi文件后和弦转音符?

保存到 MIDI 文件时,Music21 一次播放所有音符

使用 Music21(或替代方法)从 MIDI 中提取休止符并写入单独的 MIDI 轨道

Music21 Python 库将只输出钢琴声音