Mercurial > hg > camir-aes2014
comparison toolboxes/MIRtoolbox1.3.2/MIRToolbox/mirtempo.m @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e9a9cd732c1e |
---|---|
1 function varargout = mirtempo(x,varargin) | |
2 % t = mirtempo(x) evaluates the tempo in beats per minute (BPM). | |
3 % Optional arguments: | |
4 % mirtempo(...,'Total',m) selects not only the best tempo, but the m | |
5 % best tempos. | |
6 % mirtempo(...,'Frame',l,h) orders a frame decomposition of window | |
7 % length l (in seconds) and hop factor h, expressed relatively to | |
8 % the window length. For instance h = 1 indicates no overlap. | |
9 % Default values: l = 3 seconds and h = .1 | |
10 % mirtempo(...,'Min',mi) indicates the lowest tempo taken into | |
11 % consideration, expressed in bpm. | |
12 % Default value: 40 bpm. | |
13 % mirtempo(...,'Max',ma) indicates the highest tempo taken into | |
14 % consideration, expressed in bpm. | |
15 % Default value: 200 bpm. | |
16 % mirtempo(...,s) selects the tempo estimation strategy: | |
17 % s = 'Autocor': Approach based on the computation of the | |
18 % autocorrelation. (Default strategy) | |
19 % Option associated to the mirautocor function can be | |
20 % passed here as well (see help mirautocor): | |
21 % 'Enhanced' (toggled on by default here) | |
22 % s = 'Spectrum': Approach based on the computation of the | |
23 % spectrum . | |
24 % Option associated to the mirspectrum function can be | |
25 % passed here as well (see help mirspectrum): | |
26 % 'ZeroPad' (set by default to 10000 samples) | |
27 % 'Prod' (toggled off by default) | |
28 % These two strategies can be combined: the autocorrelation | |
29 % function is translated into the frequency domain in order | |
30 % to be compared to the spectrum curve. | |
31 % tempo(...,'Autocor','Spectrum') multiplies the two curves. | |
32 % Alternatively, an autocorrelation function ac or a spectrum sp | |
33 % can be directly passed to the function tempo: | |
34 % mirtempo(ac) or mirtempo(sp) | |
35 % The options related to the onset detection phase can be specified | |
36 % here as well (see help mironsets): | |
37 % onset detection strategies: 'Envelope', 'DiffEnvelope' | |
38 % (corresponding to 'Envelope', 'Diff'), 'SpectralFlux, | |
39 % 'Pitch', 'Log', 'Mu', 'Filterbank' | |
40 % mironsets(...,'Sum',w) specifies when to sum the channels. | |
41 % Possible values: | |
42 % w = 'Before': sum before the autocorrelation or | |
43 % spectrum computation. | |
44 % w = 'After': autocorrelation or spectrum computed | |
45 % for each band, and summed into a "summary". | |
46 % mirenvelope options: 'HalfwaveCenter','Diff' (toggled on by | |
47 % default here),'HalfwaveDiff','Center','Smooth', | |
48 % 'Sampling' | |
49 % mirflux options: 'Inc','Halfwave','Complex','Median' | |
50 % mirtempo(...,'Resonance',r) specifies the resonance curve, which | |
51 % emphasizes the periods that are more easily perceived. | |
52 % Possible values: 'ToiviainenSnyder' (default), 0 (toggled off) | |
53 % Optional arguments used for the peak picking (cf. help mirpeaks) | |
54 % mirtempo(...,'Contrast',thr): a threshold value. A given local | |
55 % maximum will be considered as a peak if its distance with the | |
56 % previous and successive local minima (if any) is higher than | |
57 % this threshold. This distance is expressed with respect to the | |
58 % total amplitude of the autocorrelation function. | |
59 % if no value for thr is given, the value thr=0.1 is chosen | |
60 % by default. | |
61 % | |
62 % [t,p] = mirtempo(...) also displays the result of the signal analysis | |
63 % leading to the tempo estimation, and shows in particular the | |
64 % peaks corresponding to the tempo values. | |
65 | |
66 | |
67 sum.key = 'Sum'; | |
68 sum.type = 'String'; | |
69 sum.choice = {'Before','After','Adjacent',0}; | |
70 sum.default = 'Before'; | |
71 option.sum = sum; | |
72 | |
73 %% options related to mironsets: | |
74 | |
75 frame.key = 'Frame'; | |
76 frame.type = 'Integer'; | |
77 frame.number = 2; | |
78 frame.default = [0 0]; | |
79 frame.keydefault = [3 .1]; | |
80 option.frame = frame; | |
81 | |
82 fea.type = 'String'; | |
83 fea.choice = {'Envelope','DiffEnvelope','SpectralFlux','Pitch'}; | |
84 fea.default = 'Envelope'; | |
85 option.fea = fea; | |
86 | |
87 %% options related to 'Envelope': | |
88 | |
89 envmeth.key = 'Method'; | |
90 envmeth.type = 'String'; | |
91 envmeth.choice = {'Filter','Spectro'}; | |
92 envmeth.default = 'Filter'; | |
93 option.envmeth = envmeth; | |
94 | |
95 %% options related to 'Filter': | |
96 | |
97 fb.key = 'Filterbank'; | |
98 fb.type = 'Integer'; | |
99 fb.default = 10; | |
100 option.fb = fb; | |
101 | |
102 fbtype.key = 'FilterbankType'; | |
103 fbtype.type = 'String'; | |
104 fbtype.choice = {'Gammatone','Scheirer','Klapuri'}; | |
105 fbtype.default = 'Gammatone'; | |
106 option.fbtype = fbtype; | |
107 | |
108 ftype.key = 'FilterType'; | |
109 ftype.type = 'String'; | |
110 ftype.choice = {'IIR','HalfHann'}; | |
111 ftype.default = 'IIR'; | |
112 option.ftype = ftype; | |
113 | |
114 %% options related to 'Spectro': | |
115 | |
116 band.type = 'String'; | |
117 band.choice = {'Freq','Mel','Bark','Cents'}; | |
118 band.default = 'Freq'; | |
119 option.band = band; | |
120 | |
121 | |
122 chwr.key = 'HalfwaveCenter'; | |
123 chwr.type = 'Boolean'; | |
124 chwr.default = 0; | |
125 option.chwr = chwr; | |
126 | |
127 diff.key = 'Diff'; | |
128 diff.type = 'Boolean'; | |
129 diff.default = 1; % Different default for mirtempo | |
130 option.diff = diff; | |
131 | |
132 diffhwr.key = 'HalfwaveDiff'; | |
133 diffhwr.type = 'Integer'; | |
134 diffhwr.default = 0; | |
135 diffhwr.keydefault = 1; | |
136 option.diffhwr = diffhwr; | |
137 | |
138 lambda.key = 'Lambda'; | |
139 lambda.type = 'Integer'; | |
140 lambda.default = 1; | |
141 option.lambda = lambda; | |
142 | |
143 mu.key = 'Mu'; | |
144 mu.type = 'Boolean'; | |
145 mu.default = 0; | |
146 option.mu = mu; | |
147 | |
148 log.key = 'Log'; | |
149 log.type = 'Boolean'; | |
150 log.default = 0; | |
151 option.log = log; | |
152 | |
153 c.key = 'Center'; | |
154 c.type = 'Boolean'; | |
155 c.default = 0; | |
156 option.c = c; | |
157 | |
158 aver.key = 'Smooth'; | |
159 aver.type = 'Integer'; | |
160 aver.default = 0; | |
161 aver.keydefault = 30; | |
162 option.aver = aver; | |
163 | |
164 sampling.key = 'Sampling'; | |
165 sampling.type = 'Integer'; | |
166 sampling.default = 0; | |
167 option.sampling = sampling; | |
168 | |
169 %% options related to 'SpectralFlux' | |
170 | |
171 complex.key = 'Complex'; | |
172 complex.type = 'Boolean'; | |
173 complex.default = 0; | |
174 option.complex = complex; | |
175 | |
176 inc.key = 'Inc'; | |
177 inc.type = 'Boolean'; | |
178 inc.default = 1; | |
179 option.inc = inc; | |
180 | |
181 median.key = 'Median'; | |
182 median.type = 'Integer'; | |
183 median.number = 2; | |
184 median.default = [.2 1.3]; | |
185 option.median = median; | |
186 | |
187 hw.key = 'Halfwave'; | |
188 hw.type = 'Boolean'; | |
189 hw.default = 1; | |
190 option.hw = hw; | |
191 | |
192 | |
193 %% options related to mirautocor: | |
194 | |
195 aut.key = 'Autocor'; | |
196 aut.type = 'Integer'; | |
197 aut.default = 0; | |
198 aut.keydefault = 1; | |
199 option.aut = aut; | |
200 | |
201 nw.key = 'NormalWindow'; | |
202 nw.default = 0; | |
203 option.nw = nw; | |
204 | |
205 enh.key = 'Enhanced'; | |
206 enh.type = 'Integers'; | |
207 enh.default = 2:10; | |
208 enh.keydefault = 2:10; | |
209 option.enh = enh; | |
210 | |
211 r.key = 'Resonance'; | |
212 r.type = 'String'; | |
213 r.choice = {'ToiviainenSnyder','vanNoorden',0,'off','no'}; | |
214 r.default = 'ToiviainenSnyder'; | |
215 option.r = r; | |
216 | |
217 | |
218 %% options related to mirspectrum: | |
219 | |
220 spe.key = 'Spectrum'; | |
221 spe.type = 'Integer'; | |
222 spe.default = 0; | |
223 spe.keydefault = 1; | |
224 option.spe = spe; | |
225 | |
226 zp.key = 'ZeroPad'; | |
227 zp.type = 'Integer'; | |
228 zp.default = 10000; | |
229 zp.keydefault = Inf; | |
230 option.zp = zp; | |
231 | |
232 prod.key = 'Prod'; | |
233 prod.type = 'Integers'; | |
234 prod.default = 0; | |
235 prod.keydefault = 2:6; | |
236 option.prod = prod; | |
237 | |
238 | |
239 %% options related to the peak detection | |
240 | |
241 m.key = 'Total'; | |
242 m.type = 'Integer'; | |
243 m.default = 1; | |
244 option.m = m; | |
245 | |
246 thr.key = 'Contrast'; | |
247 thr.type = 'Integer'; | |
248 thr.default = 0.1; | |
249 option.thr = thr; | |
250 | |
251 mi.key = 'Min'; | |
252 mi.type = 'Integer'; | |
253 mi.default = 40; | |
254 option.mi = mi; | |
255 | |
256 ma.key = 'Max'; | |
257 ma.type = 'Integer'; | |
258 ma.default = 200; | |
259 option.ma = ma; | |
260 | |
261 track.key = 'Track'; | |
262 track.type = 'Boolean'; | |
263 track.default = 0; | |
264 option.track = track; | |
265 | |
266 pref.key = 'Pref'; | |
267 pref.type = 'Integer'; | |
268 pref.number = 2; | |
269 pref.default = [0 .2]; | |
270 option.pref = pref; | |
271 | |
272 perio.key = 'Periodicity'; | |
273 perio.type = 'Boolean'; | |
274 perio.default = 0; | |
275 option.perio = perio; | |
276 | |
277 specif.option = option; | |
278 | |
279 varargout = mirfunction(@mirtempo,x,varargin,nargout,specif,@init,@main); | |
280 | |
281 | |
282 %% INIT | |
283 | |
284 function [y type] = init(x,option) | |
285 if iscell(x) | |
286 x = x{1}; | |
287 end | |
288 if option.perio | |
289 option.m = 3; | |
290 option.enh = 2:10; | |
291 end | |
292 if not(isamir(x,'mirautocor')) && not(isamir(x,'mirspectrum')) | |
293 if isframed(x) && strcmpi(option.fea,'Envelope') && not(isamir(x,'mirscalar')) | |
294 warning('WARNING IN MIRTEMPO: The input should not be already decomposed into frames.'); | |
295 disp(['Suggestion: Use the ''Frame'' option instead.']) | |
296 end | |
297 if strcmpi(option.sum,'Before') | |
298 optionsum = 1; | |
299 elseif strcmpi(option.sum,'Adjacent') | |
300 optionsum = 5; | |
301 else | |
302 optionsum = 0; | |
303 end | |
304 if option.frame.length.val | |
305 x = mironsets(x,option.fea,'Filterbank',option.fb,... | |
306 'FilterbankType',option.fbtype,... | |
307 'FilterType',option.ftype,... | |
308 'Sum',optionsum,'Method',option.envmeth,... | |
309 option.band,'Center',option.c,... | |
310 'HalfwaveCenter',option.chwr,'Diff',option.diff,... | |
311 'HalfwaveDiff',option.diffhwr,'Lambda',option.lambda,... | |
312 'Smooth',option.aver,'Sampling',option.sampling,... | |
313 'Complex',option.complex,'Inc',option.inc,... | |
314 'Median',option.median(1),option.median(2),... | |
315 'Halfwave',option.hw,'Detect',0,... | |
316 'Mu',option.mu,'Log',option.log,... | |
317 'Frame',option.frame.length.val,... | |
318 option.frame.length.unit,... | |
319 option.frame.hop.val,... | |
320 option.frame.hop.unit); | |
321 else | |
322 x = mironsets(x,option.fea,'Filterbank',option.fb,... | |
323 'FilterbankType',option.fbtype,... | |
324 'FilterType',option.ftype,... | |
325 'Sum',optionsum,'Method',option.envmeth,... | |
326 option.band,'Center',option.c,... | |
327 'HalfwaveCenter',option.chwr,'Diff',option.diff,... | |
328 'HalfwaveDiff',option.diffhwr,'Lambda',option.lambda,... | |
329 'Smooth',option.aver,'Sampling',option.sampling,... | |
330 'Complex',option.complex,'Inc',option.inc,... | |
331 'Median',option.median(1),option.median(2),... | |
332 'Halfwave',option.hw,'Detect',0,... | |
333 'Mu',option.mu,'Log',option.log); | |
334 end | |
335 end | |
336 if option.aut == 0 && option.spe == 0 | |
337 option.aut = 1; | |
338 end | |
339 if isamir(x,'mirautocor') || (option.aut && not(option.spe)) | |
340 y = mirautocor(x,'Min',60/option.ma,'Max',60/option.mi,... | |
341 'Enhanced',option.enh,...'NormalInput','coeff',... | |
342 'Resonance',option.r,'NormalWindow',option.nw); | |
343 elseif isamir(x,'mirspectrum') || (option.spe && not(option.aut)) | |
344 y = mirspectrum(x,'Min',option.mi/60,'Max',option.ma/60,... | |
345 'Prod',option.prod,...'NormalInput',... | |
346 'ZeroPad',option.zp,'Resonance',option.r); | |
347 elseif option.spe && option.aut | |
348 ac = mirautocor(x,'Min',60/option.ma,'Max',60/option.mi,... | |
349 'Enhanced',option.enh,...'NormalInput','coeff',... | |
350 'Resonance',option.r); | |
351 sp = mirspectrum(x,'Min',option.mi/60,'Max',option.ma/60,... | |
352 'Prod',option.prod,...'NormalInput',... | |
353 'ZeroPad',option.zp,'Resonance',option.r); | |
354 y = ac*sp; | |
355 end | |
356 if ischar(option.sum) | |
357 y = mirsum(y); | |
358 end | |
359 y = mirpeaks(y,'Total',option.m,'Track',option.track,... | |
360 'Pref',option.pref(1),option.pref(2),... | |
361 'Contrast',option.thr,'NoBegin','NoEnd',... | |
362 'Normalize','Local'); | |
363 type = {'mirscalar',mirtype(y)}; | |
364 | |
365 | |
366 %% MAIN | |
367 | |
368 function o = main(p,option,postoption) | |
369 if iscell(p) | |
370 p = p{1}; | |
371 end | |
372 pt = get(p,'TrackPrecisePos'); | |
373 track = 1; | |
374 if isempty(pt) || isempty(pt{1}) | |
375 pt = get(p,'PeakPrecisePos'); | |
376 track = 0; | |
377 end | |
378 bpm = cell(1,length(pt)); | |
379 for j = 1:length(pt) | |
380 bpm{j} = cell(1,length(pt{j})); | |
381 for k = 1:length(pt{j}) | |
382 ptk = pt{j}{k}; | |
383 bpmk = cell(1,size(ptk,2)); | |
384 for h = 1:size(ptk,3) | |
385 for l = 1:size(ptk,2) | |
386 ptl = ptk{1,l,h}; | |
387 if isempty(ptl) | |
388 bpmk{1,l,h} = NaN; | |
389 else | |
390 if isa(p,'mirautocor') && not(get(p,'FreqDomain')) | |
391 bpmk{1,l,h} = 60./ptl; | |
392 else | |
393 bpmk{1,l,h} = ptl*60; | |
394 end | |
395 end | |
396 end | |
397 end | |
398 if track | |
399 bpmk = bpmk{1}; | |
400 end | |
401 bpm{j}{k} = bpmk; | |
402 end | |
403 end | |
404 t = mirscalar(p,'Data',bpm,'Title','Tempo','Unit','bpm'); | |
405 o = {t,p}; |