pythonで簡単な音声認識をやってみたいぞ。
そもそも何から始めればいいのかしら。
今回は,基本的な音声認識をpythonで行う方法をお伝えしていこうと思います。本記事はpython実践講座シリーズの内容になります。その他の記事は,こちらの「Python入門講座/実践講座まとめ」をご覧ください。
【超初心者向け】python入門講座/実践講座まとめ目次
入門講座
1.実行環境2.文字の出力3.データ型4.変数5.更新と変換6.比較演算子7.論理演算子8.条件分岐9.リスト10.辞...
スポンサーリンク
お題
ゼロ交差数を使って無声区間を検出してみよう。
流れ
今回対象とするデータは,私が喋った「あ」とします。音声データを貼り付けるのは,どこか恥ずかしさを覚えるため,代わりにスペクトログラムをお見せしておきます。しっかり「あ」の発音区間が見え,無声区間も含まれていることが分かります。
ゼロ交差数の概要
ゼロ交差数は,音声信号を時間領域の波形で見たときに「振幅の正負が何回入れ替わるか」を表す数値です。
ゼロ交差数でなにが分かるの?
ゼロ交差数は,信号が雑音っぽいときに大きくなり,周期信号っぽいときに小さい値をとる傾向にあります。つまり,ゼロ交差数の大小で「雑音 or それ以外」を大まかに判別できるということです。この記事では,波形信号を短いフレーム単位で切り出して,そのフレームでゼロ交差数をカウントして閾値を設けることで,各フレームが雑音(無音区間)なのか,それとも有声区間なのかを判定してみたいと思います。
実装
音声の読み込み
# [path_to_your_file]にはみなさんの使用するファイルを指定してください。
y, sr = librosa.load([path_to_your_file])
# フレームのズラす幅の指定
hop_length = 512
# フレームで切り出す回数
nms = ((y.shape[0])//hop_length)+1
# 最初と最後をフレームで切り出せるようにゼロパディング
y_bf = np.zeros(hop_length*2)
y_af = np.zeros(hop_length*2)
y_concat = np.concatenate([y_bf, y, y_af])
ゼロ交差数のカウント
zero_cross_list = []
for j in range(nms):
zero_cross = 0
# フレームによる切り出し
y_this = y_concat[j*512:j*512+2048]
for i in range(y_this.shape[0]-1):
# もし正負が変わったらという条件
if (np.sign(y_this[i]) - np.sign(y_this[i+1]))!=0:
zero_cross += 1
zero_cross_list.append(zero_cross)
# 最大値が1になるように正規化
zero_cross_list = np.array(zero_cross_list)/max(zero_cross_list)
# 閾値は0.4に設定(ヒューリスティックですが…)
zero_cross_list = (zero_cross_list<0.4)*1
可視化
spec = librosa.stft(y, hop_length=512, n_fft=2048)
logmel_db = librosa.feature.melspectrogram(sr=sr, S=librosa.power_to_db(np.abs(spec)**2), n_mels=80)
plt.imshow(logmel_db, vmin=np.min(logmel_db), vmax=np.max(logmel_db), cmap="gist_heat", aspect= "auto", origin="lower")
plt.plot(np.arange(logmel_db.shape[1]), (zero_cross_list)*10)
plt.xlabel("Time_frame")
plt.ylabel("Frequency [Hz]")
今回の可視化では,有声区間を「10」,無声区間を「0」として出力しました。かなり精度よく有声区間を推定できているのではないでしょうか。