-
Notifications
You must be signed in to change notification settings - Fork 0
/
segby0.m
149 lines (146 loc) · 3.77 KB
/
segby0.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
function seg = segby0(f0, minLen)
% segment F0 based on voice-unvoiced duration
% input: f0: f0 curve
% minLen: the minimum duration for a segment that can be recognized as voiced segment
len = size(f0, 2);
cnt = 0;
vld = zeros(1, len);
blk_idx = zeros(1, len);
bg = zeros(1, len);
ed = zeros(1, len);
flg = 0;
last_fake_first=-1e10; % 上一个因为时长太短而被抹去的段的开始
for i = 1:len
if flg == (f0(i)>30) %歌词段或非歌词段持续
vld(i) = flg;
continue;
else
if flg == 0 %未进入歌词段,出现第一个非零f0
% if i-last_fake_first <100
% cnt=cnt+1;
% bg(cnt)=last_fake_first;
% for kk=last_fake_first:i
% vld(kk)=1;
% end
% else
% cnt = cnt + 1;
% bg(cnt) = i;
% end
cnt = cnt + 1;
bg(cnt) = i;
flg = 1;
else %歌词段结束,出现第一个零f0
ed(cnt) = i-1;
flg = 0;
if ed(cnt) - bg(cnt) < minLen
%last_fake_first=bg(cnt);
cnt = cnt - 1;
tmp = i-1;
while vld(tmp) == 1
vld(tmp) = 0;
tmp = tmp - 1;
end
end
end
vld(i) = flg;
end
end
%为每一个f0有效域编号
% flag=0;
% idx=0;
% for i=1:len
% if(vld(i)==1 & flag==0)
% blk_idx(i)= idx;
% flag=1;
% idx = idx + 1;
% elseif(vld(i)==0 & flag==1)
% flag=0;
% blk_idx(i)
% end
if ed(cnt) < bg(cnt) %最后一段强制结束
ed(cnt) = len;
end
% 寻找是否有两个段之间有很小一段的,把这一段和前后两段合并
bg_fix=[bg(1)];
ed_fix = [];
for i=1:cnt-1
if bg(i+1)-ed(i)<100
int_len=bg(i+1)-ed(i)+1;
int_bg = ed(i)+1; int_ed = bg(i+1)-1;
sound_seg=find(f0(int_bg:int_ed)>30); % 中间的interval只有一段有音,否则是噪声
if ~isempty(sound_seg) & (sound_seg(end)-sound_seg(1)+1 == length(sound_seg)) & ...
sum(f0(int_bg:int_ed)>30)>int_len/2 % 中间的interval至少一半以上有音,把这一部分补回去
continue;
else
ed_fix = [ed_fix ed(i)];
bg_fix = [bg_fix bg(i+1)];
end
else
ed_fix = [ed_fix ed(i)];
bg_fix = [bg_fix bg(i+1)];
end
end
ed_fix = [ed_fix ed(cnt)];
bg = bg_fix; ed = ed_fix;
cnt = length(bg);
%合并段间关系
bg_modify=[]; bg_modify = [bg_modify bg(1)];
ed_modify = [];
for i=1:cnt-1
if bg(i+1)-ed(i)<=42 % 这两段直接合在一起
continue;
else
bg_modify = [bg_modify bg(i+1)];
ed_modify = [ed_modify ed(i)];
end
end
ed_modify = [ed_modify ed(cnt)];
% 再从后向前遍历一下,把每一段开始的时候前面出现的较小有音段补上
i = length(bg_modify);
while i>=1
flag=0;
idx = bg_modify(i)-1;
j=idx;
if i>1
while j > max(ed_modify(i-1),idx-34)
if f0(j)>30
while f0(j)>30
j=j-1;
end
tmp_bg=j+1;
bg_modify(i)=tmp_bg;
flag=1;
continue;
end
j=j-1;
end
else
while j > idx-34
if f0(j)>30
while f0(j)>30
j=j-1;
end
tmp_bg=j+1;
bg_modify(i)=tmp_bg;
flag=1;
continue;
end
j=j-1;
end
end
if flag==1
continue;
end
i=i-1;
end
%%
for i=1:length(ed_modify)
for j=bg_modify(i):ed_modify(i)
vld(j)=1;
end
end
seg.bg = bg_modify;
seg.ed = ed_modify;
seg.cnt = length(bg_modify);
seg.vld = vld;
end