Mercurial > hg > camir-aes2014
comparison toolboxes/MIRtoolbox1.3.2/MIRToolbox/@mirdesign/evaleach.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 [y d2] = evaleach(d,single,name) | |
2 % Top-down traversal of the design flowchart, at the beginning of the | |
3 % evaluation phase. | |
4 % Called by mirfunction, mireval, mirframe and mirsegment. | |
5 % This is during that traversal that we check whether a chunk decomposition | |
6 % needs to be performed or not, and carry out that chunk decomposition. | |
7 | |
8 if nargin<3 || isempty(name) | |
9 if not(ischar(d.method)) | |
10 name = func2str(d.method); | |
11 end | |
12 end | |
13 if nargin<2 | |
14 single = 0; | |
15 end | |
16 | |
17 CHUNKLIM = mirchunklim; | |
18 f = d.file; | |
19 fr = d.frame; | |
20 frnochunk = isfield(d.frame,'dontchunk'); | |
21 frchunkbefore = isfield(d.frame,'chunkbefore'); | |
22 sg = d.segment; | |
23 sr = d.sampling; | |
24 sr2 = d.resampling; | |
25 w = d.size; | |
26 lsz = w(2)-w(1)+1; | |
27 len = lsz/sr; | |
28 if ischar(sg) | |
29 error('ERROR in MIREVAL: mirsegment of design object accepts only array of numbers as second argument.'); | |
30 end | |
31 if not(isempty(sg)) | |
32 over = find(sg(2,:) > len); | |
33 if not(isempty(over)) | |
34 sg = sg(:,1:over-1); | |
35 end | |
36 end | |
37 a = d.argin; | |
38 ch = d.chunk; | |
39 chan = d.channel; | |
40 specif = d.specif; | |
41 if isaverage(specif) | |
42 specif.eachchunk = 'Normal'; | |
43 end | |
44 | |
45 if ischar(a) | |
46 % The top-down traversal of the design flowchart now reaches the lowest | |
47 % layer, i.e., audio file loading. | |
48 % Now the actual evaluation will be carried out bottom-up. | |
49 | |
50 if isempty(ch) | |
51 % No chunk decomposition | |
52 y = miraudio(f,'Now',[w(:)' 0 chan]); | |
53 else | |
54 % Chunk decomposition | |
55 y = miraudio(f,'Now',[ch(1),ch(2) 0 chan]); | |
56 end | |
57 if not(isempty(d.postoption)) && d.postoption.mono | |
58 y = miraudio(y,'Mono',1); | |
59 end | |
60 y = set(y,'AcrossChunks',get(d,'AcrossChunks')); | |
61 d2 = d; | |
62 | |
63 elseif d.chunkdecomposed && isempty(d.tmpfile) | |
64 % Already in a chunk decomposition process | |
65 | |
66 [y d2] = evalnow(d); | |
67 | |
68 elseif isempty(fr) || frnochunk || not(isempty(sg)) %% WHAT ABOUT CHANNELS? | |
69 % No frame or segment decomposition in the design to evaluate | |
70 % (Or particular frame decomposition, where chunks are not distributed to children (frnochunk).) | |
71 | |
72 if not(isfield(specif,'eachchunk')) ... | |
73 || d.nochunk ... | |
74 || (not(isempty(single)) && isnumeric(single) && single > 1 ... | |
75 && isfield(specif,'combinechunk') ... | |
76 && iscell(specif.combinechunk)) | |
77 chunks = []; | |
78 elseif not(isempty(sg)) | |
79 meth = 'Segment '; | |
80 if size(sg,1) == 1 | |
81 chunks = floor(sg(1:end-1)*sr)+1; | |
82 chunks(2,:) = min( floor(sg(2:end)*sr)-1,lsz-1)+1; | |
83 else | |
84 chunks = floor(sg*sr); | |
85 chunks(1,:) = chunks(1,:)+1; | |
86 end | |
87 else | |
88 meth = 'Chunk '; | |
89 if isempty(fr) | |
90 if lsz > CHUNKLIM | |
91 % The required memory exceed the max memory threshold. | |
92 nch = ceil(lsz/CHUNKLIM); | |
93 %%% TAKE INTO CONSIDERATION NUMBER OF CHANNELS; ETC... | |
94 chunks = max(0,lsz-CHUNKLIM*(nch:-1:1))+w(1); | |
95 chunks(2,:) = lsz-CHUNKLIM*(nch-1:-1:0)+w(1)-1; | |
96 else | |
97 chunks = []; | |
98 end | |
99 else | |
100 chunks = compute_frames(fr,sr,sr2,w,lsz,CHUNKLIM,d.overlap); | |
101 end | |
102 end | |
103 | |
104 if not(isempty(chunks)) | |
105 % The chunk decomposition is performed. | |
106 nch = size(chunks,2); | |
107 d = callbeforechunk(d,d,w,lsz); % Some optional initialisation | |
108 tmp = []; | |
109 if mirwaitbar | |
110 h = waitbar(0,['Computing ' name]); | |
111 else | |
112 h = 0; | |
113 end | |
114 if not(isempty(d.tmpfile)) && d.tmpfile.fid == 0 | |
115 % When applicable, a new temporary file is created. | |
116 d.tmpfile.fid = fopen('tmpfile.mirtoolbox','w'); | |
117 end | |
118 tmpfile = []; | |
119 if not(d.ascending) | |
120 chunks = fliplr(chunks); | |
121 end | |
122 | |
123 afterpostoption = d.postoption; % Used only when: | |
124 % - eachchunk is set to 'Normal', | |
125 % - combinechunk is not set to 'Average', and | |
126 % - no afterchunk field has been specified. | |
127 % afterpostoption will be used for the final call | |
128 % to the method after the chunk decomposition. | |
129 method = d.method; | |
130 if ischar(specif.eachchunk) && strcmpi(specif.eachchunk,'Normal') | |
131 if not(isempty(d.postoption)) | |
132 pof = fieldnames(d.postoption); | |
133 for o = 1:length(pof) | |
134 if isfield(specif.option.(pof{o}),'chunkcombine') | |
135 afterpostoption = rmfield(afterpostoption,pof{o}); | |
136 else | |
137 d.postoption = rmfield(d.postoption,pof{o}); | |
138 end | |
139 end | |
140 end | |
141 else | |
142 method = specif.eachchunk; | |
143 end | |
144 | |
145 d2 = d; | |
146 d2.method = method; | |
147 y = {}; | |
148 for i = 1:size(chunks,2) | |
149 disp([meth,num2str(i),'/',num2str(nch),'...']) | |
150 d2 = set(d2,'Chunk',[chunks(1,i) chunks(2,i) (i == size(chunks,2))]); | |
151 | |
152 if not(ischar(specif.eachchunk) && ... | |
153 strcmpi(specif.eachchunk,'Normal')) | |
154 if frnochunk | |
155 d2.postoption = 0; | |
156 else | |
157 diffchunks = diff(chunks); % Usual chunk size | |
158 d2.postoption = max(diffchunks) - diffchunks(i); | |
159 % Reduction of the current chunk size to be taken into | |
160 % consideration in mirspectrum, for instance, using | |
161 % zeropadding | |
162 end | |
163 end | |
164 | |
165 d2 = set(d2,'InterChunk',tmp); | |
166 d2.chunkdecomposed = 1; | |
167 | |
168 [ss d3] = evalnow(d2); | |
169 | |
170 if iscell(ss) && not(isempty(ss)) | |
171 tmp = get(ss{1},'InterChunk'); | |
172 elseif isstruct(ss) | |
173 tmp = []; | |
174 else | |
175 tmp = get(ss,'InterChunk'); | |
176 end | |
177 | |
178 % d2 is like d3 except that its argument is now evaluated. | |
179 d3.postoption = d.postoption; % Pas joli joli | |
180 d3.method = method; | |
181 d2 = d3; % This new argument is transfered to d | |
182 | |
183 y = combinechunk_noframe(y,ss,sg,i,d2,chunks,single); | |
184 | |
185 clear ss | |
186 if h | |
187 if not(d.ascending) | |
188 close(h) | |
189 h = waitbar((chunks(1,i)-chunks(1,end))/chunks(2,1),... | |
190 ['Computing ' func2str(d.method) ' (backward)']); | |
191 else | |
192 waitbar((chunks(2,i)-chunks(1))/chunks(end),h) | |
193 end | |
194 end | |
195 end | |
196 | |
197 y = afterchunk_noframe(y,lsz,d,afterpostoption,d2); | |
198 % Final operations to be executed after the chunk decomposition | |
199 | |
200 if isa(d,'mirstruct') && ... | |
201 (isempty(d.frame) || isfield(d.frame,'dontchunk')) | |
202 y = evalbranches(d,y); | |
203 end | |
204 if h | |
205 close(h) | |
206 end | |
207 drawnow | |
208 | |
209 else | |
210 % No chunk decomposition | |
211 [y d2] = evalnow(d); | |
212 if isa(d,'mirstruct') && isfield(d.frame,'dontchunk') | |
213 y = evalbranches(d,y); | |
214 end | |
215 end | |
216 elseif d.nochunk | |
217 [y d2] = evalnow(d); | |
218 else | |
219 % Frame decomposition in the design to be evaluated. | |
220 chunks = compute_frames(fr,sr,sr2,w,lsz,CHUNKLIM,d.overlap); | |
221 if size(chunks,2)>1 | |
222 % The chunk decomposition is performed. | |
223 if mirwaitbar | |
224 h = waitbar(0,['Computing ' name]); | |
225 else | |
226 h = 0; | |
227 end | |
228 inter = []; | |
229 d = set(d,'FrameDecomposition',1); | |
230 d2 = d; | |
231 nch = size(chunks,2); | |
232 y = {}; | |
233 | |
234 if frchunkbefore | |
235 d2after = d2; | |
236 d2.method = d2.argin.method; | |
237 d2.option = d2.argin.option; | |
238 d2.postoption = d2.argin.postoption; | |
239 d2.argin = d2.argin.argin; | |
240 end | |
241 | |
242 for fri = 1:nch % For each chunk... | |
243 disp(['Chunk ',num2str(fri),'/',num2str(nch),'...']) | |
244 d2 = set(d2,'Chunk',chunks(:,fri)'); | |
245 d2 = set(d2,'InterChunk',inter); | |
246 %d2.postoption = []; | |
247 [res d2] = evalnow(d2); | |
248 if not(isempty(res)) | |
249 if iscell(res) | |
250 inter = get(res{1},'InterChunk'); | |
251 elseif not(isstruct(res)) | |
252 inter = get(res,'InterChunk'); | |
253 res = {res}; | |
254 end | |
255 end | |
256 | |
257 y = combinechunk_frame(y,res,d2,fri); | |
258 if h | |
259 waitbar(chunks(2,fri)/chunks(end),h); | |
260 end | |
261 end | |
262 | |
263 if frchunkbefore | |
264 y = d2after.method(y,d2after.option,d2after.postoption); | |
265 end | |
266 | |
267 if isa(d,'mirstruct') && get(d,'Stat') | |
268 y = mirstat(y); | |
269 end | |
270 if h | |
271 close(h) | |
272 end | |
273 else | |
274 % No chunk decomposition | |
275 [y d2] = evalnow(d); | |
276 end | |
277 end | |
278 | |
279 | |
280 if iscell(y) | |
281 for i = 1:length(y) | |
282 if not(isempty(y{i}) || isstruct(y{i})) | |
283 if iscell(y{i}) | |
284 for j = 1:length(y{i}) | |
285 y{i}{j} = set(y{i}{j},'InterChunk',[]); | |
286 end | |
287 else | |
288 y{i} = set(y{i},'InterChunk',[]); | |
289 end | |
290 end | |
291 end | |
292 end | |
293 | |
294 | |
295 function chunks = compute_frames(fr,sr,sr2,w,lsz,CHUNKLIM,frov) | |
296 if strcmpi(fr.length.unit,'s') | |
297 fl = fr.length.val*sr; | |
298 fl2 = fr.length.val*sr2; | |
299 elseif strcmpi(fr.length.unit,'sp') | |
300 fl = fr.length.val; | |
301 fl2 = fl; | |
302 end | |
303 if strcmpi(fr.hop.unit,'/1') | |
304 h = fr.hop.val*fl; | |
305 h2 = fr.hop.val*fl2; | |
306 elseif strcmpi(fr.hop.unit,'%') | |
307 h = fr.hop.val*fl*.01; | |
308 h2 = fr.hop.val*fl2*.01; | |
309 elseif strcmpi(fr.hop.unit,'s') | |
310 h = fr.hop.val*sr; | |
311 h2 = fr.hop.val*sr2; | |
312 elseif strcmpi(fr.hop.unit,'sp') | |
313 h = fr.hop.val; | |
314 h2 = fr.hop.val; | |
315 elseif strcmpi(fr.hop.unit,'Hz') | |
316 h = sr/fr.hop.val; | |
317 h2 = sr2/fr.hop.val; | |
318 end | |
319 n = floor((lsz-fl)/h)+1; % Number of frames | |
320 if n < 1 | |
321 %warning('WARNING IN MIRFRAME: Frame length longer than total sequence size. No frame decomposition.'); | |
322 fp = w; | |
323 fp2 = (w-1)/sr*sr2+1; | |
324 else | |
325 st = floor(((1:n)-1)*h)+w(1); | |
326 st2 = floor(((1:n)-1)*h2)+w(1); | |
327 fp = [st; floor(st+fl-1)]; | |
328 fp(:,fp(2,:)>w(2)) = []; | |
329 fp2 = [st2; floor(st2+fl2-1)]; | |
330 fp2(:,fp2(2,:)>(w(2)-w(1))/sr*sr2+w(2)) = []; | |
331 end | |
332 fpe = (fp2-1)/sr2-(fp-1)/sr; %Rounding error if resampling | |
333 fpsz = (fp(2,1)-fp(1,1)) * n; % Total number of samples | |
334 fpsz2 = (fp2(2,1)-fp2(1,1)) * n; % Total number of samples | |
335 if max(fpsz,fpsz2) > CHUNKLIM | |
336 % The required memory exceed the max memory threshold. | |
337 nfr = size(fp,2); % Total number of frames | |
338 frch = max(ceil(CHUNKLIM/(fp(2,1)-fp(1,1))),2); % Number of frames per chunk | |
339 frch = max(frch,frov*2); | |
340 [unused cut] = min(abs(fpe(1,frch:-1:1))); | |
341 %frch = frch - cut; | |
342 % this correspond to the frame with less rounding error | |
343 nch = ceil((nfr-frch)/(frch-frov))+1; % Number of chunks | |
344 chbeg = (frch-frov)*(0:nch-1)+1; % First frame in the chunk | |
345 chend = (frch-frov)*(0:nch-1)+frch; % Last frame in the chunk | |
346 chend = min(chend,nfr); | |
347 if frov > 1 | |
348 chbeg = chend-frch+1; | |
349 end | |
350 chunks = [fp(1,chbeg) ; fp(2,chend)+1]; % After resampling, one sample may be missing, leading to a complete frame drop. | |
351 chunks(end) = min(chunks(end),fp(end)); % Last chunk should not extend beyond audio size. | |
352 else | |
353 chunks = []; | |
354 end | |
355 | |
356 | |
357 function res = combinechunk_frame(old,new,d2,fri) | |
358 if isempty(mirgetdata(new)) | |
359 res = old; | |
360 return | |
361 end | |
362 if isstruct(old) | |
363 f = fields(old); | |
364 for i = 1:length(f) | |
365 res.(f{i}) = combinechunk_frame(old.(f{i}),new.(f{i}),d2,fri); | |
366 end | |
367 return | |
368 end | |
369 if fri == 1 | |
370 res = new; | |
371 elseif isfield(d2,'specif') && isfield(d2.specif,'combineframes') | |
372 res = d2.specif.combineframes(old{1},new{1}); | |
373 else | |
374 res = combineframes(old,new); | |
375 end | |
376 | |
377 | |
378 function res = combinechunk_noframe(old,new,sg,i,d2,chunks,single) | |
379 if isempty(new) | |
380 res = {}; | |
381 return | |
382 end | |
383 if isempty(mirgetdata(new)) | |
384 res = old; | |
385 return | |
386 end | |
387 if not(iscell(new)) | |
388 new = {new}; | |
389 end | |
390 if not(iscell(old)) | |
391 old = {old}; | |
392 end | |
393 if not(isempty(old)) && isstruct(old{1}) | |
394 f = fields(old{1}); | |
395 for j = 1:length(f) | |
396 index.type = '.'; | |
397 index.subs = f{j}; | |
398 res.(f{j}) = combinechunk_noframe(old{1}.(f{j}),new{1}.(f{j}),... | |
399 sg,i,subsref(d2,index),chunks,single); | |
400 end | |
401 return | |
402 end | |
403 if ischar(single) && not(isempty(old)) | |
404 old = {old{1}}; | |
405 end | |
406 if isempty(sg) | |
407 if isaverage(d2.specif) | |
408 % Measure total size for later averaging | |
409 if iscell(new) | |
410 new1 = new{1}; | |
411 else | |
412 new1 = new; | |
413 end | |
414 dnew = get(new1,'Data'); | |
415 dnew = mircompute(@multweight,dnew,chunks(2,i)-chunks(1,i)+1); | |
416 if iscell(new) | |
417 new{1} = set(new1,'Data',dnew); | |
418 else | |
419 new = set(new1,'Data',dnew); | |
420 end | |
421 end | |
422 %tmp = get(new{1},'InterChunk'); | |
423 if not(isempty(d2.tmpfile)) && d2.tmpfile.fid > 0 | |
424 % If temporary file is used, chunk results are written | |
425 % in the file | |
426 if i < size(chunks,2) | |
427 ds = get(new{1},'Data'); | |
428 ps = get(new{1},'Pos'); | |
429 % ftell(d2.tmpfile.fid) | |
430 count = fwrite(d2.tmpfile.fid,ds{1}{1},'double'); | |
431 count = fwrite(d2.tmpfile.fid,ps{1}{1},'double'); | |
432 % ftell(d2.tmpfile.fid) | |
433 clear ds ps | |
434 end | |
435 res = new; | |
436 else | |
437 % Else, chunk results are directly combined in active | |
438 % memory | |
439 if i == 1 | |
440 res = new; | |
441 else | |
442 if isfield(d2.specif,'combinechunk') | |
443 if not(iscell(d2.specif.combinechunk)) | |
444 method = {d2.specif.combinechunk}; | |
445 else | |
446 method = d2.specif.combinechunk; | |
447 end | |
448 for z = 1:length(old) | |
449 if isframed(old{z}) | |
450 res(z) = combineframes(old{z},new{z}); | |
451 elseif ischar(method{z}) | |
452 if strcmpi(method{z},'Concat') | |
453 res{z} = concatchunk(old{z},new{z},d2.ascending); | |
454 elseif strcmpi(method{z},'Average') | |
455 res{z} = sumchunk(old{z},new{z}); | |
456 else | |
457 error(['SYNTAX ERROR: ',... | |
458 method{z},... | |
459 ' is not a known keyword for combinechunk.']); | |
460 end | |
461 else | |
462 res{z} = method{z}(old{z},new{z}); | |
463 end | |
464 end | |
465 else | |
466 for z = 1:length(old) | |
467 if isframed(old{z}) | |
468 res(z) = combineframes(old{z},new{z}); | |
469 else | |
470 mirerror('MIREVAL','Chunk recombination in non-framed mode is not available for all features yet. Please turn off the chunk decomposition.'); | |
471 end | |
472 end | |
473 end | |
474 end | |
475 end | |
476 else | |
477 if i == 1 | |
478 res = new; | |
479 else | |
480 for z = 1:length(old) | |
481 res{z} = combinesegment(old{z},new{z}); | |
482 end | |
483 end | |
484 end | |
485 | |
486 | |
487 function res = afterchunk_noframe(input,lsz,d,afterpostoption,d2) | |
488 if isstruct(input) | |
489 %mirerror('MIREVAL','Sorry, mirstruct only accepts frame-decomposed objects as ''tmp'' fields.'); | |
490 res = input; | |
491 %f = fields(input); | |
492 %for i = 1:length(f) | |
493 % index.type = '.'; | |
494 % index.subs = f{i}; | |
495 % res.(f{i}) = afterchunk_noframe(input.(f{i}),lsz,... | |
496 % subsref(d,index),afterpostoption,subsref(d2,index)); | |
497 %end | |
498 return | |
499 end | |
500 if isfield(d2.specif,'afterchunk') | |
501 res{1} = d2.specif.afterchunk(input{1},lsz,d.postoption); | |
502 elseif isaverage(d2.specif) | |
503 res{1} = divideweightchunk(input{1},lsz); | |
504 elseif not(isempty(afterpostoption)) && isempty(d2.tmpfile) | |
505 res{1} = d.method(input{1},[],afterpostoption); | |
506 else | |
507 res = input; | |
508 end | |
509 if not(isempty(d2.tmpfile)) | |
510 adr = ftell(d2.tmpfile.fid); | |
511 fclose(d2.tmpfile.fid); | |
512 ytmpfile.fid = fopen('tmpfile.mirtoolbox'); | |
513 fseek(ytmpfile.fid,adr,'bof'); | |
514 ytmpfile.data = input{1}; | |
515 ytmpfile.layer = 0; | |
516 res{1} = set(input{1},'TmpFile',ytmpfile); | |
517 end | |
518 | |
519 | |
520 function old = combineframes(old,new) | |
521 if not(iscell(old)) | |
522 old = {old}; | |
523 end | |
524 if not(iscell(new)) | |
525 new = {new}; | |
526 end | |
527 for var = 1:length(new) | |
528 ov = old{var}; | |
529 nv = new{var}; | |
530 if isa(ov,'mirscalar') | |
531 ov = combinedata(ov,nv,'Data'); | |
532 ov = combinedata(ov,nv,'Mode'); | |
533 if isa(ov,'mirpitch') | |
534 ov = combinedata(ov,nv,'Amplitude'); | |
535 end | |
536 else | |
537 if isa(ov,'mirtemporal') | |
538 [ov omatch nmatch] = combinedata(ov,nv,'Time',[],[],@modiftime); | |
539 else | |
540 [ov omatch nmatch] = combinedata(ov,nv,'Pos',[],[]); | |
541 if isa(ov,'mirspectrum') | |
542 [ov omatch nmatch] = combinedata(ov,nv,'Phase',[],[]); | |
543 end | |
544 end | |
545 ov = combinedata(ov,nv,'Data',omatch,nmatch); | |
546 end | |
547 ov = combinedata(ov,nv,'FramePos'); | |
548 ov = combinedata(ov,nv,'PeakPos'); | |
549 ov = combinedata(ov,nv,'PeakVal'); | |
550 ov = combinedata(ov,nv,'PeakMode'); | |
551 old{var} = ov; | |
552 end | |
553 | |
554 | |
555 function [ov omatch nmatch] = combinedata(ov,nv,key,omatch,nmatch,modifdata) | |
556 if isstruct(ov) | |
557 omatch = []; | |
558 nmatch = []; | |
559 f = fields(ov); | |
560 for i = 1:length(f) | |
561 ov.(f{i}) = combinedata(ov.(f{i}),nv.(f{i}),key); | |
562 end | |
563 return | |
564 end | |
565 odata = get(ov,key); | |
566 if isempty(odata) || isempty(odata{1}) | |
567 return | |
568 end | |
569 odata = odata{1}; | |
570 if iscell(odata) | |
571 if ischar(odata{1}) | |
572 return | |
573 else | |
574 odata = odata{1}; | |
575 end | |
576 end | |
577 ndata = get(nv,key); | |
578 ndata = ndata{1}; | |
579 if iscell(ndata) | |
580 ndata = ndata{1}; | |
581 end | |
582 if nargin>3 | |
583 if isempty(omatch) | |
584 ol = size(odata,1); | |
585 nl = size(ndata,1); | |
586 unmatch = ol-nl; | |
587 if unmatch>0 | |
588 [unused idx] = min(odata(1:1+unmatch,1,1)-ndata(1)); | |
589 omatch = idx:idx+nl-1; | |
590 nmatch = 1:nl; | |
591 elseif unmatch<0 | |
592 [unused idx] = min(ndata(1:1-unmatch,1,1)-odata(1)); | |
593 nmatch = idx:idx+ol-1; | |
594 omatch = 1:ol; | |
595 else | |
596 nmatch = 1:nl; | |
597 omatch = 1:ol; | |
598 end | |
599 end | |
600 odata(omatch,end+1:end+size(ndata,2),:,:) = ndata(nmatch,:,:,:); %4.D for keysom | |
601 else | |
602 odata(:,end+1:end+size(ndata,2),:,:) = ndata; | |
603 end | |
604 ov = set(ov,key,{{odata}}); %{odata} for warped chromagram for instance.... | |
605 | |
606 | |
607 function d = modiftime(d,p) | |
608 d = d + p; | |
609 | |
610 | |
611 function [y d] = evalnow(d) | |
612 % Go one step further in the top-down evaluation initialisation | |
613 argin = d.argin; | |
614 if not(iscell(argin)) | |
615 argin = {argin}; | |
616 end | |
617 for i = 1:length(argin) | |
618 a = argin{i}; | |
619 if not(d.ascending) | |
620 a.ascending = 0; | |
621 end | |
622 if isa(a,'mirdata') | |
623 % Input already computed | |
624 tmpfile = get(a,'TmpFile'); | |
625 if not(isempty(tmpfile)) && tmpfile.fid > 0 | |
626 % The input can be read from the temporary file | |
627 ch = get(d,'Chunk'); | |
628 a = tmpfile.data; | |
629 a = set(a,'InterChunk',get(d,'InterChunk'),'TmpFile',tmpfile); | |
630 channels = get(a,'Channels'); | |
631 channels = length(channels{1}); | |
632 if not(channels) | |
633 channels = 1; | |
634 end | |
635 size = (ch(2)-ch(1)+1); | |
636 current = ftell(tmpfile.fid); | |
637 fseek(tmpfile.fid,current-size*(channels+1)*8,'bof'); | |
638 %ftell(tmpfile.fid) | |
639 [data count] = fread(tmpfile.fid,[size,channels],'double'); | |
640 %count | |
641 data = reshape(data,[size,1,channels]); | |
642 [pos count] = fread(tmpfile.fid,size,'double'); | |
643 %count | |
644 % ftell(tmpfile.fid) | |
645 fseek(tmpfile.fid,current-size*(channels+1)*8,'bof'); | |
646 a = set(a,'Data',{{data}},'Pos',{{pos}}); | |
647 if ch(3) | |
648 fclose(tmpfile.fid); | |
649 delete('tmpfile.mirtoolbox'); | |
650 end | |
651 argin{i} = a; | |
652 end | |
653 elseif isa(a,'mirdesign') | |
654 if isempty(a.stored) | |
655 % The design parameters are transfered to the previous component | |
656 % in the design process | |
657 a.size = d.size; | |
658 a.chunk = d.chunk; | |
659 a.file = d.file; | |
660 a.channel = d.channel; | |
661 a.eval = 1; | |
662 a.interchunk = d.interchunk; | |
663 a.sampling = d.sampling; | |
664 if isstruct(d.frame) && isfield(d.frame,'decomposition') ... | |
665 && not(isempty(d.frame.decomposition)) | |
666 a.chunkdecomposed = 1; | |
667 else | |
668 a.chunkdecomposed = d.chunkdecomposed; | |
669 end | |
670 if not(isempty(d.frame)) && ... | |
671 not(strcmp(func2str(d.method),'mirframe')) | |
672 a.frame = d.frame; | |
673 end | |
674 a.ready = 1; | |
675 a.acrosschunks = d.acrosschunks; | |
676 a.index = d.index; | |
677 argin{i} = a; | |
678 else | |
679 % Variable already calculated | |
680 tmp = get(d,'Struct'); | |
681 if not(isempty(tmp)) | |
682 for j = 1:length(a.stored) % (if modified, modify also mirframe) | |
683 stored = a.stored{j}; | |
684 if iscell(stored) | |
685 if length(stored)>1 | |
686 tmp = tmp{stored{1},stored{2}}; | |
687 else | |
688 tmp = tmp{stored{1}}; | |
689 end | |
690 else | |
691 tmp = getfield(tmp,stored); | |
692 end | |
693 end | |
694 if iscell(tmp) | |
695 tmp = tmp{1}; | |
696 end | |
697 else | |
698 mirerror('evaleach','THERE is a problem..'); | |
699 end | |
700 argin{i} = tmp; | |
701 end | |
702 end | |
703 end | |
704 if not(iscell(d.argin)) | |
705 argin = argin{1}; | |
706 end | |
707 d.option.struct = get(d,'Struct'); | |
708 if iscell(d.postoption) | |
709 [y argin] = d.method(argin,d.option,d.postoption{:}); | |
710 else | |
711 [y argin] = d.method(argin,d.option,d.postoption); | |
712 end | |
713 d = set(d,'Argin',argin); | |
714 if isa(d,'mirstruct') && not(isfield(d.frame,'dontchunk')) && isempty(get(d,'Chunk')) | |
715 y = evalbranches(d,y); | |
716 end | |
717 | |
718 | |
719 function z = evalbranches(d,y) | |
720 % For complex flowcharts, now that the first temporary variable (y) has been | |
721 % computed, the dependent features (d) should be evaluated as well. | |
722 branch = get(d,'Data'); | |
723 | |
724 for i = 1:length(branch) | |
725 if isa(branch{i},'mirdesign') && get(branch{i},'NoChunk') == 1 | |
726 % if the value is 2, it is OK. | |
727 %mirerror('mireval','Flowchart badly designed: mirstruct should not be used if one or several final variables do not accept chunk decomposition.'); | |
728 end | |
729 end | |
730 | |
731 fields = get(d,'Fields'); | |
732 z = struct; | |
733 tmp = get(d,'Tmp'); | |
734 for i = 1:length(branch) | |
735 z.(fields{i}) = evalbranch(branch{i},tmp,y); | |
736 end | |
737 if get(d,'Stat') && isempty(get(d,'Chunk')) | |
738 z = mirstat(z,'FileNames',0); | |
739 end | |
740 | |
741 | |
742 function b = evalbranch(b,d,y) | |
743 % We need to evaluate the branch reaching the current node (b) from the parent | |
744 % corresponding to the temporary variable (d), | |
745 | |
746 if iscell(b) | |
747 mirerror('MIREVAL','Sorry, forked branching of temporary variable cannnot be evaluated in current version of MIRtoolbox.'); | |
748 end | |
749 if isstruct(b) | |
750 % Subtrees are evaluated branch after branch. | |
751 f = fields(b); | |
752 for i = 1:length(f) | |
753 b.(f{i}) = evalbranch(b.(f{i}),d,y); | |
754 end | |
755 return | |
756 end | |
757 if isequal(b,d) | |
758 %% Does it happen ever?? | |
759 b = y; | |
760 return | |
761 end | |
762 if not(isa(b,'mirdesign')) | |
763 mirerror('MIRSTRUCT','In the mirstruct object you defined, the final output should only depend on ''tmp'' variables, and should not therefore reuse the ''Design'' keyword.'); | |
764 end | |
765 v = get(b,'Stored'); | |
766 if length(v)>1 && ischar(v{2}) | |
767 % | |
768 f = fields(d); | |
769 for i = 1:length(f) | |
770 if strcmpi(v{2},f) | |
771 b = y; % OK, now the temporary variable has been found. | |
772 % End of recursion. | |
773 return | |
774 end | |
775 end | |
776 end | |
777 | |
778 argin = evalbranch(get(b,'Argin'),d,y); % Recursion one parent up | |
779 | |
780 % The operation corresponding to the branch from the parent to the node | |
781 % is finally evaluated. | |
782 if iscell(b.postoption) | |
783 b = b.method(argin,b.option,b.postoption{:}); | |
784 else | |
785 b = b.method(argin,b.option,b.postoption); | |
786 end | |
787 | |
788 | |
789 function res = isaverage(specif) | |
790 res = isfield(specif,'combinechunk') && ... | |
791 ((ischar(specif.combinechunk) && ... | |
792 strcmpi(specif.combinechunk,'Average')) || ... | |
793 (iscell(specif.combinechunk) && ... | |
794 ischar(specif.combinechunk{1}) && ... | |
795 strcmpi(specif.combinechunk{1},'Average'))); | |
796 | |
797 | |
798 function d0 = callbeforechunk(d0,d,w,lsz) | |
799 % If necessary, the chunk decomposition is performed a first time for | |
800 % initialisation purposes. | |
801 % Currently used only for miraudio(...,'Normal') | |
802 if not(ischar(d)) && not(iscell(d)) | |
803 specif = d.specif; | |
804 CHUNKLIM = mirchunklim; | |
805 nch = ceil(lsz/CHUNKLIM); | |
806 if isfield(specif,'beforechunk') ... | |
807 && ((isfield(d.option,specif.beforechunk{2}) ... | |
808 && d.option.(specif.beforechunk{2})) ... | |
809 || (isfield(d.postoption,specif.beforechunk{2}) ... | |
810 && d.postoption.(specif.beforechunk{2})) ) | |
811 if mirwaitbar | |
812 h = waitbar(0,['Preparing ' func2str(d.method)]); | |
813 else | |
814 h = 0; | |
815 end | |
816 for i = 1:nch | |
817 disp(['Chunk ',num2str(i),'/',num2str(nch),'...']) | |
818 chbeg = CHUNKLIM*(i-1); | |
819 chend = CHUNKLIM*i-1; | |
820 d2 = set(d,'Size',d0.size,'File',d0.file,... | |
821 'Chunk',[chbeg+w(1) min(chend,lsz-1)+w(1)]); | |
822 d2.method = specif.beforechunk{1}; | |
823 d2.postoption = {chend-lsz}; | |
824 d2.chunkdecomposed = 1; | |
825 [tmp d] = evalnow(d2); | |
826 d0 = set(d0,'AcrossChunks',tmp); | |
827 if h | |
828 waitbar(chend/lsz,h) | |
829 end | |
830 end | |
831 if h | |
832 close(h); | |
833 end | |
834 drawnow | |
835 else | |
836 d0 = callbeforechunk(d0,d.argin,w,lsz); | |
837 end | |
838 end | |
839 | |
840 | |
841 function y = concatchunk(old,new,ascending) | |
842 do = get(old,'Data'); | |
843 dn = get(new,'Data'); | |
844 fpo = get(old,'FramePos'); | |
845 fpn = get(new,'FramePos'); | |
846 if isa(old,'mirscalar') | |
847 y = set(old,'Data',{{[do{1}{1},dn{1}{1}]}},... | |
848 'FramePos',{{[fpo{1}{1},fpn{1}{1}]}}); | |
849 else | |
850 to = get(old,'Pos'); | |
851 tn = get(new,'Pos'); | |
852 if ascending | |
853 y = set(old,'Data',{{[do{1}{1};dn{1}{1}]}},... | |
854 'Pos',{{[to{1}{1};tn{1}{1}]}},... | |
855 'FramePos',{{[fpo{1}{1},fpn{1}{1}]}}); | |
856 else | |
857 y = set(old,'Data',{{[dn{1}{1};do{1}{1}]}},... | |
858 'Pos',{{[tn{1}{1};to{1}{1}]}},... | |
859 'FramePos',{{[fpo{1}{1},fpn{1}{1}]}}); | |
860 end | |
861 end | |
862 | |
863 | |
864 function y = combinesegment(old,new) | |
865 do = get(old,'Data'); | |
866 to = get(old,'Pos'); | |
867 fpo = get(old,'FramePos'); | |
868 ppo = get(old,'PeakPos'); | |
869 pppo = get(old,'PeakPrecisePos'); | |
870 pvo = get(old,'PeakVal'); | |
871 ppvo = get(old,'PeakPreciseVal'); | |
872 pmo = get(old,'PeakMode'); | |
873 apo = get(old,'AttackPos'); | |
874 rpo = get(old,'ReleasePos'); | |
875 tpo = get(old,'TrackPos'); | |
876 tvo = get(old,'TrackVal'); | |
877 | |
878 dn = get(new,'Data'); | |
879 tn = get(new,'Pos'); | |
880 fpn = get(new,'FramePos'); | |
881 ppn = get(new,'PeakPos'); | |
882 pppn = get(new,'PeakPrecisePos'); | |
883 pvn = get(new,'PeakVal'); | |
884 ppvn = get(new,'PeakPreciseVal'); | |
885 pmn = get(new,'PeakMode'); | |
886 apn = get(new,'AttackPos'); | |
887 rpn = get(new,'ReleasePos'); | |
888 tpn = get(new,'TrackPos'); | |
889 tvn = get(new,'TrackVal'); | |
890 | |
891 if not(isempty(do)) | |
892 y = set(old,'Data',{{do{1}{:},dn{1}{:}}}); | |
893 end | |
894 | |
895 y = set(old,'FramePos',{{fpo{1}{:},fpn{1}{:}}}); | |
896 | |
897 if not(isempty(to)) && size(do{1},2) == size(to{1},2) | |
898 y = set(y,'Pos',{{to{1}{:},tn{1}{:}}}); | |
899 end | |
900 | |
901 if not(isempty(ppo)) | |
902 y = set(y,'PeakPos',{{ppo{1}{:},ppn{1}{:}}},... | |
903 'PeakVal',{{pvo{1}{:},pvn{1}{:}}},... | |
904 'PeakMode',{{pmo{1}{:},pmn{1}{:}}}); | |
905 end | |
906 | |
907 if not(isempty(pppn)) | |
908 y = set(y,'PeakPrecisePos',{[pppo{1},pppn{1}{1}]},... | |
909 'PeakPreciseVal',{[ppvo{1},ppvn{1}{1}]}); | |
910 end | |
911 | |
912 if not(isempty(apn)) | |
913 y = set(y,'AttackPos',{[apo{1},apn{1}{1}]}); | |
914 end | |
915 | |
916 if not(isempty(rpn)) | |
917 y = set(y,'ReleasePos',{[rpo{1},rpn{1}{1}]}); | |
918 end | |
919 | |
920 if not(isempty(tpn)) | |
921 y = set(y,'TrackPos',{[tpo{1},tpn{1}{1}]}); | |
922 end | |
923 | |
924 if not(isempty(tvn)) | |
925 y = set(y,'TrackVal',{[tvo{1},tvn{1}{1}]}); | |
926 end | |
927 | |
928 if isa(old,'miremotion') | |
929 deo = get(old,'DimData'); | |
930 ceo = get(old,'ClassData'); | |
931 den = get(new,'DimData'); | |
932 cen = get(new,'ClassData'); | |
933 afo = get(old,'ActivityFactors'); | |
934 vfo = get(old,'ValenceFactors'); | |
935 tfo = get(old,'TensionFactors'); | |
936 hfo = get(old,'HappyFactors'); | |
937 sfo = get(old,'SadFactors'); | |
938 tdo = get(old,'TenderFactors'); | |
939 ago = get(old,'AngerFactors'); | |
940 ffo = get(old,'FearFactors'); | |
941 afn = get(new,'ActivityFactors'); | |
942 vfn = get(new,'ValenceFactors'); | |
943 tfn = get(new,'TensionFactors'); | |
944 hfn = get(new,'HappyFactors'); | |
945 sfn = get(new,'SadFactors'); | |
946 tdn = get(new,'TenderFactors'); | |
947 agn = get(new,'AngerFactors'); | |
948 ffn = get(new,'FearFactors'); | |
949 y = set(y,'DimData',{[deo{1},den{1}{1}]},... | |
950 'ClassData',{[ceo{1},cen{1}{1}]},... | |
951 'ActivityFactors',{[afo{1},afn{1}{1}]},... | |
952 'ValenceFactors',{[vfo{1},vfn{1}{1}]},... | |
953 'TensionFactors',{[tfo{1},tfn{1}{1}]},... | |
954 'HappyFactors',{[hfo{1},hfn{1}{1}]},... | |
955 'SadFactors',{[sfo{1},sfn{1}{1}]},... | |
956 'TenderFactors',{[tdo{1},tdn{1}{1}]},... | |
957 'AngerFactors',{[ago{1},agn{1}{1}]},... | |
958 'FearFactors',{[ffo{1},ffn{1}{1}]}... | |
959 ); | |
960 end | |
961 | |
962 | |
963 function y = sumchunk(old,new,order) | |
964 %do = mirgetdata(old); | |
965 %dn = mirgetdata(new); | |
966 do = get(old,'Data'); | |
967 do = do{1}{1}; | |
968 dn = get(new,'Data'); | |
969 dn = dn{1}{1}; | |
970 y = set(old,'ChunkData',do+dn); | |
971 | |
972 | |
973 function y = divideweightchunk(orig,length) | |
974 d = get(orig,'Data'); | |
975 if isempty(d) | |
976 y = orig; | |
977 else | |
978 v = mircompute(@divideweight,d,length); | |
979 y = set(orig,'Data',v); | |
980 end | |
981 | |
982 function e = multweight(d,length) | |
983 e = d*length; | |
984 | |
985 function e = divideweight(d,length) | |
986 e = d/length; |