見出し画像

  YOASOBI「アイドル」の音響分析(2):テンポ・リズムの可視化  

「小説を音楽にする」というユニークなコンセプトで注目を集めるユニット、YOASOBI。彼らの楽曲「アイドル」を題材に、Pythonの強力な音楽分析ライブラリLibrosaを使った音響分析の方法を解説します。Librosaは、音楽データからテンポ、リズム、ピッチなど、様々な情報を抽出するためのツールです。
音響分析データを使えば、例えば、YOASOBIの各曲の分類や、お気に入りの曲の機械学習モデルを作成して、ストリーミングから気に入りそうな曲をピックアップしたりすることができます。

この記事では、Librosaを用いて「アイドル」のテンポに焦点を当てた分析を行います。楽曲全体のテンポ(BPM)はもちろん、曲中でテンポがどのように変化していくのか、そして楽曲のリズム構造まで、音楽の重要な要素をLibrosaでどのように分析できるのかを、具体的なコードと分析結果とともに分かりやすく解説します。

具体的には、以下の3つの分析項目について、コードと結果を詳細に解説します。

  1. 基本テンポの推定: 楽曲全体の基本的なテンポ(BPM)を推定します。      

  2. テンポチェンジの可視化: 曲中でテンポがどのように変化していくのかを視覚的に表現します。

  3. リズムに関する情報: リズムのパターンや特徴を分析するためのデータを可視化します。


なぜYOASOBIの「アイドル」?

「夜に駆ける」以来のYOASOBIのファンだからです。
「アイドル」は2023年に世界的に大ヒットした曲です。
構成が複雑で、転調、テンポチェンジされていたりラップも含まれていますので、音響分析の対象として面白そうです。
譜面つきの演奏動画や、曲の解析記事も多く、音響分析結果と照合することができます。

Librosaとは

Librosaは、データサイエンスに強いプログラミング言語のPythonで使える、音楽信号や音声信号の解析や処理を専門とする強力なライブラリです。音楽や音声の研究、開発において、幅広く利用されています。テンポやキーなどの曲情報やMFCCなどの音声の特徴量を抽出できます。Librosaのdocumentationサイトには、各関数のアルゴリズムに関する論文が引用されていて、アルゴリズムを確認することができるのでとても安心感があります。

これまで、Librosaを使ってAdoさんとIKURAこと幾田りらさんの歌声のMFCC特徴量から学習モデルを作成して、幾田りらさんのような透明感のあるシンガーの探索を楽しんだりもしています。YouTubeやストリーミングサイトなどのレコメンドに満足できない方には、音響分析から自分だけのレコメンドシステム用の様々な小さな学習モデルを作成してみてはいかがでしょうか。

Pythonのコードと実行結果

「アイドル」のmp3ファイルはAmazonのデジタルミュージックで購入しました。
プログラミングと実行環境は、Google Colab Proを使っています。Google アカウントでブラウザ上でコーディングと実行ができるので、PCに依存せずにメモリー容量を拡張したり、GPU/TPUも利用で、機械学習、特に深層学習に適しています。

Install & Import

pip install librosa
import librosa
import matplotlib.pyplot as plt    
import numpy as np   

テンポ (beats/minute) の推定

Librosaでテンポを算出する関数の
librosa.beat.beat_track()を使います。
注意点は、sr(sampling rate)の指定です。srを指定しないとデフォルトの22050になりますが、読み込むmp3のsampling rateに合わせるためにsr=Noneにします。

# Run the  beat tracker
y, sr = librosa.load('アイドル.mp3', sr=None)  
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr)
print('Estimated tempo: {:.1f} beats per minute'.format(tempo[0]))

出力: Estimated tempo: 166.7 beats per minute

Spotify Apiで取得できるSpotify Featuresのtempoやアイドルのドラム演奏動画の譜面では166ですので、かなり正確に推定できています。

Beat_framesの差分からテンポチェンジを調べる

ibrosa.beat.beat_track()では、tempoの他に、検出したbeatのframeの位置beat_framesも算出します。frame数単位ですので、時間単位に変換して、beat間の差分プロットして、テンポチェンジを調べました。

y, sr = librosa.load('アイドル.mp3', sr=None)
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr)

#Convert the frame indices of beat events into timestamps
beat_times = librosa.frames_to_time(beat_frames, sr=sr)

# Calculate the differences between consecutive beat times
beat_differences = np.diff(beat_times)

# Create the plot
plt.figure(figsize=(12, 6))
plt.plot(beat_differences)
plt.xlabel('Beat Index')
plt.ylabel('Time Difference (seconds)')
plt.title('Difference between beat times')
plt.grid(True)
plt.show()

2Dメロでテンポダウンして、3Cサビでややテンポアップ、4Cサビでさらにアップして基本テンポに戻っていることがわかります。

Tempogramでテンポチェンジを可視化する

Tempogramは、楽曲の時間的なテンポ(BPM)の変化を分析するための手法です。音楽のリズム構造を視覚的に表現し、楽曲全体のテンポだけでなく、曲中でテンポがどのように変化していくのかを視覚的に把握するのに役立ちます。
librosa.feature.tempogram()関数を使ってTempogramを算出できます。Librosaでは、自己相関テンポグラムと呼ばれる手法が用いられています。これは、楽曲のonset_envelope(音の立ち上がりの強さ)の自己相関関数を計算し、テンポを推定する方法です。

y, sr = librosa.load('アイドル.mp3', sr=None)
tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr)
oenv = librosa.onset.onset_strength(y=y, sr=sr, hop_length=hop_length)
tempogram = librosa.feature.tempogram(onset_envelope=oenv, sr=sr)

# plot
fig, ax = plt.subplots(figsize=(8, 5))
#times = librosa.times_like(y=y, sr=sr)
librosa.display.specshow(tempogram, sr=sr, 
                         x_axis='s', y_axis='tempo', cmap='magma',
                         ax=ax)
ax.axhline(tempo[0], color='w', linestyle='--', alpha=1,
            label='Estimated tempo={:g}'.format(tempo[0]))
ax.legend(loc='upper right')
ax.set(title='Tempogram')
x = np.linspace(0, tempogram.shape[0] * float(hop_length) / sr,
                num=tempogram.shape[0])

上のプロットで、⇧のところ、すなはち2Dメロ、3Cサビでテンポチェンジしていることがわかります。

それでは、テンポチェンジしている、2Dメロと3Cサビの部分のテンポを推定しました。

2Dメロのテンポ推定
130〜150sの部分のテンポ推定をおこないました。

y, sr = librosa.load('アイドル.mp3', sr=None, offset=130, duration=20)
tempo, beat = librosa.beat.beat_track(y=y, sr=sr)
print('Estimated tempo: {:.1f} beats per minute'.format(tempo[0]))

出力: Estimated tempo: 147.7 beats per minute

3Cサビのテンポ推定
150〜160sの部分のテンポ推定をおこないました。

y, sr = librosa.load('アイドル.mp3', sr=None, offset=150, duration=10)
tempo, beat = librosa.beat.beat_track(y=y, sr=sr)
print('Estimated tempo: {:.1f} beats per minute'.format(tempo[0]))

出力: Estimated tempo: 156.6 beats per minute

Tempogram ratio: リズムに関する特徴量

ibrosaにおける tempogram_ratio は、テンポグラム比率の特徴。スペクトル リズム パターンとも呼ばれます。[1]
この関数は、テンポの重要な倍数におけるエネルギーを要約します。たとえば、テンポが 4 分音符の周期に対応する場合、テンポグラム比率は、8 分音符、16 分音符、2 分音符、全音符などの周期、および付点音符と 3 連音符の比率におけるエネルギーを測定するそうです。

[1]Peeters, Geoffroy. “Rhythm Classification Using Spectral Rhythm Patterns.” In ISMIR, pp. 644-647. 2005.

y, sr = librosa.load('アイドル.mp3', sr=None)
onset_env = librosa.onset.onset_strength(y=y, sr=sr,aggregate=np.median)

tempogram = librosa.feature.tempogram(y=y, sr=sr)
tgr = librosa.feature.tempogram_ratio(tg=tempogram, sr=sr)

plt.figure(figsize=(8,4))
librosa.display.specshow(tgr, x_axis='s', sr=sr)
plt.title('Tempogram ratio')
plt.minorticks_on()
#plt.tight_layout()
plt.show()

縦軸には下表の13種の音符のエネルギー特徴量の推移が可視化されています。
tempoと合わせて、テンポとリズムでYOASOBIの曲の分類をしたり、学習モデルを作成して似たようなリズムの曲を探索することができそうです。

いいなと思ったら応援しよう!