annotate aim-mat/modules/bmm/dcgc/GCFBv205.m @ 4:537f939baef0 tip

various bug fixes and changed copyright message
author Stefan Bleeck <bleeck@gmail.com>
date Tue, 16 Aug 2011 14:37:17 +0100
parents 74dedb26614d
children
rev   line source
tomwalters@0 1 %
tomwalters@0 2 % Dynamic Compressive Gammachirp Filterbank
tomwalters@0 3 % Version 2.05
tomwalters@0 4 % Toshio IRINO
tomwalters@0 5 % Created: 6 Sep 2003
tomwalters@0 6 % Modified: 7 Jun 2004
tomwalters@0 7 % Modified: 12 Jul 2004 (PpgcEstShiftERB)
tomwalters@0 8 % Modified: 14 Jul 2004 (LinPpgc)
tomwalters@0 9 % Modified: 4 Aug 2004 (introducing GCresp)
tomwalters@0 10 % Modified: 16 Aug 2004 (ExpDecayVal)
tomwalters@0 11 % Modified: 31 Aug 2004 (introducing GCFBv2_SetParam)
tomwalters@0 12 % Modified: 8 Sep 2004 (TTS. tidy up the names. 2.00 -> 2.01)
tomwalters@0 13 % Modified: 10 Sep 2004 (Normalization at Level estimation path)
tomwalters@0 14 % Modified: 7 Oct 2004 (c2val is level dependent 2.02)
tomwalters@0 15 % Modified: 22 Oct 2004 (level estimation 2.03)
tomwalters@0 16 % Modified: 8 Nov 2004 (error detection of SndIn)
tomwalters@0 17 % Modified: 30 Nov 2004 (c2val control)
tomwalters@0 18 % Modified: 23 May 2005 (v205. Pc == average of two input, RMS2dBSPL,
tomwalters@0 19 % Fast filtering when 'fix' : under construction)
tomwalters@0 20 % Modified: 24 May 2005 (v205 Mod in LinLvl1 =..., LvldB= ...)
tomwalters@0 21 % Modified: 3 Jun 2005 (v205)
tomwalters@0 22 % Modified: 1 Jun 2005 (v205, GCparam.GainCmpnstdB)
tomwalters@0 23 % Modified: 14 Jul 2005 (v205, GCparam.LvlEst.RefdB, Pwr, Weight)
tomwalters@0 24 % Modified: 15 Sep 2005 (v205, rename GCparam.LvlRefdB --> GainRefdB)
tomwalters@0 25 %
tomwalters@0 26 %
tomwalters@0 27 % function [cGCout, pGCout, Ppgc, GCparam, GCresp] = GCFB2(Snd,GCparam)
tomwalters@0 28 % INPUT: Snd: Input Sound
tomwalters@0 29 % GCparam: Gammachirp parameters
tomwalters@0 30 % GCparam.fs: Sampling rate (48000)
tomwalters@0 31 % GCparam.NumCh: Number of Channels (75)
tomwalters@0 32 % GCparam.FRange: Frequency Range of GCFB [100 6000]
tomwalters@0 33 % specifying asymptotic freq. of passive GC (Fr1)
tomwalters@0 34 %
tomwalters@0 35 % OUTPUT: cGCout: Compressive GammaChirp Filter Output
tomwalters@0 36 % pGCout: Passive GammaChirp Filter Output
tomwalters@0 37 % Ppgc: power at the output of passive GC
tomwalters@0 38 % GCparam: GCparam values
tomwalters@0 39 % GCresp : GC response result
tomwalters@0 40 %
tomwalters@0 41 % Note
tomwalters@0 42 % 1) This version is completely different from GCFB v.1.04 (obsolete).
tomwalters@0 43 % We introduced the "compressive gammachirp" to accomodate both the
tomwalters@0 44 % psychoacoustical simultaneous masking and the compressive
tomwalters@0 45 % characteristics (Irino and Patterson, 2001). The parameters were
tomwalters@0 46 % determined from large dataset (See Patterson, Unoki, and Irino, 2003.)
tomwalters@0 47 %
tomwalters@0 48 %
tomwalters@0 49 % References:
tomwalters@0 50 % Irino, T. and Unoki, M.: IEEE ICASSP'98 paper, AE4.4 (12-15, May, 1998)
tomwalters@0 51 % Irino, T. and Patterson, R.D. : JASA, Vol.101, pp.412-419, 1997.
tomwalters@0 52 % Irino, T. and Patterson, R.D. : JASA, Vol.109, pp.2008-2022, 2001.
tomwalters@0 53 % Patterson, R.D., Unoki, M. and Irino, T. : JASA, Vol.114,pp.1529-1542,2003.
tomwalters@0 54 %
tomwalters@0 55 %
tomwalters@0 56 function [cGCout, pGCout, GCparam, GCresp] = GCFBv2(SndIn,GCparam)
tomwalters@0 57
tomwalters@0 58 %%%% Handling Input Parameters %%%%%
tomwalters@0 59 if nargin < 2, help GCFBv205; end;
tomwalters@0 60
tomwalters@0 61 [nc, LenSnd] = size(SndIn);
tomwalters@0 62 if nc ~= 1, error('Check SndIn. It should be 1 ch (Monaural).' ); end;
tomwalters@0 63
tomwalters@0 64 GCparam = GCFBv205_SetParam(GCparam);
tomwalters@0 65
tomwalters@0 66 %%%%%%%%%%%%%
tomwalters@0 67 fs = GCparam.fs;
tomwalters@0 68 NumCh = GCparam.NumCh;
tomwalters@0 69 if length(GCparam.b1) == 1 & length(GCparam.c1) == 1
tomwalters@0 70 b1 = GCparam.b1(1); % Freq. independent
tomwalters@0 71 c1 = GCparam.c1(1); % Freq. independent
tomwalters@0 72 else
tomwalters@0 73 error('Not prepared yet: Freq. dependent b1, c1');
tomwalters@0 74 end;
tomwalters@0 75
tomwalters@0 76 [Fr1, ERBrate1] = EqualFreqScale('ERB',NumCh,GCparam.FRange);
tomwalters@0 77 Fr1 = Fr1(:);
tomwalters@0 78 ERBspace1 = mean(diff(ERBrate1));
tomwalters@0 79
tomwalters@0 80 GCresp.Fr1 = Fr1;
tomwalters@0 81 Fp1 = Fr2Fpeak(GCparam.n,b1,c1,Fr1);
tomwalters@0 82 GCresp.Fp1 = Fp1;
tomwalters@0 83
tomwalters@0 84 [ERBrate ERBw] = Freq2ERB(Fr1);
tomwalters@0 85 [ERBrate1kHz ERBw1kHz] = Freq2ERB(1000);
tomwalters@0 86 Ef = ERBrate/ERBrate1kHz - 1;
tomwalters@0 87 GCresp.Ef = Ef;
tomwalters@0 88 %%%%
tomwalters@0 89 % fratVal = frat(1,1) + frat(1,2)*Ef +
tomwalters@0 90 % frat(2,1)*Ppgc + frat(2,2)*Ef*Ppgc;
tomwalters@0 91 %%%
tomwalters@0 92
tomwalters@0 93 %%%%% Outer-Mid Ear Compensation %%%%
tomwalters@0 94 if length(GCparam.OutMidCrct) > 2
tomwalters@0 95 % disp(['*** Outer/Middle Ear correction: ' GCparam.OutMidCrct ' ***']);
tomwalters@0 96 CmpnOutMid = OutMidCrctFilt(GCparam.OutMidCrct,fs,0);
tomwalters@0 97 % 1kHz: -4 dB, 2kHz: -1 dB, 4kHz: +4 dB
tomwalters@0 98 Snd = filter(CmpnOutMid,1,SndIn);
tomwalters@0 99 else
tomwalters@0 100 % disp('*** No Outer/Middle Ear correction ***');
tomwalters@0 101 Snd = SndIn;
tomwalters@0 102 end;
tomwalters@0 103
tomwalters@0 104 % for compensation filer, use OutMidCrctFilt('ELC',fs,0,1);
tomwalters@0 105
tomwalters@0 106 %%%%% Gammachirp %%%
tomwalters@0 107 %disp('*** Gammmachirp Calculation ***');
tomwalters@0 108 waithand=waitbar(0, 'Generating Basilar Membrane Motion - dcGC');
tomwalters@0 109 if 0, disp(GCparam), end;
tomwalters@0 110 tic;
tomwalters@0 111
tomwalters@0 112
tomwalters@0 113
tomwalters@0 114 %%%% Start calculation %%%%%
tomwalters@0 115
tomwalters@0 116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 117 %%%%% Passive Gammachirp filtering %%%%%
tomwalters@0 118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 119
tomwalters@0 120 Tstart = clock;
tomwalters@0 121 cGCout = zeros(NumCh, LenSnd);
tomwalters@0 122 pGCout = zeros(NumCh, LenSnd);
tomwalters@0 123 Ppgc = zeros(NumCh, LenSnd);
tomwalters@0 124
tomwalters@0 125 for nch=1:NumCh
tomwalters@0 126
tomwalters@0 127 % passive gammachirp
tomwalters@0 128 pgc = GammaChirp(Fr1(nch),fs,GCparam.n,b1,c1,0,'','peak'); % pGC
tomwalters@0 129 pGCout(nch,1:LenSnd)=fftfilt(pgc,Snd); % fast fft based filtering
tomwalters@0 130
tomwalters@0 131 end
tomwalters@0 132
tomwalters@0 133
tomwalters@0 134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 135 %%%%% Compressive Gammachirp filtering %%%%%
tomwalters@0 136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 137
tomwalters@0 138 %%%%% Initial settings %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 139
tomwalters@0 140 GCresp.Fr2 = zeros(NumCh,LenSnd);
tomwalters@0 141 GCresp.fratVal = zeros(NumCh,LenSnd);
tomwalters@0 142
tomwalters@0 143 %%%% Level independent b2 & c2 for Signal path %%%
tomwalters@0 144 b2val = GCparam.b2(1,1)*ones(NumCh,1) + GCparam.b2(1,2)*Ef(:);
tomwalters@0 145 c2val = GCparam.c2(1,1)*ones(NumCh,1) + GCparam.c2(1,2)*Ef(:);
tomwalters@0 146 GCresp.b2val = b2val;
tomwalters@0 147 GCresp.c2val = c2val;
tomwalters@0 148
tomwalters@0 149 nDisp = 20*fs/1000; % display every 20 ms
tomwalters@0 150 cGCout = zeros(NumCh,LenSnd);
tomwalters@0 151 GCresp.Fr2 = zeros(NumCh,LenSnd);
tomwalters@0 152 GCresp.fratVal = zeros(NumCh,LenSnd);
tomwalters@0 153 LvldB = zeros(NumCh,LenSnd);
tomwalters@0 154 LvlLinPrev = zeros(NumCh,2);
tomwalters@0 155 ExpDecayVal = exp(-1/(GCparam.LvlEst.DecayHL*fs/1000)*log(2)); % decay exp.
tomwalters@0 156
tomwalters@0 157 NchShift = round(GCparam.LvlEst.LctERB/ERBspace1);
tomwalters@0 158 NchLvlEst = min(max(1, (1:NumCh)'+NchShift),NumCh); % shift in NumCh [1:NumCh]
tomwalters@0 159 Fp1LvlEst = Fp1(NchLvlEst(:));
tomwalters@0 160 zrs = zeros(NumCh,1);
tomwalters@0 161 LvlLinMinLim = 10^(-GCparam.LvlEst.RMStoSPLdB/20); % minimum should be 0 dBSPL
tomwalters@0 162 LvlLinRef = 10.^(( GCparam.LvlEst.RefdB - GCparam.LvlEst.RMStoSPLdB)/20);
tomwalters@0 163
tomwalters@0 164
tomwalters@0 165 %%%%% Sample-by-sample processing %%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 166
tomwalters@0 167 Tstart = clock;
tomwalters@0 168
tomwalters@0 169 %%%%% These lines moved from outside the inner loop
tomwalters@0 170 % TCW August 2006
tomwalters@0 171 if strcmp(GCparam.Ctrl(1:3),'tim') == 1
tomwalters@0 172 Fr2LvlEst = GCparam.LvlEst.frat * Fp1LvlEst;
tomwalters@0 173 [ACFcoefLvlEst] = ...
tomwalters@0 174 MakeAsymCmpFiltersV2(fs,Fr2LvlEst,GCparam.LvlEst.b2, GCparam.LvlEst.c2);
tomwalters@0 175 end
tomwalters@0 176 %%%%
tomwalters@0 177
tomwalters@0 178
tomwalters@0 179 for nsmpl=1:LenSnd
tomwalters@0 180
tomwalters@0 181 if strcmp(GCparam.Ctrl,'fix') == 1
tomwalters@0 182 LvldB(:,nsmpl) = GCparam.GainRefdB*ones(NumCh,1); % fixed value
tomwalters@0 183
tomwalters@0 184 elseif strcmp(GCparam.Ctrl(1:3),'tim') == 1, % when time-varying
tomwalters@0 185
tomwalters@0 186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 187 %%%%%%% Level estimation path %%%%%%%%
tomwalters@0 188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 189
tomwalters@0 190 % Moved the following lines outside the main loop as they're not updated
tomwalters@0 191 % each time. Improves speed by about 25%
tomwalters@0 192 % TCW August 2006
tomwalters@0 193 % Fr2LvlEst = GCparam.LvlEst.frat * Fp1LvlEst;
tomwalters@0 194 % [ACFcoefLvlEst] = ...
tomwalters@0 195 % MakeAsymCmpFiltersV2(fs,Fr2LvlEst,GCparam.LvlEst.b2, GCparam.LvlEst.c2);
tomwalters@0 196
tomwalters@0 197
tomwalters@0 198 if nsmpl == 1, %% initialization
tomwalters@0 199 [dummy,ACFstatusLvlEst] = ACFilterBank(ACFcoefLvlEst,[]);
tomwalters@0 200 end;
tomwalters@0 201 [cGCLvlEst,ACFstatusLvlEst] =...
tomwalters@0 202 ACFilterBank(ACFcoefLvlEst,ACFstatusLvlEst,pGCout(NchLvlEst,nsmpl));
tomwalters@0 203
tomwalters@0 204 %%%%% Modified: 24 May 05
tomwalters@0 205 LvlLin(1:NumCh,1) = ...
tomwalters@0 206 max([max(pGCout(NchLvlEst,nsmpl),0), LvlLinPrev(:,1)*ExpDecayVal]')';
tomwalters@0 207 LvlLin(1:NumCh,2) = ...
tomwalters@0 208 max([max(cGCLvlEst,0), LvlLinPrev(:,2)*ExpDecayVal]')';
tomwalters@0 209 LvlLinPrev = LvlLin;
tomwalters@0 210
tomwalters@0 211 %%%%% Modified: 14 July 05
tomwalters@0 212 LvlLinTtl = GCparam.LvlEst.Weight * ...
tomwalters@0 213 LvlLinRef.*(LvlLin(:,1)/LvlLinRef).^GCparam.LvlEst.Pwr(1) ...
tomwalters@0 214 + ( 1 - GCparam.LvlEst.Weight ) * ...
tomwalters@0 215 LvlLinRef.*(LvlLin(:,2)/LvlLinRef).^GCparam.LvlEst.Pwr(2);
tomwalters@0 216
tomwalters@0 217 LvldB(:,nsmpl) = 20*log10( max(LvlLinTtl,LvlLinMinLim) ) ...
tomwalters@0 218 + GCparam.LvlEst.RMStoSPLdB;
tomwalters@0 219 else
tomwalters@0 220 error([ 'GCparam.Ctrl should be "fix" or "tim[e-varying]" '])
tomwalters@0 221 end;
tomwalters@0 222
tomwalters@0 223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 224 %%%%%%%%%%% Signal path %%%%%%%%%%%%%%
tomwalters@0 225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 226 % Filtering High-Pass Asym. Comp. Filter
tomwalters@0 227 fratVal = GCparam.frat(1,1) + GCparam.frat(1,2)*Ef(:) + ...
tomwalters@0 228 (GCparam.frat(2,1) + GCparam.frat(2,2)*Ef(:)).*LvldB(:,nsmpl);
tomwalters@0 229 Fr2Val = Fp1(:).*fratVal;
tomwalters@0 230
tomwalters@0 231 [ACFcoef] = MakeAsymCmpFiltersV2(fs,Fr2Val,b2val,c2val);
tomwalters@0 232 if nsmpl == 1,
tomwalters@0 233 [dummy,ACFstatus] = ACFilterBank(ACFcoef,[]); % initiallization
tomwalters@0 234 end;
tomwalters@0 235
tomwalters@0 236 [SigOut,ACFstatus] = ACFilterBank(ACFcoef,ACFstatus,pGCout(:,nsmpl));
tomwalters@0 237 cGCout(:,nsmpl) = SigOut;
tomwalters@0 238
tomwalters@0 239 GCresp.Fr2(:,nsmpl) = Fr2Val;
tomwalters@0 240 GCresp.fratVal(:,nsmpl) = fratVal;
tomwalters@0 241
tomwalters@0 242 if nsmpl==1 || rem(nsmpl,nDisp)==0,
tomwalters@0 243 waitbar(nsmpl./LenSnd, waithand);
tomwalters@0 244 end % waitbar
tomwalters@0 245
tomwalters@0 246 end % loop over samples
tomwalters@0 247
tomwalters@0 248
tomwalters@0 249 %%%% Signal path Gain Normalization at Reference Level (GainRefdB) %%%
tomwalters@0 250
tomwalters@0 251 fratRef = GCparam.frat(1,1) + GCparam.frat(1,2)*Ef(:) + ...
tomwalters@0 252 (GCparam.frat(2,1) + GCparam.frat(2,2)*Ef(:)).*GCparam.GainRefdB;
tomwalters@0 253
tomwalters@0 254 cGCRef = CmprsGCFrsp(Fr1,fs,GCparam.n,b1,c1,fratRef,b2val,c2val);
tomwalters@0 255 GCresp.cGCRef = cGCRef;
tomwalters@0 256 GCresp.LvldB = LvldB;
tomwalters@0 257
tomwalters@0 258 GainFactor = 10^(GCparam.GainCmpnstdB/20)*(cGCRef.NormFctFp2 * ones(1,LenSnd));
tomwalters@0 259 cGCout = GainFactor.*cGCout;
tomwalters@0 260
tomwalters@0 261 %%%%%%%%%%
tomwalters@0 262 close(waithand);
tomwalters@0 263 return