Created
November 15, 2020 10:02
-
-
Save taroushirani/7c599cd482e9ecd5b8ee594914fe4f59 to your computer and use it in GitHub Desktop.
nnsvs_test_natsume_singing_official_recipe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"nbformat": 4, | |
"nbformat_minor": 0, | |
"metadata": { | |
"colab": { | |
"name": "nnsvs_test_natsume_singing_official_recipe", | |
"provenance": [], | |
"toc_visible": true, | |
"authorship_tag": "ABX9TyOk5Wchnc50eKGmgOLCeE7M", | |
"include_colab_link": true | |
}, | |
"kernelspec": { | |
"name": "python3", | |
"display_name": "Python 3" | |
}, | |
"accelerator": "GPU" | |
}, | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "view-in-github", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"<a href=\"https://colab.research.google.com/gist/taroushirani/7c599cd482e9ecd5b8ee594914fe4f59/nnsvs_test_natsume_singing_official_recipe.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "IxmW5IpLNCz3" | |
}, | |
"source": [ | |
"# NN-SVS で 夏目悠季/男性歌声データベースを使う\n", | |
"\n", | |
"ここでは[夏目悠李/男性歌声データベース](https://amanokei.hatenablog.com/)をNN-SVSで使用する方法について解説します.\n", | |
"\n", | |
"夏目悠季/男性歌声データベースのレシピは2020年11月4日にNNSVSにマージされました. 公式のレシピを使用してください.\n", | |
"\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "vEVF73GZeLUW" | |
}, | |
"source": [ | |
"## 基本的な環境構築\n", | |
"\n", | |
"\n", | |
"\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "hNIQmFn3eQP9" | |
}, | |
"source": [ | |
"### Google Colaboratoryの設定\n", | |
"Google Colaboratory の基本的な使い方に関しては割愛します. \n", | |
"画面上のメニューから「編集」-「ノートブックの設定」を選びハードウェアアクセラレータを None から GPU に変更するのを忘れないようにしてください." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "7l9qxs8leNWZ" | |
}, | |
"source": [ | |
"### NumPy, Cythonのアップグレード\n", | |
"NumPy, Cythonは最初からColaboratoryにインストールされていますが, 最新版にアップグレードしておきます." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "FCY9PjEUXT5i" | |
}, | |
"source": [ | |
"! pip install -U numpy cython" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "bHIYMRLgNTd6" | |
}, | |
"source": [ | |
"### hts_engine_API, sinsy のビルド\n", | |
"\n", | |
"NN-SVS は楽譜 (musicxml ファイル) から歌声合成に必要な情報が書かれたラベルファイル (lab ファイル) に変換するために [Sinsy](http://sinsy.sourceforge.net/) の python wrapper である Pysinsy を使います. Pysinsy のインストールに必要な [hts_engine_API](http://hts-engine.sourceforge.net/), Sinsy をビルドしますが, それぞれ公式からのリリースではなく NN-SVS の作者である Ryuichi Yamamoto 氏の fork を使います." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "iV4ghgxzXaNt" | |
}, | |
"source": [ | |
"! git clone -q https://github.com/r9y9/hts_engine_API\n", | |
"! cd hts_engine_API/src && ./waf configure --prefix=/usr/ && ./waf build > hts_engine_API_build.log 2>&1 && ./waf install\n", | |
"! git clone -q https://github.com/r9y9/sinsy\n", | |
"! cd sinsy/src/ && mkdir -p build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=/usr/ .. && make -j > sinsy_build.log 2>&1 && make install" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "88So6I-WNocS" | |
}, | |
"source": [ | |
"### Pysinsy, nnmnkwii, NN-SVS のインストール\n", | |
"\n", | |
"NN-SVS は音声合成システムを作るためのライブラリである [nnmnkwii](https://github.com/r9y9/nnmnkwii) 上に構築されています. Pysinsy, nnmnkwii, NN-SVS をインストールします. また夏目悠李/男声歌声データベース用のレシピがjaconv,pyyamlを必要とするためインストールします." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "UdRQ5pMuYtFj" | |
}, | |
"source": [ | |
"# Python dependencies\n", | |
"! git clone -q https://github.com/r9y9/pysinsy\n", | |
"! cd pysinsy && export SINSY_INSTALL_PREFIX=/usr/ && pip install -q .\n", | |
"! git clone -q https://github.com/r9y9/nnmnkwii\n", | |
"! cd nnmnkwii && pip install -q .\n", | |
"! git clone -q https://github.com/r9y9/nnsvs \n", | |
"! cd nnsvs && pip install -q .\n", | |
"! pip install -q -U jaconv pyyaml" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "SKszyhHhcGm7" | |
}, | |
"source": [ | |
"これでNN-SVSを使う準備が出来ました." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "o1Qe7mM2Nx9p" | |
}, | |
"source": [ | |
"## データとレシピの準備\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "_jcYY1qreWe-" | |
}, | |
"source": [ | |
"### 夏目悠李/男声歌声データベースのダウンロード\n", | |
"\n", | |
"[夏目悠李/男声歌声データベース配布、始めました!【2020/10/10更新】](https://amanokei.hatenablog.com/entry/2020/04/30/230003) から利用規約に同意して Natsume_Singing_DB.zip をダウンロードします. ダウンロードされたファイルを Google Drive 上にアップロードします.\n", | |
"\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "SoVOKcR_eXiH" | |
}, | |
"source": [ | |
"### Google Driveのマウント\n", | |
"\n", | |
"Google Drive にアップロードしたファイルを Colaboratory から使うために Google Drive を Colaboratory にマウントします. 以下のセルを実行し, 表示されたリンクをクリックして Google アカウントへのアクセスを許可してください. 表示されたコードをコピーして Colaboratory 上に戻ってセル中の\"Enter your authorization code:\"の下の欄にペーストします." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "XpoUEOtIWx9X" | |
}, | |
"source": [ | |
"from google.colab import drive\n", | |
"drive.mount('/content/drive')" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "BWq-G9ptO9kR" | |
}, | |
"source": [ | |
"一部のシェルスクリプトはファイル名にスペースが含まれていると上手く動作しないことがあります. /content/gdrive から Google Drive 上のファイルにアクセスできるようシンボリックリンクを貼ります.\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "yeCIXI50O3Qp" | |
}, | |
"source": [ | |
"!ln -s \"/content/drive/My Drive\" /content/gdrive" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "VcvGd0A2PCV6" | |
}, | |
"source": [ | |
"これでさきほどアップロードした Natsume_Singing_DB.zip に /content/gdrive/Natsume_Singing_DB.zip からアクセスできるようになりました." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "JmcKK61zPj4_" | |
}, | |
"source": [ | |
"### 夏目悠李/男声歌声データベースの解凍\n", | |
"\n", | |
"セルに以下のように入力して Natsume_Singing_DB.zip を解凍します." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "_QhtzUCKfvjc" | |
}, | |
"source": [ | |
"! cd /content/gdrive && unzip -u /content/gdrive/Natsume_Singing_DB.zip" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "k1UPW4daPeWy" | |
}, | |
"source": [ | |
"### レシピのダウンロード\n", | |
"夏目悠李/男声歌声データベース用のレシピは2020年11月4日に NNSVS 本家にマージされました. nnsvs_natsume_singing をダウンロードする必要はもうありません." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "j7dG_jgfQW_9" | |
}, | |
"source": [ | |
"夏目悠李/男声歌声データベース用のレシピがあるディレクトリに変数 RECIPE_ROOT でアクセスできるようにします." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "m-TVJk1SGW_n" | |
}, | |
"source": [ | |
"RECIPE_ROOT=\"/content/nnsvs/egs/natsume_singing/svs-world-conv/\"" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "9XqfzxIPQrN3" | |
}, | |
"source": [ | |
"### \\$RECIPE_ROOT/config.yaml の編集\n", | |
"夏目悠李/男声歌声データベース用のレシピは実際には $RECIPE_ROOT/run.sh というシェルスクリプトの形で提供されます. レシピに展開した Natsume_Singing_DB の場所を設定します. \n", | |
"\n", | |
"画面右端にある「ファイル」アイコンから $RECIPE_ROOT/config.yaml を開き, 10 行目の db_root を直接編集するか, 以下のセルを実行します. \n", | |
"\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "hT4crM1wgCd7" | |
}, | |
"source": [ | |
"! sed -i 's#\\~\\/data#\\/content\\/gdrive#g' $RECIPE_ROOT/config.yaml" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "KErdcntbRe26" | |
}, | |
"source": [ | |
"# 夏目悠季/男性歌声データベース用レシピを試す\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "4Gn6IusAeoiH" | |
}, | |
"source": [ | |
"## ステージ-1(データのダウンロード) の実行\n", | |
"ここからは基本的にレシピの提供するステージに沿って実行していきます. NN-SVSではステージ-1はデータのダウンロードですが, ライセンスの関係でこのレシピではデータを自動的にダウンロードするようにはしていません. 予め上記の指示に従って Natsume_Singing_DB.zip をダウンロードしておいてください.\n", | |
"\n", | |
"データのダウンロードを行わない代わりに, db_rootで設定された場所に解凍されたNatsume_Singing_DBが見つからない場合はダウンロードを促すメッセージを出力するように変更してあります." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "Veas7tJiGj8E" | |
}, | |
"source": [ | |
"! cd $RECIPE_ROOT && bash run.sh --stage -1 --stop-stage -1" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "oe2yY-btSh91" | |
}, | |
"source": [ | |
"## ステージ0(データの準備)の実行\n", | |
"\n", | |
"夏目悠季/男性歌声データベースのデータをNN-SVSで扱いやすい形に整えます. Colaboratory の CPU はそれほど高速ではないので時間がかかります." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "8Ce6Fq2fGt17" | |
}, | |
"source": [ | |
"! cd $RECIPE_ROOT && bash run.sh --stage 0 --stop-stage 0" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "FKCYftpSV8gN" | |
}, | |
"source": [ | |
"##ステージ 1 (タイムラグ, 継続長, 言語特徴量, 音響特徴量の抽出) の実行\n", | |
"\n", | |
"歌声合成に必要なタイムラグ, 継続長, 言語特徴量, 音響特徴量を抽出します. この処理もかなりの時間がかかるので, 何度も歌声合成の実験を行う場合はレシピを Google Drive 以下に移動して Colaboratory のインスタンスが初期化されてもデータが残るようにすると良いかもしれません." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "tmI-uuTPGxxO" | |
}, | |
"source": [ | |
"! cd $RECIPE_ROOT && bash run.sh --stage 1 --stop-stage 1" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "Sv81QbPqWSeH" | |
}, | |
"source": [ | |
"## ステージ 2-4 (タイムラグモデル, 継続長モデル, 音響モデルの学習) の実行\n", | |
"ここまでは特に GPU を必要としない処理でしたが, ここからは GPU が使えると処理が高速になります. ハードウェアアクセラレータの設定を None から GPU に変更するのを忘れていた場合は, 画面上のメニューから「編集」-「ノートブックの設定」を選びハードウェアアクセラレータをGPUに変更してください(ここで変更した場合は残念ながら最初からやり直しになります).\n", | |
"\n", | |
"ステージ 2 がタイムラグモデル, ステージ 3 が継続長モデル, ステージ 4 が音響モデルの学習になります." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "ulblx4TgbU_d" | |
}, | |
"source": [ | |
"! cd $RECIPE_ROOT && bash run.sh --stage 2 --stop-stage 2" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "hfiPFgRUQJ61" | |
}, | |
"source": [ | |
"! cd $RECIPE_ROOT && bash run.sh --stage 3 --stop-stage 3 " | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "7ZWbJcYEQKMX" | |
}, | |
"source": [ | |
"! cd $RECIPE_ROOT && bash run.sh --stage 4 --stop-stage 4" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "L-30YYpIXaqo" | |
}, | |
"source": [ | |
"## ステージ 5-6 (歌声合成) の実行\n", | |
"\n", | |
"ステージ 5 は学習したモデルによるパラメータの出力, ステージ 6 が学習したモデルによる歌声合成になります. \n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "YnPWRwTgqUhg" | |
}, | |
"source": [ | |
"# stage5-6の実行(パラメータの出力および歌声合成)\n", | |
"! cd $RECIPE_ROOT && bash run.sh --stage 5 --stop-stage 6" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "QnA0F2LHXmxl" | |
}, | |
"source": [ | |
"ステージ6を実行すると, 学習の評価用に設定されている曲(本レシピでは50, 51)の歌声が合成されます. 合成結果は $RECIPE_ROOT/exp/natsumeyuuri/synthesis 以下に出力されます. Colaboratory からインタラクティブに視聴するにはセルに以下のように入力します.\n", | |
"\n", | |
"*注意* この処理は非常に重くColaboratoryの接続が切れる場合があるようです. 画面左端の[ファイル]からファイルをダウンロードしてローカルで視聴することをお勧めします.\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "w_Wy9DNLQhLv" | |
}, | |
"source": [ | |
"#import IPython\n", | |
"#from IPython.display import Audio\n", | |
"#from glob import glob\n", | |
"#from os.path import join\n", | |
"#sample_rate=48000\n", | |
"#synthesized_wav_paths = sorted(glob(join(RECIPE_ROOT, \"exp/**/*.wav\"), recursive=True))\n", | |
"\n", | |
"#for wav_path in synthesized_wav_paths:\n", | |
"# print(wav_path)\n", | |
"# IPython.display.display(Audio(wav_path, rate=sample_rate))" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "kR4Vk31NYIeD" | |
}, | |
"source": [ | |
"## 学習したモデルから任意の歌声を合成する\n", | |
"レシピを見るとわかりますが NN-SVS では nnsvs-synthesis に学習した各種パラメータと合成するラベルファイル(音素の位置指定に使用する単音素のラベルファイルではなく楽譜から生成されたHTSフルコンテキストラベルファイル)のリストを渡すことで歌声合成を行います.\n", | |
"\n", | |
"Google Drive に sample フォルダを作成し歌声合成したい曲の楽譜をアップロードしてみましょう(Colaboratoryからは/content/gdrive/sampleに見えます).\n", | |
"\n", | |
"Pysinsyを用いて楽譜をHTSフルコンテキストラベルファイルに変換します.\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "uPPsi7pHbSXL" | |
}, | |
"source": [ | |
"import pysinsy\n", | |
"from os.path import basename, join, splitext\n", | |
"from glob import glob\n", | |
"sample_dir=\"/content/gdrive/sample\"\n", | |
"song_list_file=join(sample_dir, \"song_list.txt\")\n", | |
"\n", | |
"sinsy = pysinsy.sinsy.Sinsy()\n", | |
"# Set language to Japanese\n", | |
"assert sinsy.setLanguages(\"j\", join(RECIPE_ROOT, \"../../_common/no2/dic\"))\n", | |
"\n", | |
"song_list = []\n", | |
"musicxml_files = glob(join(sample_dir, \"*.*xml\"))\n", | |
"for musicxml_file in musicxml_files:\n", | |
" assert sinsy.loadScoreFromMusicXML(musicxml_file)\n", | |
" is_mono = False\n", | |
" labels = sinsy.createLabelData(is_mono, 1, 1).getData()\n", | |
" song_name = splitext(basename(musicxml_file))[0]\n", | |
" song_list.append(song_name)\n", | |
" lab_file_path = join(sample_dir, song_name + \".lab\")\n", | |
" with open(lab_file_path, \"w\") as f:\n", | |
" f.write(\"\\n\".join(labels))\n", | |
"\n", | |
" sinsy.clearScore()\n", | |
"\n", | |
"with open(song_list_file, \"w\") as f:\n", | |
" f.write(\"\\n\".join(song_list))" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "AdzKn88wav-c" | |
}, | |
"source": [ | |
"nnsvs-synthesisに先ほど学習したモデルと, 合成したい曲のリストを渡します. 出力先は out_dirで指定します. 今回は $RECIPE_ROOT/exp/synthesis/sample にしました." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "RPzBOcckZqaM" | |
}, | |
"source": [ | |
"spk=\"natsumeyuuri\"\n", | |
"exp_dir=join(RECIPE_ROOT, \"exp\", spk)\n", | |
"dump_dir=join(RECIPE_ROOT, \"dump\")\n", | |
"dump_org_dir=join(dump_dir, spk, \"org\")\n", | |
"dump_norm_dir=join(dump_dir, spk, \"norm\")\n", | |
"conf_dir=join(RECIPE_ROOT, \"../../_common/hed\")\n", | |
"out_dir=join(exp_dir, \"synthesis/sample\")\n", | |
"\n", | |
"! nnsvs-synthesis question_path=$conf_dir/jp_qst001_nnsvs.hed \\\n", | |
"timelag.checkpoint=$exp_dir/timelag/latest.pth \\\n", | |
"timelag.in_scaler_path=$dump_norm_dir/in_timelag_scaler.joblib \\\n", | |
"timelag.out_scaler_path=$dump_norm_dir/out_timelag_scaler.joblib \\\n", | |
"timelag.model_yaml=$exp_dir/timelag/model.yaml \\\n", | |
"duration.checkpoint=$exp_dir/duration/latest.pth \\\n", | |
"duration.in_scaler_path=$dump_norm_dir/in_duration_scaler.joblib \\\n", | |
"duration.out_scaler_path=$dump_norm_dir/out_duration_scaler.joblib \\\n", | |
"duration.model_yaml=$exp_dir/duration/model.yaml \\\n", | |
"acoustic.checkpoint=$exp_dir/acoustic/latest.pth \\\n", | |
"acoustic.in_scaler_path=$dump_norm_dir/in_acoustic_scaler.joblib \\\n", | |
"acoustic.out_scaler_path=$dump_norm_dir/out_acoustic_scaler.joblib \\\n", | |
"acoustic.model_yaml=$exp_dir/acoustic/model.yaml \\\n", | |
"utt_list=$song_list_file \\\n", | |
"in_dir=$sample_dir \\\n", | |
"out_dir=$out_dir \\\n", | |
"ground_truth_duration=false\n" | |
], | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "T2Id2zV2c1GB" | |
}, | |
"source": [ | |
" Colaboratory からインタラクティブに視聴するにはセルに以下のように入力します.\n", | |
"\n", | |
" 注意 この処理は非常に重くColaboratoryの接続が切れる場合があるようです. 画面左端の[ファイル]からファイルをダウンロードしてローカルで視聴することをお勧めします." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"metadata": { | |
"id": "7dlkdPCQeT-O" | |
}, | |
"source": [ | |
"#synthesized_wav_paths = sorted(glob(join(out_dir, \"*.wav\"), recursive=True))\n", | |
"\n", | |
"#for wav_path in synthesized_wav_paths:\n", | |
"# print(wav_path)\n", | |
"# IPython.display.display(Audio(wav_path, rate=sample_rate))" | |
], | |
"execution_count": null, | |
"outputs": [] | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment