从上次的短时时域性质,隔了很长时间才开始进行这个。这个频域写完,后面的安排就是首先就是语音的特征,然后把VQ,DTW,HMM,GMM和语音识别系统的一些东西写下。希望这个系列可以丰富点。由于最近在看信息检索,大数据的一些东西,总是感觉自己学的是不是太广了,所以有时候停下来要不断的去思考自己所走的路,所学的东西。前几天,在qq空间看到一个工作2年的人说没有了目标,学会了安逸。也许就是没有目标吧,我似乎总是能找到需要学的东西,但是这样无形我的压力很大,所以适当的目标是合适,祝愿你可以开心的学习,开心的生活。有点煽情,接下来,我们去看看语音的短时频域分析吧。希望你有所收获。
说到频域,似乎大家都会想到傅里叶变换。对于连续的信号是FFT,对于离散的信号时DFT。一般的傅里叶变换适合周期信号和平稳随机信号,但不适合语音信号。为什么?因为语音是短时平稳的。所以只能用短时傅里叶去分析。就是分帧后才对其进行傅里叶变换。某一帧的短时傅里叶变换的定义如下:
一般我们求短时傅里叶变换时都用汉明窗。为什么用这个窗?而不是用矩阵窗和汉宁窗呢?原因见下图:
原因是:
这些都是《数字语音处理及MATLAB仿真》这本书上的。感觉介绍的比我的好,所以……
最后,说下这个重要性。语音的频域性质就这一个。所以时域解决不了就是它了。后面我希望自己可以把这个代码贴出来。
好吧,找到c的代码。
float stft(float *input,float *output,int fftsize,int hopsize) { uintptr_t handle; int posin,posout,i,data_len; float *sigframe,*specframe, *window; FILE *zhong=fopen("zhong.txt","w+"); handle=fa_fft_init(FFTSIZE); sigframe= (float *)malloc(sizeof(fftsize) * 2); specframe= (float *)malloc(sizeof(fftsize) *2); window= (float *)malloc(sizeof(fftsize) *2);q //window for (i=0;i<fftsize;i++) //compute hanning at the length of 512 window[i]=(1.0-cos(2.0*pi*i/(fftsize-1)))/2.0; //window is hanning for(posin=posout=0;posin<data_len;posin+=hopsize) { // window a signal frame for(i= 0;i<fftsize;i++) if (posin+i<data_len) sigframe[i] = input[posin+i]*window[i]; else sigframe[i]=0; // transform it fa_fft(handle,sigframe); for (i = 0; i <fftsize ; i++) specframe[i]=sqrt(fft_inbuf[2*i]*fft_inbuf[2*i]+fft_inbuf[2*i+1]*fft_inbuf[2*i+1]); //output it for ( i=0;i<fftsize;i++,posout++) output[posout]=specframe[i]; } free(sigframe); free(specframe); return posout ; }
这里需要调用fft的函数。大家应该可以看到stft'的公式和代码的结合。
matlab的stft的代码在网上很多。我们在求频谱的时候需要用到这个函数。虽然matlab求语音频谱有库函数,但是仔细分析还是挺麻烦的。这里就不贴matlab的代码。有STFT的公式,其实对于matlab代码很快就可以搞定。不知道的可以留言。
好了,这个短时频域分析就说到这里,期待下一次的mfcc,lpcc的特征。
有任何问题,欢迎指正。