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