*********************************************************废话****************************************
近日一直想找一篇能够讲解比较详细的文章,奈何不是纯原理就是读不懂代码(对于小白有注释那也是天书级别),经过多日酝酿,终于能够大概看懂一些,在这里希望能够做一些笔记,顺便给接下来想了解这一部分的人一些借鉴,可以一起探讨,等大家看到这篇文章时就是我及百家之所长略懂皮毛之时。
*********************************************************正题*****************************************
何谓声音特征提取,我们究竟要提取什么?提取过程需要做什么?为什么这么做?这些。。。。我都不讲,大家写的都比我好得多。
我在这里主要是以说明参数为主要目的,我所能做的也只是简单使用,根据自己需要调整参数,里边有些函数例如 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,:);