Mercurial > hg > emotion-detection-top-level
diff Code/Descriptors/yin/private/yink.m @ 4:92ca03a8fa99 tip
Update to ICASSP 2013 benchmark
author | Dawn Black |
---|---|
date | Wed, 13 Feb 2013 11:02:39 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Code/Descriptors/yin/private/yink.m Wed Feb 13 11:02:39 2013 +0000 @@ -0,0 +1,147 @@ +function r=yink(p,fileinfo) +% YINK - fundamental frequency estimator +% new version (feb 2003) +% +% + +%global jj; +%jj=0; +% process signal a chunk at a time +idx=p.range(1)-1; +totalhops=round((p.range(2)-p.range(1)+1) / p.hop); +r1=nan*zeros(1,totalhops);r2=nan*zeros(1,totalhops); +r3=nan*zeros(1,totalhops);r4=nan*zeros(1,totalhops); +idx2=0+round(p.wsize/2/p.hop); +while (1) + start = idx+1; + stop = idx+p.bufsize; + stop=min(stop, p.range(2)); + xx=sf_wave(fileinfo, [start, stop], []); +% if size(xx,1) == 1; xx=xx'; end + xx=xx(:,1); % first channel if multichannel + [prd,ap0,ap,pwr]=yin_helper(xx,p); + n=size(prd ,2); + if (~n) break; end; + idx=idx+n*p.hop; + + r1(idx2+1:idx2+n)= prd; + r2(idx2+1:idx2+n)= ap0; + r3(idx2+1:idx2+n)= ap; + r4(idx2+1:idx2+n)= pwr; + idx2=idx2+n; +end +r.r1=r1; % period estimate +r.r2=r2; % gross aperiodicity measure +r.r3=r3; % fine aperiodicity measure +r.r4=r4; % power +sf_cleanup(fileinfo); +% end of program + + + +% Estimate F0 of a chunk of signal +function [prd,ap0,ap,pwr]=yin_helper(x,p,dd) +smooth=ceil(p.sr/p.lpf); +x=rsmooth(x,smooth); % light low-pass smoothing +x=x(smooth:end-smooth+1); +[m,n]=size(x); +maxlag = ceil(p.sr/p.minf0); +minlag = floor(p.sr/p.maxf0); +mxlg = maxlag+2; % +2 to improve interp near maxlag + + +hops=floor((m-mxlg-p.wsize)/p.hop); +prd=zeros(1,hops); +ap0=zeros(1,hops); +ap=zeros(1,hops); +pwr=zeros(1,hops); +if hops<1; return; end + +% difference function matrix +dd=zeros(floor((m-mxlg-p.hop)/p.hop),mxlg); +if p.shift == 0 % windows shift both ways + lags1=round(mxlg/2) + round((0:mxlg-1)/2); + lags2=round(mxlg/2) - round((1:mxlg)/2); + lags=[lags1; lags2]; +elseif p.shift == 1 % one window fixed, other shifts right + lags=[zeros(1,mxlg); 1:mxlg]; +elseif p.shift == -1 % one window fixed, other shifts right + lags=[mxlg-1:-1:0; mxlg*ones(1,mxlg)]; +else + error (['unexpected shift flag: ', num2str(p.shift)]); +end +rdiff_inplace(x,x,dd,lags,p.hop); +rsum_inplace(dd,round(p.wsize/p.hop)); +dd=dd'; +[dd,ddx]=minparabolic(dd); % parabolic interpolation near min +cumnorm_inplace(dd);; % cumulative mean-normalize + +% first period estimate +%global jj; +for j=1:hops + d=dd(:,j); + if p.relflag + pd=dftoperiod2(d,[minlag,maxlag],p.thresh); + else + pd=dftoperiod(d,[minlag,maxlag],p.thresh); + end + ap0(j)=d(pd+1); + prd(j)=pd; +end + +% replace each estimate by best estimate in range +range = 2*round(maxlag/p.hop); +if hops>1; prd=prd(mininrange(ap0,range*ones(1,hops))); end +%prd=prd(mininrange(ap0,prd)); + + +% refine estimate by constraining search to vicinity of best local estimate +margin1=0.6; +margin2=1.8; +for j=1:hops + d=dd(:,j); + dx=ddx(:,j); + pd=prd(j); + lo=floor(pd*margin1); lo=max(minlag,lo); + hi=ceil(pd*margin2); hi=min(maxlag,hi); + pd=dftoperiod(d,[lo,hi],0); + ap0(j)=d(pd+1); + pd=pd+dx(pd+1)+1; % fine tune based on parabolic interpolation + prd(j)=pd; + + % power estimates + idx=(j-1)*p.hop; + k=(1:ceil(pd))'; + x1=x(k+idx); + x2=k+idx+pd-1; + interp_inplace(x,x2); + x3=x2-x1; + x4=x2+x1; + x1=x1.^2; rsum_inplace(x1,pd); + x3=x3.^2; rsum_inplace(x3,pd); + x4=x4.^2; rsum_inplace(x4,pd); + + x1=x1(1)/pd; + x2=x2(1)/pd; + x3=x3(1)/pd; + x4=x4(1)/pd; + % total power + pwr(j)=x1; + + % fine aperiodicity + ap(j)=(eps+x3)/(eps+(x3+x4)); % accurate, only for valid min + + %ap(j) + %plot(min(1, d)); pause + + prd(j)=pd; +end + + + +%cumulative mean-normalize +function y=cumnorm(x) +[m,n]=size(x); +y = cumsum(x); +y = (y)./ (eps+repmat((1:m)',1,n)); % cumulative mean +y = (eps+x) ./ (eps+y);