前回の記事では、適応ノッチフィルタを使って音高が未知の正弦波を除去しました.
しかし、正弦波が複数ある区間ではうまく動作しませんでした。
そこで、今回は複数の正弦波を除去できる、多段適応ノッチフィルタを紹介します。
また、多段適応ノッチフィルタの活用方法としてドラム・打楽器音を抽出してみます。
多段適応ノッチフィルタの構成
[px]
構成方法としては、任意の数の適応ノッチフィルタを直列で接続すればOKです。
基本的には、接続した適応ノッチフィルタの数だけパワーの大きいサイン波を除去できます。
しかし、適応ノッチフィルタの数が除去したいサイン波の数を超えている場合、所望信号の周波数成分を削ってしまい音質が劣化する恐れがあります。
実装
前回実装したAdaptiveNotchFilter
クラスを単純に直列接続しています。
if __name__ == "__main__": filepath = "./music.wav" savefilepath = "./save.wav" sig, sr = sf.read(filepath, always_2d=True) M = 8 #16 #32 anf_list = [[AdaptiveNotchFilter(sr), AdaptiveNotchFilter(sr)] for m in range(M)] current_frame = 0 blocksize = 512 tmpdata = np.zeros((blocksize, sig.shape[1])) tmpdata2 = np.zeros((blocksize, sig.shape[1])) savedata = np.zeros(sig.shape) def callback(outdata, frames, time, status): global current_frame, tmpdata, tmpdata2, anf, anf_list chunksize = min(sig.shape[0] - current_frame, frames) tmpdata[:] *= 0.0 tmpdata[0:chunksize] = sig[current_frame:current_frame + chunksize] for m in range(M): for k in range(outdata.shape[1]): anf_list[m][k].online(tmpdata[:,k], tmpdata2[:,k]) tmpdata[:] = tmpdata2 tmpdata2[:] *= 0.0 outdata[:] = tmpdata if chunksize < frames: raise sd.CallbackStop() else: savedata[current_frame:current_frame + chunksize] = outdata[:] current_frame += chunksize event = threading.Event() with sd.OutputStream( samplerate=sr, blocksize=blocksize, channels=sig.shape[1], callback=callback, finished_callback=event.set ): event.wait() sf.write(savefilepath, savedata, sr)
適用結果
■正弦波1~2本+白色雑音(前回の記事の音源)
まず、前回と同じ「正弦波1~2本+白色雑音」の音源に適用してみました。
適応ノッチフィルタの数は 8 としています。
上図は入力信号の波形・スペクトログラム、下図がフィルタリング後の信号の波形・スペクトログラムです。
前回は2つの正弦波が同時になっている区間ではうまく除去できていませんでしたが、今回は除去できていることが確認できます。
■オルゴール 次に、正弦波として除去できそうな楽器音であるオルゴールの音で試してみました。
適応ノッチフィルタの数は 8 としています。
こちらも綺麗に除去できており、鳴り始めのアタック音のみ残っています。
■楽曲 (白亜の庭園、白昼の夢) 最後に、楽曲信号に対して多段適応ノッチフィルタを適用できるか試してみました。
適応ノッチフィルタの数は 8, 16, 32 の3パターンを比較しました。
予想通り、適応ノッチフィルタの数が増えるほど打楽器的な音のみが残りますが、音質の劣化も確認できます。
まとめ
多段適応ノッチフィルタで複数の正弦波を除去/ドラムや打楽器音の抽出を試してみました。
C言語でのプログラミングやチューニングのコツについては、プログラム101付き 音声信号処理 が参考になると思います。