annotate toolboxes/MIRtoolbox1.3.2/MIRToolbox/mirpulseclarity.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 = mirpulseclarity(orig,varargin)
wolffd@0 2 % r = mirpulseclarity(x) estimates the rhythmic clarity, indicating the
wolffd@0 3 % strength of the beats estimated by the mirtempo function.
wolffd@0 4 % Optional arguments:
wolffd@0 5 % mirpulseclarity(...,s): specifies a strategy for pulse clarity
wolffd@0 6 % estimation.
wolffd@0 7 % Possible values: 'MaxAutocor' (default), 'MinAutocor',
wolffd@0 8 % 'KurtosisAutocor', MeanPeaksAutocor', 'EntropyAutocor',
wolffd@0 9 % 'InterfAutocor', 'TempoAutocor', 'ExtremEnvelop',
wolffd@0 10 % 'Attack', 'Articulation'
wolffd@0 11 % mirpulseclarity(...,'Frame',l,h): orders a frame decomposition of
wolffd@0 12 % the audio input of window length l (in seconds) and hop factor
wolffd@0 13 % h, expressed relatively to the window length.
wolffd@0 14 % Default values: l = 5 seconds and h = .1
wolffd@0 15 % Onset detection strategies: 'Envelope' (default), 'DiffEnvelope',
wolffd@0 16 % 'SpectralFlux', 'Pitch'.
wolffd@0 17 % Options related to the autocorrelation computation can be specified
wolffd@0 18 % as well: 'Min', 'Max', 'Resonance', 'Enhanced'
wolffd@0 19 % Options related to the tempo estimation can be specified here
wolffd@0 20 % as well: 'Sum', 'Total', 'Contrast'.
wolffd@0 21 % cf. User's Manual for more details.
wolffd@0 22 % [r,a] = mirpulseclarity(x) also returns the beat autocorrelation.
wolffd@0 23
wolffd@0 24 model.key = 'Model';
wolffd@0 25 model.type = 'Integer';
wolffd@0 26 model.default = 0;
wolffd@0 27 option.model = model;
wolffd@0 28
wolffd@0 29 stratg.type = 'String';
wolffd@0 30 stratg.choice = {'MaxAutocor','MinAutocor','MeanPeaksAutocor',...
wolffd@0 31 'KurtosisAutocor','EntropyAutocor',...
wolffd@0 32 'InterfAutocor','TempoAutocor','ExtremEnvelop',...
wolffd@0 33 'Attack','Articulation'}; ...,'AttackDiff'
wolffd@0 34 stratg.default = 'MaxAutocor';
wolffd@0 35 option.stratg = stratg;
wolffd@0 36
wolffd@0 37 frame.key = 'Frame';
wolffd@0 38 frame.type = 'Integer';
wolffd@0 39 frame.number = 2;
wolffd@0 40 frame.keydefault = [5 .1];
wolffd@0 41 frame.default = [0 0];
wolffd@0 42 option.frame = frame;
wolffd@0 43
wolffd@0 44 %% options related to mironsets:
wolffd@0 45
wolffd@0 46 fea.type = 'String';
wolffd@0 47 fea.choice = {'Envelope','DiffEnvelope','SpectralFlux','Pitch'};
wolffd@0 48 fea.default = 'Envelope';
wolffd@0 49 option.fea = fea;
wolffd@0 50
wolffd@0 51
wolffd@0 52 %% options related to 'Envelope':
wolffd@0 53
wolffd@0 54 envmeth.key = 'Method';
wolffd@0 55 envmeth.type = 'String';
wolffd@0 56 envmeth.choice = {'Filter','Spectro'};
wolffd@0 57 envmeth.default = 'Spectro';
wolffd@0 58 option.envmeth = envmeth;
wolffd@0 59
wolffd@0 60 %% options related to 'Filter':
wolffd@0 61
wolffd@0 62 ftype.key = 'FilterType';
wolffd@0 63 ftype.type = 'String';
wolffd@0 64 ftype.choice = {'IIR','HalfHann'};
wolffd@0 65 ftype.default = 'IIR';
wolffd@0 66 option.ftype = ftype;
wolffd@0 67
wolffd@0 68 fb.key = 'Filterbank';
wolffd@0 69 fb.type = 'Integer';
wolffd@0 70 fb.default = 20;
wolffd@0 71 option.fb = fb;
wolffd@0 72
wolffd@0 73 fbtype.key = 'FilterbankType';
wolffd@0 74 fbtype.type = 'String';
wolffd@0 75 fbtype.choice = {'Gammatone','Scheirer','Klapuri'};
wolffd@0 76 fbtype.default = 'Scheirer';
wolffd@0 77 option.fbtype = fbtype;
wolffd@0 78
wolffd@0 79 %% options related to 'Spectro':
wolffd@0 80
wolffd@0 81 band.type = 'String';
wolffd@0 82 band.choice = {'Freq','Mel','Bark','Cents'};
wolffd@0 83 band.default = 'Freq';
wolffd@0 84 option.band = band;
wolffd@0 85
wolffd@0 86
wolffd@0 87 diffhwr.key = 'HalfwaveDiff';
wolffd@0 88 diffhwr.type = 'Integer';
wolffd@0 89 diffhwr.default = 0;
wolffd@0 90 diffhwr.keydefault = 1;
wolffd@0 91 option.diffhwr = diffhwr;
wolffd@0 92
wolffd@0 93 lambda.key = 'Lambda';
wolffd@0 94 lambda.type = 'Integer';
wolffd@0 95 lambda.default = 1;
wolffd@0 96 option.lambda = lambda;
wolffd@0 97
wolffd@0 98 aver.key = 'Smooth';
wolffd@0 99 aver.type = 'Integer';
wolffd@0 100 aver.default = 0;
wolffd@0 101 aver.keydefault = 30;
wolffd@0 102 option.aver = aver;
wolffd@0 103
wolffd@0 104 oplog.key = 'Log';
wolffd@0 105 oplog.type = 'Boolean';
wolffd@0 106 oplog.default = 0;
wolffd@0 107 option.log = oplog;
wolffd@0 108
wolffd@0 109 mu.key = 'Mu';
wolffd@0 110 mu.type = 'Boolean';
wolffd@0 111 mu.default = 1;
wolffd@0 112 option.mu = mu;
wolffd@0 113
wolffd@0 114 %% options related to 'SpectralFlux'
wolffd@0 115
wolffd@0 116 inc.key = 'Inc';
wolffd@0 117 inc.type = 'Boolean';
wolffd@0 118 inc.default = 1;
wolffd@0 119 option.inc = inc;
wolffd@0 120
wolffd@0 121 median.key = 'Median';
wolffd@0 122 median.type = 'Integer';
wolffd@0 123 median.number = 2;
wolffd@0 124 median.default = [0 0]; % Not same default as in mirtempo
wolffd@0 125 option.median = median;
wolffd@0 126
wolffd@0 127 hw.key = 'Halfwave';
wolffd@0 128 hw.type = 'Boolean';
wolffd@0 129 hw.default = 0; %NaN; %0; % Not same default as in mirtempo
wolffd@0 130 option.hw = hw;
wolffd@0 131
wolffd@0 132
wolffd@0 133 %% options related to mirattackslope
wolffd@0 134 slope.type = 'String';
wolffd@0 135 slope.choice = {'Diff','Gauss'};
wolffd@0 136 slope.default = 'Diff';
wolffd@0 137 option.slope = slope;
wolffd@0 138
wolffd@0 139 %% options related to mirautocor:
wolffd@0 140
wolffd@0 141 enh.key = 'Enhanced';
wolffd@0 142 enh.type = 'Integers';
wolffd@0 143 enh.default = [];
wolffd@0 144 enh.keydefault = 2:10;
wolffd@0 145 option.enh = enh;
wolffd@0 146
wolffd@0 147 r.key = 'Resonance';
wolffd@0 148 r.type = 'String';
wolffd@0 149 r.choice = {'ToiviainenSnyder','vonNoorden',0,'off','no'};
wolffd@0 150 r.default = 'ToiviainenSnyder';
wolffd@0 151 option.r = r;
wolffd@0 152
wolffd@0 153 mi.key = 'Min';
wolffd@0 154 mi.type = 'Integer';
wolffd@0 155 mi.default = 40;
wolffd@0 156 option.mi = mi;
wolffd@0 157
wolffd@0 158 ma.key = 'Max';
wolffd@0 159 ma.type = 'Integer';
wolffd@0 160 ma.default = 200;
wolffd@0 161 option.ma = ma;
wolffd@0 162
wolffd@0 163 %% options related to mirtempo:
wolffd@0 164
wolffd@0 165 sum.key = 'Sum';
wolffd@0 166 sum.type = 'String';
wolffd@0 167 sum.choice = {'Before','After','Adjacent'};
wolffd@0 168 sum.default = 'Before';
wolffd@0 169 option.sum = sum;
wolffd@0 170
wolffd@0 171 m.key = 'Total';
wolffd@0 172 m.type = 'Integer';
wolffd@0 173 m.default = 1;
wolffd@0 174 option.m = m;
wolffd@0 175
wolffd@0 176 thr.key = 'Contrast';
wolffd@0 177 thr.type = 'Integer';
wolffd@0 178 thr.default = 0.01; % Not same default as in mirtempo
wolffd@0 179 option.thr = thr;
wolffd@0 180
wolffd@0 181 specif.option = option;
wolffd@0 182
wolffd@0 183 varargout = mirfunction(@mirpulseclarity,orig,varargin,nargout,specif,@init,@main);
wolffd@0 184
wolffd@0 185
wolffd@0 186
wolffd@0 187 %% Initialisation
wolffd@0 188
wolffd@0 189 function [x type] = init(x,option)
wolffd@0 190 %if isframed(x)
wolffd@0 191 % warning('WARNING IN MIRPULSECLARITY: The input should not be already decomposed into frames.');
wolffd@0 192 % disp(['Suggestion: Use the ''Frame'' option instead.'])
wolffd@0 193 %end
wolffd@0 194 if iscell(x)
wolffd@0 195 x = x{1};
wolffd@0 196 end
wolffd@0 197 if isamir(x,'mirautocor')
wolffd@0 198 type = {'mirscalar','mirautocor'};
wolffd@0 199 elseif length(option.model) > 1
wolffd@0 200 a = x;
wolffd@0 201 type = {'mirscalar'};
wolffd@0 202 for m = 1:length(option.model)
wolffd@0 203 if option.frame.length.val
wolffd@0 204 y = mirpulseclarity(a,'Model',option.model(m),...
wolffd@0 205 'Frame',option.frame.length.val,...
wolffd@0 206 option.frame.length.unit,...
wolffd@0 207 option.frame.hop.val,...
wolffd@0 208 option.frame.hop.unit);
wolffd@0 209 else
wolffd@0 210 y = mirpulseclarity(a,'Model',option.model(m));
wolffd@0 211 end
wolffd@0 212 if m == 1
wolffd@0 213 x = y;
wolffd@0 214 else
wolffd@0 215 x = x + y;
wolffd@0 216 end
wolffd@0 217 end
wolffd@0 218 else
wolffd@0 219 if option.model
wolffd@0 220 switch option.model
wolffd@0 221 case 1
wolffd@0 222 case 2
wolffd@0 223 option.envmeth = 'Filter';
wolffd@0 224 option.fbtype = 'Gammatone';
wolffd@0 225 option.mu = 0;
wolffd@0 226 option.r = 0;
wolffd@0 227 option.lambda = .8;
wolffd@0 228 option.sum = 'After';
wolffd@0 229 end
wolffd@0 230 end
wolffd@0 231 if length(option.stratg)>7 && strcmpi(option.stratg(end-6:end),'Autocor')
wolffd@0 232 if (strcmpi(option.stratg,'MaxAutocor') || ...
wolffd@0 233 strcmpi(option.stratg,'MinAutocor') || ...
wolffd@0 234 strcmpi(option.stratg,'EntropyAutocor'))
wolffd@0 235 option.m = 0;
wolffd@0 236 end
wolffd@0 237 if strcmpi(option.stratg,'MinAutocor')
wolffd@0 238 option.enh = 0;
wolffd@0 239 end
wolffd@0 240 if option.frame.length.val
wolffd@0 241 [t,x] = mirtempo(x,option.fea,'Method',option.envmeth,...
wolffd@0 242 option.band,...
wolffd@0 243 'Sum',option.sum,'Enhanced',option.enh,...
wolffd@0 244 'Resonance',option.r,'Smooth',option.aver,...
wolffd@0 245 'HalfwaveDiff',option.diffhwr,...
wolffd@0 246 'Lambda',option.lambda,...
wolffd@0 247 'Frame',option.frame.length.val,...
wolffd@0 248 option.frame.length.unit,...
wolffd@0 249 option.frame.hop.val,...
wolffd@0 250 option.frame.hop.unit,...
wolffd@0 251 'FilterbankType',option.fbtype,...
wolffd@0 252 'FilterType',option.ftype,...
wolffd@0 253 'Filterbank',option.fb,'Mu',option.mu,...
wolffd@0 254 'Log',option.log,...
wolffd@0 255 'Inc',option.inc,'Halfwave',option.hw,...
wolffd@0 256 'Median',option.median(1),option.median(2),...
wolffd@0 257 'Min',option.mi,'Max',option.ma,...
wolffd@0 258 'Total',option.m,'Contrast',option.thr);
wolffd@0 259 else
wolffd@0 260 [t,x] = mirtempo(x,option.fea,'Method',option.envmeth,...
wolffd@0 261 option.band,...
wolffd@0 262 'Sum',option.sum,'Enhanced',option.enh,...
wolffd@0 263 'Resonance',option.r,'Smooth',option.aver,...
wolffd@0 264 'HalfwaveDiff',option.diffhwr,...
wolffd@0 265 'Lambda',option.lambda,...
wolffd@0 266 'FilterbankType',option.fbtype,...
wolffd@0 267 'FilterType',option.ftype,...
wolffd@0 268 'Filterbank',option.fb,'Mu',option.mu,...
wolffd@0 269 'Log',option.log,...
wolffd@0 270 'Inc',option.inc,'Halfwave',option.hw,...
wolffd@0 271 'Median',option.median(1),option.median(2),...
wolffd@0 272 'Min',option.mi,'Max',option.ma,...
wolffd@0 273 'Total',option.m,'Contrast',option.thr);
wolffd@0 274 end
wolffd@0 275 type = {'mirscalar','mirautocor'};
wolffd@0 276 elseif strcmpi(option.stratg,'ExtremEnvelop')
wolffd@0 277 x = mironsets(x,'Filterbank',option.fb);
wolffd@0 278 type = {'mirscalar','mirenvelope'};
wolffd@0 279 elseif strcmpi(option.stratg,'Attack')
wolffd@0 280 x = mirattackslope(x,option.slope);
wolffd@0 281 type = {'mirscalar','mirenvelope'};
wolffd@0 282 % elseif strcmpi(option.stratg,'AttackDiff')
wolffd@0 283 % type = {'mirscalar','mirenvelope'};
wolffd@0 284 elseif strcmpi(option.stratg,'Articulation')
wolffd@0 285 x = mirlowenergy(x,'ASR');
wolffd@0 286 type = {'mirscalar','mirscalar'};
wolffd@0 287 else
wolffd@0 288 type = {'mirscalar','miraudio'};
wolffd@0 289 end
wolffd@0 290 end
wolffd@0 291
wolffd@0 292
wolffd@0 293
wolffd@0 294 %% Main function
wolffd@0 295
wolffd@0 296 function o = main(a,option,postoption)
wolffd@0 297 if option.model == 2
wolffd@0 298 option.stratg = 'InterfAutocor';
wolffd@0 299 end
wolffd@0 300 if isa(a,'mirscalar') && not(strcmpi(option.stratg,'Attack')) % not very nice test... to improve.
wolffd@0 301 o = {a};
wolffd@0 302 return
wolffd@0 303 end
wolffd@0 304 if option.m == 1 && ...
wolffd@0 305 (strcmpi(option.stratg,'InterfAutocor') || ...
wolffd@0 306 strcmpi(option.stratg,'MeanPeaksAutocor'))
wolffd@0 307 option.m = Inf;
wolffd@0 308 end
wolffd@0 309 if iscell(a)
wolffd@0 310 a = a{1};
wolffd@0 311 end
wolffd@0 312 if strcmpi(option.stratg,'MaxAutocor')
wolffd@0 313 d = get(a,'Data');
wolffd@0 314 rc = mircompute(@max,d);
wolffd@0 315 elseif strcmpi(option.stratg,'MinAutocor')
wolffd@0 316 d = get(a,'Data');
wolffd@0 317 rc = mircompute(@minusmin,d);
wolffd@0 318 elseif strcmpi(option.stratg,'MeanPeaksAutocor')
wolffd@0 319 m = get(a,'PeakVal');
wolffd@0 320 rc = mircompute(@meanpeaks,m);
wolffd@0 321 elseif strcmpi(option.stratg,'KurtosisAutocor')
wolffd@0 322 a = mirpeaks(a,'Extract','Total',option.m,'NoBegin','NoEnd');
wolffd@0 323 k = mirkurtosis(a);
wolffd@0 324 %d = get(k,'Data');
wolffd@0 325 %rc = mircompute(@meanpeaks,d);
wolffd@0 326 rc = mirmean(k);
wolffd@0 327 elseif strcmpi(option.stratg,'EntropyAutocor')
wolffd@0 328 rc = mirentropy(a);
wolffd@0 329 elseif strcmpi(option.stratg,'InterfAutocor')
wolffd@0 330 a = mirpeaks(a,'Total',option.m,'NoBegin','NoEnd');
wolffd@0 331 m = get(a,'PeakVal');
wolffd@0 332 p = get(a,'PeakPosUnit');
wolffd@0 333 rc = mircompute(@interf,m,p);
wolffd@0 334 elseif strcmpi(option.stratg,'TempoAutocor')
wolffd@0 335 a = mirpeaks(a,'Total',1,'NoBegin','NoEnd');
wolffd@0 336 p = get(a,'PeakPosUnit');
wolffd@0 337 rc = mircompute(@tempo,p);
wolffd@0 338 elseif strcmpi(option.stratg,'ExtremEnvelop')
wolffd@0 339 a = mirenvelope(a,'Normal');
wolffd@0 340 p = mirpeaks(a,'Order','Abscissa');
wolffd@0 341 p = get(p,'PeakPreciseVal');
wolffd@0 342 n = mirpeaks(a,'Valleys','Order','Abscissa');
wolffd@0 343 n = get(n,'PeakPreciseVal');
wolffd@0 344 rc = mircompute(@shape,p,n);
wolffd@0 345 elseif strcmpi(option.stratg,'Attack')
wolffd@0 346 rc = mirmean(a);
wolffd@0 347 %elseif strcmpi(option.stratg,'AttackDiff')
wolffd@0 348 % a = mirpeaks(a);
wolffd@0 349 % m = get(a,'PeakVal');
wolffd@0 350 % rc = mircompute(@meanpeaks,m);
wolffd@0 351 elseif strcmpi(option.stratg,'Articulation')
wolffd@0 352 rc = a;
wolffd@0 353 end
wolffd@0 354
wolffd@0 355 if iscell(rc)
wolffd@0 356 pc = mirscalar(a,'Data',rc,'Title','Pulse clarity');
wolffd@0 357 else
wolffd@0 358 pc = set(rc,'Title',['Pulse clarity (',get(rc,'Title'),')']);
wolffd@0 359 end
wolffd@0 360
wolffd@0 361 if option.model
wolffd@0 362 switch option.model
wolffd@0 363 case 1
wolffd@0 364 alpha = 0;
wolffd@0 365 beta = 2.2015;
wolffd@0 366 lambda = .1;
wolffd@0 367 case 2
wolffd@0 368 alpha = 0;
wolffd@0 369 beta = 3.5982;
wolffd@0 370 lambda = 1.87;
wolffd@0 371 end
wolffd@0 372 if not(lambda == 0)
wolffd@0 373 pc = (pc+alpha)^lambda * beta;
wolffd@0 374 else
wolffd@0 375 pc = log(pc+alpha) * beta;
wolffd@0 376 end
wolffd@0 377 title = ['Pulse clarity (Model ',num2str(option.model),')'];
wolffd@0 378 pc = set(pc,'Title',title);
wolffd@0 379 end
wolffd@0 380
wolffd@0 381 o = {pc a};
wolffd@0 382
wolffd@0 383
wolffd@0 384 %% Routines
wolffd@0 385
wolffd@0 386 function r = shape(p,n)
wolffd@0 387 p = p{1};
wolffd@0 388 n = n{1};
wolffd@0 389 if length(p)>length(n)
wolffd@0 390 d = sum(p(1:end-1) - n) + sum(p(2:end) - n);
wolffd@0 391 r = d/(2*length(n));
wolffd@0 392 elseif length(p)<length(n)
wolffd@0 393 d = sum(p - n(1:end-1)) + sum(p - n(2:end));
wolffd@0 394 r = d/(2*length(p));
wolffd@0 395 else
wolffd@0 396 d = sum(p(2:end) - n(1:end-1)) + sum(p(1:end-1) - n(2:end));
wolffd@0 397 r = d/(2*(length(p)-1));
wolffd@0 398 end
wolffd@0 399
wolffd@0 400
wolffd@0 401 function rc = minusmin(ac)
wolffd@0 402 rc = -min(ac);
wolffd@0 403
wolffd@0 404
wolffd@0 405 function rc = meanpeaks(ac)
wolffd@0 406 rc = zeros(1,length(ac));
wolffd@0 407 for j = 1:length(ac)
wolffd@0 408 if isempty(ac{j})
wolffd@0 409 rc(j) = NaN;
wolffd@0 410 else
wolffd@0 411 rc(j) = mean(ac{j});
wolffd@0 412 end
wolffd@0 413 end
wolffd@0 414
wolffd@0 415
wolffd@0 416 function rc = interf(mk,pk)
wolffd@0 417 rc = zeros(size(mk));
wolffd@0 418 for j = 1:size(mk,3)
wolffd@0 419 for i = 1:size(mk,2)
wolffd@0 420 pij = pk{1,i,j};
wolffd@0 421 mij = mk{1,i,j};
wolffd@0 422 if isempty(pij)
wolffd@0 423 rc(1,i,j) = 0;
wolffd@0 424 else
wolffd@0 425 high = max(pij(2:end),pij(1));
wolffd@0 426 low = min(pij(2:end),pij(1));
wolffd@0 427 quo = rem(high,low)./low;
wolffd@0 428 nomult = quo>.15 & quo<.85;
wolffd@0 429 fij = mij(2:end)/mij(1) .*nomult;
wolffd@0 430 fij(fij<0) = 0;
wolffd@0 431 rc(1,i,j) = exp(-sum(fij)/4); % Pulsations that are not in integer ratio
wolffd@0 432 % with dominant pulse decrease clarity
wolffd@0 433 end
wolffd@0 434 end
wolffd@0 435 end
wolffd@0 436
wolffd@0 437
wolffd@0 438 function rc = tempo(pk)
wolffd@0 439 rc = zeros(size(pk));
wolffd@0 440 for j = 1:size(pk,3)
wolffd@0 441 for i = 1:size(pk,2)
wolffd@0 442 pij = pk{1,i,j};
wolffd@0 443 if isempty(pij)
wolffd@0 444 rc(1,i,j) = 0;
wolffd@0 445 else
wolffd@0 446 rc(1,i,j) = exp(-pij(1)/4)/exp(-.33/4); % Fast dominant pulse
wolffd@0 447 % increases clarity
wolffd@0 448 end
wolffd@0 449 end
wolffd@0 450 end