Mercurial > hg > camir-aes2014
view toolboxes/MIRtoolbox1.3.2/MIRToolbox/mirfilterbank.m @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
line wrap: on
line source
function varargout = mirfilterbank(orig,varargin) % b = mirfilterbank(x) performs a filterbank decomposition of an audio % waveform. % Optional arguments: % mirfilterbank(...,t) selects a type of filterbank. % Possible values: % t = 'Gammatone' (default for audio files). % Requires the Auditory Toolbox. % mirfilterbank(...,'Lowest',f): lowest frequency in Hz % (default: 50) % t = '2Channels' proposed in (Tolonen & Karjalainen, 2000) % mirfilterbank(...,'NbChannels',N), or simply filterbank(x,N): % specifies the number of channels in the bank. % (default: N = 10) % mirfilterbank(...,'Channel',c) only output the channels whose % ranks are indicated in the array c. % (default: c = (1:N)) % mirfilterbank(...,'Manual',f) specifies a set of low-pass, band- % pass and high-pass eliptic filters (Scheirer, 1998). % The series of cut-off frequencies as to be specified % as next parameter f. % If this series of frequencies f begins with -Inf, % the first filter is low-pass. % If this series of frequencies f ends with Inf, % the last filter is high-pass. % mirfilterbank(...,'Order',o) specifies the order of the filter. % (Default: o = 4) (Scheirer, 1998) % mirfilterbank(...,'Hop',h) specifies the degree of spectral % overlapping between successive channels. % If h = 1 (default value), the filters are non-overlapping. % If h = 2, the filters are half-overlapping. % If h = 3, the spectral hop factor between successive % filters is a third of the whole frequency region, etc. % mirfilterbank(...,p) specifies predefined filterbanks, all % implemented using elliptic filters, by default of order 4. % Possible values: % p = 'Mel' (mel-scale) % p = 'Bark' (bark-scale) % p = 'Scheirer' proposed in (Scheirer, 1998) corresponds to % 'Manual',[-Inf 200 400 800 1600 3200 Inf] % p = 'Klapuri' proposed in (Klapuri, 1999) corresponds to % 'Manual',44*[2.^ ([ 0:2, ( 9+(0:17) )/3 ]) ] nCh.key = 'NbChannels'; nCh.type = 'Integer'; nCh.default = 10; option.nCh = nCh; Ch.key = {'Channel','Channels'}; Ch.type = 'Integer'; Ch.default = 0; option.Ch = Ch; lowF.key = 'Lowest'; lowF.type = 'Integer'; lowF.default = 50; option.lowF = lowF; freq.key = 'Manual'; freq.type = 'Integer'; freq.default = NaN; option.freq = freq; overlap.key = 'Hop'; overlap.type = 'Boolean'; overlap.default = 1; option.overlap = overlap; filtertype.type = 'String'; filtertype.choice = {'Gammatone','2Channels',0}; filtertype.default = 'Gammatone'; option.filtertype = filtertype; filterorder.key = 'Order'; filterorder.type = 'Integer'; filterorder.default = 4; option.filterorder = filterorder; presel.type = 'String'; presel.choice = {'Scheirer','Klapuri','Mel','Bark'}; presel.default = ''; option.presel = presel; specif.option = option; specif.eachchunk = @eachchunk; specif.combinechunk = @combinechunk; varargout = mirfunction(@mirfilterbank,orig,varargin,nargout,specif,@init,@main); function [x type] = init(x,option) type = 'miraudio'; function b = main(x,option,postoption) if iscell(x) x = x{1}; end f = get(x,'Sampling'); if strcmpi(option.presel,'Scheirer') option.freq = [-Inf 200 400 800 1600 3200 Inf]; elseif strcmpi(option.presel,'Klapuri') option.freq = 44*[2.^([0:2,(9+(0:17))/3])]; elseif strcmpi(option.presel,'Mel') lowestFrequency = 133.3333; linearFilters = 13; linearSpacing = 66.66666666; logFilters = 27; logSpacing = 1.0711703; totalFilters = linearFilters + logFilters; cepstralCoefficients = 13; option.freq = lowestFrequency + (0:linearFilters-1)*linearSpacing; option.freq(linearFilters+1:totalFilters+2) = ... option.freq(linearFilters) * logSpacing.^(1:logFilters+2); option.overlap = 2; elseif strcmpi(option.presel,'Bark') option.freq = [10 20 30 40 51 63 77 92 108 127 148 172 200 232 ... 270 315 370 440 530 640 770 950 1200 1550]*10; %% Hz end if not(isnan(option.freq)) option.filtertype = 'Manual'; end d = get(x,'Data'); if size(d{1}{1},3) > 1 warning('WARNING IN MIRFILTERBANK: The input data is already decomposed into channels. No more channel decomposition.'); if option.Ch cx = get(x,'Channels'); db = cell(1,length(d)); for k = 1:length(d) db{k} = cell(1,length(d{k})); for l = 1:length(d{k}) for i = 1:length(option.Ch) db{k}{l}(:,:,i) = d{k}{l}(:,:,find(cx{k} == option.Ch(i))); end end end b = set(x,'Data',db,'Channels',option.Ch); else b = x; end else i = 1; while i <= length(d) if size(d{i}{1},2) > 1 warning('WARNING IN MIRFILTERBANK: The frame decomposition should be performed after the filterbank decomposition.'); disp(['Suggestion: Use the ' char(34) 'Frame' char(34) ' option available to some of the MIRtoolbox functions.']) break end i = i+1; end nCh = option.nCh; Ch = option.Ch; if strcmpi(option.filtertype, 'Gammatone'); [tmp x] = gettmp(x); %get(x,'Tmp'); if not(Ch) Ch = 1:nCh; end erb = cell(1,length(d)); for i = 1:length(d) erb{i} = cell(1,length(d{i})); nch{i} = Ch; for j = 1:length(d{i}) try coef = MakeERBFilters(f{i},nCh,option.lowF); catch error(['ERROR IN MIRFILTERBANK: Auditory Toolbox needs to be installed.']); end [erb{i}{j} tmp] = ERBfilterbank(d{i}{j},coef,Ch,tmp); end end b = set(x,'Data',erb,'Channels',nch);%,'Tmp',tmp); clear erb b = settmp(b,tmp); elseif strcmpi(option.filtertype, '2Channels'); if not(Ch) Ch = 1:2; end output = cell(1,length(d)); try for i = 1:length(d) output{i} = cell(1,length(d{i})); [bl,al] = butter(4,[70 1000]/f{i}*2); k = 1; if ismember(1,Ch) Hdl = dfilt.df2t(bl,al); %fvtool(Hdl) Hdl.PersistentMemory = true; for j = 1:length(d{i}) low = filter(Hdl,d{i}{j}); output{i}{j}(:,:,k) = low; end k = k+1; end if ismember(2,Ch) if f{i} < 20000 [bh,ah] = butter(2,1000/f{i}*2,'high'); else [bh,ah] = butter(2,[1000 10000]/f{i}*2); end Hdlh = dfilt.df2t(bl,al); %fvtool(Hdlh) Hdh = dfilt.df2t(bh,ah); %fvtool(Hdh) Hdlh.PersistentMemory = true; Hdh.PersistentMemory = true; for j = 1:length(d{i}) high = filter(Hdh,d{i}{j}); high = max(high,0); high = filter(Hdlh,high); output{i}{j}(:,:,k) = high; end end nch{i} = Ch; end b = set(x,'Data',output,'Channels',nch); catch warning(['WARNING IN MIRFILTERBANK: Signal Processing Toolbox (version 6.2.1, or higher) not installed: no filterbank decomposition.']); b = x; end elseif strcmpi(option.filtertype,'Manual'); output = cell(1,length(d)); for i = 1:length(d) freqi = option.freq; j = 1; while j <= length(freqi) if not(isinf(freqi(j))) && freqi(j)>f{i}/2 if j == length(freqi) freqi(j) = Inf; else freqi(j) = []; j = j-1; end end j = j+1; end output{i} = cell(1,length(d{i})); step = option.overlap; for j = 1:length(freqi)-step if isinf(freqi(j)) [z{j},p{j},k{j}] = ellip(option.filterorder,3,40,... freqi(j+step)/f{i}*2); elseif isinf(freqi(j+step)) [z{j},p{j},k{j}] = ellip(option.filterorder,3,40,... freqi(j)/f{i}*2,'high'); else [z{j},p{j},k{j}] = ellip(option.filterorder,3,40,... freqi([j j+step])/f{i}*2); end end for j = 1:length(z) [sos,g] = zp2sos(z{j},p{j},k{j}); Hd(j) = dfilt.df2tsos(sos,g); Hd(j).PersistentMemory = true; for h = 1:length(d{i}) output{i}{h}(:,:,j) = filter(Hd(j),d{i}{h}); end end %fvtool(Hd) nch{i} = 1:length(freqi)-step; end b = set(x,'Data',output,'Channels',nch); end end function [output tmp] = ERBfilterbank(x, fcoefs, chans, tmp) % The following is based on the source code from Auditory Toolbox % (A part that I could not call directly from MIRtoolbox, and that I % generalize to chunk decomposition) % (Malcolm Slaney, August 1993, (c) 1998 Interval Research Corporation) % Process an input waveform with a gammatone filter bank. % The fcoefs parameter, which completely specifies the Gammatone filterbank, % should be designed with the MakeERBFilters function. A0 = fcoefs(:,1); A11 = fcoefs(:,2); A12 = fcoefs(:,3); A13 = fcoefs(:,4); A14 = fcoefs(:,5); A2 = fcoefs(:,6); B0 = fcoefs(:,7); B1 = fcoefs(:,8); B2 = fcoefs(:,9); gain= fcoefs(:,10); lc = length(chans); output = zeros(size(x,1),size(x,2),lc); if isempty(tmp) emptytmp = 1; else emptytmp = 0; end for i = 1:lc chan = length(gain)-chans(i)+1; % Revert the channels order aa1 = [A0(chan)/gain(chan) A11(chan)/gain(chan) A2(chan)/gain(chan)]; bb1 = [B0(chan) B1(chan) B2(chan)]; aa2 = [A0(chan) A12(chan) A2(chan)]; bb2 = [B0(chan) B1(chan) B2(chan)]; aa3 = [A0(chan) A12(chan) A2(chan)]; bb3 = [B0(chan) B1(chan) B2(chan)]; aa4 = [A0(chan) A13(chan) A2(chan)]; bb4 = [B0(chan) B1(chan) B2(chan)]; if emptytmp [y1 tmp(:,:,i,1)] = filter(aa1,bb1,x); [y2 tmp(:,:,i,2)] = filter(aa2,bb2,y1); [y3 tmp(:,:,i,3)] = filter(aa3,bb3,y2); [y4 tmp(:,:,i,4)] = filter(aa4,bb4,y3); else [y1 tmp(:,:,i,1)] = filter(aa1,bb1,x,tmp(:,:,i,1)); [y2 tmp(:,:,i,2)] = filter(aa2,bb2,y1,tmp(:,:,i,2)); [y3 tmp(:,:,i,3)] = filter(aa3,bb3,y2,tmp(:,:,i,3)); [y4 tmp(:,:,i,4)] = filter(aa4,bb4,y3,tmp(:,:,i,4)); end output(:,:,i) = y4; end function [y orig] = eachchunk(orig,option,missing) y = mirfilterbank(orig,option); function y = combinechunk(old,new) do = get(old,'Data'); to = get(old,'Time'); dn = get(new,'Data'); tn = get(new,'Time'); y = set(old,'Data',{{[do{1}{1};dn{1}{1}]}},... 'Time',{{[to{1}{1};tn{1}{1}]}});