声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 2123|回复: 9

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

[复制链接]
发表于 2006-11-23 09:05 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

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

[ 本帖最后由 zhangnan3509 于 2007-7-4 14:18 编辑 ]
回复
分享到:

使用道具 举报

发表于 2006-12-6 10:37 | 显示全部楼层
xcorr
 楼主| 发表于 2006-12-7 10:03 | 显示全部楼层
谢谢你
xcorr做基音的程序,好象时间太长了

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

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

%设计巴特沃斯低通滤波器
rp=9;%通带衰减不大于
rs=60;%阻带衰减不小于
wp=900;%通带截止频率
ws=1800;%阻带截止频率
[N,Wn]=buttord(wp/(fs/2),ws/(fs/2),rp,rs);
[b,a]=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
    [y,p]=max(newrk(21:150))
end

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

toc;
 楼主| 发表于 2006-12-7 10:29 | 显示全部楼层
上面的说法应该改为
有的语音段求出的基音频率是44100,有的不是
那对于求出的基音频率是44100,请问应该调整什么参数呢?
 楼主| 发表于 2006-12-7 11:23 | 显示全部楼层
另外,用fft变换的方法也是可以求取的
请问进行fft之后应该如何计算呢
fname = sprintf('F:\\code\\music\\%d.wav',5);
[sour,fs,bits] = wavread(fname);

TIME=abs(fftn(sour)).^2;%通过频率域的傅立叶变换方法求基音;
TIME=ifftn(TIME);
谢谢
 楼主| 发表于 2006-12-8 11:04 | 显示全部楼层
请问该怎么修改?
谢谢
 楼主| 发表于 2006-12-8 14:32 | 显示全部楼层
上面的程序是从别人那里拿来的
我自己也试着写了一个,是通过自相关函数来实现的
但是在最后求差分的时候
怎么就是找不到零点呢
我的程序如下
请指出问题出在哪里
[x,fs,bits] = wavread('F:\code\music\88.wav');
win=fs*20/1000;
inc=win*0.5;

f=enframe(x,win,inc);
[M,N]=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));
[c,r,v]=find(cor_diff3==0);
先在这里谢谢了
发表于 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;%通过频率域的傅立叶变换方法求基音;
...

如果想从频率域的傅立叶变换方法求基音,应该用倒谱的方法可能更好。
 楼主| 发表于 2006-12-8 15:40 | 显示全部楼层
谢谢
那求完倒谱之后
怎么求取基音呢
谢谢
 楼主| 发表于 2006-12-8 16:32 | 显示全部楼层
现在我通过时间域的自相关函数和频率域的倒谱法求得的基音怎么会差的很多呢
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-5-18 12:09 , Processed in 0.047222 second(s), 17 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表