はじめに
私はデータ分析以外の趣味としては、トランペットの演奏があります。個人でプイプイ吹いているだけのしょうもない趣味ですけどね。
先日、楽器屋に新しいマウスピース(楽器を口に当てる金属部分、振動させる部分)を買いに行ったのですが、吹いているうちによくわからなくなったので、録音した音声波形などを可視化することで、いいなと思う音がどんな波形をしているのかを明らかにしたいと思います。
進め方
- 録音データを用意(iPhoneのムービー)
- FFmpegで動画から音声のみを切り出し、サンプルレートを変え、モノラルにする
- Pythonで基本周波数(F0)などを可視化
データの準備
今回はチューニングB♭(ベー)の音3種類(Yamaha 11C4、Bach 5C、Bach 3C)と、練習曲(ルパン三世のフレーズ)の音2種類(Yamaha 11C4、Bach 5C)の計5つの音源を扱います。
マウスピースのイメージ
- Yamaha 11C4:オールマイティー(これまで使っていたやつ)
- Bach 5C:少し深くて、少し内径が小さい
- Bach 3C:少し深くて、少し内径が小さい(5Cと3Cの違いは当て心地?)
指標の説明
- 音声波形:波動の振動の大きさを表す非負のスカラー量を縦軸に、横軸を時間とした場合のグラフを音声波形と呼ぶ。
- ピッチマーク:単位波形を抽出する基準点でエポックマーカーと呼ばれる。音が鳴った際に1をとり音がない際は0を取る。
- 基本周波数:信号を正弦波の合成で表したときの最も低い周波数成分の周波数で、音程に該当する。
- 相関係数:ピッチマークの検出に使う指標でNCCF(Normalized Cross-Correlation Function)というものを使って計算している。自己相関のようなもので-1から1の間を取る。
音声ファイルのあるディレクトリで以下のコマンドを実行します。(私の環境はMacです。)
1 2 3 4 5 6 7 8 |
# チューニングベーのファイルの変換 ffmpeg -i IMG_3506.MOV -ss 2 -to 7 -ar 16000 -ac 1 b_5C.wav ffmpeg -i IMG_3506.MOV -ss 25 -to 30 -ar 16000 -ac 1 b_3C.wav ffmpeg -i IMG_3506.MOV -ss 38 -to 43 -ar 16000 -ac 1 b_11C4.wav # 練習曲のファイルの変換 ffmpeg -i IMG_3468.MOV -ss 32 -to 42 -ar 16000 -ac 1 rupin_11C4.wav ffmpeg -i IMG_3517.MOV -ss 43.5 -to 54 -ar 16000 -ac 1 rupin_5C.wav |
音声波形などの可視化〜チューニングB♭(ベー)〜
ここでは単純にチューニングベーの音を比較します。まず音源ですが、以下で実際に聴けるようになっています。(耳を痛めないように、最も小さい音で聴いてから調整してください。)
しかし、慣れないマウスピースで音程が不安定になっているのが悲しいですね。
・Yamaha 11C4のチューニングベー
・Bach 5Cのチューニングベー
・Bach 3Cのチューニングベー
以前書いたブログと同様に、pyreaperというREAPERのラッパーとなっているライブラリを用います。REAPERはGoogleが開発していて、C++で書かれています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import pyreaper import pysptk from scipy.io import wavfile from IPython.display import Audio file = "/dataset/wavefile/b_11C4.wav" fs_11c4_b, x_11c4_b = wavfile.read(file) file = "/dataset/wavefile/b_5C.wav" fs_5c_b, x_5c_b = wavfile.read(file) file = "/dataset/wavefile/b_3C.wav" fs_3c_b, x_3c_b = wavfile.read(file) # pyreaperモジュールを使ってピッチマークやF0や相関係数を計算する。 pm_times_11c4_b, pm_11c4_b, f0_times_11c4_b, f0_11c4_b, corr_11c4_b = pyreaper.reaper(x_11c4_b, fs_11c4_b) pm_times_5c_b, pm_5c_b, f0_times_5c_b, f0_5c_b, corr_5c_b = pyreaper.reaper(x_5c_b, fs_5c_b) pm_times_3c_b, pm_3c_b, f0_times_3c_b, f0_3c_b, corr_3c_b = pyreaper.reaper(x_3c_b, fs_3c_b) |
音声波形の比較
1 2 3 4 5 6 7 8 9 10 11 |
plt.plot(x_11c4_b); plt.title('11c4') plt.show(); plt.plot(x_5c_b); plt.title('5c') plt.show(); plt.plot(x_3c_b); plt.title('3c') plt.show(); |
やはり慣れている分、11c4が安定してそうな波形に見えますね。3Cは結構ブレてそうです。実際の音源でもわかりますね。
ピッチの比較
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
plt.plot(pm_times_11c4_b, pm_11c4_b, linewidth=3, color="red", label="Pitch mark") plt.legend(fontsize=15); plt.title('11c4') plt.show(); plt.plot(pm_times_5c_b, pm_5c_b, linewidth=3, color="red", label="Pitch mark") plt.title('5c') plt.legend(fontsize=15); plt.show(); plt.plot(pm_times_3c_b, pm_3c_b, linewidth=3, color="red", label="Pitch mark") plt.title('3c') plt.legend(fontsize=15); plt.show(); |
発音のあったところで1となる指標です。今回は伸ばしているだけなので、何の面白味もないです。
基本周波数(F0)の比較
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
plt.plot(f0_times_11c4_b, f0_11c4_b, linewidth=3, color="green", label="F0 contour") plt.legend(fontsize=15); plt.title('11c4') plt.show(); plt.plot(f0_times_5c_b, f0_5c_b, linewidth=3, color="green", label="F0 contour") plt.legend(fontsize=15); plt.title('5c') plt.show(); plt.plot(f0_times_3c_b, f0_3c_b, linewidth=3, color="green", label="F0 contour") plt.legend(fontsize=15); plt.title('3c') plt.show(); |
音程をつかさどるF0に関しては3Cが安定してそうです。聴いたらブレブレなのに。
相関係数の比較
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
plt.plot(f0_times_11c4_b, corr_11c4_b, linewidth=3, color="blue", label="Correlations") plt.legend(fontsize=15); plt.title('11c4') plt.show(); plt.plot(f0_times_5c_b, corr_5c_b, linewidth=3, color="blue", label="Correlations") plt.legend(fontsize=15); plt.title('5c') plt.show(); plt.plot(f0_times_3c_b, corr_3c_b, linewidth=3, color="blue", label="Correlations") plt.legend(fontsize=15); plt.title('3c') plt.show(); |
いつも使っている11c4がブレにくいようで、5Cが比較的に上下動が多いように見えます。
音声波形などの可視化〜練習曲〜
結局、マウスピースは5Cを購入して、その後スタジオで練習曲の音を比較しました。先ほどと同様に音源が以下で実際に聴けるようになっています。(耳を痛めないように、最も小さい音で聴いてから調整してください。)私は、実際に録音して、マウスピースでこんなに変わるんだと驚きを隠せないです。チューニングベーを比較するだけではわかりにくいんですかね。私としては、5Cの音の方が好きです。
・Yamaha 11C4での練習曲
・Bach 5Cでの練習曲
1 2 3 4 5 6 7 8 9 |
file = "/dataset/wavefile/rupin_11C4.wav" fs_11c4, x_11c4 = wavfile.read(file) file = "/dataset/wavefile/rupin_5C.wav" fs_5c, x_5c = wavfile.read(file) # pyreaperモジュールを使ってピッチマークやF0や相関係数を計算する。 pm_times_11c4, pm_11c4, f0_times_11c4, f0_11c4, corr_11c4 = pyreaper.reaper(x_11c4, fs_11c4) pm_times_5c, pm_5c, f0_times_5c, f0_5c, corr_5c = pyreaper.reaper(x_5c, fs_5c) |
音声波形の比較
1 2 3 4 5 6 7 |
plt.plot(x_11c4); plt.title('11c4') plt.show(); plt.plot(x_5c); plt.title('5c') plt.show(); |
5Cのほうが上下の大きさが対称に近いような印象を受けます。いい音を捉える参考になるんですかね?
ピッチの比較
1 2 3 4 5 6 7 8 9 |
plt.plot(pm_times_11c4, pm_11c4, linewidth=3, color="red", label="Pitch mark") plt.legend(fontsize=15); plt.title('11c4') plt.show(); plt.plot(pm_times_5c, pm_5c, linewidth=3, color="red", label="Pitch mark") plt.title('5c') plt.legend(fontsize=15); plt.show(); |
おそらく、11c4の音源の息継ぎのタイミングがやや長くなった結果、ピッチに差が出たのではないかと思います。
基本周波数(F0)の比較
1 2 3 4 5 6 7 8 9 |
plt.plot(f0_times_11c4, f0_11c4, linewidth=3, color="green", label="F0 contour") plt.legend(fontsize=15); plt.title('11c4') plt.show(); plt.plot(f0_times_5c, f0_5c, linewidth=3, color="green", label="F0 contour") plt.legend(fontsize=15); plt.title('5c') plt.show(); |
比較が難しいですが、最後の伸ばしは5Cのほうが安定しているようです。
相関係数の比較
1 2 3 4 5 6 7 8 9 |
plt.plot(f0_times_11c4, corr_11c4, linewidth=3, color="blue", label="Correlations") plt.legend(fontsize=15); plt.title('11c4') plt.show(); plt.plot(f0_times_5c, corr_5c, linewidth=3, color="blue", label="Correlations") plt.legend(fontsize=15); plt.title('5c') plt.show(); |
5Cのほうが上下動をしているように見えます。いいなと思う音の方が上下動しやすいのでしょうか。気になるところ。
追記:スペクトログラムの比較
どうやら音色を考えるうえで、縦軸に周波数、横軸に時間をとったスペクトログラムというものを可視化するのも良いらしいです。参考文献に従って行ってみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
import sys import numpy as np import librosa import matplotlib.pyplot as plt import scipy.io.wavfile import librosa.display ## 11C4 # 16bitの音声ファイルのデータを-1から1に正規化 data = x_11c4 / 32768 # フレーム長 fft_size = 1024 # フレームシフト長 hop_length = int(fft_size / 4) # 短時間フーリエ変換実行 amplitude = np.abs(librosa.core.stft(data, n_fft=fft_size, hop_length=hop_length)) # 振幅をデシベル単位に変換 log_power = librosa.core.amplitude_to_db(amplitude) # グラフ表示 librosa.display.specshow(log_power, sr=fs_11c4, hop_length=hop_length, x_axis='time', y_axis='hz') plt.colorbar(format='%+2.0f dB') plt.title('11c4') plt.show() ## 5C # 16bitの音声ファイルのデータを-1から1に正規化 data = x_5c / 32768 # フレーム長 fft_size = 1024 # フレームシフト長 hop_length = int(fft_size / 4) # 短時間フーリエ変換実行 amplitude = np.abs(librosa.core.stft(data, n_fft=fft_size, hop_length=hop_length)) # 振幅をデシベル単位に変換 log_power = librosa.core.amplitude_to_db(amplitude) # グラフ表示 librosa.display.specshow(log_power, sr=fs_5c, hop_length=hop_length, x_axis='time', y_axis='hz') plt.colorbar(format='%+2.0f dB') plt.title('5c') plt.show() |
5Cよりも11C4が赤い線が1つ多いように見えます。幅広く音が鳴っていてモサっとしてしまっているのでしょうか。私としては5Cの方が音が鋭くて好きです。
おわりに
音声波形で音色の比較がうまくできるかどうか試してみたのですが、良いと思われる音とそうでない音で相関係数や音声波形などのデータの可視化において違いが生じやすいのかなという印象でした。そして音色をつかさどるとされるスペクトログラムにおいても、違いがありそうでした。
もっと音源を集めていっていい音の研究をしていこうと思います。あと、音楽の理論の方も細々と学んでいきます。
参考文献
IPythonデータサイエンスクックブック ―対話型コンピューティングと可視化のためのレシピ集
pyreaperで音声データのピッチを掴むためのメモ書き(F0の抽出)
Pythonで音声解析 – 音声データの周波数特性を調べる方法
基本周波数についてのまとめ
イラストで学ぶ 音声認識 (KS情報科学専門書)