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