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