Pythonの音楽分析モジュールLibROSA
には、v.0.7から線形予測分析(https://ja.wikipedia.org/wiki/%E7%B7%9A%E5%BD%A2%E4%BA%88%E6%B8%AC%E6%B3%95)を行う関数librosa.lpc
が追加されました。
線形予測分析は音声の音素や声色を分析するのによく利用されています。
今回は、このlibrosa.lpc
の紹介と、利用例として歌声に適用してみたいと思います。
librosa.lpc
の仕様
librosa/audio.py at main · librosa/librosa · GitHub
a = librosa.lpc(y, order)
- y: np.array
- モノラル信号(時間領域)
- order: int
- 線形予測次数
- 線形予測分析で抽出する周波数スペクトル包絡の細かさを操作する
- 大きい値になるほど、より細かい包絡成分を抽出する
- サンプリング周波数にも依るが、12~24くらいがよく使われている
- a: np.array
- 線形予測係数
- この係数をIIRフィルタの分母項の係数とすることで、そのフィルタは分析音源の周波数包絡を表す
librosa.lpc
の実行例
分析する音源は、以下の合成音声(初音ミク)を使いました。
まず、librosa.display.specshow
を使って2次元プロットしてみます。すると音声の音素ごとに線形予測係数のIIRフィルタの周波数応答が変わっていることが確認できます。
もう少し分かりやすい例として、各時間のスペクトル包絡を動画にしてみました。
この結果から、音声の音素変化とともに周波数スペクトル包絡が変化し、また、同じ音素では周波数スペクトル包絡が似ていることが確認できます*1。
以上より、LibROSAの線形予測分析モジュールlibrosa.lpc
を使うことで歌声の音素成分が分析できることを確認しました。
ソースコード
filepath = "audio/miku_doremi120.wav" sr = 16000 y, _ = librosa.load(filepath, sr=sr, mono=True) # パラメタ order = 12 #線形予測次数 frame_length = 320 #線形予測する信号長(フレーム長) length = y.shape[0] n_frame = length // frame_length worN = 513 #周波数応答プロット用 envelope = np.zeros((worN, n_frame)) eps = 1e-3 for k in range(n_frame): slc = slice(k*n_frame, (k+1)*n_frame) print(k) try: a = librosa.lpc(y[slc], order) freqs, h = scipy.signal.freqz(1.0, a, worN=worN) envelope[:,k] = np.abs(h) except FloatingPointError: pass env_min = -120 with np.errstate(divide='ignore'): envelope = 20 * np.log10(envelope/np.max(envelope)) envelope[envelope<env_min] = env_min plt.clf() librosa.display.specshow( envelope, sr=sr, hop_length=frame_length, x_axis='time', y_axis='log', cmap="jet" ) plt.colorbar(format='%+2.0f dB') plt.title(f"Spect
*1:なお、LPCでは基音が高い音声の分析は苦手としており、最後の方は基音が高いためFoにLPCが引っ張られていることも確認できます。ラグ窓かけたりしたら多少はマシになるかもしれません