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;