Daniel@0: function [f x] = mirframe(x,varargin) Daniel@0: % f = mirframe(x) creates the frame decomposition of the audio signal x. Daniel@0: % (x can be a file name as well.) Daniel@0: % Optional arguments: Daniel@0: % mirframe(x,'Length',w,wu): Daniel@0: % w is the length of the window in seconds (default: .05 seconds) Daniel@0: % u is the unit, either Daniel@0: % 's' (seconds, default unit) Daniel@0: % or 'sp' (number of samples) Daniel@0: % mirframe(x,'Hop',h,hu): Daniel@0: % h is the hop factor, or distance between successive frames Daniel@0: % (default: half overlapping: each frame begins at the middle Daniel@0: % of the previous frame) Daniel@0: % u is the unit, either Daniel@0: % '/1' (ratio with respect to the frame length, default unit) Daniel@0: % '%' (ratio as percentage) Daniel@0: % 's' (seconds) Daniel@0: % 'sp' (number of samples) Daniel@0: % or 'Hz' (hertz), i.e., number of frames per second: the Daniel@0: % exactness of the frame rate is ensured and may cause a Daniel@0: % slight fluctuation of the elementary hop distances. Daniel@0: % These arguments can also be written as follows: Daniel@0: % mirframe(x,w,wu,h,hu) Daniel@0: % (where some of these parameters can be omitted). Daniel@0: Daniel@0: if isempty(x) Daniel@0: f = {}; Daniel@0: return Daniel@0: end Daniel@0: if iscell(x) Daniel@0: x = x{1}; Daniel@0: end Daniel@0: if nargin == 0 Daniel@0: f = miraudio; Daniel@0: elseif isa(x,'mirdesign') Daniel@0: if not(get(x,'Eval')) Daniel@0: % During bottom-up construction of the general design Daniel@0: Daniel@0: para = scanargin(varargin); Daniel@0: type = get(x,'Type'); Daniel@0: f = mirdesign(@mirframe,x,para,{},struct,type); Daniel@0: Daniel@0: fl = get(x,'FrameLength'); Daniel@0: fh = get(x,'FrameHop'); Daniel@0: flu = get(x,'FrameLengthUnit'); Daniel@0: fhu = get(x,'FrameHopUnit'); Daniel@0: if fl Daniel@0: f = set(f,'FrameLength',fl,'FrameLengthUnit',flu,... Daniel@0: 'FrameHop',fh,'FrameHopUnit',fhu); Daniel@0: else Daniel@0: f = set(f,'FrameLength',para.wlength.val,... Daniel@0: 'FrameLengthUnit',para.wlength.unit,... Daniel@0: 'FrameHop',para.hop.val,... Daniel@0: 'FrameHopUnit',para.hop.unit); Daniel@0: end Daniel@0: f = set(f,'FrameEval',1,... Daniel@0: 'SeparateChannels',get(x,'SeparateChannels')); Daniel@0: if not(isamir(x,'miraudio')) Daniel@0: f = set(f,'NoChunk',1); Daniel@0: end Daniel@0: else Daniel@0: % During top-down evaluation initiation Daniel@0: Daniel@0: if isstruct(varargin{1}) && isfield(varargin{1},'struct') Daniel@0: tmp = varargin{1}.struct; Daniel@0: x = set(x,'Struct',tmp); Daniel@0: varargin{1} = rmfield(varargin{1},'struct'); Daniel@0: end Daniel@0: e = evaleach(x); Daniel@0: if iscell(e) Daniel@0: e = e{1}; Daniel@0: end Daniel@0: if isempty(mirgetdata(e)) Daniel@0: f = e; Daniel@0: else Daniel@0: f = mirframe(e,varargin{:}); Daniel@0: end Daniel@0: end Daniel@0: elseif isa(x,'mirdata') Daniel@0: if isframed(x) Daniel@0: warning('WARNING IN MIRFRAME: The input data is already decomposed into frames. No more frame decomposition.'); Daniel@0: f = x; Daniel@0: else Daniel@0: x = purgedata(x); Daniel@0: dx = get(x,'Data'); Daniel@0: if isa(x,'mirtemporal') Daniel@0: dt = get(x,'Time'); Daniel@0: else Daniel@0: dt = get(x,'FramePos'); Daniel@0: end Daniel@0: sf = get(x,'Sampling'); Daniel@0: para = scanargin(varargin); Daniel@0: dx2 = cell(1,length(dx)); % magnitude in framed structure Daniel@0: dt2 = cell(1,length(dx)); % time positions in framed structure Daniel@0: fp = cell(1,length(dx)); % frame positions Daniel@0: for k = 1:length(dx) % For each audio file, ... Daniel@0: dxk = dx{k}; Daniel@0: dtk = dt{k}; Daniel@0: if strcmpi(para.wlength.unit,'s') Daniel@0: l = para.wlength.val*sf{k}; Daniel@0: elseif strcmpi(para.wlength.unit,'sp') Daniel@0: l = para.wlength.val; Daniel@0: end Daniel@0: if strcmpi(para.hop.unit,'/1') Daniel@0: h = para.hop.val*l; Daniel@0: elseif strcmpi(para.hop.unit,'%') Daniel@0: h = para.hop.val*l*.01; Daniel@0: elseif strcmpi(para.hop.unit,'s') Daniel@0: h = para.hop.val*sf{k}; Daniel@0: elseif strcmpi(para.hop.unit,'sp') Daniel@0: h = para.hop.val; Daniel@0: elseif strcmpi(para.hop.unit,'Hz') Daniel@0: h = sf{k}/para.hop.val; Daniel@0: end Daniel@0: l = floor(l); Daniel@0: dx2k = cell(1,length(dxk)); Daniel@0: dt2k = cell(1,length(dxk)); Daniel@0: fpk = cell(1,length(dxk)); Daniel@0: for j = 1:length(dxk) % For each segment, ... Daniel@0: dxj = dxk{j}; Daniel@0: dtj = dtk{j}; Daniel@0: if not(isa(x,'mirtemporal')) Daniel@0: dxj = dxj'; Daniel@0: dtj = dtj(1,:)'; Daniel@0: end Daniel@0: Daniel@0: n = floor((size(dxj,1)-l)/h)+1; % Number of frames Daniel@0: dx2j = zeros(l,n,size(dxj,3)); Daniel@0: dt2j = zeros(l,n); Daniel@0: fpj = zeros(2,n); Daniel@0: if n < 1 Daniel@0: disp('Frame length longer than total sequence size. No frame decomposition.'); Daniel@0: dx2j = dxj(:,1,:); Daniel@0: dt2j = dtj; Daniel@0: fpj = [dtj(1) ; dtj(end)]; Daniel@0: else Daniel@0: for i = 1:n % For each frame, ... Daniel@0: st = floor((i-1)*h+1); Daniel@0: stend = st+l-1; Daniel@0: dx2j(:,i,:) = dxj(st:stend,1,:); Daniel@0: dt2j(:,i) = dtj(st:stend); Daniel@0: fpj(:,i) = [dtj(st) dtj(stend)]; Daniel@0: end Daniel@0: end Daniel@0: dx2k{j} = dx2j; Daniel@0: dt2k{j} = dt2j; Daniel@0: fpk{j} = fpj; Daniel@0: end Daniel@0: dx2{k} = dx2k; Daniel@0: dt2{k} = dt2k; Daniel@0: fp{k} = fpk; Daniel@0: end Daniel@0: if isa(x,'mirtemporal') Daniel@0: f = set(x,'Time',dt2,'Data',dx2,'FramePos',fp); Daniel@0: else Daniel@0: f = mirtemporal([],'Time',dt2,'Data',dx2,'FramePos',fp,... Daniel@0: 'Sampling',get(x,'Sampling'),'Name',get(x,'Name'),... Daniel@0: 'Label',get(x,'Label'),'Channels',get(x,'Channels'),... Daniel@0: 'Centered',0,'Title',get(x,'Title')); Daniel@0: end Daniel@0: end Daniel@0: else Daniel@0: f = mirframe(miraudio(x),varargin{:}); Daniel@0: end Daniel@0: Daniel@0: Daniel@0: function para = scanargin(v) Daniel@0: if not(isempty(v)) && isstruct(v{1}) Daniel@0: if length(v) == 1 Daniel@0: para = v{1}; Daniel@0: else Daniel@0: para.wlength = v{1}; Daniel@0: para.hop = v{2}; Daniel@0: end Daniel@0: return Daniel@0: end Daniel@0: para.wlength.val = 0.05; Daniel@0: para.wlength.unit = 's'; Daniel@0: para.hop.val = 0.5; Daniel@0: para.hop.unit = '/1'; Daniel@0: nv = length(v); Daniel@0: i = 1; Daniel@0: j = 1; Daniel@0: while i <= nv Daniel@0: arg = v{i}; Daniel@0: if strcmpi(arg,'WinLength') || strcmpi(arg,'Length') Daniel@0: if i < nv && isnumeric(v{i+1}) Daniel@0: i = i+1; Daniel@0: j = 0; Daniel@0: para.wlength.val = v{i}; Daniel@0: else Daniel@0: error('ERROR IN MIRFRAME: Incorrect use of Length option. See help mirframe.'); Daniel@0: end Daniel@0: if i < nv && ischar(v{i+1}) && ... Daniel@0: (strcmpi(v{i+1},'s') || strcmpi(v{i+1},'sp')) Daniel@0: i = i+1; Daniel@0: para.wlength.unit = v{i}; Daniel@0: end Daniel@0: elseif strcmpi(arg,'Hop') Daniel@0: if i < nv && isnumeric(v{i+1}) Daniel@0: i = i+1; Daniel@0: j = 0; Daniel@0: para.hop.val = v{i}; Daniel@0: else Daniel@0: error('ERROR IN MIRFRAME: Incorrect use of Hop option. See help mirframe.'); Daniel@0: end Daniel@0: if i < nv && ischar(v{i+1}) && ... Daniel@0: (strcmpi(v{i+1},'%') || strcmpi(v{i+1},'/1') || ... Daniel@0: strcmpi(v{i+1},'s') || strcmpi(v{i+1},'sp') || ... Daniel@0: strcmpi(v{i+1},'Hz')) Daniel@0: i = i+1; Daniel@0: para.hop.unit = v{i}; Daniel@0: end Daniel@0: elseif isnumeric(arg) Daniel@0: switch j Daniel@0: case 1 Daniel@0: j = 2; Daniel@0: para.wlength.val = arg; Daniel@0: if i < nv && ischar(v{i+1}) && ... Daniel@0: (strcmpi(v{i+1},'s') || strcmpi(v{i+1},'sp')) Daniel@0: i = i+1; Daniel@0: para.wlength.unit = v{i}; Daniel@0: end Daniel@0: case 2 Daniel@0: j = 3; Daniel@0: para.hop.val = arg; Daniel@0: if i < nv && ischar(v{i+1}) && ... Daniel@0: (strcmpi(v{i+1},'%') || strcmpi(v{i+1},'/1') || ... Daniel@0: strcmpi(v{i+1},'s') || strcmpi(v{i+1},'sp') || ... Daniel@0: strcmpi(v{i+1},'Hz')) Daniel@0: i = i+1; Daniel@0: para.hop.unit = v{i}; Daniel@0: end Daniel@0: otherwise Daniel@0: error('ERROR IN MIRFRAME: Syntax error. See help mirframe.'); Daniel@0: end Daniel@0: elseif not(isempty(arg)) Daniel@0: error('ERROR IN MIRFRAME: Syntax error. See help mirframe.'); Daniel@0: end Daniel@0: i = i+1; Daniel@0: end