Force Alignment
一、.最好采用做两遍FA
1. 第一遍词的
字典采用两行的silsp的。
eg:衣Q [y_i1_k_iu1_sil] y i1 k iu1 sil
衣Q [y_i1_k_iu1_sp] y i1 k iu1 sp
注意字典中不包含<s></s>sp,包含sil sil;做FA后结果是中括号中的内容
awk 'NR==FNR{w[$1]=1}NR!=FNR{if(NF>2){z=0;num=split($3,a,"_");for(i=1;i<num;i++){if(a[i] in w){}else{z=1;}}if(z==1){x=gensub(/.* (.*)\_.*/,"\\1",$3);print x;}else{for(i=1;i<num;i++){print a[i];}}}else{print;}}' pinyin.dict train.tmp,align.mlf >train.align.pinyin.mlf
pinyin.dict :所以出现的中文必须包含在里面。中英文混合的按照英文处理
eg:AB型 [ei1_b_i1_x_i2_ng_sil] ei1 b i1 x i2 ng sil
AB型 [ei1_b_i1_x_i2_ng_sp] ei1 b i1 x i2 ng sp
map中: ei1_b_i1_x_i2_ng ei1 b i1 x i2 ng
2. 第二遍字的
采用三行的silsp,第一列是第一遍词括号中的phone标注
eg:z_y_i1 z y i1
z_y_i1 z y i1 sil
z_y_i1 z y i1 sp
FA后就是phone级别的标注了
注意check sil sp
sp>=5帧替换为sil。sil<5帧替换为sp
gmm: echo '#!MLF!#' >use.train.align.model.mlf
cat train.align.model.mlf|awk '$0!~/MLF/{print}' | awk 'BEGIN{RS="\n[.]\n";FS="\n"}{printf"%s\n%s\n",$1,$2;for(i=3;i<=NF-1;i++){num=split($i,a," ");if(a[3]=="sil"&&(a[2]-a[1])/100000<5){gsub("sil","sp",a[3]);}else{if(a[3]=="sp"&&(a[2]-a[1])/100000>=5){gsub("sp","sil",a[3]);}};for(j=1;j<=num;j++)printf"%s ",a[j];printf"\n";}printf"%s\n.\n",$NF}' >>use.train.align.model.mlf
dnn:./mlf2dnn.sh train.align.state.mlf tri.xwrd.cluster.list correct_train.align.state.mlf
总结:第一遍采用词可以避免多音字的错误,第二遍可以得到字间的sil和sp
只采用词做FA得不到字间的sil sp信息,只采用字做FA会有多音的影响
二、DNN做FA和GMM的区别
1. 对于DNN需要state级别的标注,gmm需要model级别的标注
hvite中 -m 是得到model级别的,-f 是state级别的
2. dnn做FA需要dnn的hvite,gmm做FA普通的hvite就ok