『Yukarinライブラリ』become-yukarinの ipynb ブランチでリアルタイム変換

# 1. 概要

『ディープラーニングの力で結月ゆかりの声になるリポジトリ』の [ipynb](https://github.com/Hiroshiba/become-yukarin/tree/ipynb) ブランチのリアルタイム変換サンプルの利用方法を解説します。
動作確認用にレポジトリも用意してありますので合わせてご参照ください。
**とはいえ、筆者の環境ではGPUパワー or メモリが低いため、正常なリアルタイム変換はできておりません。**
**おそらく、PCスペックが十分であれば問題ないとは思いますが、そうでない場合はご了承ください。**

＊注：最新のコードは[https://github.com/Hiroshiba/yukarin](https://github.com/Hiroshiba/yukarin)になります。本解説は旧コード版になります。


### 前提知識
[「ディープラーニングの力で結月ゆかりの声になる」ための基礎知識とコマンド操作](https://qiita.com/atticatticattic/items/f1e4c671d73d815bbad2)


### 筆者の動作環境(リアルタイム処理が追いつかない)
OS: **Windows 7**
CPU: Ryzen 1700X
Mem: 16 GB
GPU: GTX 1070Ti

* 諸事情によりWindowsで実行しています。Windows環境で学習処理はできませんが、音声合成処理だけならば実行できました。
* Windowsを使ったのはLinux環境で動作するマイクがなかったためで、3.2さえ動けばLinux環境でも実行可能と思います。

### 必要スペックと動作報告

1秒あたりの変換時間が 1秒以内に処理できる必要がる。
わかっている範囲では少なくとも下記のPC性能が必要なようです。
- GPU: GTX1080以上
- Mem: 16G 以上

|  判定      |  CPU       |  GPU        |  Mem  | 変換時間  |   確認者      | コメント        |
|:----------:|:---------:|:-----------:|:-------:|:--------:|:-------------:|:---------------|
|  NG       | i7 900番台 | GTX 970    |  16G    |  1.4[s]   | 筆者            |               |
|  NG       | Ryzen 1700X | GTX 1070Ti | 16G    |  1.4[s]   | 筆者           | 実行環境の問題?  |
|  **OK**   | i7-7700K | GTX 1080    | 32G    | 0.8[s]    | @mituruaoi061 様 |             |
|  **OK**   | i7 8700     | RTX2070     | 16G    |  0.8[s]   | @mituruaoi061 様 |             |

# 2. 解説の流れ

- 3.1 処理概要
- 3.2 事前確認方法(マイク動作確認)
- 3.3 プログラムの準備
- 3.4 リアルタイムを試しに実行
- 3.5 リアルタイムを自分のファイルに差し替えて実行

# 3. 解説
**動作確認レポジトリ**

**ゆかり音声の学習データの配布はVoiceroidの利用規約に違反している可能性があるので削除しました**

~~次のURLに配置してあります。**大容量のnpzファイルもあるため、git-lfsが使える状態で cloneしてください！**~~
~~githubのダウンロードを使用している場合は、下記の2ファイルを個別にダウンロードして配置してください。~~

- ~~[become-yukarin_rt/dat/model/yukari_1st_w825_f0c1_250_cut430_mdio_ydio/predictor_165000.npz](https://github.com/YoshikazuOota/become-yukarin_rt/blob/master/dat/model/yukari_1st_w825_f0c1_250_cut430_mdio_ydio/predictor_165000.npz)~~
- ~~[become-yukarin_rt/dat/model/yukari_2nd_22050/predictor_255000.npz
](https://github.com/YoshikazuOota/become-yukarin_rt/blob/master/dat/model/yukari_2nd_22050/predictor_255000.npz)~~

https://github.com/YoshikazuOota/become-yukarin_rt

## 3.1 リアルタイム変換の処理概要
オリジナルレポジトリの ipynbブランチにある、`scripts/realtime_voice_changer.py` がリアルタイム変換用のコードになります。
本プログラムは下図のようにバッファリング処理をしています。
構造的に処理には 2+x[s]かかります。また、変換処理時間 xは1秒以下になるスペックが必要です(1秒の変換に1秒以上かかってしまったら無理ということ)。

**補足**
自分の環境ではリアルタイム処理は動いていないので確認できませんが、聞いた話ではレスポンスに4[s]ほどかかるとのことです。
よって、下記の図に加えて何らかの遅れが発生する処理があると推定されます。
しかし、概ねの処理は下図のようになるようなので、図はそのままにしております。

<img width="1013" alt="スクリーンショット 2019-01-07 18.00.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/12429/c69c8414-f184-233b-544f-c29364c79267.png">


## 3.2 事前確認方法(マイク動作確認) 
先立って、まずはマイクとスピーカの動作確認をします。
pyaudio を下記コマンでインストールします。

```
  pip install pyaudio
```

そして、下記を実行して、マイクに音声入力してください(**ハウリング注意！**)。

```
  python script/pyaudio_test.py
```

Windows環境で正常に動作していれば、通常使っているマイクへの声が、通常使っているスピーカから出力されます。
うまく行かない場合は、Windowsのサウンドで利用デバイスが、"既定のデイバス"になっているか確認してください。

## 3.3 プログラムの準備

レポジトリのプログラムファイルは、オリジナルを筆者が少し修正しています。
変えているのは、設定ファイルの参照処理や、プログラム実行時のデバッグ出力などで、基本的な処理には手を入れていません。
気になる方は、オリジナルと差分をとってください。


### 動作環境
Linux環境の動作環境構築した時と同じ要領で、Windowsでpython実行環境を構築してください。
おそらく下記2点を忘れずに設定すればハマることはないかと思います。
GPUは必ず使用できるようにしてください。

- WORLD4py
- PYTHONPATH設定

### 用意するデータ

下記のデータが必要になります。
- 第1変換の学習データ **XXX.npz**
- 第1変換の自声の学習用データの **mean.npy**, **var.npy**
- 第1変換のターゲット(ゆかり)の学習用データの **mean.npy**, **var.npy**
- 第1変換の設定ファイル　**config.json**
- 第2変換の学習データ **XXX.npz**, 
- 第2変換の設定ファイル　**config.json**

レポジトリの dat 以下に、サンプルとして配置してあります。

**補足**
- **XXX.npz** : 学習データ長時間放置して計算したやつ
- **mean.npy**, **var.npy** : **第1段学習用データ(npy)** を作った時に一緒にできる npyファイル
- **config.json:** 学習を回す時の設定ファイル 

## 3.4 リアルタイムを試しに実行
レポジトリをダウンロードした状態で、筆者の学習ファイル(22050Hz)がセットされています。
そのままで、下記コマンドを実行してエラーが発生しないことを確認してください。
(第1段の変換は筆者が作ったものなので、変換精度はとても悪いかとは思います)

```
  python script/realtime_voice_changer.py
```

終了する時は、Ctrl-C でブレイクするか、タスクマネージャーで Pythonのプロセスを殺してください。


#### 実行時のデバッグ出力の見方
下図の用に実行するとデバッグ出力がされます。
簡単に意味を説明します。

![スクリーンショット 2019-01-07 13.29.18.png](https://qiita-image-store.s3.amazonaws.com/0/12429/29b62031-5b4b-9278-f55e-6093b454c992.png)


**データ読み込み**

```
   model 1 loaded!
   model 2 loaded!
```

最初に第1・2段の学習データを読み込みます。


**話者の1秒間のデータを読み込み**

```
  input 22050
```

処理概要の図でいえば、青のデータを読み込む処理です。
input XXXXX(データサンプル数) と出力されます。
サンプルでは22050Hzなのでサンプル数も22050個になります。

**変換処理**

```
  tiem X.XXX
  converted wave 22048
```

処理概要の図でいえば、x[s]の処理部分になります。
私の環境の場合　1[s]を超えているため、徐々に処理がずれ込んでいることがわかります。

**1秒間分の出力データをセット**

```
  output 22050
```

処理概要の図の赤データをセットする処理です。
これがセットされるとスピーカーから音が出るはずです。


## 3.5 リアルタイムを自分のファイルに差し替えて実行

ここまでできれば、あとは第1・2段のデータを差し替えるだけです。
各ファイルのパスの書き方さえ間違えなければ、問題ないかと思います。

#### script/setting.json の設定
下記の4ファイルを設置して、 script/setting.json のパスを対応するものに書き換えてください

- 第1変換の学習データ **XXX.npz**
- 第1変換の設定ファイル **config.json**
- 第2変換の学習データ **XXX.npz**
- 第2変換の設定ファイル **config.json**

###　第1変換の設定ファイルsetting.json のパス確認 
第1変換の下記4ファイルのパスは"第1変換の設定ファイルsetting.json"に記載されています。
必要があれば実行環境に合わせてパスを記述してください。

- 第1変換の自声の学習用データの **mean.npy**, **var.npy**
- 第1変換のターゲット(ゆかり)の学習用データの **mean.npy**, **var.npy**

実行して、エラーが出なければ成功です。

```
python script/realtime_voice_changer.py
```

# 4. まとめ・所感
#### 精度について
オフラインで変換する場合に比べると、精度はかなり落ちます。
これは第2段変換のアルゴリズムがリアルタイム処理と相性がよくないためと思っています。
リアルタイム処理では1秒ごとに音声を切り出してしまうため、学習の場合と条件が大きく違ってしまうからだと思います。

#### サンプリング数について
筆者は処理速度の観点で、22050Hz で学習データを作成しました。筆者が試した範囲では44100Hzと22050Hzではあまり精度が変わらないように感じたため、処理負荷が減らせる、22050Hzでいいように思います。


もし、上記で処理速度的にうまく変換できた方がいらっしゃいましたら、ご報告願います！
また、不明点ありましたらコメントください、補記します。
以上！