のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

Pythonを使った音楽解析をやってみる

Sponsored Links

皆さんこんにちは
お元気ですか。私は元気です。

本記事はPythonアドベントカレンダー第6日です。
qiita.com

本日はPythonを使った音楽解析に挑戦します。
偶然にも音楽解析に便利なライブラリを発見したので、試してみたいと思います!

音楽解析

本日の挑戦は特徴量抽出と一部の音楽の加工です。
基本的な音楽ファイルの読み込みや特徴量抽出、音楽の加工分離です。
音楽解析に便利なライブラリ、librosaを紹介します。

librosa

librosaとは

librosaは音楽とオーディオの解析のためのライブラリです。
このライブラリは特徴量抽出、音楽の加工分離等の処理ができます。

github.com

音楽を解析してみた。

音楽を取得する。

librosaを試すための音楽を取得します。
今回の音楽データはhttp://marsyasweb.appspot.com/download/data_sets/:GTZANより、GTZAN Genre Collectionを使います。特徴は次の3つがあります。

  1. 30秒程度
  2. 16bitのオーディオファイル
  3. 10種類のジャンル

データ読み込み

取得したデータを読み込みます。
試しに「blues.00000.au」ファイルを読み込みます。

music, fs = librosa.audio.load(filename)

変数musicは信号、fsがサンプリング周波数を示しています。
この信号を可視化すると、次のグラフになります。

f:id:tereka:20161116231921p:plain

音楽情報を取得する。

音楽の情報の取得ができます。
例えば、音楽の時間、ピッチやビートの位置を計算できます。

時間の計算

サンプリング周波数と動画から取得できるベクトルから
時間を計算することが可能です。

print(librosa.samples_to_time(len(music), fs))
ピッチやテンポの計算

次の関数を使うと、ピッチやビートの位置を計算できます。

tempo, beats = librosa.beat.beat_track(y=music, sr=fs)
# (95.703125,
# array([  13,   40,   66,   94,  119,  146,  173,  201,  229,  257,  283,
#         310,  338,  364,  393,  420,  447,  475,  501,  528,  556,  584,
#         612,  640,  667,  694,  720,  748,  775,  803,  829,  856,  883,
#         911,  939,  966,  993, 1021, 1050, 1078, 1106, 1133, 1161, 1190,
#       1217]))

また、このビートの位置の単位はフレームです。そのため、実際の信号の位置は
別途計算しなければなりません。
それから、実際の信号の位置は次のように計算できます。

librosa.frames_to_samples(beat_frames)

スペクトラム分析をやってみる。

スペクトラム分析、いわゆる、周波数分析にも挑戦できます。
通常のスペクトラム分析で使われるのは離散フーリエ変換です。
しかし、離散フーリエ変換は時間の概念がないため、インパルス信号やノイズに弱い傾向にあります。

そのため、短時間で区切りフーリエ変換をかける短時間フーリエ変換(STFT)を行うことが多いです。
短時間フーリエ変換は次のように計算できます。

D= librosa.stft(music)
print D.shape
# (1025, 1293)

また、短時間フーリエ変換の結果をスペクトログラムで表示できます。
スペクトログラムは信号を計算して周波数スペクトルを計算した結果を示します。
x軸を時間、y軸を周波数、色を強度(db)として示しています。

import numpy as np
librosa.display.specshow(librosa.logamplitude(np.abs(D)**2,ref_power=np.max),y_axis='log', x_axis='time')
plt.title('Power spectrogram')
plt.colorbar(format='%+2.0f dB')
plt.tight_layout()

1.blues.00000.au
f:id:tereka:20161117000402p:plain

2.classical.00000.au
f:id:tereka:20161117000521p:plain

音楽特徴量を取得する。

librosaは音楽で頻繁に使われる特徴量を取得できます。

  1. メルスペクトラムグラム
  2. メル周波数ケプストラム係数(MFCC)
  3. クロマ
  4. それらのデルタを計算する

これらは全てlibrosa.featureパッケージを使用すれば特徴量を取得できます。
例えば、音声解析でよく使われるMFCCを取得したい場合は次のように記述できます。

mfcc_feature = librosa.feature.mfcc(music,n_mfcc=13)
mfcc_feature.shape
# (13, 1293)

音楽を加工する。

これまで音楽の解析を行ってきました。
librosaは音楽に対する加工用のメソッドも準備されています。

時間の引き伸ばし、短縮

音楽自体を引き伸ばしたり、短縮したりすることができます。

music_fast = librosa.effects.time_stretch(music, 2.0)
music_slow = librosa.effects.time_stretch(music, 0.5)

print(librosa.samples_to_time(len(music_fast), fs))
print(librosa.samples_to_time(len(music_slow), fs))

要素の抽出

打楽器要素とハーモニック要素を抽出するアルゴリズム
librosaには実装されています。
Documentationによれば、この手法は次の論文のアルゴリズムを利用しています。

http://dafx10.iem.at/papers/DerryFitzGerald_DAFx10_P15.pdf

打楽器要素の抽出

次のコードで打楽器要素を抽出できます。

y_percussive = librosa.effects.percussive(music, margin=3.0)
ハーモニック要素の抽出

また、ハーモニック要素は次のコードで抽出できます。

y_harmonic = librosa.effects.harmonic(music, margin=3.0)

音楽の保存

最後に音楽の保存方法です。
ファイル名と保存したい音楽、サンプリング周波数を入力し保存します。

librosa.output.write_wav("music.wav", music, fs)