Jupyter Notebook と VS Code でバッハの平均律第1番を分析する
Jupyter Notebook で、楽譜を表示したり、その楽譜を再生してみたり、曲を分析したりしてみました。そのことについて書きます。分析といっても簡単なものです。
目次
Code, .ipynb
- Jupyter Notebook: https://mybinder.org/v2/gh/hhyyg/miso.py.music21bach/master
- ここにある2つの .ipynb ファイルから確認できます
- ただし、画像・音声生成部分などは再実行ができません
- GitHub: https://github.com/hhyyg/miso.py.music21bach
環境
- Mac
- Visual Studio Code
- Python 3.6
- Jupyter Notebook
- ライブラリ: music21 5.5.0
- LilyPond.app
VS Code で Jupyter Notebook
VS CodeからJupyter Notebookを使ってみよう (1/3):Visual Studio Codeで始めるPythonプログラミング - @IT
こちらの記事を参考にしながらセットアップを行いました。VS Code の拡張機能により、以下のように VS Code 内で結果が描画されます。
music21 とは
- music21: a Toolkit for Computer-Aided Musicology
- GitHub: cuthbertLab/music21: music21 is a Toolkit for Computational Musicology
music21 は、音楽を解析するための Python ライブラリです。music21 の 21 とは、ここ によるとマサチューセッツ工科大学の学部の 1 つである、Music and Theater Arts に付与された通し番号の 21 のようです。
どのような音楽データを解析できるかというと、MusicXML、MIDI、ABC記法のテキストデータなどの譜面データをサポートしています(ここの Converter.defaultSubconverters()から一覧を確認できます)。
music21 を使うと解析の他に、グラフ・楽譜・MIDI ファイルの出力ができるようで、それぞれ外部ライブラリを参照しています。グラフは Matplotlib ライブラリ、楽譜の画像の生成部分は LilyPond、楽譜データを表示するときは MuseScore などが参照されます(Extending music21 with Additional Software。自分の場合は、LilyPond.app と MuseScore.app を併用しました。これらの参照先は、次のようなユーザー設定を出力するコードで確認できます。
from music21 import environment settings = environment.UserSettings() for key in sorted(settings.keys()): print(key + ":") if key is not 'localCorpusPath': print(settings[key])
出力結果:
autoDownload: ask braillePath: None debug: 0 directoryScratch: None graphicsPath: /Applications/Preview.app ipythonShowFormat: ipython.musicxml.png lilypondBackend: ps lilypondFormat: pdf lilypondPath: /Applications/Lilypond.app/Contents/Resources/bin/lilypond lilypondVersion: None localCorporaSettings: {} localCorpusPath: localCorpusSettings: LocalCorpusSettings([]) manualCoreCorpusPath: None midiPath: /Applications/Utilities/QuickTime Player 7.app musescoreDirectPNGPath: /Applications/MuseScore 2.app/Contents/MacOS/mscore musicxmlPath: /Applications/MuseScore 2.app/Contents/MacOS/mscore pdfPath: /Applications/Preview.app showFormat: musicxml vectorPath: /Applications/Preview.app warnings: 1 writeFormat: musicxml
曲の作成と表示
まずは、簡単に音を構築して五線譜で表示してみました。
from music21 import note,stream,corpus,chord,environment,converter,midi stream1 = stream.Stream() note = note.Note("C4", quarterLength = 1) stream1.repeatAppend(note, 4) stream1.show()
.show()
ではなくstream1.show('xml')
とすれば、MuseScore などの楽譜表示ソフトが立ち上がります。
耳で聞きたい場合は、stream1.show('midi')
とします。VS Code の拡張機能上では聞くことはできませんが、ブラウザ上の Jupyter Notebook では聞くことができます。
コードで音を構築するのは面倒な場合、TinyNotation という記法が使えます。これは、music21 が LilyPond や ABC記法などを参考にして作った記法です。
例えば、TinyNotation でスーパーマリオのテーマの冒頭を記述するとこのようになります:
s = converter.parse('tinyNotation: 4/4 e8 e8 r e8 r c8 e8 r g4 r G4 r')
s.show()
バッハの平均律を分析
実際に、バッハの平均律クラヴィア曲集 第1巻 第1番 プレリュード を分析してみました。ピアノの旧約聖書とも言われる平均律のうちの最初の曲、ハ長調で、多くの人が一度は耳にしていると思います。
この曲は楽譜でみるとこのように2ページになっています:
全ての小節で似たような音形になっています。
music21 では、あらかじめいくつかの楽曲が MusicXML 形式で格納されており(場所)、次のようなコードで曲情報を扱うことができます。.measures(1, 2).show()
で、1小節目と2小節目を表示しています。参照: User’s Guide, Chapter 11: Corpus Searching
from music21 import note,stream,corpus,chord,environment,converter,midi #%% bwv846 = corpus.parse('bach/bwv846') bwv846.measures(1, 2).show()
bwv846
の意味は、BWVはバッハの作品番号で、846番がこの曲のことを指しています。
このように music21 の中にある MusicXML ファイルを参照できますが、ローカルにあるファイルを参照することも可能です。また、バッハの曲は433曲収納されていますが、そのうち平均律はこの1曲しかないようです。ちなみにショパンは1曲だけでした。
music21 は Matplotlib を参照してプロット図を生成します。
bwv846.plot()
.plot()
では、x軸が小節番号(時間軸)、y軸がピッチ(上が音が高く、下が音が低い)の図が出力されます。DTM でよくみるピアノロール式の表示です。この図からは、線の長さで上下で2つ別れているように見えます。これは上半分は右手のパートである、十六分音符が連続していて細かく動いていること、下半分は左手のパートであり、長い音が続いていることが分かります。これは、五線譜からみても分かることです。また、音の高さが時間が経つにつれ全体的に下降しているように見えます。
そして、他と比べて一定の高さの音が続いている箇所があります(下の図の赤線)。曲の最後の左手のソ(G)とハ(C)です。この曲はハ長調なので、属音から主音への解決を、割と長い時間をかけて行なっていることがわかります。
また、途中で、左手が綺麗に音が降りているところがあります(上の図の青線)。ここを楽譜でピックアップして見てみると、確かに左手の2番目に弾く音が一音ずつ下がっていることが確認できます。
bwv846.measures(11, 16).show()
これらは、情報処理をせずとも楽譜からやMIDIをDTMで表示したときに分かることで、ほとんどの演奏者も譜読みの段階で自ずと意識しています。気になった部分の小節を五線譜として表示したり、MIDIで耳で聞いてみたり、あるいは何か値を算出したりできるのが music21 ならではだと感じます。
分析 後半
次は、ヒストグラムを表示してみます。グラフ中の文字が小さくなるので、次のようにグラフの解像度を上げておきます。
import matplotlib as pyplot pyplot.rcParams['figure.figsize'] = (20.0, 10.0) pyplot.rcParams["figure.dpi"] = 200
ヒストグラムで音の高さ(ピッチ)毎に出現回数を表示してみます。
bwv846.plot('histogram', 'pitch')
真ん中のド(C)を中心に左右に広がっています。ハ長調だからとはいえこんなに真ん中のド(C)が多くなるのでしょうか?他の曲と比べてみないとなんとも言えません。また、曲中で一番高い音はラ(A)、低い音はド(C)であることが分かります。
次の図は同じくピッチのヒストグラムですが、pitchClass
と指定していることで、オクターブでグルーピングして出現回数を表しています。ハ長調なので、やはり白鍵(♯♭がついていない音)が多いです。
bwv846.plot('histogram', 'pitchClass')
3Dの図も見てみたり:
bwv846.plot('3dbars', 'pitchClass')
音の長さのヒストグラムも表示してみます。音の長さはquarterLengh
と指定します。右手と左手で分けて表示してみます。四分音符は1で表され、八分音符は0.5、十六分音符は0.25です。
# 右手 bwv846.parts[0].plot('histogram', 'quarterLength', title='right hand') # 左手 bwv846.parts[1].plot('histogram', 'quarterLength', title='left hand')
左手 | 右手 |
---|---|
ここで、上の図から右手の0.25(十六分音符)の数が400ピッタリなのでは、と推測できます。図の解像度からは確信できないので、コードで右手の十六分音符を数えてみます。
f = bwv846.parts[0].flat right16notes = [note for note in f.notes if note.quarterLength == 0.25] len(right16notes)
出力:
400
本当に400でした。キリのいい数字です。
といったように、music21、Jupyter Notebook、VS Code を使えば曲の分析を行うことができます。今回は1曲だけでしたが、他にも、バッハの平均律全曲や、ショパンの練習曲全曲など、複数の曲を対象としてみたく思います。十二音技法も良さそうです。
参考
- music21 Documentation — music21 Documentation
- music21 の使い方を知りたいときはここ
- music21で春の海
- music21~インストール・動作確認まで | Nature | Photography | Music | Art
- Pythonで音楽学 - ならば
- ショパンの黒鍵を分析
- DSpace@MIT: music21: A Toolkit for Computer-Aided Musicology and Symbolic Music Data
- Example of getting Bach from MusicXML using music21
- Making Music and Embedding Sounds in Jupyter Notebooks – OUseful.Info, the blog…
- showntell/4.1.0 Music Notation.ipynb at music · psychemedia/showntell
TECH PLAY女子部 Advent Calendar 2018 - Adventar
追記
ちょっと環境変えた後に描画できなくなっていたので調べたら、MuseScore 2 ではなく MuseScore 3 が入っていたためでした。以下のように設定を変えて描画できました。
settings = environment.UserSettings() settings['musescoreDirectPNGPath'] = '/Applications/MuseScore 3.app/Contents/MacOS/mscore' settings['musicxmlPath'] = '/Applications/MuseScore 3.app/Contents/MacOS/mscore'