Daniel@0: function varargout = mirmfcc(orig,varargin) Daniel@0: % c = mirmfcc(a) finds the Mel frequency cepstral coefficients (ceps), Daniel@0: % a numerical description of the spectrum envelope. Daniel@0: % Daniel@0: % Requires the Auditory Toolbox. Daniel@0: % Daniel@0: % Optional arguments: Daniel@0: % c = mirmfcc(...,'Rank',N) computes the coefficients of rank(s) N Daniel@0: % (default: N = 1:13). Daniel@0: % If a is a frame decomposition, the temporal evolution of the MFCC, Daniel@0: % along the successive frames, is returned. In this case, a second Daniel@0: % option is available: Daniel@0: % mirmfcc(...,'Delta',d) performs d temporal differentiations of Daniel@0: % the coefficients, also called delta-MFCC (for d = 1) or Daniel@0: % delta-delta-MFCC (for d = 2). Daniel@0: % mirmfcc(...,'Delta') corresponds to mirmfcc(...,'Delta',1) Daniel@0: % Optional arguments related to the delta computation: Daniel@0: % mirmfcc(...,'Radius',r) specifies, for each frame, the number of Daniel@0: % successive and previous neighbouring frames taken into Daniel@0: % consideration for the least-square approximation. Daniel@0: % Usually 1 or 2. Daniel@0: % Default value: 2. Daniel@0: Daniel@0: nbbands.key = 'Bands'; Daniel@0: nbbands.type = 'Integer'; Daniel@0: nbbands.default = 40; Daniel@0: option.nbbands = nbbands; Daniel@0: Daniel@0: rank.key = 'Rank'; Daniel@0: rank.type = 'Integer'; Daniel@0: rank.default = 1:13; Daniel@0: option.rank = rank; Daniel@0: Daniel@0: delta.key = 'Delta'; Daniel@0: delta.type = 'Integer'; Daniel@0: delta.default = 0; Daniel@0: delta.keydefault = 1; Daniel@0: option.delta = delta; Daniel@0: Daniel@0: radius.key = 'Radius'; Daniel@0: radius.type = 'Integer'; Daniel@0: radius.default = 2; Daniel@0: option.radius = radius; Daniel@0: Daniel@0: specif.option = option; Daniel@0: Daniel@0: varargout = mirfunction(@mirmfcc,orig,varargin,nargout,specif,@init,@main); Daniel@0: Daniel@0: Daniel@0: function [x type] = init(x,option) Daniel@0: if isamir(x,'miraudio') || isamir(x,'mirspectrum') Daniel@0: x = mirspectrum(x,'Mel','log','Bands',option.nbbands); Daniel@0: end Daniel@0: type = 'mirmfcc'; Daniel@0: Daniel@0: Daniel@0: function c = main(orig,option,postoption) Daniel@0: if iscell(orig) Daniel@0: orig = orig{1}; Daniel@0: end Daniel@0: if isa(orig,'mirmfcc') Daniel@0: c = orig; Daniel@0: if option.rank Daniel@0: magn = get(c,'Data'); Daniel@0: rank = get(c,'Rank'); Daniel@0: for h = 1:length(magn) Daniel@0: for k = 1:length(magn{h}) Daniel@0: m = magn{h}{k}; Daniel@0: r = rank{h}{k}; Daniel@0: r1 = r(:,1,1); Daniel@0: range = find(ismember(r1,option.rank)); Daniel@0: magn{h}{k} = m(range,:,:); Daniel@0: rank{h}{k} = r(range,:,:); Daniel@0: end Daniel@0: end Daniel@0: c = set(c,'Data',magn,'Rank',rank); Daniel@0: end Daniel@0: c = modif(c,option); Daniel@0: else Daniel@0: c.delta = 0; Daniel@0: %disp('Computing Mel frequency cepstral coefficients...'); Daniel@0: e = get(orig,'Magnitude'); Daniel@0: Daniel@0: % The following is largely based on the source code from Auditory Toolbox Daniel@0: % (A part that I could not call directly from MIRtoolbox) Daniel@0: Daniel@0: % (Malcolm Slaney, August 1993, (c) 1998 Interval Research Corporation) Daniel@0: Daniel@0: try Daniel@0: MakeERBFilters(1,1,1); % Just to be sure that the Auditory Toolbox is installed Daniel@0: catch Daniel@0: error(['ERROR IN MIRFILTERBANK: Auditory Toolbox needs to be installed.']); Daniel@0: end Daniel@0: Daniel@0: dc = cell(1,length(e)); Daniel@0: rk = cell(1,length(e)); Daniel@0: for h = 1:length(e) Daniel@0: dc{h} = cell(1,length(e{h})); Daniel@0: rk{h} = cell(1,length(e{h})); Daniel@0: for i = 1:length(e{h}) Daniel@0: ei = e{h}{i}; Daniel@0: totalFilters = size(ei,3); %Number of mel bands. Daniel@0: Daniel@0: % Figure out Discrete Cosine Transform. We want a matrix Daniel@0: % dct(i,j) which is totalFilters x cepstralCoefficients in size. Daniel@0: % The i,j component is given by Daniel@0: % cos( i * (j+0.5)/totalFilters pi ) Daniel@0: % where we have assumed that i and j start at 0. Daniel@0: mfccDCTMatrix = 1/sqrt(totalFilters/2)*... Daniel@0: cos(option.rank' * ... Daniel@0: (2*(0:(totalFilters-1))+1) * ... Daniel@0: pi/2/totalFilters); Daniel@0: rank0 = find(option.rank == 0); Daniel@0: mfccDCTMatrix(rank0,:) = mfccDCTMatrix(rank0,:) * sqrt(2)/2; Daniel@0: ceps = zeros(size(mfccDCTMatrix,1),size(ei,2)); Daniel@0: for j = 1:size(ei,2) Daniel@0: ceps(:,j) = mfccDCTMatrix * permute(ei(1,j,:),[3 1 2]); Daniel@0: end Daniel@0: dc{h}{i} = ceps; Daniel@0: rk{h}{i} = repmat(option.rank(:),[1 size(ceps,2) size(ceps,3)]); Daniel@0: end Daniel@0: end Daniel@0: c = class(c,'mirmfcc',mirdata(orig)); Daniel@0: c = purgedata(c); Daniel@0: c = set(c,'Title','MFCC','Abs','coefficient ranks','Ord','magnitude',... Daniel@0: 'Data',dc,'Rank',rk); Daniel@0: c = modif(c,option); Daniel@0: end Daniel@0: c = {c orig}; Daniel@0: Daniel@0: Daniel@0: function c = modif(c,option) Daniel@0: d = get(c,'Data'); Daniel@0: fp = get(c,'FramePos'); Daniel@0: t = get(c,'Title'); Daniel@0: if option.delta Daniel@0: M = option.radius; Daniel@0: for k = 1:option.delta Daniel@0: for h = 1:length(d) Daniel@0: for i = 1:length(d{h}) Daniel@0: nc = size(d{h}{i},2)-2*M; Daniel@0: di = zeros(size(d{h}{i},1),nc); Daniel@0: for j = 1:M Daniel@0: di = di + j * (d{h}{i}(:,M+j+(1:nc)) ... Daniel@0: - d{h}{i}(:,M-j+(1:nc))); Daniel@0: end Daniel@0: di = di / 2 / sum((1:M).^2); % MULTIPLY BY 2 INSTEAD OF SQUARE FOR NORMALIZATION ? Daniel@0: d{h}{i} = di; Daniel@0: fp{h}{i} = fp{h}{i}(:,M+1:end-M); Daniel@0: end Daniel@0: end Daniel@0: t = ['Delta-',t]; Daniel@0: end Daniel@0: end Daniel@0: c = set(c,'Data',d,'FramePos',fp,'Delta',get(c,'Delta')+option.delta,... Daniel@0: 'Title',t);