wolffd@0: function [y d2] = evaleach(d,single,name) wolffd@0: % Top-down traversal of the design flowchart, at the beginning of the wolffd@0: % evaluation phase. wolffd@0: % Called by mirfunction, mireval, mirframe and mirsegment. wolffd@0: % This is during that traversal that we check whether a chunk decomposition wolffd@0: % needs to be performed or not, and carry out that chunk decomposition. wolffd@0: wolffd@0: if nargin<3 || isempty(name) wolffd@0: if not(ischar(d.method)) wolffd@0: name = func2str(d.method); wolffd@0: end wolffd@0: end wolffd@0: if nargin<2 wolffd@0: single = 0; wolffd@0: end wolffd@0: wolffd@0: CHUNKLIM = mirchunklim; wolffd@0: f = d.file; wolffd@0: fr = d.frame; wolffd@0: frnochunk = isfield(d.frame,'dontchunk'); wolffd@0: frchunkbefore = isfield(d.frame,'chunkbefore'); wolffd@0: sg = d.segment; wolffd@0: sr = d.sampling; wolffd@0: sr2 = d.resampling; wolffd@0: w = d.size; wolffd@0: lsz = w(2)-w(1)+1; wolffd@0: len = lsz/sr; wolffd@0: if ischar(sg) wolffd@0: error('ERROR in MIREVAL: mirsegment of design object accepts only array of numbers as second argument.'); wolffd@0: end wolffd@0: if not(isempty(sg)) wolffd@0: over = find(sg(2,:) > len); wolffd@0: if not(isempty(over)) wolffd@0: sg = sg(:,1:over-1); wolffd@0: end wolffd@0: end wolffd@0: a = d.argin; wolffd@0: ch = d.chunk; wolffd@0: chan = d.channel; wolffd@0: specif = d.specif; wolffd@0: if isaverage(specif) wolffd@0: specif.eachchunk = 'Normal'; wolffd@0: end wolffd@0: wolffd@0: if ischar(a) wolffd@0: % The top-down traversal of the design flowchart now reaches the lowest wolffd@0: % layer, i.e., audio file loading. wolffd@0: % Now the actual evaluation will be carried out bottom-up. wolffd@0: wolffd@0: if isempty(ch) wolffd@0: % No chunk decomposition wolffd@0: y = miraudio(f,'Now',[w(:)' 0 chan]); wolffd@0: else wolffd@0: % Chunk decomposition wolffd@0: y = miraudio(f,'Now',[ch(1),ch(2) 0 chan]); wolffd@0: end wolffd@0: if not(isempty(d.postoption)) && d.postoption.mono wolffd@0: y = miraudio(y,'Mono',1); wolffd@0: end wolffd@0: y = set(y,'AcrossChunks',get(d,'AcrossChunks')); wolffd@0: d2 = d; wolffd@0: wolffd@0: elseif d.chunkdecomposed && isempty(d.tmpfile) wolffd@0: % Already in a chunk decomposition process wolffd@0: wolffd@0: [y d2] = evalnow(d); wolffd@0: wolffd@0: elseif isempty(fr) || frnochunk || not(isempty(sg)) %% WHAT ABOUT CHANNELS? wolffd@0: % No frame or segment decomposition in the design to evaluate wolffd@0: % (Or particular frame decomposition, where chunks are not distributed to children (frnochunk).) wolffd@0: wolffd@0: if not(isfield(specif,'eachchunk')) ... wolffd@0: || d.nochunk ... wolffd@0: || (not(isempty(single)) && isnumeric(single) && single > 1 ... wolffd@0: && isfield(specif,'combinechunk') ... wolffd@0: && iscell(specif.combinechunk)) wolffd@0: chunks = []; wolffd@0: elseif not(isempty(sg)) wolffd@0: meth = 'Segment '; wolffd@0: if size(sg,1) == 1 wolffd@0: chunks = floor(sg(1:end-1)*sr)+1; wolffd@0: chunks(2,:) = min( floor(sg(2:end)*sr)-1,lsz-1)+1; wolffd@0: else wolffd@0: chunks = floor(sg*sr); wolffd@0: chunks(1,:) = chunks(1,:)+1; wolffd@0: end wolffd@0: else wolffd@0: meth = 'Chunk '; wolffd@0: if isempty(fr) wolffd@0: if lsz > CHUNKLIM wolffd@0: % The required memory exceed the max memory threshold. wolffd@0: nch = ceil(lsz/CHUNKLIM); wolffd@0: %%% TAKE INTO CONSIDERATION NUMBER OF CHANNELS; ETC... wolffd@0: chunks = max(0,lsz-CHUNKLIM*(nch:-1:1))+w(1); wolffd@0: chunks(2,:) = lsz-CHUNKLIM*(nch-1:-1:0)+w(1)-1; wolffd@0: else wolffd@0: chunks = []; wolffd@0: end wolffd@0: else wolffd@0: chunks = compute_frames(fr,sr,sr2,w,lsz,CHUNKLIM,d.overlap); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: if not(isempty(chunks)) wolffd@0: % The chunk decomposition is performed. wolffd@0: nch = size(chunks,2); wolffd@0: d = callbeforechunk(d,d,w,lsz); % Some optional initialisation wolffd@0: tmp = []; wolffd@0: if mirwaitbar wolffd@0: h = waitbar(0,['Computing ' name]); wolffd@0: else wolffd@0: h = 0; wolffd@0: end wolffd@0: if not(isempty(d.tmpfile)) && d.tmpfile.fid == 0 wolffd@0: % When applicable, a new temporary file is created. wolffd@0: d.tmpfile.fid = fopen('tmpfile.mirtoolbox','w'); wolffd@0: end wolffd@0: tmpfile = []; wolffd@0: if not(d.ascending) wolffd@0: chunks = fliplr(chunks); wolffd@0: end wolffd@0: wolffd@0: afterpostoption = d.postoption; % Used only when: wolffd@0: % - eachchunk is set to 'Normal', wolffd@0: % - combinechunk is not set to 'Average', and wolffd@0: % - no afterchunk field has been specified. wolffd@0: % afterpostoption will be used for the final call wolffd@0: % to the method after the chunk decomposition. wolffd@0: method = d.method; wolffd@0: if ischar(specif.eachchunk) && strcmpi(specif.eachchunk,'Normal') wolffd@0: if not(isempty(d.postoption)) wolffd@0: pof = fieldnames(d.postoption); wolffd@0: for o = 1:length(pof) wolffd@0: if isfield(specif.option.(pof{o}),'chunkcombine') wolffd@0: afterpostoption = rmfield(afterpostoption,pof{o}); wolffd@0: else wolffd@0: d.postoption = rmfield(d.postoption,pof{o}); wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: else wolffd@0: method = specif.eachchunk; wolffd@0: end wolffd@0: wolffd@0: d2 = d; wolffd@0: d2.method = method; wolffd@0: y = {}; wolffd@0: for i = 1:size(chunks,2) wolffd@0: disp([meth,num2str(i),'/',num2str(nch),'...']) wolffd@0: d2 = set(d2,'Chunk',[chunks(1,i) chunks(2,i) (i == size(chunks,2))]); wolffd@0: wolffd@0: if not(ischar(specif.eachchunk) && ... wolffd@0: strcmpi(specif.eachchunk,'Normal')) wolffd@0: if frnochunk wolffd@0: d2.postoption = 0; wolffd@0: else wolffd@0: diffchunks = diff(chunks); % Usual chunk size wolffd@0: d2.postoption = max(diffchunks) - diffchunks(i); wolffd@0: % Reduction of the current chunk size to be taken into wolffd@0: % consideration in mirspectrum, for instance, using wolffd@0: % zeropadding wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: d2 = set(d2,'InterChunk',tmp); wolffd@0: d2.chunkdecomposed = 1; wolffd@0: wolffd@0: [ss d3] = evalnow(d2); wolffd@0: wolffd@0: if iscell(ss) && not(isempty(ss)) wolffd@0: tmp = get(ss{1},'InterChunk'); wolffd@0: elseif isstruct(ss) wolffd@0: tmp = []; wolffd@0: else wolffd@0: tmp = get(ss,'InterChunk'); wolffd@0: end wolffd@0: wolffd@0: % d2 is like d3 except that its argument is now evaluated. wolffd@0: d3.postoption = d.postoption; % Pas joli joli wolffd@0: d3.method = method; wolffd@0: d2 = d3; % This new argument is transfered to d wolffd@0: wolffd@0: y = combinechunk_noframe(y,ss,sg,i,d2,chunks,single); wolffd@0: wolffd@0: clear ss wolffd@0: if h wolffd@0: if not(d.ascending) wolffd@0: close(h) wolffd@0: h = waitbar((chunks(1,i)-chunks(1,end))/chunks(2,1),... wolffd@0: ['Computing ' func2str(d.method) ' (backward)']); wolffd@0: else wolffd@0: waitbar((chunks(2,i)-chunks(1))/chunks(end),h) wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: y = afterchunk_noframe(y,lsz,d,afterpostoption,d2); wolffd@0: % Final operations to be executed after the chunk decomposition wolffd@0: wolffd@0: if isa(d,'mirstruct') && ... wolffd@0: (isempty(d.frame) || isfield(d.frame,'dontchunk')) wolffd@0: y = evalbranches(d,y); wolffd@0: end wolffd@0: if h wolffd@0: close(h) wolffd@0: end wolffd@0: drawnow wolffd@0: wolffd@0: else wolffd@0: % No chunk decomposition wolffd@0: [y d2] = evalnow(d); wolffd@0: if isa(d,'mirstruct') && isfield(d.frame,'dontchunk') wolffd@0: y = evalbranches(d,y); wolffd@0: end wolffd@0: end wolffd@0: elseif d.nochunk wolffd@0: [y d2] = evalnow(d); wolffd@0: else wolffd@0: % Frame decomposition in the design to be evaluated. wolffd@0: chunks = compute_frames(fr,sr,sr2,w,lsz,CHUNKLIM,d.overlap); wolffd@0: if size(chunks,2)>1 wolffd@0: % The chunk decomposition is performed. wolffd@0: if mirwaitbar wolffd@0: h = waitbar(0,['Computing ' name]); wolffd@0: else wolffd@0: h = 0; wolffd@0: end wolffd@0: inter = []; wolffd@0: d = set(d,'FrameDecomposition',1); wolffd@0: d2 = d; wolffd@0: nch = size(chunks,2); wolffd@0: y = {}; wolffd@0: wolffd@0: if frchunkbefore wolffd@0: d2after = d2; wolffd@0: d2.method = d2.argin.method; wolffd@0: d2.option = d2.argin.option; wolffd@0: d2.postoption = d2.argin.postoption; wolffd@0: d2.argin = d2.argin.argin; wolffd@0: end wolffd@0: wolffd@0: for fri = 1:nch % For each chunk... wolffd@0: disp(['Chunk ',num2str(fri),'/',num2str(nch),'...']) wolffd@0: d2 = set(d2,'Chunk',chunks(:,fri)'); wolffd@0: d2 = set(d2,'InterChunk',inter); wolffd@0: %d2.postoption = []; wolffd@0: [res d2] = evalnow(d2); wolffd@0: if not(isempty(res)) wolffd@0: if iscell(res) wolffd@0: inter = get(res{1},'InterChunk'); wolffd@0: elseif not(isstruct(res)) wolffd@0: inter = get(res,'InterChunk'); wolffd@0: res = {res}; wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: y = combinechunk_frame(y,res,d2,fri); wolffd@0: if h wolffd@0: waitbar(chunks(2,fri)/chunks(end),h); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: if frchunkbefore wolffd@0: y = d2after.method(y,d2after.option,d2after.postoption); wolffd@0: end wolffd@0: wolffd@0: if isa(d,'mirstruct') && get(d,'Stat') wolffd@0: y = mirstat(y); wolffd@0: end wolffd@0: if h wolffd@0: close(h) wolffd@0: end wolffd@0: else wolffd@0: % No chunk decomposition wolffd@0: [y d2] = evalnow(d); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: wolffd@0: if iscell(y) wolffd@0: for i = 1:length(y) wolffd@0: if not(isempty(y{i}) || isstruct(y{i})) wolffd@0: if iscell(y{i}) wolffd@0: for j = 1:length(y{i}) wolffd@0: y{i}{j} = set(y{i}{j},'InterChunk',[]); wolffd@0: end wolffd@0: else wolffd@0: y{i} = set(y{i},'InterChunk',[]); wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: wolffd@0: function chunks = compute_frames(fr,sr,sr2,w,lsz,CHUNKLIM,frov) wolffd@0: if strcmpi(fr.length.unit,'s') wolffd@0: fl = fr.length.val*sr; wolffd@0: fl2 = fr.length.val*sr2; wolffd@0: elseif strcmpi(fr.length.unit,'sp') wolffd@0: fl = fr.length.val; wolffd@0: fl2 = fl; wolffd@0: end wolffd@0: if strcmpi(fr.hop.unit,'/1') wolffd@0: h = fr.hop.val*fl; wolffd@0: h2 = fr.hop.val*fl2; wolffd@0: elseif strcmpi(fr.hop.unit,'%') wolffd@0: h = fr.hop.val*fl*.01; wolffd@0: h2 = fr.hop.val*fl2*.01; wolffd@0: elseif strcmpi(fr.hop.unit,'s') wolffd@0: h = fr.hop.val*sr; wolffd@0: h2 = fr.hop.val*sr2; wolffd@0: elseif strcmpi(fr.hop.unit,'sp') wolffd@0: h = fr.hop.val; wolffd@0: h2 = fr.hop.val; wolffd@0: elseif strcmpi(fr.hop.unit,'Hz') wolffd@0: h = sr/fr.hop.val; wolffd@0: h2 = sr2/fr.hop.val; wolffd@0: end wolffd@0: n = floor((lsz-fl)/h)+1; % Number of frames wolffd@0: if n < 1 wolffd@0: %warning('WARNING IN MIRFRAME: Frame length longer than total sequence size. No frame decomposition.'); wolffd@0: fp = w; wolffd@0: fp2 = (w-1)/sr*sr2+1; wolffd@0: else wolffd@0: st = floor(((1:n)-1)*h)+w(1); wolffd@0: st2 = floor(((1:n)-1)*h2)+w(1); wolffd@0: fp = [st; floor(st+fl-1)]; wolffd@0: fp(:,fp(2,:)>w(2)) = []; wolffd@0: fp2 = [st2; floor(st2+fl2-1)]; wolffd@0: fp2(:,fp2(2,:)>(w(2)-w(1))/sr*sr2+w(2)) = []; wolffd@0: end wolffd@0: fpe = (fp2-1)/sr2-(fp-1)/sr; %Rounding error if resampling wolffd@0: fpsz = (fp(2,1)-fp(1,1)) * n; % Total number of samples wolffd@0: fpsz2 = (fp2(2,1)-fp2(1,1)) * n; % Total number of samples wolffd@0: if max(fpsz,fpsz2) > CHUNKLIM wolffd@0: % The required memory exceed the max memory threshold. wolffd@0: nfr = size(fp,2); % Total number of frames wolffd@0: frch = max(ceil(CHUNKLIM/(fp(2,1)-fp(1,1))),2); % Number of frames per chunk wolffd@0: frch = max(frch,frov*2); wolffd@0: [unused cut] = min(abs(fpe(1,frch:-1:1))); wolffd@0: %frch = frch - cut; wolffd@0: % this correspond to the frame with less rounding error wolffd@0: nch = ceil((nfr-frch)/(frch-frov))+1; % Number of chunks wolffd@0: chbeg = (frch-frov)*(0:nch-1)+1; % First frame in the chunk wolffd@0: chend = (frch-frov)*(0:nch-1)+frch; % Last frame in the chunk wolffd@0: chend = min(chend,nfr); wolffd@0: if frov > 1 wolffd@0: chbeg = chend-frch+1; wolffd@0: end wolffd@0: chunks = [fp(1,chbeg) ; fp(2,chend)+1]; % After resampling, one sample may be missing, leading to a complete frame drop. wolffd@0: chunks(end) = min(chunks(end),fp(end)); % Last chunk should not extend beyond audio size. wolffd@0: else wolffd@0: chunks = []; wolffd@0: end wolffd@0: wolffd@0: wolffd@0: function res = combinechunk_frame(old,new,d2,fri) wolffd@0: if isempty(mirgetdata(new)) wolffd@0: res = old; wolffd@0: return wolffd@0: end wolffd@0: if isstruct(old) wolffd@0: f = fields(old); wolffd@0: for i = 1:length(f) wolffd@0: res.(f{i}) = combinechunk_frame(old.(f{i}),new.(f{i}),d2,fri); wolffd@0: end wolffd@0: return wolffd@0: end wolffd@0: if fri == 1 wolffd@0: res = new; wolffd@0: elseif isfield(d2,'specif') && isfield(d2.specif,'combineframes') wolffd@0: res = d2.specif.combineframes(old{1},new{1}); wolffd@0: else wolffd@0: res = combineframes(old,new); wolffd@0: end wolffd@0: wolffd@0: wolffd@0: function res = combinechunk_noframe(old,new,sg,i,d2,chunks,single) wolffd@0: if isempty(new) wolffd@0: res = {}; wolffd@0: return wolffd@0: end wolffd@0: if isempty(mirgetdata(new)) wolffd@0: res = old; wolffd@0: return wolffd@0: end wolffd@0: if not(iscell(new)) wolffd@0: new = {new}; wolffd@0: end wolffd@0: if not(iscell(old)) wolffd@0: old = {old}; wolffd@0: end wolffd@0: if not(isempty(old)) && isstruct(old{1}) wolffd@0: f = fields(old{1}); wolffd@0: for j = 1:length(f) wolffd@0: index.type = '.'; wolffd@0: index.subs = f{j}; wolffd@0: res.(f{j}) = combinechunk_noframe(old{1}.(f{j}),new{1}.(f{j}),... wolffd@0: sg,i,subsref(d2,index),chunks,single); wolffd@0: end wolffd@0: return wolffd@0: end wolffd@0: if ischar(single) && not(isempty(old)) wolffd@0: old = {old{1}}; wolffd@0: end wolffd@0: if isempty(sg) wolffd@0: if isaverage(d2.specif) wolffd@0: % Measure total size for later averaging wolffd@0: if iscell(new) wolffd@0: new1 = new{1}; wolffd@0: else wolffd@0: new1 = new; wolffd@0: end wolffd@0: dnew = get(new1,'Data'); wolffd@0: dnew = mircompute(@multweight,dnew,chunks(2,i)-chunks(1,i)+1); wolffd@0: if iscell(new) wolffd@0: new{1} = set(new1,'Data',dnew); wolffd@0: else wolffd@0: new = set(new1,'Data',dnew); wolffd@0: end wolffd@0: end wolffd@0: %tmp = get(new{1},'InterChunk'); wolffd@0: if not(isempty(d2.tmpfile)) && d2.tmpfile.fid > 0 wolffd@0: % If temporary file is used, chunk results are written wolffd@0: % in the file wolffd@0: if i < size(chunks,2) wolffd@0: ds = get(new{1},'Data'); wolffd@0: ps = get(new{1},'Pos'); wolffd@0: % ftell(d2.tmpfile.fid) wolffd@0: count = fwrite(d2.tmpfile.fid,ds{1}{1},'double'); wolffd@0: count = fwrite(d2.tmpfile.fid,ps{1}{1},'double'); wolffd@0: % ftell(d2.tmpfile.fid) wolffd@0: clear ds ps wolffd@0: end wolffd@0: res = new; wolffd@0: else wolffd@0: % Else, chunk results are directly combined in active wolffd@0: % memory wolffd@0: if i == 1 wolffd@0: res = new; wolffd@0: else wolffd@0: if isfield(d2.specif,'combinechunk') wolffd@0: if not(iscell(d2.specif.combinechunk)) wolffd@0: method = {d2.specif.combinechunk}; wolffd@0: else wolffd@0: method = d2.specif.combinechunk; wolffd@0: end wolffd@0: for z = 1:length(old) wolffd@0: if isframed(old{z}) wolffd@0: res(z) = combineframes(old{z},new{z}); wolffd@0: elseif ischar(method{z}) wolffd@0: if strcmpi(method{z},'Concat') wolffd@0: res{z} = concatchunk(old{z},new{z},d2.ascending); wolffd@0: elseif strcmpi(method{z},'Average') wolffd@0: res{z} = sumchunk(old{z},new{z}); wolffd@0: else wolffd@0: error(['SYNTAX ERROR: ',... wolffd@0: method{z},... wolffd@0: ' is not a known keyword for combinechunk.']); wolffd@0: end wolffd@0: else wolffd@0: res{z} = method{z}(old{z},new{z}); wolffd@0: end wolffd@0: end wolffd@0: else wolffd@0: for z = 1:length(old) wolffd@0: if isframed(old{z}) wolffd@0: res(z) = combineframes(old{z},new{z}); wolffd@0: else wolffd@0: mirerror('MIREVAL','Chunk recombination in non-framed mode is not available for all features yet. Please turn off the chunk decomposition.'); wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: else wolffd@0: if i == 1 wolffd@0: res = new; wolffd@0: else wolffd@0: for z = 1:length(old) wolffd@0: res{z} = combinesegment(old{z},new{z}); wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: wolffd@0: function res = afterchunk_noframe(input,lsz,d,afterpostoption,d2) wolffd@0: if isstruct(input) wolffd@0: %mirerror('MIREVAL','Sorry, mirstruct only accepts frame-decomposed objects as ''tmp'' fields.'); wolffd@0: res = input; wolffd@0: %f = fields(input); wolffd@0: %for i = 1:length(f) wolffd@0: % index.type = '.'; wolffd@0: % index.subs = f{i}; wolffd@0: % res.(f{i}) = afterchunk_noframe(input.(f{i}),lsz,... wolffd@0: % subsref(d,index),afterpostoption,subsref(d2,index)); wolffd@0: %end wolffd@0: return wolffd@0: end wolffd@0: if isfield(d2.specif,'afterchunk') wolffd@0: res{1} = d2.specif.afterchunk(input{1},lsz,d.postoption); wolffd@0: elseif isaverage(d2.specif) wolffd@0: res{1} = divideweightchunk(input{1},lsz); wolffd@0: elseif not(isempty(afterpostoption)) && isempty(d2.tmpfile) wolffd@0: res{1} = d.method(input{1},[],afterpostoption); wolffd@0: else wolffd@0: res = input; wolffd@0: end wolffd@0: if not(isempty(d2.tmpfile)) wolffd@0: adr = ftell(d2.tmpfile.fid); wolffd@0: fclose(d2.tmpfile.fid); wolffd@0: ytmpfile.fid = fopen('tmpfile.mirtoolbox'); wolffd@0: fseek(ytmpfile.fid,adr,'bof'); wolffd@0: ytmpfile.data = input{1}; wolffd@0: ytmpfile.layer = 0; wolffd@0: res{1} = set(input{1},'TmpFile',ytmpfile); wolffd@0: end wolffd@0: wolffd@0: wolffd@0: function old = combineframes(old,new) wolffd@0: if not(iscell(old)) wolffd@0: old = {old}; wolffd@0: end wolffd@0: if not(iscell(new)) wolffd@0: new = {new}; wolffd@0: end wolffd@0: for var = 1:length(new) wolffd@0: ov = old{var}; wolffd@0: nv = new{var}; wolffd@0: if isa(ov,'mirscalar') wolffd@0: ov = combinedata(ov,nv,'Data'); wolffd@0: ov = combinedata(ov,nv,'Mode'); wolffd@0: if isa(ov,'mirpitch') wolffd@0: ov = combinedata(ov,nv,'Amplitude'); wolffd@0: end wolffd@0: else wolffd@0: if isa(ov,'mirtemporal') wolffd@0: [ov omatch nmatch] = combinedata(ov,nv,'Time',[],[],@modiftime); wolffd@0: else wolffd@0: [ov omatch nmatch] = combinedata(ov,nv,'Pos',[],[]); wolffd@0: if isa(ov,'mirspectrum') wolffd@0: [ov omatch nmatch] = combinedata(ov,nv,'Phase',[],[]); wolffd@0: end wolffd@0: end wolffd@0: ov = combinedata(ov,nv,'Data',omatch,nmatch); wolffd@0: end wolffd@0: ov = combinedata(ov,nv,'FramePos'); wolffd@0: ov = combinedata(ov,nv,'PeakPos'); wolffd@0: ov = combinedata(ov,nv,'PeakVal'); wolffd@0: ov = combinedata(ov,nv,'PeakMode'); wolffd@0: old{var} = ov; wolffd@0: end wolffd@0: wolffd@0: wolffd@0: function [ov omatch nmatch] = combinedata(ov,nv,key,omatch,nmatch,modifdata) wolffd@0: if isstruct(ov) wolffd@0: omatch = []; wolffd@0: nmatch = []; wolffd@0: f = fields(ov); wolffd@0: for i = 1:length(f) wolffd@0: ov.(f{i}) = combinedata(ov.(f{i}),nv.(f{i}),key); wolffd@0: end wolffd@0: return wolffd@0: end wolffd@0: odata = get(ov,key); wolffd@0: if isempty(odata) || isempty(odata{1}) wolffd@0: return wolffd@0: end wolffd@0: odata = odata{1}; wolffd@0: if iscell(odata) wolffd@0: if ischar(odata{1}) wolffd@0: return wolffd@0: else wolffd@0: odata = odata{1}; wolffd@0: end wolffd@0: end wolffd@0: ndata = get(nv,key); wolffd@0: ndata = ndata{1}; wolffd@0: if iscell(ndata) wolffd@0: ndata = ndata{1}; wolffd@0: end wolffd@0: if nargin>3 wolffd@0: if isempty(omatch) wolffd@0: ol = size(odata,1); wolffd@0: nl = size(ndata,1); wolffd@0: unmatch = ol-nl; wolffd@0: if unmatch>0 wolffd@0: [unused idx] = min(odata(1:1+unmatch,1,1)-ndata(1)); wolffd@0: omatch = idx:idx+nl-1; wolffd@0: nmatch = 1:nl; wolffd@0: elseif unmatch<0 wolffd@0: [unused idx] = min(ndata(1:1-unmatch,1,1)-odata(1)); wolffd@0: nmatch = idx:idx+ol-1; wolffd@0: omatch = 1:ol; wolffd@0: else wolffd@0: nmatch = 1:nl; wolffd@0: omatch = 1:ol; wolffd@0: end wolffd@0: end wolffd@0: odata(omatch,end+1:end+size(ndata,2),:,:) = ndata(nmatch,:,:,:); %4.D for keysom wolffd@0: else wolffd@0: odata(:,end+1:end+size(ndata,2),:,:) = ndata; wolffd@0: end wolffd@0: ov = set(ov,key,{{odata}}); %{odata} for warped chromagram for instance.... wolffd@0: wolffd@0: wolffd@0: function d = modiftime(d,p) wolffd@0: d = d + p; wolffd@0: wolffd@0: wolffd@0: function [y d] = evalnow(d) wolffd@0: % Go one step further in the top-down evaluation initialisation wolffd@0: argin = d.argin; wolffd@0: if not(iscell(argin)) wolffd@0: argin = {argin}; wolffd@0: end wolffd@0: for i = 1:length(argin) wolffd@0: a = argin{i}; wolffd@0: if not(d.ascending) wolffd@0: a.ascending = 0; wolffd@0: end wolffd@0: if isa(a,'mirdata') wolffd@0: % Input already computed wolffd@0: tmpfile = get(a,'TmpFile'); wolffd@0: if not(isempty(tmpfile)) && tmpfile.fid > 0 wolffd@0: % The input can be read from the temporary file wolffd@0: ch = get(d,'Chunk'); wolffd@0: a = tmpfile.data; wolffd@0: a = set(a,'InterChunk',get(d,'InterChunk'),'TmpFile',tmpfile); wolffd@0: channels = get(a,'Channels'); wolffd@0: channels = length(channels{1}); wolffd@0: if not(channels) wolffd@0: channels = 1; wolffd@0: end wolffd@0: size = (ch(2)-ch(1)+1); wolffd@0: current = ftell(tmpfile.fid); wolffd@0: fseek(tmpfile.fid,current-size*(channels+1)*8,'bof'); wolffd@0: %ftell(tmpfile.fid) wolffd@0: [data count] = fread(tmpfile.fid,[size,channels],'double'); wolffd@0: %count wolffd@0: data = reshape(data,[size,1,channels]); wolffd@0: [pos count] = fread(tmpfile.fid,size,'double'); wolffd@0: %count wolffd@0: % ftell(tmpfile.fid) wolffd@0: fseek(tmpfile.fid,current-size*(channels+1)*8,'bof'); wolffd@0: a = set(a,'Data',{{data}},'Pos',{{pos}}); wolffd@0: if ch(3) wolffd@0: fclose(tmpfile.fid); wolffd@0: delete('tmpfile.mirtoolbox'); wolffd@0: end wolffd@0: argin{i} = a; wolffd@0: end wolffd@0: elseif isa(a,'mirdesign') wolffd@0: if isempty(a.stored) wolffd@0: % The design parameters are transfered to the previous component wolffd@0: % in the design process wolffd@0: a.size = d.size; wolffd@0: a.chunk = d.chunk; wolffd@0: a.file = d.file; wolffd@0: a.channel = d.channel; wolffd@0: a.eval = 1; wolffd@0: a.interchunk = d.interchunk; wolffd@0: a.sampling = d.sampling; wolffd@0: if isstruct(d.frame) && isfield(d.frame,'decomposition') ... wolffd@0: && not(isempty(d.frame.decomposition)) wolffd@0: a.chunkdecomposed = 1; wolffd@0: else wolffd@0: a.chunkdecomposed = d.chunkdecomposed; wolffd@0: end wolffd@0: if not(isempty(d.frame)) && ... wolffd@0: not(strcmp(func2str(d.method),'mirframe')) wolffd@0: a.frame = d.frame; wolffd@0: end wolffd@0: a.ready = 1; wolffd@0: a.acrosschunks = d.acrosschunks; wolffd@0: a.index = d.index; wolffd@0: argin{i} = a; wolffd@0: else wolffd@0: % Variable already calculated wolffd@0: tmp = get(d,'Struct'); wolffd@0: if not(isempty(tmp)) wolffd@0: for j = 1:length(a.stored) % (if modified, modify also mirframe) wolffd@0: stored = a.stored{j}; wolffd@0: if iscell(stored) wolffd@0: if length(stored)>1 wolffd@0: tmp = tmp{stored{1},stored{2}}; wolffd@0: else wolffd@0: tmp = tmp{stored{1}}; wolffd@0: end wolffd@0: else wolffd@0: tmp = getfield(tmp,stored); wolffd@0: end wolffd@0: end wolffd@0: if iscell(tmp) wolffd@0: tmp = tmp{1}; wolffd@0: end wolffd@0: else wolffd@0: mirerror('evaleach','THERE is a problem..'); wolffd@0: end wolffd@0: argin{i} = tmp; wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: if not(iscell(d.argin)) wolffd@0: argin = argin{1}; wolffd@0: end wolffd@0: d.option.struct = get(d,'Struct'); wolffd@0: if iscell(d.postoption) wolffd@0: [y argin] = d.method(argin,d.option,d.postoption{:}); wolffd@0: else wolffd@0: [y argin] = d.method(argin,d.option,d.postoption); wolffd@0: end wolffd@0: d = set(d,'Argin',argin); wolffd@0: if isa(d,'mirstruct') && not(isfield(d.frame,'dontchunk')) && isempty(get(d,'Chunk')) wolffd@0: y = evalbranches(d,y); wolffd@0: end wolffd@0: wolffd@0: wolffd@0: function z = evalbranches(d,y) wolffd@0: % For complex flowcharts, now that the first temporary variable (y) has been wolffd@0: % computed, the dependent features (d) should be evaluated as well. wolffd@0: branch = get(d,'Data'); wolffd@0: wolffd@0: for i = 1:length(branch) wolffd@0: if isa(branch{i},'mirdesign') && get(branch{i},'NoChunk') == 1 wolffd@0: % if the value is 2, it is OK. wolffd@0: %mirerror('mireval','Flowchart badly designed: mirstruct should not be used if one or several final variables do not accept chunk decomposition.'); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: fields = get(d,'Fields'); wolffd@0: z = struct; wolffd@0: tmp = get(d,'Tmp'); wolffd@0: for i = 1:length(branch) wolffd@0: z.(fields{i}) = evalbranch(branch{i},tmp,y); wolffd@0: end wolffd@0: if get(d,'Stat') && isempty(get(d,'Chunk')) wolffd@0: z = mirstat(z,'FileNames',0); wolffd@0: end wolffd@0: wolffd@0: wolffd@0: function b = evalbranch(b,d,y) wolffd@0: % We need to evaluate the branch reaching the current node (b) from the parent wolffd@0: % corresponding to the temporary variable (d), wolffd@0: wolffd@0: if iscell(b) wolffd@0: mirerror('MIREVAL','Sorry, forked branching of temporary variable cannnot be evaluated in current version of MIRtoolbox.'); wolffd@0: end wolffd@0: if isstruct(b) wolffd@0: % Subtrees are evaluated branch after branch. wolffd@0: f = fields(b); wolffd@0: for i = 1:length(f) wolffd@0: b.(f{i}) = evalbranch(b.(f{i}),d,y); wolffd@0: end wolffd@0: return wolffd@0: end wolffd@0: if isequal(b,d) wolffd@0: %% Does it happen ever?? wolffd@0: b = y; wolffd@0: return wolffd@0: end wolffd@0: if not(isa(b,'mirdesign')) wolffd@0: 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.'); wolffd@0: end wolffd@0: v = get(b,'Stored'); wolffd@0: if length(v)>1 && ischar(v{2}) wolffd@0: % wolffd@0: f = fields(d); wolffd@0: for i = 1:length(f) wolffd@0: if strcmpi(v{2},f) wolffd@0: b = y; % OK, now the temporary variable has been found. wolffd@0: % End of recursion. wolffd@0: return wolffd@0: end wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: argin = evalbranch(get(b,'Argin'),d,y); % Recursion one parent up wolffd@0: wolffd@0: % The operation corresponding to the branch from the parent to the node wolffd@0: % is finally evaluated. wolffd@0: if iscell(b.postoption) wolffd@0: b = b.method(argin,b.option,b.postoption{:}); wolffd@0: else wolffd@0: b = b.method(argin,b.option,b.postoption); wolffd@0: end wolffd@0: wolffd@0: wolffd@0: function res = isaverage(specif) wolffd@0: res = isfield(specif,'combinechunk') && ... wolffd@0: ((ischar(specif.combinechunk) && ... wolffd@0: strcmpi(specif.combinechunk,'Average')) || ... wolffd@0: (iscell(specif.combinechunk) && ... wolffd@0: ischar(specif.combinechunk{1}) && ... wolffd@0: strcmpi(specif.combinechunk{1},'Average'))); wolffd@0: wolffd@0: wolffd@0: function d0 = callbeforechunk(d0,d,w,lsz) wolffd@0: % If necessary, the chunk decomposition is performed a first time for wolffd@0: % initialisation purposes. wolffd@0: % Currently used only for miraudio(...,'Normal') wolffd@0: if not(ischar(d)) && not(iscell(d)) wolffd@0: specif = d.specif; wolffd@0: CHUNKLIM = mirchunklim; wolffd@0: nch = ceil(lsz/CHUNKLIM); wolffd@0: if isfield(specif,'beforechunk') ... wolffd@0: && ((isfield(d.option,specif.beforechunk{2}) ... wolffd@0: && d.option.(specif.beforechunk{2})) ... wolffd@0: || (isfield(d.postoption,specif.beforechunk{2}) ... wolffd@0: && d.postoption.(specif.beforechunk{2})) ) wolffd@0: if mirwaitbar wolffd@0: h = waitbar(0,['Preparing ' func2str(d.method)]); wolffd@0: else wolffd@0: h = 0; wolffd@0: end wolffd@0: for i = 1:nch wolffd@0: disp(['Chunk ',num2str(i),'/',num2str(nch),'...']) wolffd@0: chbeg = CHUNKLIM*(i-1); wolffd@0: chend = CHUNKLIM*i-1; wolffd@0: d2 = set(d,'Size',d0.size,'File',d0.file,... wolffd@0: 'Chunk',[chbeg+w(1) min(chend,lsz-1)+w(1)]); wolffd@0: d2.method = specif.beforechunk{1}; wolffd@0: d2.postoption = {chend-lsz}; wolffd@0: d2.chunkdecomposed = 1; wolffd@0: [tmp d] = evalnow(d2); wolffd@0: d0 = set(d0,'AcrossChunks',tmp); wolffd@0: if h wolffd@0: waitbar(chend/lsz,h) wolffd@0: end wolffd@0: end wolffd@0: if h wolffd@0: close(h); wolffd@0: end wolffd@0: drawnow wolffd@0: else wolffd@0: d0 = callbeforechunk(d0,d.argin,w,lsz); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: wolffd@0: function y = concatchunk(old,new,ascending) wolffd@0: do = get(old,'Data'); wolffd@0: dn = get(new,'Data'); wolffd@0: fpo = get(old,'FramePos'); wolffd@0: fpn = get(new,'FramePos'); wolffd@0: if isa(old,'mirscalar') wolffd@0: y = set(old,'Data',{{[do{1}{1},dn{1}{1}]}},... wolffd@0: 'FramePos',{{[fpo{1}{1},fpn{1}{1}]}}); wolffd@0: else wolffd@0: to = get(old,'Pos'); wolffd@0: tn = get(new,'Pos'); wolffd@0: if ascending wolffd@0: y = set(old,'Data',{{[do{1}{1};dn{1}{1}]}},... wolffd@0: 'Pos',{{[to{1}{1};tn{1}{1}]}},... wolffd@0: 'FramePos',{{[fpo{1}{1},fpn{1}{1}]}}); wolffd@0: else wolffd@0: y = set(old,'Data',{{[dn{1}{1};do{1}{1}]}},... wolffd@0: 'Pos',{{[tn{1}{1};to{1}{1}]}},... wolffd@0: 'FramePos',{{[fpo{1}{1},fpn{1}{1}]}}); wolffd@0: end wolffd@0: end wolffd@0: wolffd@0: wolffd@0: function y = combinesegment(old,new) wolffd@0: do = get(old,'Data'); wolffd@0: to = get(old,'Pos'); wolffd@0: fpo = get(old,'FramePos'); wolffd@0: ppo = get(old,'PeakPos'); wolffd@0: pppo = get(old,'PeakPrecisePos'); wolffd@0: pvo = get(old,'PeakVal'); wolffd@0: ppvo = get(old,'PeakPreciseVal'); wolffd@0: pmo = get(old,'PeakMode'); wolffd@0: apo = get(old,'AttackPos'); wolffd@0: rpo = get(old,'ReleasePos'); wolffd@0: tpo = get(old,'TrackPos'); wolffd@0: tvo = get(old,'TrackVal'); wolffd@0: wolffd@0: dn = get(new,'Data'); wolffd@0: tn = get(new,'Pos'); wolffd@0: fpn = get(new,'FramePos'); wolffd@0: ppn = get(new,'PeakPos'); wolffd@0: pppn = get(new,'PeakPrecisePos'); wolffd@0: pvn = get(new,'PeakVal'); wolffd@0: ppvn = get(new,'PeakPreciseVal'); wolffd@0: pmn = get(new,'PeakMode'); wolffd@0: apn = get(new,'AttackPos'); wolffd@0: rpn = get(new,'ReleasePos'); wolffd@0: tpn = get(new,'TrackPos'); wolffd@0: tvn = get(new,'TrackVal'); wolffd@0: wolffd@0: if not(isempty(do)) wolffd@0: y = set(old,'Data',{{do{1}{:},dn{1}{:}}}); wolffd@0: end wolffd@0: wolffd@0: y = set(old,'FramePos',{{fpo{1}{:},fpn{1}{:}}}); wolffd@0: wolffd@0: if not(isempty(to)) && size(do{1},2) == size(to{1},2) wolffd@0: y = set(y,'Pos',{{to{1}{:},tn{1}{:}}}); wolffd@0: end wolffd@0: wolffd@0: if not(isempty(ppo)) wolffd@0: y = set(y,'PeakPos',{{ppo{1}{:},ppn{1}{:}}},... wolffd@0: 'PeakVal',{{pvo{1}{:},pvn{1}{:}}},... wolffd@0: 'PeakMode',{{pmo{1}{:},pmn{1}{:}}}); wolffd@0: end wolffd@0: wolffd@0: if not(isempty(pppn)) wolffd@0: y = set(y,'PeakPrecisePos',{[pppo{1},pppn{1}{1}]},... wolffd@0: 'PeakPreciseVal',{[ppvo{1},ppvn{1}{1}]}); wolffd@0: end wolffd@0: wolffd@0: if not(isempty(apn)) wolffd@0: y = set(y,'AttackPos',{[apo{1},apn{1}{1}]}); wolffd@0: end wolffd@0: wolffd@0: if not(isempty(rpn)) wolffd@0: y = set(y,'ReleasePos',{[rpo{1},rpn{1}{1}]}); wolffd@0: end wolffd@0: wolffd@0: if not(isempty(tpn)) wolffd@0: y = set(y,'TrackPos',{[tpo{1},tpn{1}{1}]}); wolffd@0: end wolffd@0: wolffd@0: if not(isempty(tvn)) wolffd@0: y = set(y,'TrackVal',{[tvo{1},tvn{1}{1}]}); wolffd@0: end wolffd@0: wolffd@0: if isa(old,'miremotion') wolffd@0: deo = get(old,'DimData'); wolffd@0: ceo = get(old,'ClassData'); wolffd@0: den = get(new,'DimData'); wolffd@0: cen = get(new,'ClassData'); wolffd@0: afo = get(old,'ActivityFactors'); wolffd@0: vfo = get(old,'ValenceFactors'); wolffd@0: tfo = get(old,'TensionFactors'); wolffd@0: hfo = get(old,'HappyFactors'); wolffd@0: sfo = get(old,'SadFactors'); wolffd@0: tdo = get(old,'TenderFactors'); wolffd@0: ago = get(old,'AngerFactors'); wolffd@0: ffo = get(old,'FearFactors'); wolffd@0: afn = get(new,'ActivityFactors'); wolffd@0: vfn = get(new,'ValenceFactors'); wolffd@0: tfn = get(new,'TensionFactors'); wolffd@0: hfn = get(new,'HappyFactors'); wolffd@0: sfn = get(new,'SadFactors'); wolffd@0: tdn = get(new,'TenderFactors'); wolffd@0: agn = get(new,'AngerFactors'); wolffd@0: ffn = get(new,'FearFactors'); wolffd@0: y = set(y,'DimData',{[deo{1},den{1}{1}]},... wolffd@0: 'ClassData',{[ceo{1},cen{1}{1}]},... wolffd@0: 'ActivityFactors',{[afo{1},afn{1}{1}]},... wolffd@0: 'ValenceFactors',{[vfo{1},vfn{1}{1}]},... wolffd@0: 'TensionFactors',{[tfo{1},tfn{1}{1}]},... wolffd@0: 'HappyFactors',{[hfo{1},hfn{1}{1}]},... wolffd@0: 'SadFactors',{[sfo{1},sfn{1}{1}]},... wolffd@0: 'TenderFactors',{[tdo{1},tdn{1}{1}]},... wolffd@0: 'AngerFactors',{[ago{1},agn{1}{1}]},... wolffd@0: 'FearFactors',{[ffo{1},ffn{1}{1}]}... wolffd@0: ); wolffd@0: end wolffd@0: wolffd@0: wolffd@0: function y = sumchunk(old,new,order) wolffd@0: %do = mirgetdata(old); wolffd@0: %dn = mirgetdata(new); wolffd@0: do = get(old,'Data'); wolffd@0: do = do{1}{1}; wolffd@0: dn = get(new,'Data'); wolffd@0: dn = dn{1}{1}; wolffd@0: y = set(old,'ChunkData',do+dn); wolffd@0: wolffd@0: wolffd@0: function y = divideweightchunk(orig,length) wolffd@0: d = get(orig,'Data'); wolffd@0: if isempty(d) wolffd@0: y = orig; wolffd@0: else wolffd@0: v = mircompute(@divideweight,d,length); wolffd@0: y = set(orig,'Data',v); wolffd@0: end wolffd@0: wolffd@0: function e = multweight(d,length) wolffd@0: e = d*length; wolffd@0: wolffd@0: function e = divideweight(d,length) wolffd@0: e = d/length;