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