Code covered by the BSD License  

Highlights from
MIRtoolbox

image thumbnail
from MIRtoolbox by Olivier Lartillot
An innovative environment, on top of Matlab, for music and audio analysis

mirframe(x,varargin)
function [f x] = mirframe(x,varargin)
%   f = mirframe(x) creates the frame decomposition of the audio signal x.
%       (x can be a file name as well.)
%   Optional arguments:
%       mirframe(x,'Length',w,wu):
%           w is the length of the window in seconds (default: .05 seconds)
%           u is the unit, either 
%               's' (seconds, default unit) 
%            or 'sp' (number of samples)
%       mirframe(x,'Hop',h,hu):
%           h is the hop factor, or distance between successive frames
%               (default: half overlapping: each frame begins at the middle
%                   of the previous frame)
%           u is the unit, either 
%               '/1' (ratio with respect to the frame length, default unit)
%               '%' (ratio as percentage)
%               's' (seconds)
%               'sp' (number of samples)
%            or 'Hz' (hertz), i.e., number of frames per second: the
%                   exactness of the frame rate is ensured and may cause a
%                   slight fluctuation of the elementary hop distances.
%       These arguments can also be written as follows:
%           mirframe(x,w,wu,h,hu)
%               (where some of these parameters can be omitted).

if isempty(x)
    f = {};
    return
end
if iscell(x)
    x = x{1};
end
if nargin == 0
    f = miraudio;
elseif isa(x,'mirdesign')
    if not(get(x,'Eval'))
        % During bottom-up construction of the general design
        
        para = scanargin(varargin);
        type = get(x,'Type');
        f = mirdesign(@mirframe,x,para,{},struct,type);
        
        fl = get(x,'FrameLength');
        fh = get(x,'FrameHop');
        flu = get(x,'FrameLengthUnit');
        fhu = get(x,'FrameHopUnit');
        if fl
            f = set(f,'FrameLength',fl,'FrameLengthUnit',flu,...
                      'FrameHop',fh,'FrameHopUnit',fhu);
        else
            f = set(f,'FrameLength',para.wlength.val,...
                      'FrameLengthUnit',para.wlength.unit,...
                      'FrameHop',para.hop.val,...
                      'FrameHopUnit',para.hop.unit);
        end
        f = set(f,'FrameEval',1,...
                  'SeparateChannels',get(x,'SeparateChannels'));
        if not(isamir(x,'miraudio'))
            f = set(f,'NoChunk',1);
        end
    else
        % During top-down evaluation initiation
        
        if isstruct(varargin{1}) && isfield(varargin{1},'struct')
            tmp = varargin{1}.struct;
            x = set(x,'Struct',tmp);
            varargin{1} = rmfield(varargin{1},'struct');
        end
        e = evaleach(x);
        if iscell(e)
            e = e{1};
        end
        if isempty(mirgetdata(e))
            f = e;
        else
            sc = get(x,'Scale');
            if ~isempty(sc)
                varargin{1}.wlength.val = varargin{1}.wlength.val(sc);
                if length(varargin{1}.hop.val)>1
                    varargin{1}.hop.val = varargin{1}.hop.val(sc);
                end
            end
            f = mirframe(e,varargin{:});
        end
    end
elseif isa(x,'mirdata')
    if isframed(x)
        warning('WARNING IN MIRFRAME: The input data is already decomposed into frames. No more frame decomposition.');
        f = x;
    else
        x = purgedata(x);
        dx = get(x,'Data');
        if isa(x,'mirtemporal')
            dt = get(x,'Time');
        else
            dt = get(x,'FramePos');
        end
        sf = get(x,'Sampling');
        para = scanargin(varargin);
        dx2 = cell(1,length(dx));   % magnitude in framed structure 
        dt2 = cell(1,length(dx));   % time positions in framed structure
        fp = cell(1,length(dx));    % frame positions
        for k = 1:length(dx)    % For each audio file, ...
            dxk = dx{k};
            dtk = dt{k};
            if strcmpi(para.wlength.unit,'s')
                l = para.wlength.val*sf{k};
            elseif strcmpi(para.wlength.unit,'sp')
                l = para.wlength.val;
            end
            if strcmpi(para.hop.unit,'/1')
                h = para.hop.val*l;
            elseif strcmpi(para.hop.unit,'%')
                h = para.hop.val*l*.01;
            elseif strcmpi(para.hop.unit,'s')
                h = para.hop.val*sf{k};
            elseif strcmpi(para.hop.unit,'sp')
                h = para.hop.val;
            elseif strcmpi(para.hop.unit,'Hz')
                h = sf{k}/para.hop.val;
            end
            l = floor(l);
            dx2k = cell(1,length(dxk));
            dt2k = cell(1,length(dxk));
            fpk = cell(1,length(dxk));
            if size(l)==1
                for j = 1:length(dxk)   % For each segment, ...
                    dxj = dxk{j};
                    dtj = dtk{j};
                    if not(isa(x,'mirtemporal'))
                        dxj = dxj';
                        dtj = dtj(1,:)';
                    end

                    n = floor((size(dxj,1)-l)/h)+1; % Number of frames
                    dx2j = zeros(l,n,size(dxj,3));
                    dt2j = zeros(l,n);
                    fpj = zeros(2,n);
                    if n < 1
                        disp('Frame length longer than total sequence size. No frame decomposition.');
                        dx2j = dxj(:,1,:);
                        dt2j = dtj;
                        fpj = [dtj(1) ; dtj(end)];
                    else
                        for i = 1:n % For each frame, ...
                            st = floor((i-1)*h+1);
                            stend = st+l-1;
                            dx2j(:,i,:) = dxj(st:stend,1,:);
                            dt2j(:,i) = dtj(st:stend);
                            fpj(:,i) = [dtj(st) dtj(stend)];
                        end
                    end
                    dx2k{j} = dx2j;
                    dt2k{j} = dt2j;
                    fpk{j} = fpj;
                end
                dx2{k} = dx2k;
                dt2{k} = dt2k;
                fp{k} = fpk;
            else % Multi-scale version
                if size(h) == 1
                    h = repmat(h,size(l));
                end
                for j = 1:length(l)   % For each scale, ...
                    dxj = dxk{1};
                    dtj = dtk{1};
                    if not(isa(x,'mirtemporal'))
                        dxj = dxj';
                        dtj = dtj(1,:)';
                    end

                    n = floor((size(dxj,1)-l(j))/h(j))+1; % Number of frames
                    dx2j = zeros(l(j),n,size(dxj,3));
                    dt2j = zeros(l(j),n);
                    fpj = zeros(2,n);
                    if n < 1
                        disp('Frame length longer than total sequence size. No frame decomposition.');
                        dx2j = dxj(:,1,:);
                        dt2j = dtj;
                        fpj = [dtj(1) ; dtj(end)];
                    else
                        for i = 1:n % For each frame, ...
                            st = floor((i-1)*h(j)+1);
                            stend = st+l(j)-1;
                            dx2j(:,i,:) = dxj(st:stend,1,:);
                            dt2j(:,i) = dtj(st:stend);
                            fpj(:,i) = [dtj(st) dtj(stend)];
                        end
                    end
                    dx2k{j} = dx2j;
                    dt2k{j} = dt2j;
                    fpk{j} = fpj;
                end
                dx2{k} = dx2k;
                dt2{k} = dt2k;
                fp{k} = fpk;
            end
        end
        if isa(x,'mirtemporal')
            f = set(x,'Time',dt2,'Data',dx2,'FramePos',fp);
        else
            f = mirtemporal([],'Time',dt2,'Data',dx2,'FramePos',fp,...
                    'Sampling',get(x,'Sampling'),'Name',get(x,'Name'),...
                    'Label',get(x,'Label'),'Channels',get(x,'Channels'),...
                    'Centered',0,'Title',get(x,'Title'));
        end
    end
else
    f = mirframe(miraudio(x),varargin{:});
end


function para = scanargin(v)
if not(isempty(v)) && isstruct(v{1})
    if length(v) == 1
        para = v{1};
    else
        para.wlength = v{1};
        para.hop = v{2};
    end
    return
end
para.wlength.val = 0.05;
para.wlength.unit = 's';
para.hop.val = 0.5;
para.hop.unit = '/1';
nv = length(v);
i = 1;
j = 1;
while i <= nv
    arg = v{i};
    if strcmpi(arg,'WinLength') || strcmpi(arg,'Length')
        if i < nv && isnumeric(v{i+1})
            i = i+1;
            j = 0;
            para.wlength.val = v{i};
        else
            error('ERROR IN MIRFRAME: Incorrect use of Length option. See help mirframe.'); 
        end
        if i < nv && ischar(v{i+1}) && ...
                (strcmpi(v{i+1},'s') || strcmpi(v{i+1},'sp'))
            i = i+1;
            para.wlength.unit = v{i};
        end
    elseif strcmpi(arg,'Hop')
        if i < nv && isnumeric(v{i+1})
            i = i+1;
            j = 0;
            para.hop.val = v{i};
        else
            error('ERROR IN MIRFRAME: Incorrect use of Hop option. See help mirframe.'); 
        end
        if i < nv && ischar(v{i+1}) && ...
                (strcmpi(v{i+1},'%') || strcmpi(v{i+1},'/1') || ...
                 strcmpi(v{i+1},'s') || strcmpi(v{i+1},'sp') || ...
                 strcmpi(v{i+1},'Hz'))
            i = i+1;
            para.hop.unit = v{i};
        end
    elseif isnumeric(arg)
        switch j
            case 1
                j = 2;
                para.wlength.val = arg;
                if i < nv && ischar(v{i+1}) && ...
                        (strcmpi(v{i+1},'s') || strcmpi(v{i+1},'sp'))
                    i = i+1;
                    para.wlength.unit = v{i};
                end
            case 2
                j = 3;
                para.hop.val = arg;
                if i < nv && ischar(v{i+1}) && ...
                        (strcmpi(v{i+1},'%') || strcmpi(v{i+1},'/1') || ...
                         strcmpi(v{i+1},'s') || strcmpi(v{i+1},'sp') || ...
                         strcmpi(v{i+1},'Hz'))
                    i = i+1;
                    para.hop.unit = v{i};
                end
            otherwise
                error('ERROR IN MIRFRAME: Syntax error. See help mirframe.');
        end
    elseif not(isempty(arg))
        error('ERROR IN MIRFRAME: Syntax error. See help mirframe.');
    end
    i = i+1;
end

Contact us at files@mathworks.com