music21~基本操作 | Nature | Photography | Music | Art

Nature | Photography | Music | Art

日々好奇心の趣くまま

サイト内の写真の使用ならびに無断転用を禁じます。

前回の続き。

 

music21は広範囲な機能を有しており、おそらく全部は使わないし把握もしきれていないので、自身がよく使う機能の備忘録となりますがご了承を。


とりあえずは楽譜をPythonプログラムから生成するまでの必要最低限の操作を順を追って。

まずは音符の生成から。いろいろな方法でF#4のQuater Noteの作り方。
 


from music21 import *

noteList = []

# from note name
n = note.Note("F#4",quarterLength = 1)
noteList.append(n)

# from pitch with note name
p = pitch.Pitch("F#4")
n = note.Note(pitch=p,quarterLength = 1)
noteList.append(n)

# from midi note F#4=66
curnote = 66 
n = note.Note(midi=curnote,quarterLength = 1)
noteList.append(n)

# deep copy
n2 = note.Note(n.pitch,quarterLength=n.quarterLength)
noteList.append(n2)

meas = stream.Measure()
meas.append(noteList)

meas.show('lily.png')

noteクラスはそのまま音符になる。音高や音長やその他の音符を構成するための情報を持っている。
pitchクラスは音高の情報で音長の情報はもたない。通常noteクラスのattributeとして使われる。
midiノート番号から音高を指定する方法もあり、便利なので個人的にはこればかり使っている。ただし#/bのエンハーモニックの制御ができない短所あり。
最後は既存のnoteを複製(深いコピー)する方法。単純にnoteクラスを=で代入すると浅いコピー(参照)になって片方を変更するとコピー先も変更される。


streamの詳細に関しては後述するが、ここではnoteListにnoteをappendしてnoteリストを作成してから最後にmeasに一括してappendしている。
直接measにnoteをappendしていっても構わない。

音高を文字列で指定するには"C3","E#4","B-7","D##5"などピッチクラスと臨時記号の数とオクターブ番号で指定。flatが"-"であるのに注意。
 


from music21 import *

noteList = []

n = note.Note("C3",quarterLength = 1)
noteList.append(n)

n = note.Note("E#4",quarterLength = 1)
noteList.append(n)

n = note.Note("B-7",quarterLength = 1)
noteList.append(n)

n = note.Note("D##5",quarterLength = 1)
noteList.append(n)

meas = stream.Measure()
meas.append(noteList)

meas.show('lily.png')


次に音長の指定方法。幾つかの方法があるが、特殊な場合を除いてquarterLengthに分数の形式で指定するのが(個人的には)一番楽。 ただしtripletはlilypondではなぜかうまくいかない。
 


from music21 import *

noteList = []

# Mid C
curnote = 60 

n = note.Note(midi=curnote,quarterLength = 1)
noteList.append(n)
curnote = curnote + 2

for i in range(2):
    n = note.Note(midi=curnote,quarterLength = 1./2.)
    noteList.append(n)
    curnote = curnote + 2

for i in range(3):
    n = note.Note(midi=curnote,quarterLength = 1./3.)
    noteList.append(n)
    curnote = curnote + 2

for i in range(4):
    n = note.Note(midi=curnote,quarterLength = 1./4.)
    noteList.append(n)
    curnote = curnote + 2

meas = stream.Measure()
meas.append(noteList)

#meas.show('lily.png') # not work?
meas.show('musicxml')

複雑な連符の場合にはappendTupletを使う。
 


from music21 import *

s = stream.Stream()
tuplets = [3, 5, 7, 9, 11, 13]

for t in tuplets:
    d = duration.Duration('eighth')
    d.appendTuplet(duration.Tuplet(t, 2))
    n = note.Note(60)
    n.duration = d
    s.repeatAppend(n, t)


s.insert(0, meter.TimeSignature('2/4'))
s.makeNotation(inPlace=True)
s.makeBeams(inPlace=True)
s.show('lily.png')

 

休符はこんな感じ。音高の指定以外はnoteと同じ。
 


from music21 import *

meas = stream.Measure()
restList = []
curnote = 60

n = note.Rest(quarterLength = 1)
restList.append(n)
curnote = curnote + 2

for i in range(2):
    n = note.Rest(quarterLength = 1./2.)
    restList.append(n)
    curnote = curnote + 2

for i in range(3):
    n = note.Rest(quarterLength = 1./3.)
    restList.append(n)
    curnote = curnote + 2

for i in range(4):
    n = note.Rest(quarterLength = 1./4.)
    restList.append(n)
    curnote = curnote + 2

meas.append(restList)
meas.show('musicxml')

 

タイの付け方。
 


from music21 import *

noteList = []

n = note.Note("F#4",quarterLength = 1)
noteList.append(n)

n = note.Note("F#4",quarterLength = 1)
noteList.append(n)

n = note.Note("F#4",quarterLength = 1)
noteList.append(n)

n = note.Note("F#4",quarterLength = 1)
noteList.append(n)

noteList[0].tie = tie.Tie('start')
noteList[1].tie = tie.Tie('continue')
noteList[2].tie = tie.Tie('continue')
noteList[3].tie = tie.Tie('stop')

meas = stream.Measure()
meas.append(noteList)

meas.show('lily.png')

 

スラーの付け方。(lilypondだと動かない)
 


from music21 import *

noteList = []

n = note.Note("C4",quarterLength = 1)
noteList.append(n)

n = note.Note("G#4",quarterLength = 1)
noteList.append(n)

n = note.Note("B4",quarterLength = 1)
noteList.append(n)

n = note.Note("E4",quarterLength = 1)
noteList.append(n)

sl1 = spanner.Slur([noteList[0], noteList[3]])

meas = stream.Measure()
meas.append(sl1)
meas.append(noteList)
#meas.insert(0.0, sl1) # also works

meas.show('musicxml')

 

和音を作るにはchordクラスを使う。
 


from music21 import *

meas = stream.Measure()

for i in range(8):
    notes = []
    for n in range(5):
        p = pitch.Pitch(60 + (n * 5) + ((i * 7) % 12))
        notes.append(p)

    c = chord.Chord(notes,quarterLength = 1./2.)
    meas.append(c)

meas.show('lily.png')

 

Grace Noteの作り方。(lilypondだと動かない)
 


from music21 import *

meas = stream.Measure()

n = note.Note("G4",quarterLength = 1)
meas.append(n)

d = note.Note('A4', type='eighth')
dGrace = d.getGrace()
meas.append(dGrace)

n = note.Note("G4",quarterLength = 1)
meas.append(n)

n = note.Note("F4",quarterLength = 1)
meas.append(n)

n = note.Note("E4",quarterLength = 1)
meas.append(n)

meas.show('musicxml')

 

Lyricの付け方。個人的には音符の素性をノートしたり本来の用途以外で多用している。
 


from music21 import *

meas = stream.Measure()

n = note.Note("G4",quarterLength = 1.5)
n.addLyric('ho-')
meas.append(n)

n = note.Note("C5",quarterLength = 0.5)
n.addLyric('ge')
meas.append(n)

n = note.Note("B4",quarterLength = 1.5)
n.addLyric('ho-')
meas.append(n)

n = note.Note("F4",quarterLength = 0.5)
n.addLyric('ge')
meas.append(n)

meas.show('lily.png')

 

複数声部を持つ方法。
 


from music21 import *

note1 = note.Note("B4",quarterLength=2)
note2 = note.Note("A4",quarterLength=2)

note1.stemDirection='up'
note2.stemDirection='up'

note3 = note.Note("E4",quarterLength=2)
note4 = note.Note("D4",quarterLength=1)
note5 = note.Note("C4",quarterLength=1)

note3.stemDirection='down'
note4.stemDirection='down'
note5.stemDirection='down'

soprano = stream.Voice()
alto = stream.Voice()

soprano.append(note1);
soprano.append(note2);

alto.append(note3);
alto.append(note4);
alto.append(note5);

staff = stream.Part()

staff.insert(0,alto);
staff.insert(0,soprano);

staff.show('lily.png')

 

ここまでほとんどは一小節のみの例だったが、実用上は複数小節・複数パートの楽譜になるのが一般的。
その際に必要になるのがこれまで暗黙に使っていたStreamクラス。
説明が難しいが、Stream≒譜表もしくはその一部、もしくはその集合と考えれば大きく外さない。

一つのStreamは他の複数のStreamを含むことができ、更にStreamの主な派生クラスとしてScore,Part,Measureなどがあって、
大規模な楽譜の場合、構成は

Score -> 複数のPart -> 複数のMeasure

という感じで階層構造になる。
Streamはフレキシブルな使い方が可能なのだが、経験上以下の進め方が確実。

各Partの作成:Measureを一小節作成→それをPartにappend→その繰り返し
Scoreの作成: 完成したPartをScoreにappend

例を示すのが分かりやすいかと思うので以下。(lilypondだと変な動作)
 


from music21 import *

s = stream.Score()

stream1 = stream.Part()
stream2 = stream.Part()

inst1 = instrument.Instrument()
inst2 = instrument.Instrument()
inst1.partName = "Inst 1"
inst2.partName = "Inst 2"

stream1.append(inst1)
stream2.append(inst2)

tc = clef.TrebleClef()
bc = clef.BassClef()

stream1.append(tc)
stream2.append(bc)

half = duration.Duration(2)

r = note.Rest()
r.duration = half

# inst1
for x in range(8):
    meas = stream.Measure()
    x2 = x + 60
    n=note.Note(x2)
    n.duration = half
    meas.append(n)
    r = note.Rest()
    r.duration = half
    meas.append(r)
    stream1.append(meas)
    
# inst2
for x in range(8):
    meas = stream.Measure()
    x2 = x + 48
    n=note.Note(x2)
    n.duration = half
    meas.append(n)
    r = note.Rest()
    r.duration = half
    meas.append(r)
    stream2.append(meas)

s = stream.Score()
s.append(stream1)
s.append(stream2)

s.show('musicxml')

 

基本的に大規模な譜面の場合はlilypondよりmusescoreを使ったほうが誤動作が少ないように思う。

Streamに別のStreamを加えるにはここではappendを使用したが、insertも使える。
appendは後ろに加えていくやり方、insertは位置を指定して入れ込んでいくやり方。
個人的にはinsertの動作がイマイチ把握できてないので必要な時以外はほとんどappendしか使ってない。

つづいてClef, Key, Time Signature, Barlineの指定をまとめて。
 


from music21 import *

stream1 = stream.Part()

ts = meter.TimeSignature('3/4')
ts.priority = -1
k = key.Key('C-')
k.priority = -1
bc = clef.BassClef()

meas = stream.Measure()
meas.insert(0, ts)
meas.insert(0, k)
meas.insert(0, bc)

a_note = note.Note('D-3')
a_note.quarterLength = 0.5
meas.append(a_note)

a_note = note.Note('C3')
a_note.quarterLength = 0.5
meas.append(a_note)

a_note = note.Note('B-2')
a_note.quarterLength = 0.5
meas.append(a_note)

a_note = note.Rest()
a_note.quarterLength = 1.5
meas.append(a_note)

stream1.append(meas)

ts = meter.TimeSignature('4/4')
ts.priority = -1
k = key.Key('F#')
k.priority = -1
bc = clef.TrebleClef()

meas = stream.Measure()
meas.insert(0, ts)
meas.insert(0, k)
meas.insert(0, bc)

a_note = note.Note('G#5')
a_note.quarterLength = 1
meas.append( a_note)

a_note = note.Note('F5')
a_note.quarterLength = 1.5
meas.append(a_note)

a_note = note.Note('E5')
a_note.quarterLength = 0.5
meas.append(a_note)

a_note = note.Note('D-5')
a_note.quarterLength = 1
meas.append(a_note)

meas.rightBarline = bar.Barline('double')

stream1.append(meas)

stream1.show()

 

priorityは同じタイミングに挿入されたアイテムの並べる順番を指定するもので、数が小さいほど左に現れる。

その他にも数限りなく機能があるが、とりあえずここまで踏まえていればメモ程度の譜面作成には十分かと思います。

 

補足

music21~Slonimsky Generator