Music21简明指南

music21简明指南

music21是一个由MIT开发的功能强大的计算音乐学分析Python库。相比于pretty_midi库只能处理MIDI文件,music21可以处理包括MusicXML,MIDI,abc等多种格式的音乐文件,并可以从零开始构建音乐文件或对音乐进行分析。

在搜索引擎中搜索music21,大概率会被引导到这个网址:https://web.mit.edu/music21/。我在初次接触music21时看到这个网页感觉版面杂乱,不知何从下手。但是,进入右侧的Get Started with music21,并一步步查看教程,这时结构就清晰了许多,并且一步一步由浅入深阅读就可掌握music21的使用方法了。

music21官方教程其实介绍相当详尽易懂,教程中由浅入深介绍了music21的各个模块和使用方式。即使你对Python不甚了解,直接阅读官方教程也不会特别吃力,因为教程中有针对Python特性以及使用方法的介绍。

唯一的缺点是官方教程过于冗长,共有58章,每章也很长。如果需要快速上手,生成一份音乐文件,那一步步阅读教程所耗费的时间就过长了。因此,本文介绍了一些简单功能,足以使读者在短时间内使用music21生成需要的音乐文件,并令读者概略了解music21的使用方式。本文中大部分内容是从music21官方教程中摘录而来,并假设读者对Python有简单的了解。

首先,导入music21包,在这里我们使用官方教程中的习惯对music21包进行全部加载,但使用时建议通过import music21进行导入以避免污染命名空间。music21可以很方便的使用pip install music21安装。

from music21 import *

创建音符

音符是音乐中的最基本单位,music21库的风格是强类型的。基本来说,构成乐谱的每个音乐元素都有相应的类,并有其成员、方法。所有元素的类型都应是明确的。音符在music21中为music.note.Note类型,可以直接使用note.Note()初始化该类的实例(note.Note()中无参数则返回一个C4音高的四分音符)。

f = note.Note("F5#") #创建一个音高为F5#的音符
f.name #音符的音名
'F#'
f.step #音符的音级(不包含变化音及八度信息的音名,这里成为音级严格来说并不准确)
'F'
f.pitch.pitchClassString #音级(以C为0级的音程数)
'6'
f.octave #八度
5
f.pitch #音符的音高,返回一个音高对象
<music21.pitch.Pitch F#5>
f.duration #音符的时值,返回一个时值对象
<music21.duration.Duration 1.0>
f.duration.type #音符的时值的类型
'quarter'

在音符创建后,可修改其中的属性

f.octave=6
f.pitch
<music21.pitch.Pitch F#6>
f = note.Note("F5#") #可以在note.Note()中指定音高、八度及变化音来初始化音符对象
f.pitch.accidental=pitch.Accidental(-1) #pitch.accidental是变化音的类型
f
<music21.note.Note F->
f.duration.dots+=1 #改变符点数量
f.duration
<music21.duration.Duration 1.5>
f.duration.quarterLength=2 #直接改变时值,以四分音符计
f.duration
<music21.duration.Duration 2.0>

也可以添加泛音等标记
https://web.mit.edu/music21/doc/moduleReference/moduleArticulations.html?highlight=staccato#music21.articulations.Staccato

f.articulations = [articulations.Staccato()]

和弦

除了音符之外,乐谱中的另一个重要元素为和弦。和弦在music21中也有其单独的类型music21.chord.Chord

cMajor = chord.Chord(["E3","C4","G4"]) #初始化和弦
print(cMajor)
<music21.chord.Chord E3 C4 G4>
cMajor = chord.Chord() #也可以初始化一个空白类并一个个添加
cMajor.add(note.Note("E3"))
cMajor.add(note.Note("C4"))
cMajor.add(note.Note("G4"))
print(cMajor)
<music21.chord.Chord E3 C4 G4>
# 与Note类似,和弦也可以修改时值:
cMajor.duration.quarterLength=2

Stream

Stream是在music21中类似list的基本单位,它可以储存任意music21对象及其组合。

创建一个stream:

stream1 = stream.Stream()
stream1.append(f)
n3 = note.Note('D#5')
stream1.repeatAppend(n3, 4)
print(len(stream1))
5

当需要显示Stream以及整个乐谱等复杂结构的内容时,需要使用.show()方法。.show()方法不加参数是打开默认的乐谱编辑器,但是其设置较为麻烦,请读者自行配置。本文中皆使用.show('text')进行文字显示。

stream1.show('text')
{0.0} <music21.note.Note F->
{2.0} <music21.note.Note D#>
{3.0} <music21.note.Note D#>
{4.0} <music21.note.Note D#>
{5.0} <music21.note.Note D#>

当然也可以当迭代器使用:

for thisNote in stream1:
    print(thisNote.step)
F
D
D
D
D

也支持如列表的查找和删除:

note3Index = stream1.index(f)
stream1.pop(note3Index)
<music21.note.Note F->
stream1[2] == n3
True
stream1.show('text')
{2.0} <music21.note.Note D#>
{3.0} <music21.note.Note D#>
{4.0} <music21.note.Note D#>
{5.0} <music21.note.Note D#>

添加元素或添加Stream

stream可以嵌套使用,形成层级关系。

biggerStream = stream.Stream()
note2 = note.Note("D#5")
biggerStream.insert(0, note2)
biggerStream.append(stream1)
biggerStream.show('text')  # 在文字显示的缩进上可以看出层级的关系
{0.0} <music21.note.Note D#>
{1.0} <music21.stream.Stream 0x1cd59e005f8>
    {2.0} <music21.note.Note D#>
    {3.0} <music21.note.Note D#>
    {4.0} <music21.note.Note D#>
    {5.0} <music21.note.Note D#>

小节 (Measure):

m1=stream.Measure(number=0)
m1.repeatAppend(f, 4)
m2=stream.Measure(number=1)
m2.repeatAppend(n3, 2)
stream2=stream.Stream()
stream2.append(m1)
stream2.append(m2)
ts=meter.TimeSignature()
ts.denominator=4
ts.numerator=int(m1.duration.quarterLength)
m1.insert(0,ts)
m1.show('text')
{0.0} <music21.meter.TimeSignature 8/4>
{0.0} <music21.note.Note F->
{2.0} <music21.note.Note F->
{4.0} <music21.note.Note F->
{6.0} <music21.note.Note F->

查找:

可以查找所有指定的类,getElementsByClass返回迭代器:

for thisNote in stream1.getElementsByClass(note.Note): 
    print(thisNote, thisNote.offset)
<music21.note.Note D#> 2.0
<music21.note.Note D#> 3.0
<music21.note.Note D#> 4.0
<music21.note.Note D#> 5.0
stream1.append(note.Rest())
for thisNote in stream1.getElementsByClass(["Note", "Rest"]): 
    print(thisNote, thisNote.offset)
<music21.note.Note D#> 2.0
<music21.note.Note D#> 3.0
<music21.note.Note D#> 4.0
<music21.note.Note D#> 5.0
<music21.note.Rest rest> 6.0

也可以列出所有音高(不管时值)

stream1.pitches
[<music21.pitch.Pitch D#5>,
 <music21.pitch.Pitch D#5>,
 <music21.pitch.Pitch D#5>,
 <music21.pitch.Pitch D#5>]

有些子方法与使用getElementsByClass查找的用途一直,例如.notes相当于.getElementsByClass(["Note", "Chord"]).notesAndRests相当于.getElementsByClass(['Note', 'Chord', 'Rest'])

分析最大音高与最小音高的差:

stream1.analyze('ambitus')
<music21.interval.Interval P1>

生成乐谱

创建一个乐谱对象:

score = stream.Score()

添加声部:

part = stream.Part()
part.partName = 'Example Part'

将之前生成的Stream添加到声部中:

part.append(stream2)

将声部添加到乐谱中:

score.insert(0, part)

添加题目、作者等元数据:

score.insert(0, metadata.Metadata())
score.metadata.title = 'example title'
score.metadata.composer = 'example composer'

写入文件:

score.write('xml',fp=r'example.xml')
  • 16
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值