音声データのノイズ除去

時間や場所にとらわれずに柔軟な働き方を実現する「Web会議」。すっかり身近になりましたね。

Web会議は、必要な時にその場ですぐに会議を開催することができるので、情報共有や意思決定を迅速に行うことができます。日程調整もしやすいので、参加者の予定を合わせやすいですね。ただ、ブレストのような自由に意見を出し合う類いの打合せは、ちょっと向いてないかなと最近感じます。座ったままPCと睨めっこ状態だと、なかなか良いアイデアも生まれてきません。これも慣れなのかしら。

ここでWeb会議あるある、です。

1. ミュートしたまま話続ける
相槌や意見を言い続けたのに、ミュートだったと気付いた時は虚しさ半端ないです。

2. 思わぬ来客
宅配便でーす!ご飯まだー?にゃあ。
日常が見えて、微笑ましいですね。

3. 雑音トラブル
カタカタカタ…ガタンゴトンガタンゴトン…どんがらがっしゃーん!
なかなか自分では気付かないことが多いです。

などなど...
どうでしょう。みなさんも思い当たるふしがあるかと思います。

さて、今回は「3. 雑音トラブル」をPythonで解決してみましょう!

ノイズ除去処理の流れ

  1. 高速フーリエ変換FFT)を用いて、ノイズデータの周波数成分を取得。あるアルゴリズムにより、ノイズと見なすしきい値を計算する。

  2. 高速フーリエ変換FFT)を用いて、ノイズを含む音声データの周波数成分を取得。1のしきい値によりノイズの部分をマスクする。

  3. 音声として復元する。

が大まかな処理の流れとなります。 pypi.org 今回は、こちらの「noisereduce」ライブラリを使用します。簡単にノイズ除去を試すことができます。

1. ライブラリの定義

import IPython
from scipy.io import wavfile
import noisereduce as nr
import soundfile as sf
from noisereduce.generate_noise import band_limited_noise
import matplotlib.pyplot as plt

2. 音声データの読み込み

data, rate = sf.read('voice.wav')
fig, ax = plt.subplots(figsize=(20,3))
ax.plot(data)

f:id:KenjiU:20200607215236p:plain
音声データ

3. ノイズデータの読み込み

noise_data, noise_rate = sf.read('noise.wav')
IPython.display.Audio(data=noise_data, rate=noise_rate)

fig, ax = plt.subplots(figsize=(20,4))
ax.plot(noise_data)

f:id:KenjiU:20200607215240p:plain
ノイズデータ

4. ノイズを含んだ音声データを生成

snr = 2 # signal to noise ratio
noise_clip = noise_data/snr
audio_clip = data + noise_clip
IPython.display.Audio(data=audio_clip, rate=noise_rate)

fig, ax = plt.subplots(figsize=(20,4))
ax.plot(audio_clip)

f:id:KenjiU:20200607215247p:plain
ノイズを含んだ音声データ

5. ノイズを除去し音声として復元

なんと以下のたったの一行でノイズ除去が実現できてしまいます。

noise_reduced = nr.reduce_noise(audio_clip=audio_clip, noise_clip=noise_clip, verbose=True)

f:id:KenjiU:20200607215254p:plain
ノイズ
f:id:KenjiU:20200607215257p:plain
ノイズと見なすしきい値を計算
f:id:KenjiU:20200607215312p:plain
入力音声データ
f:id:KenjiU:20200607215318p:plain
ノイズの部分をマスク
f:id:KenjiU:20200607215333p:plain
音声として復元

IPython.display.Audio(data=noise_reduced, rate=rate)

どうでしょう。完璧とは言えませんが、雑音トラブル無事解決!?

fig, ax = plt.subplots(figsize=(20,3))
ax.plot(noise_reduced)

f:id:KenjiU:20200607215336p:plain
ノイズ除去済み音声データ

今回は以上です!
1/fゆらぎのBGMを聞いていたら眠くなってきました( *˘ω˘)スヤァ…