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}; |