機械学習で（楽曲の）音声信号処理をするならlibrosaが便利

## 目的
機械学習で音楽関連のなにかをやりたいと思い触ってみました。
音声データについて知識が皆無だったのですが、librosaはサクッといい感じに音声データ処理を色々試せそうだったので、使ってみました。

インストールはpip で

`pip install librosa`

とすると入ります。

## やったこと
librosaの[ドキュメント](https://librosa.github.io/)にある、

-  [Demonstration](http://nbviewer.jupyter.org/github/librosa/librosa/blob/master/examples/LibROSA%20demo.ipynb)で基本的なデータ読み込み、特徴量抽出とか
- [Audio effects](http://nbviewer.jupyter.org/github/librosa/librosa/blob/master/examples/LibROSA%20audio%20effects%20and%20playback.ipynb)でボーカル分離とかエフェクト効果とか

をjupyterで実行結果見ながら試してみました。
他にもいろいろ出来るようだけど、結局ここに書いてあるMFCCとかを使ってます。


### librosaの基本的な使い方

基本的には[チュートリアルのページ](http://nbviewer.jupyter.org/github/librosa/librosa/blob/master/examples/LibROSA%20demo.ipynb)の内容を解説しています。

まずは色々importしておきます

```python
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
import IPython.display
import librosa
import librosa.display
```
（最後の `librosa.display` は変換したデータを表示するときに必要になります。）

次に、音声データを読み込みます。

```python
y, sr = librosa.load(audio_path)
```

このaudio_pathは、

```python
audio_path = "./example/song/data.wav"
```
こんな感じで、直接ディレクトリを指定して書いてもOKです。
読み込むデータフォーマットはwavじゃないとダメみたいです。

### mer spectrogram を求める

以下でメル周波係数が出てきます。

```python
S = librosa.feature.melspectrogram(y, sr=sr, n_mels=128)
```

これを

```python

log_S = librosa.amplitude_to_db(S, ref=np.max)
```
こうして、dBに変換します。
dBに変換したものをmatplot libで可視化します。

```python

plt.figure(figsize=(12, 4))
librosa.display.specshow(log_S, sr=sr, x_axis='time', y_axis='mel')
plt.title('mel power spectrogram')
plt.colorbar(format='%02.0f dB')
plt.tight_layout()
```
librosaには結果を表示させるための関数が用意されているので、基本これ（`librosa.display.specshow`）を利用します。
引数は、表示させるデータ、サンプリングレート、どの値をx軸、y軸に持ってくるかの指定などです。
だいたい、上の4パラメーターを指定することが多いです。
可視化したものはこんな感じになります。
![mps.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75196/25377cd4-3b50-0556-bb73-c046163bc1be.png)


### ハーモニー部分とパーカッション部分の分離

音声データを[ハーモニー部分とパーカッション部分を分離](https://nbviewer.jupyter.org/github/librosa/librosa/blob/master/examples/LibROSA%20demo.ipynb#Harmonic-percussive-source-separation) するためには、

```python

y_harmonic, y_percussive = librosa.effects.hpss(y)
```

で分離できます。
少し処理が重いので、大量のデータに対して適用するときはちょっと時間がかかります。

分離自体は、結構大まかなので、パーカッション部分は、主にビートを刻む打楽器系が抽出され、ハーモニー部分はパーカッション部分を差し引いたような感じです。

![harmonic_percussive.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75196/e6c8e253-5f3e-7eb3-3c37-9823d85ee3b2.png)

可視化されると、なんとなく打楽器系が分離されているのが分かります。
ただ、わかりやすいビートが刻まれていないジャズやクラシックではあまり良い結果が出ないようです。

### Chroma（和音）を抽出する

librosaには、だいたいこの辺の音がなってるよね、という[コードの分離](https://nbviewer.jupyter.org/github/librosa/librosa/blob/master/examples/LibROSA%20demo.ipynb#Chromagram) もやってくれます。

```python

C = librosa.feature.chroma_cqt(y=y_harmonic, sr=sr)
```

C～Bのうちどの成分が多いかという強度が示されているみたいです。
下を実行すると可視化できるので、実際にどのように分離されているのかがわかりやすいです。

```python

plt.figure(figsize=(12,4))
librosa.display.specshow(C, sr=sr, x_axis='time', y_axis='chroma', vmin=0, vmax=1)
plt.title('Chromagram')
plt.colorbar()
plt.tight_layout()
```
![chromagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75196/34b2ebe6-0d56-1b7e-5b2d-fb42c46a73b0.png)


このへん上手くやると、なっているコードの検出とかもできそう。


### メル周波ケプストラム係数を出す

音声解析で良く使われているメル周波ケプストラム係数（mfcc）の出し方も簡単で、

```python

mfcc = librosa.feature.mfcc(S=log_S, n_mfcc=13)
```
で出せます。
引数のn_mfccで特徴量の次元を指定できます。



チュートリアルでは、mfccにさらに処理を行う、delta mfc やdelta^2 mfccも求めていますが、これが何をしているかが理解できてません。。

ほかにもまだまだ面白いのがありますが、いったんここまで。

---

2019/12/26 追記

- log_Sを求める関数がlogamplitudeだったので、amplitude_to_dbに修正しました。
- `librosa.display` が必要になるようになっていたので修正しました。