私は音楽大好き人間なんですが、librosa
というPythonライブラリを使うと音楽を簡単に分析できるらしい!ってことで遊んでみました。(ちなみに音響工学的な話は無知です)
準備物
- Jupyter notebook
- python3.7
- librosaライブラリ
- numpy
- matplotlib
- 適当な音楽ファイル(mp3)
まずは音楽ファイルを読み込んで再生
import librosa
import IPython
import librosa.display
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
y_full, sr_full = librosa.load("/path/to/sample.mp3")
IPython.display.Audio(data=y_full, rate=sr_full)
全部再生されますね。jupyter notebookは音楽の再生もできてすごい。
音楽ファイルのうち、一部を取り出してみる
y, sr = librosa.load("/path/to/sample.mp3", offset=115, duration=15)
IPython.display.Audio(data=y, rate=sr)
音楽ファイルのうち、115秒〜130秒の区間のみ再生されました。
これ以降のフェーズはファイルがでかいと時間がかかったりグラフが潰れたりするので、小さくしておきます。
BPMを取り出してみる
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr)
print(tempo)
# 129.19921875
音源を調波音と打楽器音に分解(HPSS)
y_harmonic, y_percussive = librosa.effects.hpss(y)
IPython.display.Audio(data=y_harmonic, rate=sr)
IPython.display.Audio(data=y_percussive, rate=sr)
これ、面白い。
旋律や和声を表現する調波音(y_harmonic
)とリズムを表現する打楽器音(y_percussive
)が分離された音源が生成されます。「HPSS(Harmonic Percussive Sound Separation)」という手法らしく、検索すると論文などがいくつかでてきます。
ただし、やってみるとわかりますが、例えばベース・ピアノ・ドラムというオーソドックスなJazzトリオの演奏であっても、ドラムとピアノが綺麗に分離することはなく、打楽器音のほうにピアノが入ってきたり、調波音のほうにシンバルが入ってきたりはするようです。まぁリズムをとっている音はドラムだけではなく、ピアノやベースもリズム作っている部分があるので当然ですね。
margin調整で分離を顕著に
marginを調整すると、もっと分離が顕著になります。
y_harmonic_m3, y_percussive_m3 = librosa.effects.hpss(y, margin=3.0)
marginを設定することで、調波音とも打楽器音とも言えない微妙な音を取り除くようです。大きくするほど分離が強くなり、音も少なくなっていきます。
librosaではこの辺の論文をもとに実装されている様子。
グラフで理論を理解する
この分離は、「調波音のスペクトログラムは時間方向に滑らか」、「打楽器音のスペクトログラムは周波数方向に滑らか」という特徴を利用しているようです。何をいっているのかよくわからないですが、グラフにしてみるとちょっと理解できた気がします。
スペクトログラムはwikipediaによると「横軸が時間を表し、縦軸が周波数を表す。そして、各点の明るさや色である時点のある周波数での強さ(振幅)を表す。」グラフだそうです。
librosaのドキュメントにexampleがあったので拝借しました。
D = librosa.stft(y)
H, P = librosa.decompose.hpss(D, margin=3.0)
plt.figure()
plt.subplot(3, 1, 1)
librosa.display.specshow(librosa.amplitude_to_db(np.abs(D), ref=np.max), y_axis='log')
plt.colorbar(format='%+2.0f dB')
plt.title('Full power spectrogram')
plt.subplot(3, 1, 2)
librosa.display.specshow(librosa.amplitude_to_db(np.abs(H), ref=np.max), y_axis='log')
plt.colorbar(format='%+2.0f dB')
plt.title('Harmonic power spectrogram')
plt.subplot(3, 1, 3)
librosa.display.specshow(librosa.amplitude_to_db(np.abs(P), ref=np.max), y_axis='log')
plt.colorbar(format='%+2.0f dB')
plt.title('Percussive power spectrogram')
plt.tight_layout()
plt.show()
こんな感じででてきました。確かに調波音は横に滑らかな一方、打楽器音は縦方向に滑らかに伸びています。
とりあえずここまで。音響の基礎的なことを理解していないのでもうちょい知らないとな。