ASPについて学ぶ-1

はじめに

今回からASP(audio signal processing)について
text to speech(TTS)タスクに対するDeep Learning
を中心に調査・検証していく。

TTS

text to speechは文字情報を音声に変換する技術である。
読み上げ技術においてはSiriに代表されるAIアシスタントなど
すでに実用化されているものも多いが、その裏にある技術
がどうなっているかを知りたい。

TTSのタスクは以下の3つの処理に分割可能
(参考 : https://www.slideshare.net/f2forest/nips2017-speech-audio-86474213)

  • テキスト解析 : 文章を音に変換しやすいように分割
  • 音響モデリング : 言語特徴量を音響特徴量に変換
  • ボコーダー : 音響特徴量から音声を合成

テキスト解析

テキスト解析は生の文章データを音響モデリングしやすいように
言語特徴量(linguistic features)に分解する。

音響モデリング

言語特徴量から音響特徴量(acoustic features)を求める。
音響特徴量としては以下のようなものが考えられる。
- 基本周波数(F0)1
- スペクトル、ケプストラム

ボコーダー

音響特徴量から実際に耳に聞こえる音声信号を生成する。
WORLDという音響特徴量抽出・ボコーダーライブラリがある。

Deep Learningアーキテクチャによっては上記の処理いくつかをまとめたものもある2

音声特徴量検証

torchaudio3を使って音声特徴量について検証した。
データは自分の音声を録音したwavファイル(あ、い、う、え、おに対応)を用いた。

音声ファイルの読み込み

import torch
import torchaudio
import matplotlib.pyplot as plt
%matplotlib inline

keys =["a", "i", "u", "e", "o"]
waves = {}
for key in keys:
  #ファイル名指定
  filename = "{}.wav".format(key)
  # ファイル名を指定するとtensorとサンプルレートが返ってくる
  waveform, sample_rate = torchaudio.load(filename)
  waves[key] = waveform
  print("Shape of waveform: {}".format(waveform.size()))
  print("Sample rate of waveform: {}".format(sample_rate))

スペクトルグラム作成

短時間フーリエ変換(STFT)は時系列の信号情報を分割して
フーリエ変換をかけることによって時間的に変化する周波数情報を
可視化するものである。
分割の端をなめらかにするためにウィンドウ関数をかける。

デフォルトで

  • ウィンドウサイズ : 400
  • ウィンドウ : ハン窓関数(cos)
  • ホップサイズ (ウィンドウをずらす幅): ウィンドウサイズの半分
fig, _ = plt.subplots(figsize=(20, 6), ncols=5)

for n, (k, waveform) in enumerate(waves.items()):
  specgram = torchaudio.transforms.Spectrogram()(waveform)
  fig.axes[n].imshow(specgram.log2()[0,:,:].numpy(), cmap="gray")
  fig.axes[n].set_title(k)

f:id:nakamrnk:20200421130258j:plain

横軸は時間、縦軸は周波数を表し、時間ー周波数空間における信号の強さを表す。

メルスペクトルグラム

周波数を人間の聴覚特性に合わせたメルスケール4に変換したスペクトルグラム。
Tacotron 25ではこのメルスペクトルグラム推定を経由して音声合成しているらしい。

fig, _ = plt.subplots(figsize=(20, 6), ncols=5)

for n, (k, waveform) in enumerate(waves.items()):
  specgram = torchaudio.transforms.MelSpectrogram(sample_rate=sample_rate)(waveform)
  fig.axes[n].imshow(specgram.log2()[0,:,:].numpy(), cmap="gray")
  fig.axes[n].set_title(k)

f:id:nakamrnk:20200421131834j:plain

データセット解析

YESNO6データセットと呼ばれるデータを解析する。

YESNOデータセット

  • ヘブライ語のYes, Noに対応する言葉の音声データ
  • 1つのサンプル当たり8回のYes, No発音からなる
  • 各発音がYesかNoかのラベルが与えられている
  • 60サンプルほど。同一の発音者。データサイズは4.5MBほどで扱いやすい。

以下がひとつのデータサンプルに対する例である。

yesno_data = torchaudio.datasets.YESNO('./', download=True)
i = 0
waveform, sample_rate, labels = yesno_data[i]
plt.plot(waveform[0, :])
plt.title("labels {}".format(labels))

f:id:nakamrnk:20200421160126j:plain

1つのデータには8つの山があり、それぞれがひとつの言葉に対応している。
最初の2つの山と最後の3つの山がYes, それ以外の山がNoである。
この信号情報を見ただけではどちらの言葉かは素人目には分からづらい。
(真ん中3つの山はやや幅が広い?)

このデータをMelSpectrogramに変換してみる。

specgram = torchaudio.transforms.MelSpectrogram(sample_rate=sample_rate)(waveform)
plt.imshow(specgram.log2()[0,:,:].numpy(), cmap="gray")
plt.title("labels {}".format(labels))

f:id:nakamrnk:20200421160744j:plain

真ん中の3つの山は中央付近で他の5つと異なっているため
この図からなら容易にYes, No判定ができそうである。

まとめと今後

今回はText To Speechの各処理について簡単に調査した。
また、torchaudioを用いていくつかの音響特徴量を検証し、
YESNOデータセットに適用してみた。
次回以降はWavenetなどのDeep Learningモデルに触れてみたい。

参考文献