有关方言的数据集寻找困难,而且水平参差不齐,于是自己制作:
音频直接剪辑下载的命名不方便,可以按照这个方法:
CTRL+A全选,点击F2,批量重命名
例如,我将文档里面的音频命名为cs-m(表示长沙方言,男性),确认后自动将名称按照cs-m + (序号) 的方式命名,注意m后面有空格,括号为半角括号:
于是数据集便以规范命名制作完毕。
接下来需要批量导入音频文件,我试了网上的一些方法,感觉比较乱而且不符合我的需求。我的需求是:
代码如下:
clear all;
clc;
[FileName,PathName]=uigetfile({'*.wav'},'wav文件读取','MultiSelect','on');
% 选择需要用到的wav文件,存入FileName
aveCC=zeros(30,13);
for k=1:30
% 每次读入一个音频
str = cell2mat(FileName(k));
[y2,fs]=audioread(str);
% 双音道变为单音道
y1=y2(:,1);
CC = mymfcc(y1,fs);
col=size(CC,2);
% 求平均值
sum=zeros(1,col);
row=size(CC,1);
for i=1:row
sum=sum+CC(i,:);
end
ave=sum/row;
aveCC(k,:)=ave;
end
disp(aveCC);
% 写成一个xlsx
xlswrite('yy-m.xlsx',aveCC);
关于MFCC的原理,大家可以参考语音信号处理之(四)梅尔频率倒谱系数(MFCC)
写的很详细,按照原理可以很简单的写出代码。
这里是我自己的函数mymfcc
,其中的2个归一化的原因和原理我比较模糊,欢迎大神指点迷津:
function mfccmat = mymfcc(x,fs)
% mfcc特征提取函数
% 输入:x为信号,fs抽样率
% 输出:mfccmat是一帧语音的MFCC系数矩阵
% 参数
n = 24; % Mel滤波器阶数
p = 12; % 倒谱阶数
nwin = 256; % 帧长
% 获得Mel滤波器组,这是voicebox中的函数
bank = melbankm(n,nwin,fs,0,0.5,'t');
% 归一化mel滤波器组系数
bank = full(bank); % 将稀疏矩阵转换全矩阵
bank = bank/max(bank(:));
% 归一化倒谱提升窗口
w = 1+0.5*p*sin(pi*(1:p)./p);
w = w/max(w);
% 预加重滤波器
x = double(x);
x = filter([1,-0.9375],1,x);
% 分帧,这也是voicebox中的函数
xframe = enframe(x,nwin);
nframe = size(xframe,1);% 总帧数
% 计算每帧的MFCC参数,留出13个位置,最后一个位置是短时能量
mfccmat = zeros(nframe,p+1);
for i = 1:nframe
y = xframe(i,:)';
y = y.*hamming(nwin); % 加窗
energy = log(sum(y.^2)+eps); % 短时能量
y = abs(fft(y));
y = y(1:fix(nwin/2)+1); % 使y的长度和Mel滤波器组相同
% Discrete cosine transform 离散余弦变换,用于逆变换取代ifft
c = dct(log(bank*y+eps));
c = c(2:p+1)'.*w; % 取2~p+1个系数,并且倒谱提升
mfcc = [c,energy]; % 将能量加入,作为特征的一个元素
mfccmat(i,:) = mfcc;
end
end
在KNN实现鸢尾花分类中:https://blog.csdn.net/qq_45510888/article/details/106158889
已经详细介绍了KNN分类器原理和代码,这里就不赘述。
将做好的数据集按照7:3的比例分成训练集和测试集,然后使用KNN分类器导入数据,便可以进行分类。为了操作方便,进行了小修改。与上一版相比较增加的内容有:
feature=13;sort=feature+1;% 特征数和分类所在位置
k = 9;% 确定k的值,取值不同分类结果不同
% 读入训练集,分类:长沙1,河南2,南昌3,闽南4,普通话5,粤语6
train = xlsread('train.xlsx');
trainData = train(:,1:feature);% 前几列是特征
trainClass = train(:,sort);% 最后1列是分类
最终分类结果:
由于KNN最理想的情况应该是实现2分类,对于多分类(例如本文的6分类),经常会出现最大值有2个或者更多、无法确定此测试样本的最终分类的情况。作者还没想到更好的解决方法,暂且只是将第一顺序位的类别赋予结果,同样希望有相关经验的朋友交流讨论!
最后,大家在使用KNN时要规避其存在的一些不足之处:
关于KNN的改进,这里推荐一篇博客:KNN分类器