查看: 1550|回复: 38|关注: 0

[已解决] 如何求一段元音的基音周期的个数

[复制链接]

新手

46 麦片

财富积分


050


86

主题

185

帖子

0

最佳答案
  • 关注者: 2
如书上第八章可以求出基音周期,但是我现在想要求元音/a/的一个基音周期内的某参数(如能量),所以需要先求出该元音的基音周期个数,然后就可以for循环求每一个基音周期内的某参数(如能量),请问应该如何操作才能得到基音周期的个数呢?

新手

46 麦片

财富积分


050


86

主题

185

帖子

0

最佳答案
  • 关注者: 2
 楼主| 发表于 2018-1-19 11:56:01 | 显示全部楼层
或者说,我要求出一个基因周期内有多少个样本点?然后就可以分帧处理

论坛优秀回答者

17

主题

4734

帖子

1075

最佳答案
  • 关注者: 481
发表于 2018-1-19 14:33:30 | 显示全部楼层
从第8章的程序中求出基音周期T和基音频率F。基音周期T就是就以样点为单位的,当然是给出一帧数据的平均值,平均基音周期。
我明白LZ是要以基音周期来分帧,所以要对每一个基音周期进行标注。我建议LZ可以参看一下10.7节中基音分帧的方法,或许对你会有所帮助。

新手

46 麦片

财富积分


050


86

主题

185

帖子

0

最佳答案
  • 关注者: 2
 楼主| 发表于 2018-1-22 16:40:23 | 显示全部楼层
songzy41 发表于 2018-1-19 14:33
从第8章的程序中求出基音周期T和基音频率F。基音周期T就是就以样点为单位的,当然是给出一帧数据的平均值, ...

宋老师,我按照10.7.1对语音进行标注,结果如图片所示,后面的标注显然是有问题的,程序如下,语音在附件中。
clear all; clc; close all;
[xx,Fs]=wavread('G:/healthy/male-(20-30)-healthy/N/a/706-a_n.wav');                      % 读取文件
fs=11000;xx=resample(xx,11000,Fs);%降采样
xx=xx-mean(xx);                            % 去除直流分量
x=xx/max(abs(xx));                         % 归一化
N=length(x);                               % 数据长度
time=(0:N-1)/fs;                           % 求出对应的时间序列

[LowPass] = LowPassFilter(x, fs, 500);     % 低通滤波
p = PitchEstimation(LowPass, fs);                   % 计算基音频率
[u, v] = UVSplit(p);                       % 求出有话段和无话段信息
lu=size(u,1); lv=size(v,1);                % 初始化

pm = [];
ca = [];
for i = 1 : length(v(:,1))
    range = (v(i, 1) : v(i, 2));           % 取一个有话段信息
    in = x(range);                         % 取有话段数据
% 对一个有话段寻找基音脉冲标注
    [marks, cans] = VoicedSegmentMarking(in, p(range), fs);

    pm = [pm  (marks + range(1))];         % 保存基音脉冲标注位置
    ca = [ca;  (cans + range(1))];         % 保存基音脉冲标注候选名单
end
% 作图
figure(1)
pos = get(gcf,'Position');
set(gcf,'Position',[pos(1), pos(2)-150,pos(3),pos(4)+100]);
subplot 211; plot(time,x,'k'); axis([0 max(time) -1 1.2]);
for k=1 : lv
    line([time(v(k,1)) time(v(k,1))],[-1 1.2 ],'color','k','linestyle','-')
    line([time(v(k,2)) time(v(k,2))],[-1 1.2 ],'color','k','linestyle','--')
end
title('语音信号波形和端点检测');
xlabel(['时间/s' 10 '(a)']); ylabel('幅值');
%figure(2)
%pos = get(gcf,'Position');
%set(gcf,'Position',[pos(1), pos(2)-100,pos(3),(pos(4)-160)]);
subplot 212; plot(x,'k'); axis([0 N -1 0.8]);
line([0 N],[0 0],'color','k')
lpm=length(pm);
for k=1 : lpm
    line([pm(k) pm(k)],[0 0.8],'color','k','linestyle','-.')
end
xlim([3000 4000]);
title('部分语音信号波形和相应基音脉冲标注');
xlabel(['样点' 10 '(b)']); ylabel('幅值');


捕获11.PNG

706-a_n.rar

50.21 KB, 下载次数: 3

语音

新手

46 麦片

财富积分


050


86

主题

185

帖子

0

最佳答案
  • 关注者: 2
 楼主| 发表于 2018-1-22 16:44:22 | 显示全部楼层
songzy41 发表于 2018-1-19 14:33
从第8章的程序中求出基音周期T和基音频率F。基音周期T就是就以样点为单位的,当然是给出一帧数据的平均值, ...

而且不需要对语音进行有话段区分,因为语音的开始就是有话段,那么范围就是整个语音的范围,那range=语音从头到尾,这个语句应该怎么写呢?

论坛优秀回答者

17

主题

4734

帖子

1075

最佳答案
  • 关注者: 481
发表于 2018-1-23 10:43:43 | 显示全部楼层
guolele 发表于 2018-1-22 16:40
宋老师,我按照10.7.1对语音进行标注,结果如图片所示,后面的标注显然是有问题的,程序如下,语音在附件 ...

因为我是引用的程序,看来屯是不能满足你的要求。
我仔细看了一下,程序运行到
lu=size(u,1); lv=size(v,1);                % 初始化
时还是可以的。虽然p在前后都丢了一些数据,但只要补上就能用的。以后部分二建议LZ自已编程,方法为:
1,把p修改一下:
p(u(1,1):u(1,2))=p(v(1,1));
p(u(2,1):u(2,2))=p(v(1,2));
使从1到9017都有p值。
2,先在LowPass的1至p(1)中找出极大值,极大值位置yl存放在pm中。
然后通过循环一个个往下找局部的大值,可以通过  while语句 来实现。每一次寻找的范围是从本次极大值位置yl来计算:yl+p(yl)*0.5:yl+p(yl)*1.5,这样得到新的极大值位置yl,再存放在pm中。直至对LowPass都搜找了。

新手

46 麦片

财富积分


050


86

主题

185

帖子

0

最佳答案
  • 关注者: 2
 楼主| 发表于 2018-1-23 16:32:21 | 显示全部楼层
songzy41 发表于 2018-1-23 10:43
因为我是引用的程序,看来屯是不能满足你的要求。
我仔细看了一下,程序运行到
lu=size(u,1); lv=size(v, ...

宋老师,针对你说的2,我不明白。
1.p(1)代表什么?应该是在lowpass的1:end中找出极大值吧?
2.这个while循环的循环体是什么?
我用[yl,xl]=findpeaks(LowPass(1:end));语句,得到yl有379个值,然后应该在这379个之中循环?
3.每一次寻找的范围是从本次极大值位置yl来计算:yl+p(yl)*0.5:yl+p(yl)*1.5,
这句话写成语句是[pm]=findpeaks(lowpass(yl+p(yl)*0.5:yl+p(yl)*1.5))吗?好像哪里有问题

论坛优秀回答者

17

主题

4734

帖子

1075

最佳答案
  • 关注者: 481
发表于 2018-1-24 09:47:25 | 显示全部楼层
guolele 发表于 2018-1-23 16:32
宋老师,针对你说的2,我不明白。
1.p(1)代表什么?应该是在lowpass的1:end中找出极大值吧?
2.这个whil ...

1,在第6层中(1),对p作了修改,使p从1--9017都有数值。所以要在1至p(1)中寻找第1个基音峰值(用PitchEdstimation估算基音的结果与本书中其他程序表示都不完全一样,该函数提取基音得到的结果是每个样点都有一个基音周期值)。
2,因为不知这段语音有多少个基音峰值,所以用while语句来循环。
LZ用findpeaks(LowPass(1:end));语句把该段语音中的所有峰值都寻找了,如下图1所示那样,用圆圈表示的峰值是我们所需要的,而用方块框的峰值我们不需要的。
3,在下图2所示的,如果已知某一个峰值的位置在yl(yl是LowPass索引号),那怎么寻找下一个基音峰值,我是在yl+p(yl)*0.5至yl+p(yl)*1.5区间中寻找,如图所示。而其中不是用findpeaks函数,而是用max函数,找到极大值位置修正后放入pm序列中。

图2

图2

图1

图1

新手

46 麦片

财富积分


050


86

主题

185

帖子

0

最佳答案
  • 关注者: 2
 楼主| 发表于 2018-1-24 11:06:55 | 显示全部楼层
songzy41 发表于 2018-1-24 09:47
1,在第6层中(1),对p作了修改,使p从1--9017都有数值。所以要在1至p(1)中寻找第1个基音峰值(用PitchE ...

我按照理解又重新写了如下:
[xl,yl]=max(LowPass(1:p(1)));
while i<p
pm(i)=max(LowPass(yl+p(yl)*0.5:yl+p(yl)*1.5));
maxxl=[yl;pm(i)];
end
提示出错,问题是,下标索引必须为正整数类型或逻辑类型。
出错在 pm(i)=max(LowPass(xl+p(xl)*0.5:xl+p(xl)*1.5));这一句
可是我的第一句中p(1)= 113.4021,却没有提示出错,
我把yl+p(yl)*0.5:yl+p(yl)*1.5分别向下向上取整为fix(yl+p(yl)*0.5): ceil(yl+p(yl)*1.5),结果还是出错,

论坛优秀回答者

17

主题

4734

帖子

1075

最佳答案
  • 关注者: 481
发表于 2018-1-24 11:50:12 | 显示全部楼层
guolele 发表于 2018-1-24 11:06
我按照理解又重新写了如下:
[xl,yl]=max(LowPass(1:p(1)));
while i

1,while i<p显然不合适,i是一个循环变量,一般 不知道它最大为多少,如果知道就可以用for循环了。又p是一个数组,所以while i<p不合适。
2,max(LowPass(yl+p(yl)*0.5:yl+p(yl)*1.5))中是否应该把(yl+p(yl)*0.5和(yl+p(yl)*1.5前加上floor函数
3,max(LowPass(yl+p(yl)*0.5:yl+p(yl)*1.5))计算出数值yv1和位置yl1,而且这个位置是(yl+p(yl)*0.5和(yl+p(yl)*1.5之间的位置,不是LowPass数组的索引号, 所以我在8层中提到了要对极大值位置修正为索引号。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐上一条 /3 下一条

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