annotate Code/Descriptors/yin/yin.m @ 4:92ca03a8fa99 tip

Update to ICASSP 2013 benchmark
author Dawn Black
date Wed, 13 Feb 2013 11:02:39 +0000
parents ea0c737c6323
children
rev   line source
dawn@0 1 function [prd, fileinfo] = yin(x,p)
dawn@0 2 % YIN - Fundamental frequency (F0) of file or vector
dawn@0 3 %
dawn@0 4 % YIN('FILE') estimates and plots the F0 of signal in FILE.
dawn@0 5 % F0 is plotted in octaves re: 440 Hz, together with residual
dawn@0 6 % (aperiodicity) and power measures. A 'best' estimate is printed.
dawn@0 7 % YIN(X,SR) estimates and plots the F0 of array X assuming sampling rate SR (Hz).
dawn@0 8 %
dawn@0 9 % R=YIN(X) produces no plot but returns result in structure R:
dawn@0 10 % R.f0: fundamental frequency in octaves re: 440 Hz
dawn@0 11 % R.ap: aperiodicity measure (ratio of aperiodic to total power)
dawn@0 12 % R.pwr: period-smoothed instantaneous power
dawn@0 13 % (R also lists the parameters used by YIN)
dawn@0 14 %
dawn@0 15 % YIN(NAME,P) uses parameters stored in P:
dawn@0 16 % P.minf0: Hz - minimum expected F0 (default: 30 Hz)
dawn@0 17 % P.maxf0: Hz - maximum expected F0 (default: SR/(4*dsratio))
dawn@0 18 % P.thresh: threshold (default: 0.1)
dawn@0 19 % P.relfag: if ~0, thresh is relative to min of difference function (default: 1)
dawn@0 20 % P.hop: samples - interval between estimates (default: 32)
dawn@0 21 % P.range: samples - range of samples ([start stop]) to process
dawn@0 22 % P.bufsize: samples - size of computation buffer (default: 10000)
dawn@0 23 % P.sr: Hz - sampling rate (usually taken from file header)
dawn@0 24 % P.wsize: samples - integration window size (defaut: SR/minf0)
dawn@0 25 % P.lpf: Hz - intial low-pass filtering (default: SR/4)
dawn@0 26 % P.shift 0: shift symmetric, 1: shift right, -1: shift left (default: 0)
dawn@0 27 %
dawn@0 28 % See 'yin.html' for more info.
dawn@0 29 % Version 28 July 2003.
dawn@0 30
dawn@0 31 % Alain de Cheveign? CNRS/Ircam, 2002.
dawn@0 32 % Copyright (c) 2002 Centre National de la Recherche Scientifique.
dawn@0 33 %
dawn@0 34 % Permission to use, copy, modify, and distribute this software without
dawn@0 35 % fee is hereby granted FOR RESEARCH PURPOSES only, provided that this
dawn@0 36 % copyright notice appears in all copies and in all supporting
dawn@0 37 % documentation, and that the software is not redistributed for any
dawn@0 38 % fee (except for a nominal shipping charge).
dawn@0 39 %
dawn@0 40 % For any other uses of this software, in original or modified form,
dawn@0 41 % including but not limited to consulting, production or distribution
dawn@0 42 % in whole or in part, specific prior permission must be obtained from CNRS.
dawn@0 43 % Algorithms implemented by this software may be claimed by patents owned
dawn@0 44 % by CNRS, France Telecom, Ircam or others.
dawn@0 45 %
dawn@0 46 % The CNRS makes no representations about the suitability of this
dawn@0 47 % software for any purpose. It is provided "as is" without express
dawn@0 48 % or implied warranty.
dawn@0 49
dawn@0 50
dawn@0 51 % Hidden parameters are integration window size (set equal to sr/minf0), search
dawn@0 52 % range for 'best neighboring estimate' (set equal to +/- sr/(2*minf0)), maximum
dawn@0 53 % expected width of period dip (stop/start ratio == 1.85), margin for "beam search"
dawn@0 54 % of final estimate (+1.8/-0.6 times the initial estimate).
dawn@0 55
dawn@0 56
dawn@0 57 % default parameter values ([]: to be determined)
dawn@0 58 minf0 = 30; % Hz - minimum frequency
dawn@0 59 maxf0 = []; % Hz - maximum frequency
dawn@0 60 wsize = []; % s - integration window size
dawn@0 61 lpf = []; % Hz - lowpass prefiltering cutoff
dawn@0 62 thresh = 0.1; % difference function threshold
dawn@0 63 relflag = 1; % if true threshold is relative to global min of difference function
dawn@0 64 bufsize=10000; % computation buffer size
dawn@0 65 hop = 32; % samples - interval between estimates
dawn@0 66 range=[]; % range of file samples to process
dawn@0 67 sr=[]; % sampling rate
dawn@0 68 shift=0; % flag to control the temporal shift of analysis windows (left/sym/right)
dawn@0 69 plotthreshold=0.2; % aperiodicity above which plot is green or yellow
dawn@0 70
dawn@0 71 % if 2~=exist('allread')
dawn@0 72 % error('sf routines missing: put them in your path & try again');
dawn@0 73 % end
dawn@0 74
dawn@0 75
dawn@0 76 % handle parameters
dawn@0 77 if nargin<1; help yin; return; end
dawn@0 78 if nargin<2; p=[]; end
dawn@0 79 fileinfo=sf_info(x); if ~isempty(fileinfo.sr) p.sr=fileinfo.sr; end % get sr from file
dawn@0 80 if fileinfo.nchans > 1
dawn@0 81 disp(['warning: using column 1 of ', num2str(fileinfo.nchans), '-column data']);
dawn@0 82 end
dawn@0 83 if isa(p, 'double') p.sr=p; end
dawn@0 84 if ~isfield(p, 'sr'); p.sr=sr; end
dawn@0 85 if isempty(p.sr); error('YIN2: must specify SR'); end
dawn@0 86 if ~isfield(p, 'range') | isempty(p.range); p.range=[1 fileinfo.nsamples]; end
dawn@0 87 if ~isfield(p, 'minf0'); p.minf0=minf0; end
dawn@0 88 if ~isfield(p, 'thresh'); p.thresh=thresh; end
dawn@0 89 if ~isfield(p, 'relflag'); p.relflag=relflag; end
dawn@0 90 if ~isfield(p, 'bufsize'); p.bufsize=bufsize; end
dawn@0 91 if ~isfield(p, 'hop'); p.hop=hop; end
dawn@0 92 if ~isfield(p, 'maxf0'); p.maxf0=floor(p.sr/4); end % default
dawn@0 93 if ~isfield(p, 'wsize'); p.wsize=ceil(p.sr/p.minf0); end % default
dawn@0 94 if ~isfield(p, 'lpf'); p.lpf=p.sr/4; end % default
dawn@0 95 if mod(p.hop,1); error('hop should be integer'); end
dawn@0 96 if ~isfield(p, 'shift'); p.shift=shift; end % default
dawn@0 97 if ~isfield(p, 'plotthreshold'); p.plotthreshold=plotthreshold; end % default
dawn@0 98
dawn@0 99 % estimate period
dawn@0 100 r=yink(p,fileinfo);
dawn@0 101 prd=r.r1; % period in samples
dawn@0 102 ap0=r.r2; % gross aperiodicity measure
dawn@0 103 ap= r.r3; % fine aperiodicity measure
dawn@0 104 pwr=r.r4; % period-smoothed instantaneous power
dawn@0 105 f0 = log2(p.sr ./ prd) - log2(440); % convert to octaves re: 440 Hz
dawn@0 106 %figure();
dawn@0 107 %plot(prd);
dawn@0 108 %dlmwrite('pitch.txt',prd,'delimiter','\n');
dawn@0 109 %display(length(prd));
dawn@0 110
dawn@0 111 % load estimates and major parameters in result structure
dawn@0 112 clear r;
dawn@0 113 r.f0 = f0;
dawn@0 114 r.ap0 = ap0;
dawn@0 115 r.ap = ap;
dawn@0 116 r.pwr = pwr;
dawn@0 117 r.sr = p.sr;
dawn@0 118 r.range=p.range;
dawn@0 119 r.minf0 = p.minf0;
dawn@0 120 r.maxf0 = p.maxf0;
dawn@0 121 r.thresh=p.thresh;
dawn@0 122 r.relflag=p.relflag;
dawn@0 123 r.hop = p.hop;
dawn@0 124 r.bufsize = p.bufsize;
dawn@0 125 r.wsize = p.wsize;
dawn@0 126 r.lpf = p.lpf;
dawn@0 127 r.shift = p.shift;
dawn@0 128 r.plotthreshold=p.plotthreshold;
dawn@0 129
dawn@0 130
dawn@0 131 % plot estimates (if nargout == 0)
dawn@0 132 if nargout<1
dawn@0 133 if isnan(f0)
dawn@0 134 display('no estimates: signal too short or buffersize too small');
dawn@0 135 return;
dawn@0 136 end
dawn@0 137 % choose sample to report as "the" f0 of the entire signal
dawn@0 138 [mn, idx] = min(ap0);
dawn@0 139 best=f0(idx);
dawn@0 140 disp(['best: ', num2str(2^best*440), 'Hz (', note(best),...
dawn@0 141 ') at ', num2str(idx/(p.sr/p.hop)), 's (aperiodic/total power: ', num2str(mn), ')']);
dawn@0 142 % plot f0 in 3 colors according to periodicity
dawn@0 143 good = f0;
dawn@0 144 good(find(ap0>p.plotthreshold*2)) = nan;
dawn@0 145 best = f0;
dawn@0 146 best(find(ap0>p.plotthreshold)) = nan;
dawn@0 147 subplot(211);
dawn@0 148 fsr=p.sr/p.hop;
dawn@0 149 nframes=size(prd,2);
dawn@0 150 if nframes <2; error('F0 track is too short to plot'); end
dawn@0 151 plot((1:nframes)/fsr, f0, 'y', (1:nframes)/fsr, good, 'g', (1:nframes)/fsr, best, 'b');
dawn@0 152 lo = max(min(f0),min(good)); hi=min(max(f0),max(good));
dawn@0 153 set(gca, 'ylim', [lo-0.5; hi+0.5]);
dawn@0 154 set(gca, 'xlim', [1,nframes]/fsr);
dawn@0 155 set(get(gca,'ylabel'), 'string', 'Oct. re: 440 Hz');
dawn@0 156 set(get(gca,'xlabel'), 'string', 's');
dawn@0 157 % plot periodicity
dawn@0 158 ap0=max(0,ap0); ap=max(0,ap);
dawn@0 159 ap1=ap;
dawn@0 160 ap(find(ap0>plotthreshold)) = nan;
dawn@0 161 subplot(413); plot((1:nframes), ap0.^0.5, 'b');
dawn@0 162 %subplot(413); plot((1:nframes), ap0.^0.5, 'c', (1:nframes), ap1.^0.5, 'y', (1:nframes), ap.^0.5, 'b');
dawn@0 163 set(gca, 'ylim', [0 1]);
dawn@0 164 set(gca, 'xlim', [1, nframes]);
dawn@0 165 set(get(gca,'ylabel'), 'string', 'sqrt(apty)');
dawn@0 166 % plot power
dawn@0 167 subplot(414); plot((1:nframes), sqrt(pwr), 'b');
dawn@0 168 set(gca, 'xlim', [1, nframes]);
dawn@0 169 set(get(gca,'ylabel'), 'string', 'sqrt(power)');
dawn@0 170 set(get(gca,'xlabel'), 'string', 'frames');
dawn@0 171 if isa(x, 'double')
dawn@0 172 set(gcf, 'Name', 'workspace matrix');
dawn@0 173 else
dawn@0 174 set (gcf, 'Name', x);
dawn@0 175 end
dawn@0 176 end
dawn@0 177
dawn@0 178
dawn@0 179 % convert octave re 440 to note:
dawn@0 180 function s=note(o)
dawn@0 181 n=round(12*o);
dawn@0 182 cents = 100*(12*o-n);
dawn@0 183 oct=floor((n-3)/12)+5;
dawn@0 184 chroma=mod(n,12);
dawn@0 185 chromalist = {'A'; 'A#'; 'B'; 'C'; 'C#'; 'D'; 'D#'; 'E'; 'F'; 'F#';...
dawn@0 186 'G'; 'G#'};
dawn@0 187 cents = sprintf('%+.0f',cents);
dawn@0 188 s=[char(chromalist(chroma+1)),num2str(oct),' ',num2str(cents), ' cents'];