声音特征提取-MFCC详解

       *********************************************************废话****************************************

       近日一直想找一篇能够讲解比较详细的文章,奈何不是纯原理就是读不懂代码(对于小白有注释那也是天书级别),经过多日酝酿,终于能够大概看懂一些,在这里希望能够做一些笔记,顺便给接下来想了解这一部分的人一些借鉴,可以一起探讨,等大家看到这篇文章时就是我及百家之所长略懂皮毛之时。

       *********************************************************正题*****************************************

       何谓声音特征提取,我们究竟要提取什么?提取过程需要做什么?为什么这么做?这些。。。。我都不讲,大家写的都比我好得多。

     我在这里主要是以说明参数为主要目的,我所能做的也只是简单使用,根据自己需要调整参数,里边有些函数例如 audioread()之类的都可以在官方文档(help)中找到比较详细的说明,基本上我提到的参数就是需要根据你需求作出调整的。

    不墨迹了,还是直接上代码了,原理自己去看吧

    预处理比较全的一篇   https://blog.csdn.net/u011108244/article/details/68076921

    求参比较全的一篇      https://blog.csdn.net/yjjat1989/article/details/44962139

    原理讲解最细致的      https://blog.csdn.net/u013378306/article/details/65954965

 

       *******************************************************代码分析************************************** 

 

 第一步:读取声音文件

[sampledata,FS] = audioread('F:1.mp3'); % sampledata是保存音频数据信号 fs是采样频率 然后替换自己文件路径就可以了

第二步:(如果你是双声道,采样本不要给自己找麻烦,又不是给自己听,搞那么复杂干嘛)变换声道,双声

道变成单声道。这一部分没有需要咱们做的,不用懂,记得做就可以了。

function sample = calsample(sampledata,FS)temp_sample = resample(sampledata,1,FS/11025);

[m,n] = size(temp_sample);

if (n == 2)

sample = temp_sample(:,1);

else

sample = temp_sample;

end end

第三步:归一化mel滤波器系组数

                bank=melbankm(M,N,fs,0,0.5,'m');       % M:滤波器数量  N:一帧采样个数  fs:前边函数计算得到   

                这个函数在这自己看吧     http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/doc/voicebox/melbankm.html

                bank=full(bank);

                bank=bank/max(bank(:));

 

         第四步:求dct系数 (此为12*23)  

      补充一下DCT:离散余弦变换,舍弃高频部分,保留低频,为了进行压缩。

       23是滤波器的数量,12是数据维度,最后会得到1*12维数据,加上一阶差分是1*24                                                                   最后得到的数据  你的 数据源数量*24 维的矩阵 (以后去做分类训练的数据 )

                                 for i=1:12

                                 j=0:23;

 

                                 dctcoef(i,:)=cos((2*j+1)*i*pi/(2*24));

                                 end

 

           第五步:      一部分预处理操作

                                 % 预加重
                                 AggrK=double(sampledata);      % sampledata:读取文件时得到的
                                 AggrK=filter([1,-0.9375],1,AggrK);
                                 % 分帧                                                  %    N个点放在一帧,将128个点重叠
                                 FrameK=enframe(AggrK,N,128);    
                                 % 加窗                                                  %   对点N加hamming窗(多种)
                                 for i=1:size(FrameK,1)
                                 FrameK(i,:)=(FrameK(i,:))'.*hamming(N);
                                 end

                                 FrameK=FrameK';

            第六步:    离散傅里叶变换

                                  % 归一化倒谱提升窗口   ,  w为窗口函数,     目的是为了对MFCC中某些谱线增强
                                  w=1+6*sin(pi*[1:12]./12);
                                  w=w/max(w) ;

                              t=abs(fft(s));                               %  傅里叶快速变换算法

                              t=t.^2;  

                                  P=bank*t(1:129,:);                            %   将功率谱通过滤波器

                                  

                                 %取对数后做离散变换

                                  D=dctcoef*log(P);                             
                                  for i=1:size(D,2)
                                  m(i,:)=(D(:,i).*w')';

 

                                  end

 

                第七步:差分方程                   

                       %为了将帧变成连续的,一般求取当前帧与前后各一帧的十三个特征的差值

                        (十二个倒谱特征加一个能量特征)

                                   dtm=zeros(size(m));
                                   for i=3:size(m,1)-2
                                   dtm(i,:)=-2*m(i-2,:)-m(i-1,:)+m(i+1,:)+2*m(i+2,:);
                                   end

                                   dtm=dtm/3;

                                   需要可以再求二阶的

                   第八步:得到MFCC向量

                               %合并mfcc参数和一阶差分mfcc参数
                                    cc=[m,dtm];

                                    

                                    %去除首尾两帧,因为这两帧的一阶差分参数为0

                                    cc=cc(3:size(m,1)-2,:);

 

 

 

 

你可能感兴趣的:(机器学习)