annotate toolboxes/MIRtoolbox1.3.2/MIRToolbox/mironsets.m @ 0:cc4b1211e677 tip

initial commit to HG from Changeset: 646 (e263d8a21543) added further path and more save "camirversion.m"
author Daniel Wolff
date Fri, 19 Aug 2016 13:07:06 +0200
parents
children
rev   line source
Daniel@0 1 function varargout = mironsets(x,varargin)
Daniel@0 2 % o = mironsets(x) shows a temporal curve where peaks relate to the
Daniel@0 3 % position of note onset times, and estimates those note onset
Daniel@0 4 % positions.
Daniel@0 5 % Optional arguments:
Daniel@0 6 % mironsets(...,f) selects the strategy for the computation of the
Daniel@0 7 % onset detection function.
Daniel@0 8 % f = 'Envelope': Envelope of the audio signal. (Default choice).
Daniel@0 9 % With two methods for envelope extraction:
Daniel@0 10 % mironsets(...,'Spectro') (Default):
Daniel@0 11 % mironsets(...,'SpectroFrame',fl,fh) species the frame
Daniel@0 12 % length fl (in s.) and the hop factor fh (as a value
Daniel@0 13 % between 0 and 1)
Daniel@0 14 % Default values: fl = .1 s., fh = .1
Daniel@0 15 % the frequency reassigment method can be specified:
Daniel@0 16 % 'Freq' (default), 'Mel', 'Bark' or 'Cents' (cf. mirspectrum).
Daniel@0 17 % mironsets(...,'Filter'):
Daniel@0 18 % mironsets(...,'Filterbank',nc) specifies a preliminary
Daniel@0 19 % filterbank decomposition into nc channels. If nc = 0,
Daniel@0 20 % no decomposition is performed.
Daniel@0 21 % Default value: 40.
Daniel@0 22 % mironsets(...,'FilterbankType',ft) specifies the type of
Daniel@0 23 % filterbank (see mirfilterbank).
Daniel@0 24 % Default value: 'Gammatone';
Daniel@0 25 % Options associated to the mirenvelope function can be
Daniel@0 26 % passed here as well (see help mirenvelope):
Daniel@0 27 % 'FilterType','Tau','PreDecim'
Daniel@0 28 % mironsets(...,'Sum','no') does not sum back the channels at
Daniel@0 29 % the end of the computation. The resulting onset curve
Daniel@0 30 % remains therefore decomposed into several channels.
Daniel@0 31 % Options associated to the mirenvelope function can be
Daniel@0 32 % passed here as well (see help mirenvelope):
Daniel@0 33 % 'HalfwaveCenter','Diff','HalfwaveDiff','Center',
Daniel@0 34 % 'Smooth', 'Sampling','Log','Power','Lambda',
Daniel@0 35 % ,'PostDecim','UpSample'
Daniel@0 36 % f = 'SpectralFlux': Spectral flux of the audio signal.
Daniel@0 37 % Options associated to the mirflux function can be
Daniel@0 38 % passed here as well (see help mirflux):
Daniel@0 39 % 'Inc' (toggled on by default here),
Daniel@0 40 % 'Halfwave' (toggled on by default here),
Daniel@0 41 % 'Complex' (toggled off by default),
Daniel@0 42 % 'Median' (toggled on by default here)
Daniel@0 43 % f = 'Pitch ':computes a frame-decomposed autocorrelation function ,
Daniel@0 44 % of same default characteristics than those returned
Daniel@0 45 % by mirpitch, with however a range of frequencies set by
Daniel@0 46 % the following options:
Daniel@0 47 % 'Min' (set by default to 30 Hz),
Daniel@0 48 % 'Max' (set by default to 1000 Hz),
Daniel@0 49 % and subsequently computes the novelty curve of the
Daniel@0 50 % resulting similatrix matrix.
Daniel@0 51 % Option associated to the mirnovelty function can be
Daniel@0 52 % passed here as well (see help mirnovelty):
Daniel@0 53 % 'KernelSize' (set by default to 32 samples)
Daniel@0 54 % mironsets(...,'Detect',d) toggles on or off the onset detection,
Daniel@0 55 % which is based on the onset detection function.
Daniel@0 56 % (By default toggled on.)
Daniel@0 57 % Option associated to the mirpeaks function can be specified as
Daniel@0 58 % well:
Daniel@0 59 % 'Contrast' with default value c = .01
Daniel@0 60 % 'Threshold' with default value t = 0
Daniel@0 61 % mironsets(...,'Attack') (or 'Attacks') detects attack phases.
Daniel@0 62 % mironsets(...,'Release') (or 'Releases') detects release phases.
Daniel@0 63 % mironsets(...,'Gauss',o) estimate the attack and/or release
Daniel@0 64 % points using a gaussian envelope smoothing of order o of the
Daniel@0 65 % onset curve.
Daniel@0 66 % mironsets(...,'Frame',...) decomposes into frames, with default frame
Daniel@0 67 % length 3 seconds and hop factor .1
Daniel@0 68 % Preselected onset detection models:
Daniel@0 69 % mironsets(...,'Scheirer') corresponds to (Scheirer, 1998):
Daniel@0 70 % mironsets(...,'FilterBankType','Scheirer',...
Daniel@0 71 % 'FilterType','HalfHann','Sampling',200,...
Daniel@0 72 % 'HalfWaveDiff','Sum',0,'Detect',0)
Daniel@0 73 % mironsets(...,'Klapuri99') corresponds to most of (Klapuri, 1999).
Daniel@0 74
Daniel@0 75 %% options related to 'Envelope':
Daniel@0 76
Daniel@0 77 env.key = 'Envelope';
Daniel@0 78 env.type = 'Boolean';
Daniel@0 79 env.default = NaN;
Daniel@0 80 option.env = env;
Daniel@0 81
Daniel@0 82 envmethod.key = 'Method'; % optional
Daniel@0 83 envmethod.type = 'Boolean';
Daniel@0 84 option.envmethod = envmethod;
Daniel@0 85
Daniel@0 86 envmeth.type = 'String';
Daniel@0 87 envmeth.choice = {'Filter','Spectro'};
Daniel@0 88 envmeth.default = 'Spectro';
Daniel@0 89 option.envmeth = envmeth;
Daniel@0 90
Daniel@0 91 %% options related to 'Filter':
Daniel@0 92
Daniel@0 93 filter.key = 'FilterType';
Daniel@0 94 filter.type = 'String';
Daniel@0 95 filter.choice = {'IIR','HalfHann'};
Daniel@0 96 filter.default = 'IIR';
Daniel@0 97 option.filter = filter;
Daniel@0 98
Daniel@0 99 tau.key = 'Tau';
Daniel@0 100 tau.type = 'Integer';
Daniel@0 101 tau.default = .02;
Daniel@0 102 option.tau = tau;
Daniel@0 103
Daniel@0 104 fb.key = {'Filterbank','NbChannels'};
Daniel@0 105 fb.type = 'Integer';
Daniel@0 106 fb.default = 40;
Daniel@0 107 option.fb = fb;
Daniel@0 108
Daniel@0 109 filtertype.key = 'FilterbankType';
Daniel@0 110 filtertype.type = 'String';
Daniel@0 111 %filtertype.choice = {'Gammatone','2Channels','Scheirer','Klapuri'};
Daniel@0 112 filtertype.default = 'Gammatone';
Daniel@0 113 option.filtertype = filtertype;
Daniel@0 114
Daniel@0 115 decim.key = {'Decim','PreDecim'};
Daniel@0 116 decim.type = 'Integer';
Daniel@0 117 decim.default = 0;
Daniel@0 118 option.decim = decim;
Daniel@0 119
Daniel@0 120 %% options related to 'Spectro':
Daniel@0 121
Daniel@0 122 band.type = 'String';
Daniel@0 123 band.choice = {'Freq','Mel','Bark','Cents'};
Daniel@0 124 band.default = 'Freq';
Daniel@0 125 option.band = band;
Daniel@0 126
Daniel@0 127 specframe.key = 'SpectroFrame';
Daniel@0 128 specframe.type = 'Integer';
Daniel@0 129 specframe.number = 2;
Daniel@0 130 specframe.default = [.1 .1];
Daniel@0 131 option.specframe = specframe;
Daniel@0 132
Daniel@0 133 sum.key = 'Sum';
Daniel@0 134 sum.type = 'Boolean';
Daniel@0 135 sum.default = 1;
Daniel@0 136 option.sum = sum;
Daniel@0 137
Daniel@0 138 chwr.key = 'HalfwaveCenter';
Daniel@0 139 chwr.type = 'Boolean';
Daniel@0 140 chwr.default = 0;
Daniel@0 141 chwr.when = 'After';
Daniel@0 142 option.chwr = chwr;
Daniel@0 143
Daniel@0 144 mu.key = 'Mu';
Daniel@0 145 mu.type = 'Boolean';
Daniel@0 146 mu.default = 0;
Daniel@0 147 mu.when = 'After';
Daniel@0 148 option.mu = mu;
Daniel@0 149
Daniel@0 150 oplog.key = 'Log';
Daniel@0 151 oplog.type = 'Boolean';
Daniel@0 152 oplog.default = 0;
Daniel@0 153 oplog.when = 'After';
Daniel@0 154 option.log = oplog;
Daniel@0 155
Daniel@0 156 oppow.key = 'Power';
Daniel@0 157 oppow.type = 'Boolean';
Daniel@0 158 oppow.default = 0;
Daniel@0 159 oppow.when = 'After';
Daniel@0 160 option.power = oppow;
Daniel@0 161
Daniel@0 162 diffenv.key = 'DiffEnvelope'; % obsolete, replaced by 'Diff'
Daniel@0 163 diffenv.type = 'Boolean';
Daniel@0 164 diffenv.default = 0;
Daniel@0 165 option.diffenv = diffenv;
Daniel@0 166
Daniel@0 167 diff.key = 'Diff';
Daniel@0 168 diff.type = 'Integer';
Daniel@0 169 diff.default = 0;
Daniel@0 170 diff.keydefault = 1;
Daniel@0 171 diff.when = 'After';
Daniel@0 172 option.diff = diff;
Daniel@0 173
Daniel@0 174 diffhwr.key = 'HalfwaveDiff';
Daniel@0 175 diffhwr.type = 'Integer';
Daniel@0 176 diffhwr.default = 0;
Daniel@0 177 diffhwr.keydefault = 1;
Daniel@0 178 diffhwr.when = 'After';
Daniel@0 179 option.diffhwr = diffhwr;
Daniel@0 180
Daniel@0 181 lambda.key = 'Lambda';
Daniel@0 182 lambda.type = 'Integer';
Daniel@0 183 lambda.default = 1;
Daniel@0 184 lambda.when = 'After';
Daniel@0 185 option.lambda = lambda;
Daniel@0 186
Daniel@0 187 c.key = 'Center';
Daniel@0 188 c.type = 'Boolean';
Daniel@0 189 c.default = 0;
Daniel@0 190 c.when = 'After';
Daniel@0 191 option.c = c;
Daniel@0 192
Daniel@0 193 aver.key = 'Smooth';
Daniel@0 194 aver.type = 'Integer';
Daniel@0 195 aver.default = 0;
Daniel@0 196 aver.keydefault = 30;
Daniel@0 197 aver.when = 'After';
Daniel@0 198 option.aver = aver;
Daniel@0 199
Daniel@0 200 ds.key = {'Down','PostDecim'};
Daniel@0 201 ds.type = 'Integer';
Daniel@0 202 if isamir(x,'mirenvelope')
Daniel@0 203 ds.default = 1;
Daniel@0 204 else
Daniel@0 205 ds.default = NaN;
Daniel@0 206 end
Daniel@0 207 ds.when = 'After';
Daniel@0 208 ds.chunkcombine = 'During';
Daniel@0 209 option.ds = ds;
Daniel@0 210
Daniel@0 211 sampling.key = 'Sampling';
Daniel@0 212 sampling.type = 'Integer';
Daniel@0 213 sampling.default = 0;
Daniel@0 214 sampling.when = 'After';
Daniel@0 215 option.sampling = sampling;
Daniel@0 216
Daniel@0 217 up.key = {'UpSample'};
Daniel@0 218 up.type = 'Integer';
Daniel@0 219 up.default = 0;
Daniel@0 220 up.keydefault = 2;
Daniel@0 221 option.up = up;
Daniel@0 222
Daniel@0 223 %% options related to 'SpectralFlux'
Daniel@0 224 flux.key = 'SpectralFlux';
Daniel@0 225 flux.type = 'Boolean';
Daniel@0 226 flux.default = 0;
Daniel@0 227 option.flux = flux;
Daniel@0 228
Daniel@0 229 complex.key = 'Complex';
Daniel@0 230 complex.type = 'Boolean';
Daniel@0 231 complex.when = 'Both';
Daniel@0 232 complex.default = 0;
Daniel@0 233 option.complex = complex;
Daniel@0 234
Daniel@0 235 inc.key = 'Inc';
Daniel@0 236 inc.type = 'Boolean';
Daniel@0 237 inc.default = 1;
Daniel@0 238 option.inc = inc;
Daniel@0 239
Daniel@0 240 median.key = 'Median';
Daniel@0 241 median.type = 'Integer';
Daniel@0 242 median.number = 2;
Daniel@0 243 median.default = [.2 1.3];
Daniel@0 244 median.when = 'After';
Daniel@0 245 option.median = median;
Daniel@0 246
Daniel@0 247 hw.key = 'Halfwave';
Daniel@0 248 hw.type = 'Boolean';
Daniel@0 249 hw.default = 1;
Daniel@0 250 hw.when = 'After';
Daniel@0 251 option.hw = hw;
Daniel@0 252
Daniel@0 253 %% options related to 'Pitch':
Daniel@0 254 pitch.key = 'Pitch';
Daniel@0 255 pitch.type = 'Boolean';
Daniel@0 256 pitch.default = 0;
Daniel@0 257 option.pitch = pitch;
Daniel@0 258
Daniel@0 259 min.key = 'Min';
Daniel@0 260 min.type = 'Integer';
Daniel@0 261 min.default = 30;
Daniel@0 262 option.min = min;
Daniel@0 263
Daniel@0 264 max.key = 'Max';
Daniel@0 265 max.type = 'Integer';
Daniel@0 266 max.default = 1000;
Daniel@0 267 option.max = max;
Daniel@0 268
Daniel@0 269 kernelsize.key = 'KernelSize';
Daniel@0 270 kernelsize.type = 'Integer';
Daniel@0 271 kernelsize.default = 32;
Daniel@0 272 option.kernelsize = kernelsize;
Daniel@0 273
Daniel@0 274 %% options related to event detection
Daniel@0 275 detect.key = 'Detect';
Daniel@0 276 detect.type = 'String';
Daniel@0 277 detect.choice = {'Peaks','Valleys',0,'no','off'};
Daniel@0 278 detect.default = 'Peaks';
Daniel@0 279 detect.keydefault = 'Peaks';
Daniel@0 280 detect.when = 'After';
Daniel@0 281 option.detect = detect;
Daniel@0 282
Daniel@0 283 cthr.key = 'Contrast';
Daniel@0 284 cthr.type = 'Integer';
Daniel@0 285 cthr.default = NaN;
Daniel@0 286 cthr.when = 'After';
Daniel@0 287 option.cthr = cthr;
Daniel@0 288
Daniel@0 289 thr.key = 'Threshold';
Daniel@0 290 thr.type = 'Integer';
Daniel@0 291 thr.default = 0;
Daniel@0 292 thr.when = 'After';
Daniel@0 293 option.thr = thr;
Daniel@0 294
Daniel@0 295 attack.key = {'Attack','Attacks'};
Daniel@0 296 attack.type = 'Boolean';
Daniel@0 297 attack.default = 0;
Daniel@0 298 attack.when = 'After';
Daniel@0 299 option.attack = attack;
Daniel@0 300
Daniel@0 301 release.key = {'Release','Releases'};
Daniel@0 302 release.type = 'String';
Daniel@0 303 release.choice = {'Olivier','Valeri',0,'no','off'};
Daniel@0 304 release.default = 0;
Daniel@0 305 release.keydefault = 'Olivier';
Daniel@0 306 release.when = 'After';
Daniel@0 307 option.release = release;
Daniel@0 308
Daniel@0 309 gauss.key = 'Gauss';
Daniel@0 310 gauss.type = 'Integer';
Daniel@0 311 gauss.default = 0;
Daniel@0 312 gauss.when = 'After';
Daniel@0 313 option.gauss = gauss;
Daniel@0 314
Daniel@0 315 %% preselection
Daniel@0 316 presel.choice = {'Scheirer','Klapuri99'};
Daniel@0 317 presel.type = 'String';
Daniel@0 318 presel.default = 0;
Daniel@0 319 option.presel = presel;
Daniel@0 320
Daniel@0 321
Daniel@0 322 %% 'Frame' option
Daniel@0 323 frame.key = 'Frame';
Daniel@0 324 frame.type = 'Integer';
Daniel@0 325 frame.when = 'Both';
Daniel@0 326 frame.number = 2;
Daniel@0 327 frame.default = [0 0];
Daniel@0 328 frame.keydefault = [3 .1];
Daniel@0 329 option.frame = frame;
Daniel@0 330
Daniel@0 331 specif.option = option;
Daniel@0 332
Daniel@0 333 specif.eachchunk = 'Normal';
Daniel@0 334 specif.combinechunk = 'Concat';
Daniel@0 335 specif.extensive = 1;
Daniel@0 336
Daniel@0 337 specif.title = 'Onset curve'; %used for miroptions
Daniel@0 338
Daniel@0 339 varargout = mirfunction(@mironsets,x,varargin,nargout,specif,@init,@main);
Daniel@0 340
Daniel@0 341
Daniel@0 342 %% INIT
Daniel@0 343
Daniel@0 344 function [y type] = init(x,option)
Daniel@0 345 if iscell(x)
Daniel@0 346 x = x{1};
Daniel@0 347 end
Daniel@0 348 if ischar(option.presel)
Daniel@0 349 if strcmpi(option.presel,'Scheirer')
Daniel@0 350 option.filtertype = 'Scheirer';
Daniel@0 351 option.filter = 'HalfHann';
Daniel@0 352 option.envmeth = 'Filter';
Daniel@0 353 elseif strcmpi(option.presel,'Klapuri99')
Daniel@0 354 option.filtertype = 'Klapuri';
Daniel@0 355 option.filter = 'HalfHann';
Daniel@0 356 option.envmeth = 'Filter';
Daniel@0 357 option.decim = 180;
Daniel@0 358 end
Daniel@0 359 end
Daniel@0 360 if option.diffenv
Daniel@0 361 option.env = 1;
Daniel@0 362 end
Daniel@0 363 if isnan(option.env)
Daniel@0 364 if option.flux || option.pitch
Daniel@0 365 option.env = 0;
Daniel@0 366 else
Daniel@0 367 option.env = 1;
Daniel@0 368 end
Daniel@0 369 end
Daniel@0 370 if isamir(x,'miraudio')
Daniel@0 371 if option.env
Daniel@0 372 if strcmpi(option.envmeth,'Filter') && option.fb>1
Daniel@0 373 fb = mirfilterbank(x,option.filtertype,'NbChannels',option.fb);
Daniel@0 374 else
Daniel@0 375 fb = x;
Daniel@0 376 end
Daniel@0 377 y = mirenvelope(fb,option.envmeth,option.band,...
Daniel@0 378 'Frame',option.specframe(1),option.specframe(2),...
Daniel@0 379 'FilterType',option.filter,...
Daniel@0 380 'Tau',option.tau,'UpSample',option.up,...
Daniel@0 381 'PreDecim',option.decim,'PostDecim',0);
Daniel@0 382 type = 'mirenvelope';
Daniel@0 383 elseif option.flux
Daniel@0 384 x = mirframenow(x,option);
Daniel@0 385 y = mirflux(x,'Inc',option.inc,'Complex',option.complex);
Daniel@0 386 type = 'mirscalar';
Daniel@0 387 elseif option.pitch
Daniel@0 388 [unused ac] = mirpitch(x,'Frame','Min',option.min,'Max',option.max);
Daniel@0 389 y = mirnovelty(ac,'KernelSize',option.kernelsize);
Daniel@0 390 type = 'mirscalar';
Daniel@0 391 end
Daniel@0 392 elseif (option.pitch && not(isamir(x,'mirscalar'))) ...
Daniel@0 393 || isamir(x,'mirsimatrix')
Daniel@0 394 y = mirnovelty(x,'KernelSize',option.kernelsize);
Daniel@0 395 type = 'mirscalar';
Daniel@0 396 elseif isamir(x,'mirscalar') || isamir(x,'mirenvelope')
Daniel@0 397 y = x; %mirframenow(x,option);
Daniel@0 398 type = mirtype(x);
Daniel@0 399 else
Daniel@0 400 x = mirframenow(x,option);
Daniel@0 401 y = mirflux(x,'Inc',option.inc,'Complex',option.complex); %Not used...
Daniel@0 402 type = 'mirscalar';
Daniel@0 403 end
Daniel@0 404
Daniel@0 405
Daniel@0 406 %% MAIN
Daniel@0 407
Daniel@0 408 function o = main(o,option,postoption)
Daniel@0 409 if not(isempty(option)) && ischar(option.presel)
Daniel@0 410 if strcmpi(option.presel,'Scheirer')
Daniel@0 411 postoption.sampling = 200;
Daniel@0 412 postoption.diffhwr = 1;
Daniel@0 413 option.sum = 0;
Daniel@0 414 postoption.detect = 0;
Daniel@0 415 elseif strcmpi(option.presel,'Klapuri99')
Daniel@0 416 postoption.mu = 1;
Daniel@0 417 postoption.diffhwr = 1;
Daniel@0 418 option.sum = 0;
Daniel@0 419 postoption.ds = 0;
Daniel@0 420 o2 = o;
Daniel@0 421 end
Daniel@0 422 end
Daniel@0 423 if iscell(o)
Daniel@0 424 o = o{1};
Daniel@0 425 end
Daniel@0 426 if not(isempty(option)) && option.diffenv
Daniel@0 427 postoption.diff = 1;
Daniel@0 428 end
Daniel@0 429 if isa(o,'mirenvelope')
Daniel@0 430 if isfield(postoption,'sampling') && postoption.sampling
Daniel@0 431 o = mirenvelope(o,'Sampling',postoption.sampling);
Daniel@0 432 elseif isfield(postoption,'ds')
Daniel@0 433 if isnan(postoption.ds)
Daniel@0 434 if option.decim || strcmpi(option.envmeth,'Spectro')
Daniel@0 435 postoption.ds = 0;
Daniel@0 436 else
Daniel@0 437 postoption.ds = 16;
Daniel@0 438 end
Daniel@0 439 end
Daniel@0 440 if postoption.ds
Daniel@0 441 o = mirenvelope(o,'Down',postoption.ds);
Daniel@0 442 end
Daniel@0 443 end
Daniel@0 444 end
Daniel@0 445 if isfield(postoption,'cthr')
Daniel@0 446 if isa(o,'mirenvelope')
Daniel@0 447 if postoption.mu
Daniel@0 448 o = mirenvelope(o,'Mu');
Daniel@0 449 end
Daniel@0 450 if postoption.log
Daniel@0 451 o = mirenvelope(o,'Log');
Daniel@0 452 end
Daniel@0 453 if postoption.power
Daniel@0 454 o = mirenvelope(o,'Power');
Daniel@0 455 end
Daniel@0 456 if postoption.diff
Daniel@0 457 o = mirenvelope(o,'Diff',postoption.diff,...
Daniel@0 458 'Lambda',postoption.lambda,...
Daniel@0 459 'Complex',postoption.complex);
Daniel@0 460 end
Daniel@0 461 if postoption.diffhwr
Daniel@0 462 o = mirenvelope(o,'HalfwaveDiff',postoption.diffhwr,...
Daniel@0 463 'Lambda',postoption.lambda,...
Daniel@0 464 'Complex',postoption.complex);
Daniel@0 465 end
Daniel@0 466 if postoption.aver
Daniel@0 467 o = mirenvelope(o,'Smooth',postoption.aver);
Daniel@0 468 end
Daniel@0 469 if postoption.chwr
Daniel@0 470 o = mirenvelope(o,'HalfwaveCenter');
Daniel@0 471 end
Daniel@0 472 if postoption.c
Daniel@0 473 o = mirenvelope(o,'Center');
Daniel@0 474 end
Daniel@0 475 elseif isa(o,'mirscalar') && strcmp(get(o,'Title'),'Spectral flux')
Daniel@0 476 if postoption.median
Daniel@0 477 o = mirflux(o,'Median',postoption.median(1),postoption.median(2),...
Daniel@0 478 'Halfwave',postoption.hw);
Daniel@0 479 else
Daniel@0 480 o = mirflux(o,'Halfwave',postoption.hw);
Daniel@0 481 end
Daniel@0 482 end
Daniel@0 483 end
Daniel@0 484 if isfield(option,'sum') && option.sum
Daniel@0 485 o = mirsum(o,'Adjacent',option.sum);
Daniel@0 486 end
Daniel@0 487 if isfield(option,'presel') && ...
Daniel@0 488 ischar(option.presel) && strcmpi(option.presel,'Klapuri99')
Daniel@0 489 % o, already computed, corresponds to mirenvelope(o,'Mu','HalfwaveDiff');
Daniel@0 490 % o is the relative distance function W in (Klapuri, 99);
Daniel@0 491 o2 = mirenvelope(o2,'HalfwaveDiff');
Daniel@0 492 % o2 is the absolute distance function D in (Klapuri, 99);
Daniel@0 493 p = mirpeaks(o,'Contrast',.2,'Chrono');
Daniel@0 494 p2 = mirpeaks(o2,'ScanForward',p,'Chrono');
Daniel@0 495 o = combinepeaks(p,p2,.05);
Daniel@0 496 clear o2 p p2
Daniel@0 497 filtfreq = 44*[2.^ ([ 0:2, ( 9+(0:17) )/3 ]) ];% Center frequencies of bands
Daniel@0 498 o = mirsum(o,'Weights',(filtfreq(1:end-1)+filtfreq(2:end))/2);
Daniel@0 499 o = mirenvelope(o,'Smooth',12);
Daniel@0 500 end
Daniel@0 501 if not(isa(o,'mirscalar'))
Daniel@0 502 o = mirframenow(o,postoption);
Daniel@0 503 end
Daniel@0 504 if isfield(postoption,'detect') && ischar(postoption.detect)
Daniel@0 505 if isnan(postoption.cthr) || not(postoption.cthr)
Daniel@0 506 if ischar(postoption.detect) || postoption.detect
Daniel@0 507 postoption.cthr = .01;
Daniel@0 508 end
Daniel@0 509 elseif postoption.cthr
Daniel@0 510 if not(ischar(postoption.detect) || postoption.detect)
Daniel@0 511 postoption.detect = 'Peaks';
Daniel@0 512 end
Daniel@0 513 end
Daniel@0 514 if strcmpi(postoption.detect,'Peaks')
Daniel@0 515 o = mirpeaks(o,'Total',Inf,'SelectFirst',...
Daniel@0 516 'Threshold',postoption.thr,'Contrast',postoption.cthr,...
Daniel@0 517 'Order','Abscissa','NoBegin','NoEnd');
Daniel@0 518 elseif strcmpi(postoption.detect,'Valleys')
Daniel@0 519 o = mirpeaks(o,'Total',Inf,'SelectFirst',...
Daniel@0 520 'Threshold',postoption.thr,'Contrast',postoption.cthr,...
Daniel@0 521 'Valleys','Order','Abscissa','NoBegin','NoEnd');
Daniel@0 522 end
Daniel@0 523 nop = cell(size(get(o,'Data')));
Daniel@0 524 o = set(o,'AttackPos',nop,'ReleasePos',nop);
Daniel@0 525 end
Daniel@0 526 if (isfield(postoption,'attack') && postoption.attack) || ...
Daniel@0 527 (isfield(postoption,'release') && postoption.release)
Daniel@0 528 p = get(o,'PeakPos');
Daniel@0 529 pm = get(o,'PeakMode');
Daniel@0 530 d = get(o,'Data');
Daniel@0 531 if postoption.attack
Daniel@0 532 [st p pm] = mircompute(@startattack,d,p,pm);
Daniel@0 533 end
Daniel@0 534 if ischar(postoption.release) && ~strcmpi(postoption.release,'No') ...
Daniel@0 535 && ~strcmpi(postoption.release,'Off')
Daniel@0 536 [rl p pm st] = mircompute(@endrelease,d,p,pm,st,postoption.release);
Daniel@0 537 o = set(o,'ReleasePos',rl);
Daniel@0 538 end
Daniel@0 539 o = set(o,'AttackPos',st,'PeakPos',p,'PeakMode',pm);
Daniel@0 540 end
Daniel@0 541 title = get(o,'Title');
Daniel@0 542 if not(length(title)>11 && strcmp(title(1:11),'Onset curve'))
Daniel@0 543 o = set(o,'Title',['Onset curve (',title,')']);
Daniel@0 544 end
Daniel@0 545
Daniel@0 546
Daniel@0 547 function st = startattack(d,z,pm)
Daniel@0 548 z = sort(z{1});
Daniel@0 549 pm = pm{1};
Daniel@0 550 st = zeros(size(z));
Daniel@0 551 i = 1;
Daniel@0 552 dd = diff(d,1,1); % d'
Daniel@0 553 ddd = diff(dd,1,1); % d''
Daniel@0 554 dddd = diff(ddd,1,1); % d'''
Daniel@0 555 while i<=length(z)
Daniel@0 556 % Start attack is identified to previous peak in d''.
Daniel@0 557 p = find(dddd((z(i)-1)-1:-1:1)<0,1); % previous decreasing d''
Daniel@0 558 if isempty(p)
Daniel@0 559 st(i) = 1;
Daniel@0 560 else
Daniel@0 561 n = find(dddd((z(i)-1)-p-1:-1:1)>0,1); % previous increasing d''
Daniel@0 562 if isempty(n)
Daniel@0 563 st(i) = 1;
Daniel@0 564 else
Daniel@0 565 st(i) = ((z(i)-1)-p-(n-1))+1;
Daniel@0 566 end
Daniel@0 567 if i>1 && st(i-1)==st(i)
Daniel@0 568 if d(z(i))>d(z(i-1))
Daniel@0 569 del = i-1;
Daniel@0 570 else
Daniel@0 571 del = i;
Daniel@0 572 end
Daniel@0 573 st(del) = [];
Daniel@0 574 z(del) = [];
Daniel@0 575 pm(del) = [];
Daniel@0 576 i = i-1;
Daniel@0 577 end
Daniel@0 578 end
Daniel@0 579 i = i+1;
Daniel@0 580 end
Daniel@0 581 st = {{st} {z} {pm}};
Daniel@0 582
Daniel@0 583
Daniel@0 584 function rt = endrelease(d,z,pm,st,meth)
Daniel@0 585 z = sort(z{1});
Daniel@0 586 pm = pm{1};
Daniel@0 587 if not(isempty(st))
Daniel@0 588 st = st{1};
Daniel@0 589 end
Daniel@0 590 rt = zeros(size(z));
Daniel@0 591 i = 1;
Daniel@0 592 dd = diff(d,1,1); % d'
Daniel@0 593 ddd = diff(dd,1,1); % d''
Daniel@0 594 dddd = diff(ddd,1,1); % d'''
Daniel@0 595 while i<=length(z)
Daniel@0 596 if strcmpi(meth,'Olivier')
Daniel@0 597 % Release attack is identified to next (sufficiently positive) peak
Daniel@0 598 % in d''.
Daniel@0 599 l = find(ddd((z(i)-1):end)<min(ddd)/100,1);
Daniel@0 600 % next d'' sufficiently negative
Daniel@0 601 if isempty(l)
Daniel@0 602 rt(i) = length(d);
Daniel@0 603 else
Daniel@0 604 p = find(ddd((z(i)-1)+(l-1)+1:end)>max(ddd)/100,1); % next increasing d''
Daniel@0 605 if isempty(p)
Daniel@0 606 rt(i) = length(d);
Daniel@0 607 else
Daniel@0 608 n = find(dddd((z(i)-1)+(l-1)+p+1:end)<0,1); % next decreasing d''
Daniel@0 609 if isempty(n)
Daniel@0 610 rt(i) = length(d);
Daniel@0 611 else
Daniel@0 612 rt(i) = ((z(i)-1)+(l-1)+p+n)+1;
Daniel@0 613 end
Daniel@0 614 end
Daniel@0 615 end
Daniel@0 616 elseif strcmpi(meth,'Valeri')
Daniel@0 617 p = find(dd((z(i)-1)+1:end)>min(dd)/100,1); % find point nearest to min(dd)/100 from current peak.
Daniel@0 618 if isempty(p)
Daniel@0 619 rt(i) = length(d);
Daniel@0 620 elseif p<=3 %that means if p is less than 3 points away from the peak then it can not be considered as the end point of release.
Daniel@0 621 %Assumption is that the whole DSR(decay sustain release) section can not be shorter than 30 ms (sampling rate is 100 Hz), also, no successive note can be nearer than 30ms.
Daniel@0 622 rt(i) = z(i)+3;
Daniel@0 623 else
Daniel@0 624 rt(i) = (z(i)-1)+(p-1);
Daniel@0 625 end
Daniel@0 626 end
Daniel@0 627 if i>1 && rt(i-1)==rt(i)
Daniel@0 628 if d(z(i))>d(z(i-1))
Daniel@0 629 del = i-1;
Daniel@0 630 else
Daniel@0 631 del = i;
Daniel@0 632 end
Daniel@0 633 rt(del) = [];
Daniel@0 634 z(del) = [];
Daniel@0 635 pm(del) = [];
Daniel@0 636 if not(isempty(st))
Daniel@0 637 st(del) = [];
Daniel@0 638 end
Daniel@0 639 i = i-1;
Daniel@0 640 end
Daniel@0 641 i = i+1;
Daniel@0 642 end
Daniel@0 643 rt = {{rt} {z} {pm} {st}};