ならば

音とかで遊んでいたログ

Pythonで音楽学

Python向けライブラリmusic21の初歩*1

music21は音楽学のためのライブラリで、音楽構造の抽出、変換、編集などといったことを記号操作によって行う。外部プログラムと連携して、抽出した情報の可視化もできる。
記号操作と書いたのは、MusicXMLABCのような記譜用のマークアップ言語で書かれたファイルを入力として読み込んで、内部でも音楽要素を記号として扱って処理を実行するから。音響信号は扱えないので、WavやらMP3といった音声ファイルは読み込めない。


Pythonインタラクティブモードであれこれ試すと楽しい。音楽学はよくわからないので*2、簡単にできる範囲で可視化したりして遊んだ。

ファイルを読み込んで楽譜を表示する。
楽譜の表示にはMuseScoreかFinale(Finale Reader)が必要。どちらのソフトも演奏機能があるので聴くこともできる。

>>> from music21 import *
>>> s = converter.parse('/home/naraba/program/python/music21/etude10-05.xml')
>>> s.show()

読み込んだ作品はショパンエチュード 作品10 第5番(G♭ major*3 )、愛称「黒鍵」。


こういう曲。


音楽の調を調べる。

>>> s.analyze('key')
<music21.key.Key of F# major>

F♯ majorはG♭ majorの異名同音調


オブジェクトの階層構造は伝統的な西洋音楽の階層構造を反映していて、上からScore(総譜)、Part(パート譜)、Measure(小節)、Note(音符)などのようになっているらしい。「黒鍵」はピアノ曲で右手と左手のパートがあって、メタデータ部を合わせると3つのパートとなる。

>>> s
<music21.stream.Score 181616076>
>>> len(s)
3
>>> s[0], s[1], s[2]
(<music21.metadata.Metadata object at 0xed6a08c>, 
<music21.stream.Part piano>, 
<music21.stream.Part piano>)


左手パートの小節数は86。左手パートの冒頭10小節のピアノロールを表示。

>>> len(s[2])
86
>>> s[2][:10].plot('pianoroll')



右手パートの小節数も当然86。右手パートに含まれる音符の長さのヒストグラムを表示。

>>> len(s[1])
86
>>> s[1].plot(format='histgram', values='quarterLength')

四分音符の長さが基準で1。横軸目盛の割り切れない数の表示が困ったことになっているが、ほとんど16分音符の三連符*4しかない。


右手パートに含まれる音符のピッチクラスごとの数を集計。それに続いて、ピッチクラスの重み付き散布図を表示。

>>> s[1].pitchAttributeCount('name')
{u'E-': 163, u'D-': 254, u'F': 1, u'B-': 162, u'A-': 218, u'G-': 181}
>>> s[1].plot(format='scatterweighted', values='pitchclass')

作品の愛称「黒鍵」の由来通り、右手パートはほとんどがピアノの黒鍵の音だけど、一音だけFの音(ファ)がある。音の長さもこの作品ではレアな四分音符。


F音がどの小節にあるのか探して、その小節だけ楽譜を表示。

>>> for m in s[1].getElementsByClass('Measure'):
...     for p in m.pitches:
...             if p.name == 'F': print m.measureNumber
... 
66
>>> s[1][66].show()


全体を長2度上に移調して、右手パートのピッチクラスの散布図を表示。

>>> s.transpose(2, inPlace=True)
>>> s[1].plot(format='scatterweighted', values='pitchclass')

白鍵と黒鍵の音が混じる作品になった。



メモ:LilyPondのファイルフォーマットは複雑すぎるという話

残念ながら、music21はLilyPondの記法で書かれたlyファイルを読み込めない*5プロジェクト公式の課題トラッカーで表明されている通り、この制約は今のところというわけではなく、今後もずっと続く模様。

理由も上のリンク先に書いてあるが、lyファイルにはSchemeのコードまで書けたりして、他のプログラムが楽譜として解析するには複雑すぎる。仮に一度解析プログラムを作り上げたとしてもLilyPondは活発なプロジェクトだし、構文もよく変更されるので追随するのが大変だろう。

おそらく同じ理由で、lyファイルをMusicXMLとかABCに変換するプログラムも(探した限りでは)ない。lyファイルを他のファイルフォーマットに変換する機能をLilyPond自体に追加するのが他の手段との比較上は一番楽な気がするけど、LilyPondプロジェクトにそういう計画は(探した限りでは)ない。

ちなみに、music21はMIDIファイルなら読み込める。そこで、LilyPondでlyファイルからMIDIファイルを出力して、この出力をmusic21に読み込ませればいいのではないかというと、MIDI出力の時点で楽譜の一部の要素が欠落してしまう。MIDIは演奏データをデジタル転送するための規格で、記譜のための仕様は十分ではないので、MIDI出力でサポートされない要素があるのが理由。

諦めた。

*1:というか、ちょっと動かしてみただけ

*2:それでなぜmusic21に手を出したかというと興味本位

*3:元々のMusicXMLファイルの記述に引きずられて下の楽譜の調号はおかしくなっているけど、Cには全て臨時記号で♭がつけられている

*4:四分音符の長さを1とすると八分音符は0.5で、その三分割なので0.5/3=0.166...

*5:music21で編集した結果を楽譜としてlyファイルに書き出すことはできる