playtree 发表于 2006-11-23 09:05

请问如何求取一段语音的自相关函数

我想通过求取自相关函数来求取语音的音调(pitch)
请问该如何实现编程?
希望高手指点
谢谢

[ 本帖最后由 zhangnan3509 于 2007-7-4 14:18 编辑 ]

happy 发表于 2006-12-6 10:37

xcorr

playtree 发表于 2006-12-7 10:03

谢谢你
xcorr做基音的程序,好象时间太长了

另外我这里有一段下载的提取基音程序,但是有问题,因为我求到的基音怎么是44100,请问到底是什么地方有问题,谢谢
%巴特沃斯滤波器提取基音程序:
tic;
clear all;
clc;

fname = sprintf('F:\\code\\music\\%d.wav',5);
= wavread(fname);
% sour=interp(sour,100);%
% sour=decimate(sour,441);%decrease sampling rate

%设计巴特沃斯低通滤波器
rp=9;%通带衰减不大于
rs=60;%阻带衰减不小于
wp=900;%通带截止频率
ws=1800;%阻带截止频率
=buttord(wp/(fs/2),ws/(fs/2),rp,rs);
=butter(N,Wn); %低通滤波器
sour=filter(b,a,sour);
t=length(sour);
L=300;
N=ceil(t/L);

%取信号中间的450个采样点
j=1;
k=150;
for i=ceil(N/2)*L+1:ceil(N/2)*L+L+k
    newsour(j)=sour(i);
    j=j+1;
end

%三电平中心消波
amax=max(newsour(1:(L+k)/3));
bmax=max(newsour((L+k)/3+1:L+k));
cl=0.68*min(amax,bmax);
% cl=0.68*max(newsour);
for i=1:L+k
    if newsour(i)>cl
      newsour(i)=newsour(i)-cl;
    elseif newsour(i)<-cl
      newsour(i)=newsour(i)+cl;
    else
      newsour(i)=0;
    end
end
newsour2=sign(newsour);

%newsour为450个采样点,newsour2为450个采样点,newrk为150个采样点
newrk=zeros(1,150);
%求出零点的值
for i=21:L%21:300
    newrk(1)=newrk(1)+newsour(i)*newsour2(i);
end

%对newsour中的21:300个采样点进行自相关计算
for i=21:150   
    for j=21:L
      newrk(i)=newrk(i)+newsour(j)*newsour2(j+i);
    end
end
rmax=max(newrk(21:150))
newrk(1)
0.25*newrk(1)
%求除零点外的第一个极值点所在的位置
if rmax<0.25*newrk(1)
    p=0;
else
    =max(newrk(21:150))
end

%计算出基音周期
s=['基音周期是:',num2str(p/fs),'s','基音频率是:',num2str(fs/p),'hz'];
% s=['基音频率是:',num2str(fs/p),'hz'];
msgbox(s);

toc;

playtree 发表于 2006-12-7 10:29

上面的说法应该改为
有的语音段求出的基音频率是44100,有的不是
那对于求出的基音频率是44100,请问应该调整什么参数呢?

playtree 发表于 2006-12-7 11:23

另外,用fft变换的方法也是可以求取的
请问进行fft之后应该如何计算呢
fname = sprintf('F:\\code\\music\\%d.wav',5);
= wavread(fname);

TIME=abs(fftn(sour)).^2;%通过频率域的傅立叶变换方法求基音;
TIME=ifftn(TIME);
谢谢

playtree 发表于 2006-12-8 11:04

请问该怎么修改?
谢谢

playtree 发表于 2006-12-8 14:32

上面的程序是从别人那里拿来的
我自己也试着写了一个,是通过自相关函数来实现的
但是在最后求差分的时候
怎么就是找不到零点呢
我的程序如下
请指出问题出在哪里
= wavread('F:\code\music\88.wav');
win=fs*20/1000;
inc=win*0.5;

f=enframe(x,win,inc);
=size(f);
cor=[];
for i=1:M
   t=f(i,:);
   temp = xcorr(t);
   cor(i,:) = temp;
end

cor_diff1=cor(2:end,:)-cor(1:end-1,:);
cor_diff2=sign(cor_diff1);
cor_diff3=reshape(cor_diff2,1,size(cor_diff2,1)*size(cor_diff2,2));
=find(cor_diff3==0);
先在这里谢谢了

songzy41 发表于 2006-12-8 15:17

原帖由 playtree 于 2006-12-7 11:23 发表
另外,用fft变换的方法也是可以求取的
请问进行fft之后应该如何计算呢
fname = sprintf('F:\\code\\music\\%d.wav',5);
= wavread(fname);

TIME=abs(fftn(sour)).^2;%通过频率域的傅立叶变换方法求基音;
...
如果想从频率域的傅立叶变换方法求基音,应该用倒谱的方法可能更好。

playtree 发表于 2006-12-8 15:40

谢谢
那求完倒谱之后
怎么求取基音呢
谢谢

playtree 发表于 2006-12-8 16:32

现在我通过时间域的自相关函数和频率域的倒谱法求得的基音怎么会差的很多呢
页: [1]
查看完整版本: 请问如何求取一段语音的自相关函数