Pythonで簡単にwavファイルのノイズキャンセルを行う方法

  • このエントリーをはてなブックマークに追加

マイクで音声を録音した時、録音環境によっては不快なノイズが入ってしまいます。Pythonの外部ライブラリであるnoisereduceは難しいコードなしに簡単にノイズキャンセルをかけることができます。実波形を例にその特徴を解説します。

こんにちは。wat(@watlablog)です。今回はライブラリの力を借りてノイズキャンセルのコードを検証してみます

noisereduceでノイズキャンセルするPythonコード

noisereduceについて

今回はnoisereduceという外部ライブラリを使ってノイズキャンセルを行います。noisereduceの公式ドキュメントは以下のGitHubをご確認ください。

Advertisements

GitHub:https://github.com/timsainb/noisereduce

信号処理技術におけるノイズ除去は古くから歴史があり、スペクトル・サブトラクションウィーナーフィルタといった様々な方法があります。

今回紹介するnoisereduceは、公式ページからするとNoise Gateという手法を使っているとのことです。

この方法は信号の入力レベルにより閾値を設け、閾値を超えた信号をPassするもの…と読み取れますが、まだ詳しく学んでいないので詳細は以下のWikipediaに丸投げします。

Wikipedia:Noise Gate

この記事では単純にnoisereduceを使ってみた結果を紹介します。まずはpip install noisereduceでライブラリをインストールしましょう。

動作環境

本記事のPython環境は以下のとおりです。フーリエ変換で周波数成分を確認するためにSciPy等も使っています。

     
Python Python 3.9.6
PyCharm (IDE) PyCharm CE 2020.1
Numpy 1.21.1
Scipy 1.4.1
matplotlib 3.4.3
PySoundFile 0.9.0.post1
noisereduce 2.0.1

サンプルのwavファイル

noisereduceは録音された信号波形とは別に、背景ノイズの波形も必要です。コード内で使用するサンプルのwavファイルを用意しました。ダウンロードしてお使いください。

ピアノの音

Piano-A5.wavは筆者所有の電子ピアノの音をケーブルを使ってMacbookに取り込んだ音声です。5番目のA(ラ)の音を打鍵しました。

※再生ボタンクリックで音が出ます。

ハムノイズ

Ham-Noise.wavは打鍵していない時の背景ノイズです。ブーという音が鳴っています。

※再生ボタンクリックで音が出ます。

電子ピアノからケーブルでPCに接続していますが、どうやら電源ノイズ(いわゆるハムノイズ)が入っているようです。通常はそのようなノイズが入らないように録音するのが良いのですが、今回は良いサンプルとして使いましょう。

サンプル音声の波形観察

二つの音声を比較します。波形全体を観察すると、Piano-A5.wavは暗ノイズに比べて十分大きな振幅を持った減衰自由振動をしていることがわかります。

音声ファイルの波形

しかし無音区間を拡大すると、特徴的な時間波形になっていることがわかりました。二つのファイルは別々に録音されたものなので、位相はずれています。

電源ノイズ部分

周波数領域で見るとノイズは50[Hz]の倍数で綺麗に高周波帯域まで存在していることがわかります。これがブー音の正体ですね。

サンプル音声の周波数波形

A5音の基本周波数である440[Hz]近傍がこちら。noisereduceでどこまで消せるのか、試してみましょう。

サンプル音声の周波数波形(拡大)

noisereduceのサンプルコード

noisereduceはノイズを除去したい信号yとノイズのみの信号y_noise、サンプリングレートsrを指定して実行します。

今回は定常のノイズであるため、stationary=Falseにする必要があります(デフォルトのTrueだと非定常のノイズ除去になる)。

この辺は公式ページを参考にしてください。

波形プロットやwavファイルの入出力を追加した全コードを以下に示します。

このコードを実行すると、読み込んだ波形や周波数分析の結果がプロットされていき、プログラム実行ディレクトリにNC-Piano-A5.wavという新しい音声ファイルが作成されます。

実行結果

下図が元音声とnoisereduceによるノイズキャンセル後の音声を比較した周波数波形です。

ノイズキャンセル後の周波数波形

拡大するとこちら。見事50[Hz]の倍数成分の消失を確認できます…が、ちょっと気になる点として、振幅成分が大きく変化している部分を挙げることができます。

ノイズキャンセル後の周波数波形(拡大)

時間波形を見ると明らかです。ノイズを強力に除去することはできたものの、原音声から遠ざかってしまう結果となりました。

ノイズキャンセル後の時間波形比較

ノイズキャンセル後の音声を再生できるようにしてみました。減衰が大きく、すぐに音が消えてしまうという結果です。

※再生ボタンクリックで音が出ます。

時定数time_constant_sを5等に増やしたり、prop_decreaseを0.5等に減らすと減衰度合いは減ってきますが、ノイズ低減効果も薄れてしまうようです。

まとめ

この記事ではnoisereduceというPythonの外部ライブラリを使ってノイズキャンセルをしてみました。元音声とノイズ音声を使うというのは直感的にわかりやすく、強力なノイズ低減の効果を確認することができました。

サンプルで用意した音声は録音時によく問題となる電源ノイズが混入したファイルでしたが、noisereduceによって完全に消すことができました。

しかし減衰が大きく元音声の特徴も崩してしまうこともわかりました。
ここは設定の仕方で改善できるかも知れませんが、何かしらフィルタをかけるというのはそういうことなのかも知れません。

例えば会議のレコーディングノイズを除去するといった場合にこのライブラリはかなり活用できそうです。

しかし、原音をできる限り維持させつつノイズだけ消したいといった目的には別の手法を考えた方が良いでしょう(その場合はやはりハード的な対策しかないかも)。

ノイズ除去の分野は奥が深そうですが、1行で使えるノイズ低減コードを手に入れることができました!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!

SNSでもご購読できます。

コメントを残す

*