Dawn@4
|
1 function r=yink(p,fileinfo)
|
Dawn@4
|
2 % YINK - fundamental frequency estimator
|
Dawn@4
|
3 % new version (feb 2003)
|
Dawn@4
|
4 %
|
Dawn@4
|
5 %
|
Dawn@4
|
6
|
Dawn@4
|
7 %global jj;
|
Dawn@4
|
8 %jj=0;
|
Dawn@4
|
9 % process signal a chunk at a time
|
Dawn@4
|
10 idx=p.range(1)-1;
|
Dawn@4
|
11 totalhops=round((p.range(2)-p.range(1)+1) / p.hop);
|
Dawn@4
|
12 r1=nan*zeros(1,totalhops);r2=nan*zeros(1,totalhops);
|
Dawn@4
|
13 r3=nan*zeros(1,totalhops);r4=nan*zeros(1,totalhops);
|
Dawn@4
|
14 idx2=0+round(p.wsize/2/p.hop);
|
Dawn@4
|
15 while (1)
|
Dawn@4
|
16 start = idx+1;
|
Dawn@4
|
17 stop = idx+p.bufsize;
|
Dawn@4
|
18 stop=min(stop, p.range(2));
|
Dawn@4
|
19 xx=sf_wave(fileinfo, [start, stop], []);
|
Dawn@4
|
20 % if size(xx,1) == 1; xx=xx'; end
|
Dawn@4
|
21 xx=xx(:,1); % first channel if multichannel
|
Dawn@4
|
22 [prd,ap0,ap,pwr]=yin_helper(xx,p);
|
Dawn@4
|
23 n=size(prd ,2);
|
Dawn@4
|
24 if (~n) break; end;
|
Dawn@4
|
25 idx=idx+n*p.hop;
|
Dawn@4
|
26
|
Dawn@4
|
27 r1(idx2+1:idx2+n)= prd;
|
Dawn@4
|
28 r2(idx2+1:idx2+n)= ap0;
|
Dawn@4
|
29 r3(idx2+1:idx2+n)= ap;
|
Dawn@4
|
30 r4(idx2+1:idx2+n)= pwr;
|
Dawn@4
|
31 idx2=idx2+n;
|
Dawn@4
|
32 end
|
Dawn@4
|
33 r.r1=r1; % period estimate
|
Dawn@4
|
34 r.r2=r2; % gross aperiodicity measure
|
Dawn@4
|
35 r.r3=r3; % fine aperiodicity measure
|
Dawn@4
|
36 r.r4=r4; % power
|
Dawn@4
|
37 sf_cleanup(fileinfo);
|
Dawn@4
|
38 % end of program
|
Dawn@4
|
39
|
Dawn@4
|
40
|
Dawn@4
|
41
|
Dawn@4
|
42 % Estimate F0 of a chunk of signal
|
Dawn@4
|
43 function [prd,ap0,ap,pwr]=yin_helper(x,p,dd)
|
Dawn@4
|
44 smooth=ceil(p.sr/p.lpf);
|
Dawn@4
|
45 x=rsmooth(x,smooth); % light low-pass smoothing
|
Dawn@4
|
46 x=x(smooth:end-smooth+1);
|
Dawn@4
|
47 [m,n]=size(x);
|
Dawn@4
|
48 maxlag = ceil(p.sr/p.minf0);
|
Dawn@4
|
49 minlag = floor(p.sr/p.maxf0);
|
Dawn@4
|
50 mxlg = maxlag+2; % +2 to improve interp near maxlag
|
Dawn@4
|
51
|
Dawn@4
|
52
|
Dawn@4
|
53 hops=floor((m-mxlg-p.wsize)/p.hop);
|
Dawn@4
|
54 prd=zeros(1,hops);
|
Dawn@4
|
55 ap0=zeros(1,hops);
|
Dawn@4
|
56 ap=zeros(1,hops);
|
Dawn@4
|
57 pwr=zeros(1,hops);
|
Dawn@4
|
58 if hops<1; return; end
|
Dawn@4
|
59
|
Dawn@4
|
60 % difference function matrix
|
Dawn@4
|
61 dd=zeros(floor((m-mxlg-p.hop)/p.hop),mxlg);
|
Dawn@4
|
62 if p.shift == 0 % windows shift both ways
|
Dawn@4
|
63 lags1=round(mxlg/2) + round((0:mxlg-1)/2);
|
Dawn@4
|
64 lags2=round(mxlg/2) - round((1:mxlg)/2);
|
Dawn@4
|
65 lags=[lags1; lags2];
|
Dawn@4
|
66 elseif p.shift == 1 % one window fixed, other shifts right
|
Dawn@4
|
67 lags=[zeros(1,mxlg); 1:mxlg];
|
Dawn@4
|
68 elseif p.shift == -1 % one window fixed, other shifts right
|
Dawn@4
|
69 lags=[mxlg-1:-1:0; mxlg*ones(1,mxlg)];
|
Dawn@4
|
70 else
|
Dawn@4
|
71 error (['unexpected shift flag: ', num2str(p.shift)]);
|
Dawn@4
|
72 end
|
Dawn@4
|
73 rdiff_inplace(x,x,dd,lags,p.hop);
|
Dawn@4
|
74 rsum_inplace(dd,round(p.wsize/p.hop));
|
Dawn@4
|
75 dd=dd';
|
Dawn@4
|
76 [dd,ddx]=minparabolic(dd); % parabolic interpolation near min
|
Dawn@4
|
77 cumnorm_inplace(dd);; % cumulative mean-normalize
|
Dawn@4
|
78
|
Dawn@4
|
79 % first period estimate
|
Dawn@4
|
80 %global jj;
|
Dawn@4
|
81 for j=1:hops
|
Dawn@4
|
82 d=dd(:,j);
|
Dawn@4
|
83 if p.relflag
|
Dawn@4
|
84 pd=dftoperiod2(d,[minlag,maxlag],p.thresh);
|
Dawn@4
|
85 else
|
Dawn@4
|
86 pd=dftoperiod(d,[minlag,maxlag],p.thresh);
|
Dawn@4
|
87 end
|
Dawn@4
|
88 ap0(j)=d(pd+1);
|
Dawn@4
|
89 prd(j)=pd;
|
Dawn@4
|
90 end
|
Dawn@4
|
91
|
Dawn@4
|
92 % replace each estimate by best estimate in range
|
Dawn@4
|
93 range = 2*round(maxlag/p.hop);
|
Dawn@4
|
94 if hops>1; prd=prd(mininrange(ap0,range*ones(1,hops))); end
|
Dawn@4
|
95 %prd=prd(mininrange(ap0,prd));
|
Dawn@4
|
96
|
Dawn@4
|
97
|
Dawn@4
|
98 % refine estimate by constraining search to vicinity of best local estimate
|
Dawn@4
|
99 margin1=0.6;
|
Dawn@4
|
100 margin2=1.8;
|
Dawn@4
|
101 for j=1:hops
|
Dawn@4
|
102 d=dd(:,j);
|
Dawn@4
|
103 dx=ddx(:,j);
|
Dawn@4
|
104 pd=prd(j);
|
Dawn@4
|
105 lo=floor(pd*margin1); lo=max(minlag,lo);
|
Dawn@4
|
106 hi=ceil(pd*margin2); hi=min(maxlag,hi);
|
Dawn@4
|
107 pd=dftoperiod(d,[lo,hi],0);
|
Dawn@4
|
108 ap0(j)=d(pd+1);
|
Dawn@4
|
109 pd=pd+dx(pd+1)+1; % fine tune based on parabolic interpolation
|
Dawn@4
|
110 prd(j)=pd;
|
Dawn@4
|
111
|
Dawn@4
|
112 % power estimates
|
Dawn@4
|
113 idx=(j-1)*p.hop;
|
Dawn@4
|
114 k=(1:ceil(pd))';
|
Dawn@4
|
115 x1=x(k+idx);
|
Dawn@4
|
116 x2=k+idx+pd-1;
|
Dawn@4
|
117 interp_inplace(x,x2);
|
Dawn@4
|
118 x3=x2-x1;
|
Dawn@4
|
119 x4=x2+x1;
|
Dawn@4
|
120 x1=x1.^2; rsum_inplace(x1,pd);
|
Dawn@4
|
121 x3=x3.^2; rsum_inplace(x3,pd);
|
Dawn@4
|
122 x4=x4.^2; rsum_inplace(x4,pd);
|
Dawn@4
|
123
|
Dawn@4
|
124 x1=x1(1)/pd;
|
Dawn@4
|
125 x2=x2(1)/pd;
|
Dawn@4
|
126 x3=x3(1)/pd;
|
Dawn@4
|
127 x4=x4(1)/pd;
|
Dawn@4
|
128 % total power
|
Dawn@4
|
129 pwr(j)=x1;
|
Dawn@4
|
130
|
Dawn@4
|
131 % fine aperiodicity
|
Dawn@4
|
132 ap(j)=(eps+x3)/(eps+(x3+x4)); % accurate, only for valid min
|
Dawn@4
|
133
|
Dawn@4
|
134 %ap(j)
|
Dawn@4
|
135 %plot(min(1, d)); pause
|
Dawn@4
|
136
|
Dawn@4
|
137 prd(j)=pd;
|
Dawn@4
|
138 end
|
Dawn@4
|
139
|
Dawn@4
|
140
|
Dawn@4
|
141
|
Dawn@4
|
142 %cumulative mean-normalize
|
Dawn@4
|
143 function y=cumnorm(x)
|
Dawn@4
|
144 [m,n]=size(x);
|
Dawn@4
|
145 y = cumsum(x);
|
Dawn@4
|
146 y = (y)./ (eps+repmat((1:m)',1,n)); % cumulative mean
|
Dawn@4
|
147 y = (eps+x) ./ (eps+y);
|