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};