ifj>2
D3=D(i-1,j-2);
else
D3=realmax;
end
D(i,j)=d(i,j)+min([D1,D2,D3]);
end
end
dist=D(n,m);
end
附录5:voicebox程序“melbankm.m”
function [x,mc,mn,mx]=melbankm(p,n,fs,fl,fh,w)
if nargin < 6
w='tz';
if nargin< 5
fh=0.5;
ifnargin < 4
fl=0; % min freq is DC
end
end
end
sfact=2-any(w=='s');
wr=' '; %default warping is mel
for i=1:length(w)
ifany(w(i)=='lebf');
wr=w(i);
end
end
if any(w=='h') || any(w=='H')
mflh=[flfh];
else
mflh=[flfh]*fs;
end
if ~any(w=='H')
switch wr
case 'f'
case'l'
if fl<=0
error('Low frequency limit must be >0 for l option');
end
mflh=log10(mflh);
case'e'
mflh=frq2erb(mflh);
case'b'
mflh=frq2bark(mflh);
otherwise
mflh=frq2mel(mflh);
end
end
melrng=mflh*(-1:2:1)';
fn2=floor(n/2);
if isempty(p)
p=ceil(4.6*log10(fs));
end
if any(w=='c')
if p<1
p=round(melrng/(p*1000))+1;
end
melinc=melrng/(p-1);
mflh=mflh+(-1:2:1)*melinc;
else
if p<1
p=round(melrng/(p*1000))-1;
end
melinc=melrng/(p+1);
end
switch wr
case'f'
blim=(mflh(1)+[0 1 p p+1]*melinc)*n/fs;
case 'l'
blim=10.^(mflh(1)+[0 1 p p+1]*melinc)*n/fs;
case 'e'
blim=erb2frq(mflh(1)+[0 1 p p+1]*melinc)*n/fs;
case 'b'
blim=bark2frq(mflh(1)+[0 1 p p+1]*melinc)*n/fs;
otherwise
blim=mel2frq(mflh(1)+[0 1 p p+1]*melinc)*n/fs;
end
mc=mflh(1)+(1:p)*melinc;
b1=floor(blim(1))+1;
b4=min(fn2,ceil(blim(4))-1);
switch wr
case'f'
pf=((b1:b4)*fs/n-mflh(1))/melinc;
case 'l'
pf=(log10((b1:b4)*fs/n)-mflh(1))/melinc;
case 'e'
pf=(frq2erb((b1:b4)*fs/n)-mflh(1))/melinc;
case 'b'
pf=(frq2bark((b1:b4)*fs/n)-mflh(1))/melinc;
otherwise
pf=(frq2mel((b1:b4)*fs/n)-mflh(1))/melinc;
end
if pf(1)<0
pf(1)=[];
b1=b1+1;
end
if pf(end)>=p+1
pf(end)=[];
b4=b4-1;
end
fp=floor(pf);
pm=pf-fp;
k2=find(fp>0,1);
k3=find(fp<p,1,'last');
k4=numel(fp);
if isempty(k2)
k2=k4+1;
end
if isempty(k3)
k3=0;
end
if any(w=='y')
mn=1;
mx=fn2+1;
r=[ones(1,k2+b1-1) 1+fp(k2:k3) fp(k2:k3) repmat(p,1,fn2-k3-b1+1)];
c=[1:k2+b1-1 k2+b1:k3+b1 k2+b1:k3+b1 k3+b1+1:fn2+1];
v=[ones(1,k2+b1-1) pm(k2:k3) 1-pm(k2:k3) ones(1,fn2-k3-b1+1)];
else
r=[1+fp(1:k3) fp(k2:k4)];
c=[1:k3k2:k4];
v=[pm(1:k3)1-pm(k2:k4)];
mn=b1+1;
mx=b4+1;
end
if b1<0
c=abs(c+b1-1)-b1+1;
end
% end
if any(w=='n')
v=0.5-0.5*cos(v*pi);
elseif any(w=='m')
v=0.5-0.46/1.08*cos(v*pi);
end
if sfact==2
msk=(c+mn>2) & (c+mn<n-fn2+2);
v(msk)=2*v(msk);
end
if nargout > 2
x=sparse(r,c,v);
ifnargout == 3
mc=mn;
mn=mx;
end
else
x=sparse(r,c+mn-1,v,p,1+fn2);
end
if any(w=='u')
sx=sum(x,2);
x=x./repmat(sx+(sx==0),1,size(x,2));
end
if ~nargout || any(w=='g')
ng=201;
me=mflh(1)+(0:p+1)'*melinc;
switch wr
case 'f'
fe=me;
xg=repmat(linspace(0,1,ng),p,1).*repmat(me(3:end)-me(1:end-2),1,ng)+repmat(me(1:end-2),1,ng);
case'l'
fe=10.^me;
xg=10.^(repmat(linspace(0,1,ng),p,1).*repmat(me(3:end)-me(1:end-2),1,ng)+repmat(me(1:end-2),1,ng));
case'e'
fe=erb2frq(me);
xg=erb2frq(repmat(linspace(0,1,ng),p,1).*repmat(me(3:end)-me(1:end-2),1,ng)+repmat(me(1:end-2),1,ng));
case'b'
fe=bark2frq(me);
xg=bark2frq(repmat(linspace(0,1,ng),p,1).*repmat(me(3:end)-me(1:end-2),1,ng)+repmat(me(1:end-2),1,ng));
otherwise
fe=mel2frq(me);
xg=mel2frq(repmat(linspace(0,1,ng),p,1).*repmat(me(3:end)-me(1:end-2),1,ng)+repmat(me(1:end-2),1,ng));
end
v=1-abs(linspace(-1,1,ng));
ifany(w=='n')
v=0.5-0.5*cos(v*pi);
elseifany(w=='m')
v=0.5-0.46/1.08*cos(v*pi);
end
v=v*sfact;
v=repmat(v,p,1);
ifany(w=='y')
v(1,xg(1,:)<fe(2))=sfact;
v(end,xg(end,:)>fe(p+1))=sfact;
end
ifany(w=='u')
dx=(xg(:,3:end)-xg(:,1:end-2))/2;
dx=dx(:,[1 1:ng-2 ng-2]);
vs=sum(v.*dx,2);
v=v./repmat(vs+(vs==0),1,ng)*fs/n;
end
plot(xg',v','b');
set(gca,'xlim',[fe(1) fe(end)]);
xlabel(['Frequency (' xticksi 'Hz)']);
end
附录6:辅助程序“enframe.m”
function [f,t,w]=enframe(x,win,inc,m)
nx=length(x(:)); % 取数据长度
if nargin<2 || isempty(win)
win=nx;
end
if nargin<4 || isempty(m)
m='';
end
nwin=length(win); % 取窗长
if nwin == 1 % 判断窗长是否为1,若为1,即表示没有设窗函数
lw = win;% 是,帧长=win
w =ones(1,lw);
else
lw =nwin; % 否,帧长=窗长
w =win(:)';
end
if (nargin < 3) || isempty(inc) % 如果只有两个参数,设帧inc=帧长
inc = lw;
end
nli=nx-lw+inc;
nf = fix((nli)/inc); % 计算帧数
na=nli-inc*nf;
f=zeros(nf,lw); % 初始化
indf= inc*(0:(nf-1)).'; % 设置每帧在x中的位移量位置
inds = (1:lw); % 每帧数据对应1:len
f(:) = x(indf(:,ones(1,lw))+inds(ones(nf,1),:)); % 对数据分帧
if nargin>3 && (any(m=='z') ||any(m=='r')) && na>0
ifany(m=='r')
ix=1+mod(nx-na:nx-na+lw-1,2*nx);
f(nf+1,:)=x(ix+(ix>nx).*(2*nx+1-2*ix));
else
f(nf+1,1:na)=x(1+nx-na:nx);
end
nf=size(f,1);
end
if (nwin > 1) % 若参数中包括窗函数,把每帧乘以窗函数
f = f .*w(ones(nf,1),:);
end
if nargout>1
ifany(m=='E')
t0=sum((1:lw).*w.^2)/sum(w.^2);
elseifany(m=='A')
t0=sum((1:lw).*w)/sum(w);
else
t0=(1+lw)/2;
end
t=t0+inc*(0:(nf-1)).';
end
附录7:绘制幅频图程序(DrawFFT.m)
function [ ]= DrawFFT( x, Fs )
% DrawFFT 对输入信号进行快速傅里叶变换
% 输入参数:x :输入信号; Fs:采样频率
L = length(x);
NFFT = 2^nextpow2(L); %确定FFT变换的长度
y = fft(x, NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1); %频率向量
plot(f, 2*abs(y(1:NFFT/2+1))); %绘制频域图像
title('幅度谱');
xlabel('频率(Hz)');
ylabel('|y(f)|');
end