diff 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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toolboxes/MIRtoolbox1.3.2/MIRToolbox/mirfilterbank.m	Tue Feb 10 15:05:51 2015 +0000
@@ -0,0 +1,333 @@
+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}]}});
\ No newline at end of file