转载

【每日一博】通过机器检查你的发音是否正确

1、原来的方案:

(1)采用MFCC(梅尔倒谱)作为音频的特征

(2)采用DTW算法计算两段音频的距离,然后根据距离判断这两个音频是否是同一个音

方案的问题:经过实际数据验证,发现不同人读相同内容,计算出的距离会比较大。可能是因为我们对于MFCC每个维度的特征是同等对待的,有些特征可能是跟发音人者的音色相关度比较大,跟内容相关度小。

2、优化的方案:

根据之前的猜测,我们假设对于某个音节,可能有几个维度的特征跟其他音节差别特别大,我们需要找到这几个特征。基于这个假设,我们采用穷举法从13个特征中找到最能区分音节的特征组合。

代码如下:

# -*- coding: utf-8 -*- import os import numpy as np from scikits.audiolab import wavread import scikits.talkbox import fastdtw from scikits.talkbox import features from scikits.talkbox.features import mfcc weight=[0,1,1,1,1,1,1,1,1,1,1,1,1] fdict={} def getfeature(x):  if(fdict.has_key(x)):   return fdict[x]    else:   data, fs, enc=wavread(x)   temp=mfcc(data)[0]    fdict[x]=temp   return temp def mydist(a, b):  i_dist=0  i_len=0  for i in range(13):   if(weight[i]>0):    i_dist=i_dist+abs(a[i]-b[i])    i_len=i_len+1  return i_dist/i_len def dist(mf1, mf2):   re=fastdtw.fastdtw(mf1, mf2, 1, mydist)[0]  return re def calcsimilar(x, y):  fx=getfeature(x)   fy=getfeature(y)   d = dist(fx, fy)  return d # 获取指定路径下所有指定后缀的文件 # dir 指定路径 # ext 指定后缀,链表&不需要带点 或者不指定。例子:['xml', 'java'] def GetFileFromThisRootDir(rootdir,filelist):    for i in os.listdir(rootdir):   filepath = os.path.join(rootdir,i)   if os.path.isdir(filepath):    GetFileFromThisRootDir(filepath, filelist)   elif i.endswith('.wav') and os.path.exists(filepath):    filelist.append(filepath) def calcfactor(path, name, template):  ftemplate=getfeature(template)  files=[]  min_dist=999999  max_dist=0  GetFileFromThisRootDir(path, files)  for filename in files:   f=getfeature(filename)   d=dist(f,ftemplate)   if name+".wav" in filename:          if(d>max_dist):     max_dist=d   else:    if(d<min_dist):     min_dist=d  return (min_dist-max_dist)/max_dist def train(path, name, template):   dist=-99999  re_i=-1  re_j=-1  re_m=-1  re_n=-1  for n in range(13):   for m in range(13):    for i in range(13):     for j in range(13):      for k in range(13):       weight[k]=1      weight[i]=0      weight[j]=0      weight[m]=0      weight[n]=0      d=calcfactor(path, name, template)      print d      if(d>dist):       dist=d       re_i=i       re_j=j          re_m=m          re_n=n      return dist, re_i, re_j, re_m, re_n 
正文到此结束
Loading...