我要编一个说话人识别的程序,但是现在人在公司实习,学校急着要,在五月10号前出不来,毕业就危险了,所以求助大家帮我看一下下面程序.下面程序存在错误,主要时MEL系数提取和码书训练上,请大家伸出援助之手,我在这里先谢谢大家!
SMALL_MFCC是子程序,调用生成MEL系数,供神经网络训练使用
clear;
close all;
Time1=cputime;
CM=[];
%----------提取系数--------------------
%-----------读语音数据-------------
for sound_dgital=1:2
sound=['11.wav';'21.wav';'31.wav'];
str=double(sound);
wav_name=char(str(sound_dgital,:));
[signal,fs]=wavread(wav_name);
data1=signal(:,1);
%????????????
data2=signal(:,2);
Data=cat(1,data1,data2);
%-----------端点检测-------------
i=1;
while data1(i+1)-data1(i)<0.014
i=i+1;
end
j=length(data1);
while data1(j-1)-data1(j)<0.014
j=j-1;
end
%---------------------------
%-----------预加重-------------
figure(sound_dgital)
subplot(2,1,1)
plot(data1)
title('加重前信号')
%加重系数
a=0.98;
for n=2:length(data1)
data1(n-1)=data1(n)-a*data1(n-1);
end
figure(sound_dgital)
subplot(2,1,2)
plot(data1)
title('加重后信号')
%------------------------------
%-----------fourier变换定义-------------
N=256;shift=80;nfft=256;
numoverlap=N-shift;
t1=i/8000;t2=j/8000;
lent=length(data1);
%------------------------------
%-----------取成一维语音数据-------------
dd=1;
for d=i:1:j
data(dd)=data1(d);
dd=dd+1;
end
%------------------------------
%-------------MFCC-------------
C=small_MFCC(data,nfft,N,numoverlap,shift,fs)
CM=cat(2,CM,C)
%------------------------------
end
%-----------神经网络部分-------------
[N,m1]=size(CM);
%神经网络初始化
n1=1; %定义输入神经元个数
M=256; %定义输出神经元个数
X=CM;%预定义输入矢量矩阵
W=rand(16,256)*255; %权值的初始化
W=round(W);%权值取整
T1=n1*m1;%学习次数
T2=200;
%训练
s=round(rand(1,n1*m1)*(n1*m1-1));%产生一个随机矩阵,以便随机选取样本图像矢量,范围(0,4095)
s=s+1;%s范围变为(1,4096)
%权值调整
for(t=1:T2) %开始训练,从1到T2
t;
for(T=1:T1) %开始取输入图像矢量
NE=-132+362*exp(-T/T1); %定义邻域大小函数
NE=round(NE);
%计算邻域半径
if(rem(NE,2)==0)
R=NE/2;
else
R=(NE-1)/2;
end
%找出最小欧氏距离
for(j=1:256)
P(:,j)=(X(:,s(1,T))-W(:,j)).^2;%计算欧氏距离
Q(1,j)=sum(P(:,j)); %欧氏距离和赋予新的矩阵
[minQ,I]=min(Q);%找出最小数的下标,等同于输出矢量的下标
end
r0=I; %最小距离下标赋予r0
%在邻域内调整权值
stu=0.5*exp(-t/T2); %定义学习函数
if(I<=R) %邻域节点下标是负数时,即超出矩阵维数,邻域从1开始
for(j=1:I+R)
r=j;
stu_f=exp(-(r-r0).^2/(230*exp(-t/T2)));%定义学习加权邻域函数
W(:,j)=W(:,j)+stu*stu_f*(X(:,s(1,T))-W(:,j));
end
elseif(I>=256-R) %邻域节点下标大于256时,即超出矩阵维数,邻域到256止
for(j=I-R:256)
r=j;
stu_f=exp(-(r-r0).^2/(230*exp(-t/T2)));%定义学习加权邻域函数
W(:,j)=W(:,j)+stu*stu_f*(X(:,s(1,T))-W(:,j));
end
else
for(j=I-R:I+R)
r=j;
stu_f=exp(-(r-r0).^2/(230*exp(-t/T2)));%定义学习加权邻域函数
W(:,j)=W(:,j)+stu*stu_f*(X(:,s(1,T))-W(:,j));
end
end
end
end
W=round(W)
save codebookbeeline W; %码书保存
W=uint8(W);
mesh(W);
Time2=cputime-Time1
imwrite(W,'beeline.bmp');
figure(64)
imshow('beeline.bmp');
MFCC
function C1=small_MFCC(data,nfft,N,numoverlap,shift,fs)
%帧间移动
fft_window=specgram(data,nfft,fs,hamming(N),numoverlap);
%每列代表每帧的fft变换
fft_frequency=abs(fft_window);
SM=[];
[frame_rows,frame_sum_colums]=size(fft_frequency);
%应该加循环对每个列进行滤波,每个列代表一个窗
for fft_colums=1:frame_sum_colums
evf=fft_frequency(:,fft_colums);
for filter_S=1:24
c=100; %定义滤波器阶数97阶
fc1=[300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1123,1296,1469,1642,1815,1988,2161,2334,2507,2853];%下限截止频率
fc2=[400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000 ,1296, 1469,1642,1815,1988,2161,2334,2507,2853,3199,3545];%上限截止频率
%参数转换,将模拟滤波器的技术指标转换为数字滤波器的技术指标
w1=2*pi*fc1(filter_S)/fs;
w2=2*pi*fc2(filter_S)/fs;
%使用三角窗函数
window=triang(c+1);
%使用标准响应的加窗设计函数fir1
h=fir1(c,[w1/pi w2/pi],window);
%第frame帧滤波结果
S(:,filter_S)=filter(h,1,evf);
end
SM=cat(2,SM,S);%得到一个Mel频谱
S(:)=[];
end
%得到一个数字Mel频谱
%滤波器组输出的对数能量为CM
%206帧,每个帧经过个滤波器,最后得到206*13个对数能量输出
colums_sum=length(SM);
for colums_s=1:colums_sum %每一列进行对数能量处理
colums_s
for log_s=1:frame_rows%行循环
A=((abs(SM(log_s,colums_s)).^2)*hamming(log_s));
end
end
%得到余弦变换系数
C=dct(log(A));
C1=dct(A,16)
clear frame_sum_colums;
return