概要
今回はpythonを用いて音声データから音声強調(SE: Speech Enhancement)をやってみます。
音声強調はノイズのある音声から音声を強調し、ノイズを抑制する技術です。
雑音がある環境下での音声認識など、音声を強調する技術は今後より重要になっていくと思います。
音声強調は簡単なフィルタリングによるものなどが以前から研究されてましたが、最近では深層学習を用いたものが多いみたいですね。
音源も単チャンネルで行うものや、複数チャンネルを用いるものがあります。
今回はConv-tasnetによる学習済みモデルを用いて簡単に利用する方法を紹介します。
ESPNetのチュートリアルとほとんど同じですが、参考になればうれしいです。
やってみます
ESPNet2を使います。ESPNet2はEnd-to-Endの音声処理に関するモデルを扱うオープンソースツールキットです。音声強調だけでなく、音声に関する最先端のことがたくさんできます。
用いるライブラリはespnet2です。インストールは pip install espnet で。
https://github.com/espnet/espnet
環境はwindows、python3.7です。ちょっとインストールに手間取ったけどメモするの忘れてました。。。
用いるモデルはConv-tasnetで学習したもので、CHiME example pretrained Conv-Tasnet(Googleドライブからダウンロードして解凍します。
音声は日本声優統計学会というところからお借りしました。
https://voice-statistics.github.io/
上村彩子さんの声を用いています。
ノイズにはmixkit.coの音源をお借りしました。
https://mixkit.co/free-sound-effects/city/
mixkit-walking-crowd-at-subway-station-loop-358.wavを用いてます。
プログラム
ざっくり説明すると以下のような感じです。
- ライブラリを読み込む
- 音声強調のモデルを読み込む
- 音声とノイズのデータを読み込み、足し合わせる
- 音声強調して出力
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 |
from espnet2.bin.enh_inference import SeparateSpeech import librosa import soundfile as sf def wav_read(path): wave, fs = librosa.core.load(path, sr=22050, mono=True) return wave, fs if __name__ == "__main__": # 音声強調モデル enh_model = SeparateSpeech( enh_train_config="chime_tasnet_singlechannel/exp/enh_train_enh_conv_tasnet_raw/config.yaml", enh_model_file="chime_tasnet_singlechannel/exp/enh_train_enh_conv_tasnet_raw/5epoch.pth", normalize_segment_scale=False, show_progressbar=True, ref_channel=4, normalize_output_wav=True, device="cuda:0", ) source_voice = "src/uemura_normal_002.wav" wave_voice, fs = wav_read(source_voice) source_noise ="src/mixkit-walking-crowd-at-subway-station-loop-358.wav" wave_noise, fs = wav_read(source_noise) wave_mixed = wave_voice + wave_noise[:len(wave_voice)]*0.1 # ノイズを合成(0.1を乗じてます) source_mixed = source_voice.split(".")[0] + "_mixed" + ".wav" sf.write(source_mixed, wave_mixed*5, fs) # 合成した音声を書き出し wave_enhanced = enh_model(wave_mixed[None, ...], fs) source_enhanced = source_voice.split(".")[0] + "_enhanced" + ".wav" sf.write(source_enhanced, wave_enhanced[0].squeeze(), fs) # 強調した音声を書き出し |
実行結果
元の音声
ノイズを合成した音声
音声強調を行った音声
一応波形はこんな感じです。耳で聞いたイメージ通りですね。
無音区間も綺麗に抑制できています。
ちょっと違和感がありますが結構いい感じに雑音が抑制できているなと思いました。
あとは深層学習を用いているので計算時間がちょっとかかるのも障害になる場面が多いのかと思いました。
用途次第で色々な技術を使い分けることが必要だと思いました。
参考
音源分離の話ですが分かりやすかったです↓
https://ys0510.hatenablog.com/entry/single_separation_survey
コメント