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