语音识别,声音的特征通过mfcc算出来了以后,我们进行进行跟模板对比,进行判断语音的内容了
先录制“目标词”语音,计算出MFCC保存,然后通过录音录入声音,进行计算MFCC,然后跟目标词进行对比,对比使用DTW算法
DTW参考:https://blog.csdn.net/zouxy09/article/details/9140207
算法实现 C语言,C++比较多
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Threading.Tasks
Class DTW
Const DTWMAXNUM As Integer = 2000
Const DTWVERYBIG As Double = 100000000.0
Private distance As Double(,) = New Double(DTWMAXNUM - 1, DTWMAXNUM - 1) {}
'保存距离
Private dtwpath As Double(,) = New Double(DTWMAXNUM - 1, DTWMAXNUM - 1) {}
'保存路径
'***************************************************************************
' DTWDistance,求两个数组之间的匹配距离
' /* A,B分别为第一第二个数组,Alen,Blen为其数组长度,r为匹配窗口的大小
'
' /* r的大小一般取为数组长度的1/10到1/30
' /* 返回两个数组之间的匹配距离,如果返回-1.0,表明数组长度太大了
' /****************************************************************************
Public Function DTWDistanceFun(A As Double(), Alen As Integer, B As Double(), Blen As Integer, r As Integer) As Double
Dim i As Integer, j As Integer
Dim dist As Double
Dim istart As Integer, imax As Integer
Dim r2 As Integer = r + Math.Abs(Alen - Blen)
'匹配距离
Dim g1 As Double, g2 As Double, g3 As Double
Dim pathsig As Integer = 1
'路径的标志
'检查参数的有效性
If Alen > DTWMAXNUM OrElse Blen > DTWMAXNUM Then
'printf("Too big number\n");
Return -1.0
End If
'进行一些必要的初始化
For i = 0 To Alen - 1
For j = 0 To Blen - 1
dtwpath(i, j) = 0
distance(i, j) = DTWVERYBIG
Next
Next
'动态规划求最小距离
'这里我采用的路径是 -------
' . |
' . |
' . |
' . |
'
distance(0, 0) = CDbl(2) * Math.Abs(A(0) - B(0))
For i = 1 To r2
distance(i, 0) = distance(i - 1, 0) + Math.Abs(A(i) - B(0))
Next
For j = 1 To r2
distance(0, j) = distance(0, j - 1) + Math.Abs(A(0) - B(j))
Next
For j = 1 To Blen - 1
istart = j - r2
If j <= r2 Then
istart = 1
End If
imax = j + r2
If imax >= Alen Then
imax = Alen - 1
End If
For i = istart To imax
g1 = distance(i - 1, j) + Math.Abs(A(i) - B(j))
g2 = distance(i - 1, j - 1) + 2 * Math.Abs(A(i) - B(j))
g3 = distance(i, j - 1) + Math.Abs(A(i) - B(j))
g2 = Math.Min(g1, g2)
g3 = Math.Min(g2, g3)
distance(i, j) = g3
Next
Next
dist = distance(Alen - 1, Blen - 1) / CDbl(Alen + Blen)
Return dist
End Function
'end DTWDistance
'***************************************************************************
' DTWTemplate,进行建立模板的工作
' /* 其中A为已经建立好的模板,我们在以后加入训练样本的时候,
' /* 以已建立好的模板作为第一个参数,Alen为模板的长度,在这个模板中不再改变
' /* B为新加入的训练样本,Blen为B的长度,turn为训练的次数,在第一次
' /* 用两个数组建立模板时,r为1,这是出于权值的考虑
' /* temp保存匹配最新训练后的模板,建议temp[DTWMAXNUM],函数返回最新训练后模板的长度
' /* 如果函数返回-1,表明训练样本之间距离过大,需要重新选择训练样本,
' /* tt为样本之间距离的阀值,自行定义
' /* rltdistance保存距离,第一次两个数组建立模板时可以随意赋予一个值,
' /* 后面用前一次返回的值赋予该参数
' /****************************************************************************
Public Function DTWTemplate(A As Double(), Alen As Integer, B As Double(), Blen As Integer, temp As Double(), turn As Integer,
tt As Double, rltdistance As Double()) As Integer
Dim dist As Double
Dim i As Integer, j As Integer
Dim pathsig As Integer = 1
dist = DTWDistanceFun(A, Alen, B, Blen, CInt(Alen / 30))
If dist > tt Then
Console.WriteLine(vbLf & "Sample doesn't match!" & vbLf)
Return -1
End If
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'If turn = 1 Then
' rltdistance.Target = dist
'Else
' rltdistance.Target = ((rltdistance.Target) * (turn - 1) + dist) / turn
'End If
If turn = 1 Then
rltdistance(0) = dist
Else
rltdistance(0) = ((rltdistance(0)) * (turn - 1) + dist) / turn
End If
'----------------------------------------------------------------------------
'寻找路径,这里我采用了逆向搜索法
i = Alen - 1
j = Blen - 1
While j >= 1 OrElse i >= 1
Dim m As Double
If i > 0 AndAlso j > 0 Then
m = Math.Min(Math.Min(distance(i - 1, j), distance(i - 1, j - 1)), distance(i, j - 1))
If m = distance(i - 1, j) Then
dtwpath(i - 1, j) = pathsig
i -= 1
ElseIf m = distance(i - 1, j - 1) Then
dtwpath(i - 1, j - 1) = pathsig
i -= 1
j -= 1
Else
dtwpath(i, j - 1) = pathsig
j -= 1
End If
ElseIf i = 0 Then
dtwpath(0, j - 1) = pathsig
j -= 1
Else
'j==0
dtwpath(i - 1, 0) = pathsig
i -= 1
End If
End While
dtwpath(0, 0) = pathsig
dtwpath(Alen - 1, Blen - 1) = pathsig
'建立模板
For i = 0 To Alen - 1
Dim ftemp As Double = 0.0
Dim ntemp As Integer = 0
For j = 0 To Blen - 1
If dtwpath(i, j) = pathsig Then
ftemp += B(j)
ntemp += 1
End If
Next
ftemp /= CDbl(ntemp)
'注意这里的权值
temp(i) = (A(i) * turn + ftemp) / CDbl(turn + 1)
Next
Return Alen
'返回模板的长度
End Function
'end DTWTemplate
End Class