自己写了模仿微信声音锁的一个android程序,先录两段相同的语音信号作为模板,解锁时通过对比输入语音和该两段语音模板的相似度,如果相似度高则解锁成功。
程序界面如下,仿照微信设置,当然跟原版比效果略渣。
launcher界面: 录音界面:
解锁成功界面:
具体流程:
1.首先要用手机麦克风录制两段声音模板,提取出语音特征参数并保存,当然也要比较这两段语音的相似度,如果相似度不高则重新录制。
2.然后就可以尝试解锁了,同样用麦克风输入一段待识别语音,提取语音特征参数并与保存的模板比较,如果相似度高则弹出对话框提示解锁成功。
用到的算法:
预加重:为了加强语音在高频的部分,用一个高通滤波对信号进行处理,设输入信号为x(n),输出信号则为
y(n) = x(n) - ax(n - 1),这里我取a为0.9375。
分帧和加窗:程序设置的采样率是22050Hz,帧长为512,大概23ms为一帧,帧移为1/2。对每一帧用hamming窗来加窗,减小吉布斯效应。
端点检测:在录制的信号中检测语音段的起始点和终止点,计算每一帧的短时能量和短时过零率,并分别设置高低两个阀值,使用双门限联合判决的方法来检测语音的端点。具体方法恕不赘述。
提取MEL倒谱系数(MFCC):需要提取端点检测出来的语音段的MFCC参数,流程:对语音段每一帧做FFT,再经过N个MEL频率尺度的三角滤波器组得到N组输出(N一般取20到30个,这里我取26),对N组输出做对数运算,再进一步做离散余弦变换(DCT)即可得到MFCC。为了获取语音的动态特性,还可以对MFCC进行一阶和二阶差分,将MFCC和它的一阶二阶差分合并,作为这一帧的语音特征参数,这里我取MFCC长度为12,只取了一阶差分,所以每一帧的特征参数为一个长度为24的矢量。
DTW算法:Dynamic Time Warping,动态时间归整,该算法基于动态规划(DP)的思想,解决了发音长短不一的模板匹配问题。把输入语音和模板语音的MFCC参数进行距离测量,距离小于某个阀值则可以判断这两段语音的相似度高。具体DTW介绍可以看看大神的文章:http://www.cnblogs.com/tornadomeet/archive/2012/03/23/2413363.html
总结:
因为这里我没有对信号降噪处理,所以在噪声比较小的情况下,能够正常识别并解锁,但是在噪声大的情况下就不能正确识别并解锁了。或者也可以用其他抗噪能力强的端点检测和特征提取方法。
其实用DTW算法做声纹识别是不太可靠的,有时候别人录制同样的语音也可以解锁成功。其实就算是微信的原始版本也一样,当然我不知道微信用的什么算法。
目前说话人识别比较常用的是GMM算法,但是GMM多用于文本无关的说话人识别。文本相关也可以用到HMM,但是HMM需要的训练数据比较多。而采用DTW算法则不需要太多的训练数据,当然也就造成识别效果不够理想的问题。如果能兼顾用户体验和识别效果的话,那想必是极好的,但还有待研究。
项目简介:
项目是用android studio开发,包含两个modual:
一个是界面程序APP,一个是包含上述算法的library模块。
个人能力有限,希望能借助开源的力量,改进这个项目。
项目地址:
https://github.com/Saber904/Lock