merlin语音合成框架,关于合成部分的流程记录
代码地址github:merlin-tts
merlin合成(中文)的流程可分为以下5个部分:
- 汉字转phone
- phone转为duration model的输入
- duration model的输出转为acoustic model的输入
- acoustic model的输出转为WORLD的输入
- WORLD生成音频
下面分别记录一下时长模型和声学模型的合成流程:
duration model
- 加载问题集
- questions-mandarin.hed中的每一行转为若干个正则,QS439行,CQS28行
- 解析lab,prompt-lab/.lab --> gen-lab/.labbin
- 对原始lab中的每一行内容,先用439个QS的正则去search,只要某个QS其中有一个正则search到了,就置为1,否则置为0,于是得到(1, 439)维的one-hot向量
- 同理,对CQS,匹配该行lab中相关的数字,search到了就置为该数字,否则置为-1,得到(1, 28)的正数向量
- 合并上述两个向量,得到(1, 467)
- 最终得到(lab行数, 467)的矩阵,存入gen-lab/.labbin
- remove_silence, 然后min_max_norm, prompt-lab/.lab + gen-lab/.labbin --> gen-lab/.lab
- 从prompt-lab/.lab得到不包含sil的行(其实就只有首尾两行是sil),保留gen-lab/.labbin的这些行,存入gen-lab/.lab
- duration_model/inter_module/label_norm_HTS_467.dat 得到(934, 1)的向量,(该文件在train时find_min_max_values后写入),分别为467维的min_vector和max_vector,用于归一化
- run model
- 从gen-lab/.lab读取数据作为input, 假设lab文件有58行(已去除首尾静音行),则输入为(58, 467), 输出为(58, 1)
- 将输出存为gen-lab/.cmp
- 从duration_model/inter_module/norm_info__dur_1_MVN.dat中获的cmp_min_vector与cmp_max_vector两个数值
- 对gen-lab/.cmp的内容进行均值方差归一化,重新存入
- 对gen-lab/.cmp进行四舍五入,存入gen-lab/.dur
- 对gen-lab/.dur的每个值*5*10000,作为相应行phone的持续时间,根据prompt-lab/.lab和时间信息一起写入gen-lab/.lab,这样lab就带时间了(最终得到的gen-lab/.lab含静音行,与prompt-lab/.lab行数一致)
acoustic model
- 将gen-lab/01.lab每一phone转为若干个帧(默认帧移为5ms),每一帧的维度为471(对应的phone维度467+4维的cc_feat_matrix),4维的最后一维是通过时长计算出的帧数。如一个(58, 467)的lab,转换后的维度为(1211, 471), 1211 为所有phones的帧数之和,存入 wav/01.labbin(帧)
- 帧级别的remove_silence,删除首尾的各60帧静音,gen-lab/.lab + wav/.labbin --> wav/.lab(1211-60*2, 471)
- acoustic_model/inter_module/label_norm_HTS_471.dat得到max_vector和min_vector,维度均为471,用于归一化,重新存入wav/.lab(1211, 471)
- run_model
Tips
- wav/.cmp生成.mgc、.lf0、.bap时,这儿需要用到解矩阵方程, 为了提高计算效率,使用的是BandMat类型的矩阵,是否需要解方程由参数do_MLPG(默认为true)控制
- 合成的完整 c++ code后续会放到github
附:丑陋的流程图(数字表示被处理成的维度)
duration model | acoustic model |
---|---|