【MATLAB】ローパスフィルタで音声からセミの鳴き声をカットする

授業で習った [ローパスフィルタ](https://ja.wikipedia.org/wiki/%E3%83%AD%E3%83%BC%E3%83%91%E3%82%B9%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF) を使って何か面白いことできないかな？と思ってやってみたら良い感じになって楽しかったのでメモしておきます．

ローパスフィルタは特定の周波数までの成分のみを通過させるフィルタで，高周波の音をカットできます．
今日は7月25日で，セミがうるさいです．[セミの鳴き声は2000～9000Hz](http://www.tokorozawa-stm.ed.jp/center/kiz_tokorozawa/Nakumusi2001/naku2/02.htm)，[ヒトの鳴き声は大体100～1000Hz（男性500Hzくらい）](https://www.chiyoda-ute.co.jp/data/syaon.html)らしいので，1000Hzくらいでカットすると良い感じにノイズ（セミの声）を除去できそうです．そこで，MATLABを使って，セミとヒトの声が入った音声をローパスフィルタにかけてみました．

MATLABの使用には有料ライセンスが必要なので，持ってない人は購入するか，互換性のある[Octave](https://octave.org/)などを使うとよいのではないでしょうか（Octaveで本記事と同様のことができるかは不明）．私の場合は大学からライセンスをもらうことができました．MATLAB R2019bというバージョンを使いました．



## 1. 音声ファイルの準備
セミと一緒に適当に喋ったのをiPhoneのデフォルトアプリの[ボイスメモ](https://apps.apple.com/jp/app/%E3%83%9C%E3%82%A4%E3%82%B9%E3%83%A1%E3%83%A2/id1069512134)で録音しました．
録音に使うアプリはなんでもいいです．このアプリでは .m4a という拡張子でしか書き出せないようなので，[こちらのサイト](https://convertio.co/ja/m4a-wav/)で，MATLABが読み込める .wav という拡張子に変換しました．

## 2. wavファイルをMATLABで読み込む
MATLABのカレントディレクトリに .wav ファイルを置きます．カレントディレクトリはMATLABの上の方で確認できます．
![cd.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/203949e3-980d-dda2-ceee-02797eb9a72b.jpeg)

MATLABでの音声の読み込みには以下のコードを用います．'semi.wav' の部分にwavファイルの名前を入れてください．詳しくは[MATLABの公式サイト](https://jp.mathworks.com/help/matlab/ref/audiowrite.html)を見たほうがいいです．
```MATLAB
[y, Fs]=audioread('semi.wav');
```

sound関数で音を鳴らすことができます．セミの声と僕の声が聞こえました．
```MATLAB
sound(y,Fs);
```
plot関数で波形をプロットすることができます．
```MATLAB
plot(y)
```
こんな感じになりました．
![semi_original.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/c9a1db9b-f9de-a363-1e51-b87f242736ea.png)

## 3. ローパスフィルタにかける
2.で読み込んだ音を，500Hzまで通過するローパスフィルタにかけてみます．ローパスフィルタ関数について詳しくは[公式サイト](https://jp.mathworks.com/help/signal/ref/lowpass.html)をご覧ください．
```MATLAB
y1=lowpass(y,500,Fs)
```
グラフが勝手に出ます．MATLABが日本語だとグラフのタイトルや凡例が日本語になってちょっとださいです．
![semi_lowpass500_graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/36407de6-3326-e5b2-9514-0f4fa4d09ce2.png)

lowpass関数の実行ですでに出ていますが，波形が重なっていて見づらいので，一応y1（処理済み音声）もプロットしてみます．
```MATLAB
plot(y1)
```
レポートなどで提出する場合は軸の範囲や縦横比をきちんとそろえて，ラベルや単位も忘れずに追加ください．
![semi_lowpass500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459660/43001265-c9d9-bdf3-fb35-af90fb31aad1.png)
フィルタにかける前の波形と比べると明らかに振動数が少なくなっており，高周波成分がカットされていそうなことがわかります．

soundで処理済みの音声を聴いてみましょう．
```MATLAB
sound(y1,Fs)
```
僕の声だけになっていました．セミさんさようなら！
<br/>

YouTubeに処理前後の音をアップしました．聴いてみてください（いきなり音が出るので注意）．
<br/>
<iframe width="560" height="315" src="https://www.youtube.com/embed/q1ml5JtIuf0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<iframe width="560" height="315" src="https://www.youtube.com/embed/HGY4DqIR5f8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


## 4. 処理済みファイルの保存
filenameを指定して，処理した音声ファイルを保存できます．
```MATLAB
filename = 'semi_lowpass_500Hz.wav';
audiowrite(filename,y1,Fs)
```

<!--https://github.com/Tom4c3/wav_storage/blob/main/semi.wav?raw=true

<audio controls src="https://github.com/Tom4c3/wav_storage/main/semi.wav">
-->


## まとめ
MATLABのローパスフィルタでセミの声を除去することができました．
適当に500Hzでローパスかけたらいい感じになったので満足して終わりました．
僕の声も少しカットされて小さくなっている感じがあるので，600Hz，1000Hzとかもう少し高い周波数で試してもよさそうです．
展望としては，低い周波数のノイズもカットするためにバンドパスフィルタにしたり，今回とは逆にハイパスフィルタでセミの鳴き声のみを取り出したりすることなどが挙げられます．
今回は特定の周波数でカットしただけなのでヒトの声と同じ周波数帯のノイズはカットできませんが，ノイズキャンセルイヤホンなどは機械学習で音を判別してカットとかしてるんですかね．

MATLABで実際の音声データをフィルタ処理している記事はあまりなかったので書いておきました．参考になった方がいれば嬉しいです．