Pythonで音声処理(5)オーバーラップ+窓関数

IT

前回の記事では、リアル音声の周波数をグラフ化し、リアル音声処理を実施する上での課題について説明しました。

今回は、リアル音声を周波数解析する上で必要となる、オーバーラップ処理と窓関数の実装について、解説していきたいと思います。


今回作成するプログラムの流れは、次のようにします。

1.音声を読み込む。

2.オーバーラップ+窓関数処理を行い、一定時間ごとの音声データ群を作成する。

3.各音声データに対してFFT処理をかけて、周波数データ群を作成する。

4.周波数データ群に逆FFT処理をかけて、音声データ群に戻す。

5.音声データ群を元の音声に戻す。


一定時間ごとの周波数データに変換して、何もせずに元の音声データに戻すプログラムです。

このプログラムができてしまえば、あとは自由に周波数解析が可能になります。

では、早速プログラム全体を見ていきましょう。

少し長いですが、やっていることは上記の通りです。

今回追加したオーバーラップ+窓関数処理を見ていきましょう。

61行目で、オーバーラップ+窓関数処理の関数「half_overlap_win」の定義を開始しています。一定時間毎の音声データを作成しますが、半分をオーバーラップさせるため「half」という名前をつけています。引数として、音声データのL、RそれぞれのデータとWavファイルの情報、切り取る大きさ(ウインドウサイズ)をインプットします。

62、63行目では、オーバーラップ+窓関数処理をかけたあとの音声データをリストとして返すための戻り値配列を作成しています。

64行目では、ウインドウサイズに合った窓関数を定義しています。窓関数は最も一般的なハニング窓を利用します。

65行目〜73行目のループで、音声信号を切り取り配列に格納していきます。

65行目は、forループのループ方法を定義しています。iを0からウインドウサイズの半分ずつ加えていき、音声の最後になるまでループします。

66行目で、endi=i+ウインドウサイズを計算しています。

67行目のif文は、endiが音声データの最後を超えてしまう場合があるので、超えていない場合と超える場合で処理を分けています。68行目、69行目は超えない場合の処理です。

68、69行目で、i〜endiで音声データを切り取り、ハニング窓を乗算した上で、戻り値配列に追加しています。

70行目〜73行目は、endiが音声データの最後を超えてしまう場合の処理です。この場合、ハニング窓の大きさも変わってくるので、71行目で再定義します。

72、73行目で、i〜音声データの最後までを切り取り、ハニング窓を乗算した上で、戻り値配列に追加しています。

74行目で、LとRそれぞれのデータを戻り値として返しています。


続いて、切り取った音声データを元の音声データに戻す関数定義について見ていきましょう。

77行目で、切り取った音声データを元の音声データに戻す関数「return_how」の定義を開始しています。「how」は「half_overlap_win」の略です。引数として、LとRそれぞれの配列とWavファイルの情報、ウインドウサイズをインプットします。

78、79行目で、LとRそれぞれの元音声データを入れるための変数を定義しています。オーバーラップしたデータを加えるため、データは予めゼロ埋めしておきます。

80行目でforループを定義しています。iを0から配列の最大サイズまでループします。ループ内ではLとRの処理を行いますが、LとRの配列サイズは同じため、Lの配列で最大サイズを取得しています。

81行目で、toにウィンドウサイズを格納していますが、配列の最後には、ウィンドウサイズ未満のデータがあるので、82行目の三項演算子により、ウィンドウサイズ未満の場合は、toに配列サイズを入れるようにします。

83行目〜85行目は、切り取った音声データの中で更にjが0からtoになるまでループします。

84、85行目で、LとRそれぞれのデータに対して、i×ウィンドウサイズの半分+jの位置に、音声データを足し込んでいきます。

86行目で、LとRそれぞれで復元した音声データを返して処理完了です。


それでは、プログラムを実行して見ましょう。

入力する音声は、前回の記事と同様「arigato.wav」です。

この音声データを本プログラムで処理して得られた「i_arigato.wav」が以下になります。

色々と処理を施したにも関わらず、ほとんど何も変わっていないことがわかると思います。

これで、周波数変更のための下準備が整いました。

次回は本プログラムに、周波数変更処理を追加して、音声処理を行いたいと思います。

コメント

タイトルとURLをコピーしました