Music21
建议配合官方图片食用
音符(Notes)
标准音符的概念被包含在 note
的 Note
对象之中
直接输入 note
便可得到该模块的位置
如果你想知道 note
除了 Note
还包含什么,可以输入 dir(note)
创建音符
让我们使用 note.Note
创建一个音符
f = note.Note('F5')
音符的属性
F5
是这个音符的音名
通过 .name
.step
和 .octave
可以得到其音名、音级、八度(在第几个八度)信息
f.name f.step f.octave
'F' 'F' 5
.step
得到不包含变化音及八度信息的音名,这里成为音级严格来说并不准确
当然也可以使用 .pitch
直接得到其音名
f.pitch
<music21.pitch.Pitch F5>
使用 .pitch.frequency
得到其频率
f.pitch.frequency
音高698.456462866008
使用 .pitch.pitchClass
同样可以得到其音级(距离同一个八度中 c
的半音数字),使用 .pitch.pitchClassString
则可以得到一个 String
f.pitch.pitchClassf.pitch.pitchClassString type(f.pitch.pitchClassString)
音高5 '5' <class'str'>
在 music21 中,升降分别使用 #
和 -
,我们创建 一个新的音符
b_flat = note.Note("B2-")
使用 .pitch.accidental
可获得其属性 (accidental
在音乐中表示变音记号),使用 .pitch.accident.alter
获得其半音变化数量,使用 .pitch.accidental.name
获得其
b_flat.pitch.accidental b_flat.pitch.accidental.alter b_flat.pitch.accidental.name
<accidental flat> -1.0 'flat'
注意,这里是一个浮点数,这意味着 music21 支持四分音符之类现实中通常不使用的东西
此外,并不是每一个音符都有 accidental 的,某些音符会返回 None
我们可以使用一个判断语句来解决:
if d.pitch.accidental is not None:
print(d.pitch.accidental.name)
如果你安装了 MusicXML
阅读器,使用 f.show()
可查看其五线谱
修改音符
使用 .transpose
修改你的音符
d = b_flat.transpose("M3") #将Bb上调大三度,变为D
这种用法并没有改变音符本身,而是返回一个变量
可以使用 inplace=True
进行原地操作
休止符
使用 note.rest
a = note.rest() # 记得加括号
最后提醒一个点,不要使用 note
作为音符的变量
note = note.Note("C4")
音高(Pitch),时值(Duration)
音高
使用 pitch.pitch()
创建一个音高对象
p1 = pitch.Pitch('b-4')
有许多属性和 note
是一样的
pl.octave pl.name pl.pitchClass pl.accidental.alter
4 'B-' 10 -1.0
.transpose()
同样可以使用
.nameWithOctave
和 .midi
pl.nameWithOctave pl.midi
'B-4' 70
这些属性大多数都可以修改
pl.name = "d#"
pl.octave = 3
pl.nameWithOctave
'D#3'
这时 pl 代表的音符已经变为了 D#3
实际上,每一个 Note 对象内部,都有一个 Pitch 对象,我们对 note.Note
做的一切,都可以用 note.Note.pitch
对象代替
一些 note
不支持的属性
csharp.pitch.spanish # 获得其西班牙名称
可以使用一些其他的方法,来更清晰地打印
print(csharp.pitch.unicodeName)
C♯
获得一些同音的方法
print( csharp.pitch.getEnharmonic() )
print( csharp.pitch.getLowerEnharmonic() )
D-4
B##3
时值
任何音符的存在都离不开时值 Duration
创建一个二分音符
halfDuration = duration.Duration('half')
# ‘whole','half','quarter','eighth','16th','32th','64th' 一直到'2048th',虽太小无法在乐谱上无法显示
# 'breve','longa','maxima' 2,4,8个全音
另一种创建方法是说明他有多少个四分音符
dottedQuarter = duration.Duration(1.5)
可以使用 .quarterLength
得到时值是多少个四分音符
还可以使用 Note
创建
c = note.Note("C4", type='whole')
.type
可以得到一般类型,如 'half','quarter'
.dots
可以得到音符有多少个附点
使用 .lyric
添加歌词(具体看文档吧,不具体介绍了)
otherNote = note.Note("F6")
otherNote.lyric = "I'm the Queen of the Night!"
流 (Stream)
我们可以通过列表对 note 等对象进行处理,但是它们对音乐一无所知,因此需要一个类似于列表的对象具有一定“智能”的对象,成为 Stream
流有许多子类 Score
乐谱、Part
声部、Measure
小节
创建流
Stream
中储存的元素必须是 music21 对象,如果想加入不属于 music21 的对象,请将其放入 ElementWrapper
使用 Stream()
创建流,.append()
方法添加元素,.repeatAppend()
方法添加多个相同的音符
stream1 = stream.Stream()
stream1.append(note1)
stream1.append(note2)
stream1.append(note3)
stream2 = stream.Stream()
n3 = note.Note('D#5') # octave values can be included in creation arguments
stream2.repeatAppend(n3, 4)
使用 .show('text')
查看其中的内容及其偏移量(从 0.0 开始,一般 1 个偏移量指一个四分音符的长度)
stream1.show('text')
{0.0} <music21.note.Note C>
{2.0} <music21.note.Note F#>
{3.0} <music21.note.Note B->
流的大部分方法和列表相同,如切片、索引(还可使用 .index()
访问)、pop()
、.append()
、len()
等,并且流中也可以存放列表
按类分离元素
提供一种过滤流以获取所需元素 .getElementByClass()
for thisNote in stream1.getElementsByClass(["Note", "Rest"]):
print(thisNote, thisNote.offset)
<music21.note.Note C> 0.0
<music21.note.Note F#> 2.0
<music21.note.Note B-> 3.0
此外也可使用 .notes
、.notesAndRests
、.pitches
等来进行过滤,直接使用会返回所有,如
stream1.pitches
[<music21.pitch.Pitch D#5>,
<music21.pitch.Pitch D#5>,
<music21.pitch.Pitch D#5>,
<music21.pitch.Pitch D#5>]
for thisNote in stream1.notesAndRests:
print(thisNote)
<music21.note.Note C>
<music21.note.Note F#>
<music21.note.Note B->
通过偏移量分离元素
getElementsByOffset()
sOut = stream1.getElementsByOffset(2, 3).stream()
sOut.show('text')
{2.0} <music21.note.Note F#>
{3.0} <music21.note.Note B->
还有 getElementAtOrBefore()
(某个偏移量及其之前 score = stream.Score()
1),getElementAfterElement()
(某个偏移量之后)
更多功能
.analyze('ambitus')
获得流中的音域范围
.lowestOffset
返回偏移量的最小值
__repr__
.id
,可以自己设定,相当于名字,如
s = stream.Score(id='mainScore')
p0 = stream.Part(id='part0')
p1 = stream.Part(id='part1')
.duration
储存 Duration 对象的属性
小节 (Measure)
可以使用 corpus
访问大量的乐谱,使用 Parse()
从语料库中解析出 Score
(一种流的子类)
sBach = corpus.parse('bach/bwv57.8')
它包含一个 Metadata
对象、一个 StaffGroup
对象和四个 Part
对象。
可以使用 measures()
或 measure()
获取多个或一个小节,前者获取整个乐曲所有 Part
的小节,后者必须对一个 Measure
对象
然而一个问题是,这与使用 getElementsByClass(stream.Measure)
并不相同,因为在乐曲中存在小节并不连续的情况