5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

music21でMIDIを扱う

Last updated at Posted at 2023-02-01

はじめに

今回はmusic21のを用いてMIDIファイルの情報を抽出したり、操作したりする基本的な操作を紹介します。

MIDIファイルとは?

MIDIは、楽曲の演奏データが保存されたファイル形式のことです。
みなさんがイメージする音楽のファイル形式はmp3やwavが一般的だと思いますが、それらは演奏データではなく音声データです。
MIDIを演奏したときに出力される音声がmp3やwavになります。

music21とは?

music21は、pythonで音楽を扱うための音楽情報処理ライブラリです。
pythonでMIDIを扱う場合、他のモジュールとしてpretty_midiなどがありますが、MIDIファイルは情報が特殊なオブジェクトで保存されているので通常は扱いにくいことがあります。
music21はMIDIを読み取るだけでなく、作譜をしたりすることもできるので音楽処理には非常に優秀なライブリラリです。
インストールと環境構築に関してはこちらの記事がおすすめです。

MIDIを読み込む

まずはインポート

import music21 as m21

MIDIファイルを読み込みます。今回はかえるのうたの冒頭の演奏データが入ったMIDIを読み込みます。

path = './frog.mid'
frog = m21.converter.parse(path)
print(type(frog))

## <class 'music21.stream.base.Score'>

converter.parse()を使うと、streamというオブジェクトに変換できます。
streamは楽譜データを格納できるオブジェクトになります。

MIDIファイルを使いたい場合はこちら

MIDIの可視化

show()を使うとMIDIに格納されたデータをさまざまな形で可視化できます。
今回はその一例を紹介します。

楽譜

frog.show()

frog.png

再生

専用の再生ディスプレイが出てきます。
pygameをインストールしないと動かないことがあるので、実行する際はインストールしておきましょう。

frog.show('midi')

スクリーンショット 2023-02-01 0.31.31.png

テキスト

MIDI内の情報の全様を{オフセット} <オブジェクト名>としてテキスト表示します。
オフセットとは、四分音符の長さを1.0(quarterLengthといいます)としたとき、曲が始まってからどの位置にあるかを示す指標です。
次の項目で詳細を説明します。

frog.show('text')

## {0.0} <music21.metadata.Metadata object at 0x11edb10f0>
## {0.0} <music21.stream.Part 0x12a5de470>
##    {0.0} <music21.stream.Measure 1 offset=0.0>
##        {0.0} <music21.clef.TrebleClef>
##        {0.0} <music21.tempo.MetronomeMark animato Quarter=120.0>
##        {0.0} <music21.meter.TimeSignature 4/4>
##        {0.0} <music21.instrument.Piano 'Piano'>
##        {0.0} <music21.note.Note C>
##        {1.0} <music21.note.Note D>
##        {2.0} <music21.note.Note E>
##        {3.0} <music21.note.Note F>
##    {4.0} <music21.stream.Measure 2 offset=4.0>
##        {0.0} <music21.note.Note E>
##        {1.0} <music21.note.Note D>
##        {2.0} <music21.note.Note C>
##        {3.0} <music21.note.Rest quarter>
##    {8.0} <music21.stream.Measure 3 offset=8.0>
##        {0.0} <music21.note.Note E>
##        {1.0} <music21.note.Note F>
##        {2.0} <music21.note.Note G>
##        {3.0} <music21.note.Note A>
##    {12.0} <music21.stream.Measure 4 offset=12.0>
##        {0.0} <music21.note.Note G>
##        {1.0} <music21.note.Note F>
##        {2.0} <music21.note.Note E>
##        {3.0} <music21.note.Rest quarter>
##        {4.0} <music21.bar.Barline type=final>

streamの内部構造

show('text')で出力される内容はstreamの全体構造を表しています。
要約するとこんな感じになってます。

streamlist型と同じような仕様になっているので、appendpop を使って操作できます。
以下順に説明していきます。

stream.metadata

※こちらはmusic21のver8.1のアップデートにより追加されたオブジェクトです。
曲のタイトルや作曲者名・作成日付などを格納するオブジェクトらしいのですが、今回は扱わないので詳しい説明は省きます。

stream.Part

演奏パートのオブジェクトです。試しにかえるのうたに演奏パートを2つ追加してみましょう。

frog.append(m21.stream.Part())
frog.append(m21.stream.Part())

frog.show()

frog2.png
はい、追加されましたね。stream内では演奏パートごとに情報が格納されています。

stream.Measure

小節のオブジェクトです。1小節ごとに情報が格納されています。

len(frog[1])

## 4

frog[0]stream.metadataなので、frog[1]が演奏パートになります。
4小節あるので、lenで数えると4になりますね。
こちらも試しに小節数を増やしてみましょう。

frog[1].append(m21.stream.Measure())
frog[1].append(m21.stream.Measure())

frog.show()

frog3.png
増えましたね。
終止線が動かないのは、かえるのうたの最後の小節に終止線のオブジェクトが残っているからですね。

note.Note / note.Rest

音符と休符のことですね。かえるのうたの2小節目だけをshow()で見てみましょう。

frog[1][1].show('text')

## {0.0} <music21.note.Note E>
## {1.0} <music21.note.Note D>
## {2.0} <music21.note.Note C>
## {3.0} <music21.note.Rest quarter>

frog[1][1].show()

frog4.png
stream.Measure内にある最小オブジェクトのオフセットは、その小節が始まってからの位置を表します。
比較すると、楽譜通りの情報がテキストとして表示されているのがわかりますね。

その他のオブジェクト

小節内の最小オブジェクトは音符と休符だけではありません。
かえるのうたの1小節目だけをshow()で見てみましょう。

frog[1][0].show('text')

## {0.0} <music21.clef.TrebleClef>
## {0.0} <music21.tempo.MetronomeMark animato Quarter=120.0>
## {0.0} <music21.meter.TimeSignature 4/4>
## {0.0} <music21.instrument.Piano 'Piano'>
## {0.0} <music21.note.Note C>
## {1.0} <music21.note.Note D>
## {2.0} <music21.note.Note E>
## {3.0} <music21.note.Note F>

frog[1][0].show()

frog5.png
音符以外の情報が入ってますね。これらの情報はsetup情報として組み込まれます。
1小節目に必ず入っている情報で、あまりありませんが、曲の途中でテンポや拍子などが変化する箇所あると、その小節のオフセット{0.0}に組み込まれます。
今回は軽く触れておきます。

clef.Clef

音部記号。ト音記号やヘ音記号のことです。

tempo.MetronomeMark

テンポ。BPMのことです。

meter.TimeSignature

拍子。何拍子/何拍のような表記ができます。

instrument.Instrument

楽器。ピアノやヴァイオリン、トランペットなどにすることもできます。

情報の抽出と操作

さて、ここまでの内容を理解した上で情報を抜きとったり変えたりする基本的な操作を紹介します。

キーの分析と変更

streamに対してanalyze('key')を使うと、キーを解析してkey.Keyというオブジェクトで出力します。
この場合、Cだけを取り出したい場合、tonicPitchNameWithCaseを使います。

frog.analyze('key')

## <music21.key.Key of C major>

frog.analyze('key').tonicPitchNameWithCase

## 'C'

また、transpose( ,inPlace=True)を使うと、第一引数に入力した整数だけキーを半音上げ下げできます。

frog.transpose(-1, inPlace=True) # キーを半音下げる (Bメジャーになる)
frog.show()

frog6.png

frog.transpose(2, inPlace=True) # キーを半音上げる (Cメジャーに戻る)
frog.show()

frog.png

テンポの抽出

streamに対してmetronomeMarkBoundaries()を使うと、stream内全てのテンポオブジェクトに関して(開始オフセット, 終了オフセット, tempo.MetronomeMarkのタプルが入ったリストが出力されます。
tempo.MetronomeMarkに対してnumberを使うとfloat型で取り出せます

frog.metronomeMarkBoundaries()

## [(0.0, 16.0, <music21.tempo.MetronomeMark animato Quarter=120.0>)]

tempo_metronomeMark = frog.metronomeMarkBoundaries()[0][2]
tempo_metronomeMark

## <music21.tempo.MetronomeMark animato Quarter=120.0>

tempo_metronomeMark.number

## 120.0

拍数・拍子の抽出

meter.TimeSignatureに対し、ratioStringを使うと、/の表記が入った文字列で出力され、numeratorを使うと拍子(分子の数字)、denominatorを使うと拍数(分母の数字)を出力します。

meter_TimeSignature = frog[1][0][2]
meter_TimeSignature

## <music21.meter.TimeSignature 4/4>

meter_TimeSignature.ratioString

## '4/4'

meter_TimeSignature.ratioString = '3/4'
meter_TimeSignature.numerator

## 3

meter_TimeSignature.denominator

## 4

音符や休符情報の抽出

note.Noteに対して、nameを使うと、音階(ABC表記)を出力できます。
また、pitches[0].midiを使うと、ノートナンバー(C4=60を基準とした音階の数値化)を出力できます。

for measure in frog[1]:
    for item in measure:
        if isinstance(item, m21.note.Note):
            print(item, item.name ,item.pitches[0].midi)

## <music21.note.Note C> C 60
## <music21.note.Note D> D 62
## <music21.note.Note E> E 64
## <music21.note.Note F> F 65
## <music21.note.Note E> E 64
## <music21.note.Note D> D 62
## <music21.note.Note C> C 60
## <music21.note.Note E> E 64
## <music21.note.Note F> F 65
## <music21.note.Note G> G 67
## <music21.note.Note A> A 69
## <music21.note.Note G> G 67
## <music21.note.Note F> F 65
## <music21.note.Note E> E 64

全てのオブジェクトに対し、offsetを使うと、そのオブジェクトのオフセットを出力します。また、note.Notenote.Restに対してquarterLengthを使うと、四分音符を1.0としたときにどれぐらいの長さの音符・休符なのかを示す指標を出力します。

for measure in frog[1]:
    for item in measure:
        print(item.offset, item.quarterLength, item)

## 0.0 0.0 <music21.clef.TrebleClef>
## 0.0 0.0 <music21.tempo.MetronomeMark animato Quarter=120.0>
## 0.0 0.0 <music21.meter.TimeSignature 3/4>
## 0.0 1.0 <music21.note.Note C>
## 0.0 0.0 Piano
## 1.0 1.0 <music21.note.Note D>
## 2.0 1.0 <music21.note.Note E>
## 3.0 1.0 <music21.note.Note F>
## 0.0 1.0 <music21.note.Note E>
## 1.0 1.0 <music21.note.Note D>
## 2.0 1.0 <music21.note.Note C>
## 3.0 1.0 <music21.note.Rest quarter>
## 0.0 1.0 <music21.note.Note E>
## 1.0 1.0 <music21.note.Note F>
## 2.0 1.0 <music21.note.Note G>
## 3.0 1.0 <music21.note.Note A>
## 0.0 1.0 <music21.note.Note G>
## 1.0 1.0 <music21.note.Note F>
## 2.0 1.0 <music21.note.Note E>
## 3.0 1.0 <music21.note.Rest quarter>
## 4.0 0.0 <music21.bar.Barline type=final>

こんな感じにすれば○分音符・休符表記ができますね。

for measure in frog[1]:
    for item in measure:
        if isinstance(item, m21.note.Note):
            print(str(4/item.quarterLength) + '分音符', item)
        if isinstance(item, m21.note.Rest):
            print(str(4/item.quarterLength) + '分休符', item)

## 4.0分音符 <music21.note.Note C>
## 4.0分音符 <music21.note.Note D>
## 4.0分音符 <music21.note.Note E>
## 4.0分音符 <music21.note.Note F>
## 4.0分音符 <music21.note.Note E>
## 4.0分音符 <music21.note.Note D>
## 4.0分音符 <music21.note.Note C>
## 4.0分休符 <music21.note.Rest quarter>
## 4.0分音符 <music21.note.Note E>
## 4.0分音符 <music21.note.Note F>
## 4.0分音符 <music21.note.Note G>
## 4.0分音符 <music21.note.Note A>
## 4.0分音符 <music21.note.Note G>
## 4.0分音符 <music21.note.Note F>
## 4.0分音符 <music21.note.Note E>
## 4.0分休符 <music21.note.Rest quarter>

終わりに

music21での演奏データの操作と処理の優秀さを実感しました。
今回はほんの一部を紹介しましたが、music21はこれだけではなくまだまだ更なる可能性を秘めています。
ぜひ興味のある方は自分なりに遊んでみてはいかがでしょう。
ここまで読んでくださりありがとうございました。

参考公式ドキュメント

5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?