annotate aim-mat/modules/bmm/dcgc/GCFBv205_old.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 % Compressive Gammachirp Filterbank
tomwalters@0 3 % Version 2.05
tomwalters@0 4 % Toshio IRINO
tomwalters@0 5 % Created: 6 Sept 2003
tomwalters@0 6 % Modified: 7 June 2004
tomwalters@0 7 % Modified: 12 July 2004 (PpgcEstShiftERB)
tomwalters@0 8 % Modified: 14 July 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 Sept 2004 (TTS. tidy up the names. 2.00 -> 2.01)
tomwalters@0 13 % Modified: 10 Sept 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 July 2005 (v205, GCparam.LvlEst.RefdB, Pwr, Weight)
tomwalters@0 24 %
tomwalters@0 25 %
tomwalters@0 26 % function [cGCout, pGCout, Ppgc, GCparam, GCresp] = GCFB2(Snd,GCparam)
tomwalters@0 27 % INPUT: Snd: Input Sound
tomwalters@0 28 % GCparam: Gammachirp parameters
tomwalters@0 29 % GCparam.fs: Sampling rate (48000)
tomwalters@0 30 % GCparam.NumCh: Number of Channels (75)
tomwalters@0 31 % GCparam.FRange: Frequency Range of GCFB [100 6000]
tomwalters@0 32 % specifying asymptotic freq. of passive GC (Fr1)
tomwalters@0 33 %
tomwalters@0 34 % OUTPUT: cGCout: Compressive GammaChirp Filter Output
tomwalters@0 35 % pGCout: Passive GammaChirp Filter Output
tomwalters@0 36 % Ppgc: power at the output of passive GC
tomwalters@0 37 % GCparam: GCparam values
tomwalters@0 38 % GCresp : GC response result
tomwalters@0 39 %
tomwalters@0 40 % Note
tomwalters@0 41 % 1) This version is completely different from GCFB v.1.04 (obsolete).
tomwalters@0 42 % We introduced the "compressive gammachirp" to accomodate both the
tomwalters@0 43 % psychoacoustical simultaneous masking and the compressive
tomwalters@0 44 % characteristics (Irino and Patterson, 2001). The parameters were
tomwalters@0 45 % determined from large dataset (See Patterson, Unoki, and Irino, 2003.)
tomwalters@0 46 %
tomwalters@0 47 %
tomwalters@0 48 % References:
tomwalters@0 49 % Irino, T. and Unoki, M.: IEEE ICASSP'98 paper, AE4.4 (12-15, May, 1998)
tomwalters@0 50 % Irino, T. and Patterson, R.D. : JASA, Vol.101, pp.412-419, 1997.
tomwalters@0 51 % Irino, T. and Patterson, R.D. : JASA, Vol.109, pp.2008-2022, 2001.
tomwalters@0 52 % Patterson, R.D., Unoki, M. and Irino, T. : JASA, Vol.114,pp.1529-1542,2003.
tomwalters@0 53 %
tomwalters@0 54 %
tomwalters@0 55 function [cGCout, pGCout, GCparam, GCresp] = GCFBv2(SndIn,GCparam)
tomwalters@0 56
tomwalters@0 57 %%%% Handling Input Parameters %%%%%
tomwalters@0 58 if nargin < 2, help GCFBv205; end;
tomwalters@0 59
tomwalters@0 60 [nc, LenSnd] = size(SndIn);
tomwalters@0 61 if nc ~= 1, error('Check SndIn. It should be 1 ch (Monaural).' ); end;
tomwalters@0 62
tomwalters@0 63 GCparam = GCFBv205_SetParam(GCparam);
tomwalters@0 64
tomwalters@0 65 %%%%%%%%%%%%%
tomwalters@0 66 fs = GCparam.fs;
tomwalters@0 67 NumCh = GCparam.NumCh;
tomwalters@0 68 if length(GCparam.b1) == 1 & length(GCparam.c1) == 1
tomwalters@0 69 b1 = GCparam.b1(1); % Freq. independent
tomwalters@0 70 c1 = GCparam.c1(1); % Freq. independent
tomwalters@0 71 else
tomwalters@0 72 error('Not prepared yet: Freq. dependent b1, c1');
tomwalters@0 73 end;
tomwalters@0 74
tomwalters@0 75 [Fr1, ERBrate1] = EqualFreqScale('ERB',NumCh,GCparam.FRange);
tomwalters@0 76 Fr1 = Fr1(:);
tomwalters@0 77 ERBspace1 = mean(diff(ERBrate1));
tomwalters@0 78
tomwalters@0 79 GCresp.Fr1 = Fr1;
tomwalters@0 80 Fp1 = Fr2Fpeak(GCparam.n,b1,c1,Fr1);
tomwalters@0 81 GCresp.Fp1 = Fp1;
tomwalters@0 82
tomwalters@0 83 [ERBrate ERBw] = Freq2ERB(Fr1);
tomwalters@0 84 [ERBrate1kHz ERBw1kHz] = Freq2ERB(1000);
tomwalters@0 85 Ef = ERBrate/ERBrate1kHz - 1;
tomwalters@0 86 GCresp.Ef = Ef;
tomwalters@0 87 %%%%
tomwalters@0 88 % fratVal = frat(1,1) + frat(1,2)*Ef +
tomwalters@0 89 % frat(2,1)*Ppgc + frat(2,2)*Ef*Ppgc;
tomwalters@0 90 %%%
tomwalters@0 91
tomwalters@0 92 %%%%% Outer-Mid Ear Compensation %%%%
tomwalters@0 93 if length(GCparam.OutMidCrct) > 2
tomwalters@0 94 disp(['*** Outer/Middle Ear correction: ' GCparam.OutMidCrct ' ***']);
tomwalters@0 95 CmpnOutMid = OutMidCrctFilt(GCparam.OutMidCrct,fs,0);
tomwalters@0 96 % 1kHz: -4 dB, 2kHz: -1 dB, 4kHz: +4 dB
tomwalters@0 97 Snd = filter(CmpnOutMid,1,SndIn);
tomwalters@0 98 else
tomwalters@0 99 disp('*** No Outer/Middle Ear correction ***');
tomwalters@0 100 Snd = SndIn;
tomwalters@0 101 end;
tomwalters@0 102
tomwalters@0 103 % for compensation filer, use OutMidCrctFilt('ELC',fs,0,1);
tomwalters@0 104
tomwalters@0 105 %%%%% Gammachirp %%%
tomwalters@0 106 disp('*** Gammmachirp Calculation ***');
tomwalters@0 107 if 0, disp(GCparam), end;
tomwalters@0 108 tic;
tomwalters@0 109
tomwalters@0 110 SwFastPrcs = 0;
tomwalters@0 111 if SwFastPrcs == 1,
tomwalters@0 112 error('Fast processing for linear cGC: Under construction.');
tomwalters@0 113 %%%%%%%%%%% for HP-AF %%%
tomwalters@0 114
tomwalters@0 115 b2val = GCparam.b2(1,1)*ones(NumCh,1) + GCparam.b2(1,2)*Ef(:);
tomwalters@0 116 %c2val = GCparam.c2(1,1)*ones(NumCh,1) + GCparam.c2(1,2)*Ef(:);
tomwalters@0 117 c2valRef = GCparam.c2(1,1)*ones(NumCh,1) + GCparam.c2(1,2)*Ef(:) ...
tomwalters@0 118 + (GCparam.c2(2,1)*ones(NumCh,1) + GCparam.c2(2,2)*Ef(:))*GCparam.LvlRefdB;
tomwalters@0 119 GCresp.b2val = b2val;
tomwalters@0 120 %GCresp.c2val = c2val;
tomwalters@0 121 GCresp.c2valRef = c2valRef;
tomwalters@0 122
tomwalters@0 123 fratVal = GCparam.frat(1,1) + GCparam.frat(1,2)*Ef(:) + ...
tomwalters@0 124 (GCparam.frat(2,1) + GCparam.frat(2,2)*Ef(:))*GCparam.LvlRefdB;
tomwalters@0 125 fr2val = Fp1(:).*fratVal;
tomwalters@0 126 [ACFcoef] = MakeAsymCmpFiltersV2(fs,fr2val,b2val,c2valRef);
tomwalters@0 127 end;
tomwalters@0 128
tomwalters@0 129 %%%% Start calculation %%%%%
tomwalters@0 130
tomwalters@0 131 %%% Passive Gammachirp filtering %%%
tomwalters@0 132 Tstart = clock;
tomwalters@0 133 cGCout = zeros(NumCh, LenSnd);
tomwalters@0 134 pGCout = zeros(NumCh, LenSnd);
tomwalters@0 135 Ppgc = zeros(NumCh, LenSnd);
tomwalters@0 136
tomwalters@0 137 for nch=1:NumCh
tomwalters@0 138
tomwalters@0 139 % passive gammachirp
tomwalters@0 140 pgc = GammaChirp(Fr1(nch),fs,GCparam.n,b1,c1,0,'','peak'); % pGC
tomwalters@0 141 pGCout(nch,1:LenSnd)=fftfilt(pgc,Snd); % fast fft based filtering
tomwalters@0 142
tomwalters@0 143 %%% Fast processing for fixed cGC: Under construction. %%%
tomwalters@0 144 if SwFastPrcs == 1 & strcmp(GCparam.Ctrl,'fix') == 1
tomwalters@0 145 error('Fast processing for linear cGC: Under construction.');
tomwalters@0 146 cGCout(nch,:) = pGCout(nch,:);
tomwalters@0 147 for Nfilt = 1:4;
tomwalters@0 148 cGCout(nch,:) = filter(ACFcoef.bz(nch,:,Nfilt), ...
tomwalters@0 149 ACFcoef.ap(nch,:,Nfilt), cGCout(nch,:));
tomwalters@0 150 end;
tomwalters@0 151 end;
tomwalters@0 152
tomwalters@0 153 if nch == 1 | rem(nch,20)==0
tomwalters@0 154 disp(['Passive-Gammachirp ch #' num2str(nch) ...
tomwalters@0 155 ' / #' num2str(NumCh) '. elapsed time = ' ...
tomwalters@0 156 num2str(fix(etime(clock,Tstart)*10)/10) ' (sec)']);
tomwalters@0 157 end;
tomwalters@0 158 end;
tomwalters@0 159
tomwalters@0 160
tomwalters@0 161
tomwalters@0 162 %%%% Frequency Response for determining normalization factor
tomwalters@0 163 %%%% normalization factor for level estimation path
tomwalters@0 164
tomwalters@0 165 GCresp.Fr2 = zeros(NumCh,LenSnd);
tomwalters@0 166 GCresp.fratVal = zeros(NumCh,LenSnd);
tomwalters@0 167 %
tomwalters@0 168 % not necessary when LvlEst.frat = 1.08 ( max(pGCout) = max(cGCout) = 0 dB)
tomwalters@0 169 % cGCLvlEst = CmprsGCFrsp(Fr1,fs,GCparam.n,b1,c1, ...
tomwalters@0 170 % GCparam.LvlEst.frat,GCparam.LvlEst.b2,GCparam.LvlEst.c2);
tomwalters@0 171 % NormLvlEst = cGCLvlEst.NormFctFp2;
tomwalters@0 172 % GCresp.cGCLvlEst = cGCLvlEst;
tomwalters@0 173
tomwalters@0 174 %%%% Level independent b2 & level-dependent c2 for signal pass at LvlRefdB %%%
tomwalters@0 175 b2val = GCparam.b2(1,1)*ones(NumCh,1) + GCparam.b2(1,2)*Ef(:);
tomwalters@0 176 % c2val = GCparam.c2(1,1)*ones(NumCh,1) + GCparam.c2(1,2)*Ef(:);
tomwalters@0 177 c2valRef = GCparam.c2(1,1)*ones(NumCh,1) + GCparam.c2(1,2)*Ef(:) ...
tomwalters@0 178 + (GCparam.c2(2,1)*ones(NumCh,1) + GCparam.c2(2,2)*Ef(:))*GCparam.LvlRefdB;
tomwalters@0 179 GCresp.b2val = b2val;
tomwalters@0 180 GCresp.c2valRef = c2valRef;
tomwalters@0 181
tomwalters@0 182
tomwalters@0 183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 184 %%% Now signal path filtering
tomwalters@0 185 %%% by calculating HP-AF for every time slice
tomwalters@0 186
tomwalters@0 187 nDisp = 20*fs/1000; % display every 20 ms
tomwalters@0 188 cGCout = zeros(NumCh,LenSnd);
tomwalters@0 189 GCresp.Fr2 = zeros(NumCh,LenSnd);
tomwalters@0 190 GCresp.fratVal = zeros(NumCh,LenSnd);
tomwalters@0 191 LvldB = zeros(NumCh,LenSnd);
tomwalters@0 192 LvlLinPrev = zeros(NumCh,2);
tomwalters@0 193 ExpDecayVal = exp(-1/(GCparam.LvlEst.DecayHL*fs/1000)*log(2)); % decay exp.
tomwalters@0 194
tomwalters@0 195 NchShift = round(GCparam.LvlEst.LctERB/ERBspace1);
tomwalters@0 196 NchLvlEst = min(max(1, (1:NumCh)'+NchShift),NumCh); % shift in NumCh
tomwalters@0 197 Fp1LvlEst = Fp1(NchLvlEst(:));
tomwalters@0 198 zrs = zeros(NumCh,1);
tomwalters@0 199 LvlLinMinLim = 10^(-GCparam.LvlEst.RMStoSPLdB/20); % minimum should be 0 dBSPL
tomwalters@0 200 LvlLinRef = 10.^(( GCparam.LvlEst.RefdB - GCparam.LvlEst.RMStoSPLdB)/20);
tomwalters@0 201
tomwalters@0 202 Tstart = clock;
tomwalters@0 203 for nsmpl=1:LenSnd
tomwalters@0 204
tomwalters@0 205 if strcmp(GCparam.Ctrl,'fix') == 1
tomwalters@0 206 LvldB(:,nsmpl) = GCparam.LvlRefdB*ones(NumCh,1); % fixed value
tomwalters@0 207
tomwalters@0 208 elseif strcmp(GCparam.Ctrl(1:3),'tim') == 1, % when time-varying
tomwalters@0 209
tomwalters@0 210 %%%% Level estimation path %%%%
tomwalters@0 211 Fr2LvlEst = GCparam.LvlEst.frat * Fp1LvlEst;
tomwalters@0 212 [ACFcoefLvlEst] = ...
tomwalters@0 213 MakeAsymCmpFiltersV2(fs,Fr2LvlEst,GCparam.LvlEst.b2, GCparam.LvlEst.c2);
tomwalters@0 214 if nsmpl == 1, %% initiallization
tomwalters@0 215 [dummy,ACFstatusLvlEst] = ACFilterBank(ACFcoefLvlEst,[]);
tomwalters@0 216 end;
tomwalters@0 217 [cGCLvlEst,ACFstatusLvlEst] =...
tomwalters@0 218 ACFilterBank(ACFcoefLvlEst,ACFstatusLvlEst,pGCout(NchLvlEst,nsmpl));
tomwalters@0 219
tomwalters@0 220 %% SigLvlEst = NormLvlEst .* SigLvlEst; %%%% Removed 14 July 05
tomwalters@0 221 %% SumLvlLin = pGCout(:,nsmpl) + SigLvlEst;
tomwalters@0 222 %% SumLvlLin = abs(pGCout(:,nsmpl)) + abs(SigLvlEst);
tomwalters@0 223 %% LvlLin1 = max([pGCout(:,nsmpl), LvlLinPrev1*ExpDecayVal, zrs]')';
tomwalters@0 224 %% <-- NchLvlEst <-- Bug!
tomwalters@0 225 %% LvlLin2 = max([cGCLvlEst, LvlLinPrev2*ExpDecayVal, zrs]')';
tomwalters@0 226 %%%%% Modified: 24 May 05
tomwalters@0 227 LvlLin(1:NumCh,1) = ...
tomwalters@0 228 max([max(pGCout(NchLvlEst,nsmpl),0), LvlLinPrev(:,1)*ExpDecayVal]')';
tomwalters@0 229 LvlLin(1:NumCh,2) = ...
tomwalters@0 230 max([max(cGCLvlEst,0), LvlLinPrev(:,2)*ExpDecayVal]')';
tomwalters@0 231 LvlLinPrev = LvlLin;
tomwalters@0 232
tomwalters@0 233 %%%%
tomwalters@0 234 %% LvldB(:,nsmpl) = 20*log10(max((LvlLin1+LvlLin2)/2,0.1)) ...
tomwalters@0 235 %% + GCparam.LvlEst.RMStoSPLdB; % average <-- v205
tomwalters@0 236 %%%%% Removed: 14 July 05
tomwalters@0 237 %% LvldB(:,nsmpl) = 20*log10(max((LvlLin1+LvlLin2)/2,alim)) ...
tomwalters@0 238 %% + GCparam.LvlEst.RMStoSPLdB; % average <-- v205
tomwalters@0 239 %%%%% Modified: 14 July 05
tomwalters@0 240 LvlLinTtl = GCparam.LvlEst.Weight * ...
tomwalters@0 241 LvlLinRef.*(LvlLin(:,1)/LvlLinRef).^GCparam.LvlEst.Pwr(1) ...
tomwalters@0 242 + ( 1 - GCparam.LvlEst.Weight ) * ...
tomwalters@0 243 LvlLinRef.*(LvlLin(:,2)/LvlLinRef).^GCparam.LvlEst.Pwr(2);
tomwalters@0 244
tomwalters@0 245 LvldB(:,nsmpl) = 20*log10( max(LvlLinTtl,LvlLinMinLim) ) ...
tomwalters@0 246 + GCparam.LvlEst.RMStoSPLdB;
tomwalters@0 247 else
tomwalters@0 248 error([ 'GCparam.Ctrl should be "fix" or "tim[e-varying]" '])
tomwalters@0 249 end;
tomwalters@0 250
tomwalters@0 251 %%%%% Signal path %%%%%%%
tomwalters@0 252 % Filtering High-Pass Asym. Comp. Filter
tomwalters@0 253 fratVal = GCparam.frat(1,1) + GCparam.frat(1,2)*Ef(:) + ...
tomwalters@0 254 (GCparam.frat(2,1) + GCparam.frat(2,2)*Ef(:)).*LvldB(:,nsmpl);
tomwalters@0 255 Fr2Val = Fp1(:).*fratVal;
tomwalters@0 256 c2val = GCparam.c2(1,1)*ones(NumCh,1) + GCparam.c2(2,1)*LvldB(:,nsmpl);
tomwalters@0 257
tomwalters@0 258 [ACFcoef] = MakeAsymCmpFiltersV2(fs,Fr2Val,b2val,c2val);
tomwalters@0 259 if nsmpl == 1,
tomwalters@0 260 [dummy,ACFstatus] = ACFilterBank(ACFcoef,[]); % initiallization
tomwalters@0 261 end;
tomwalters@0 262
tomwalters@0 263 [SigOut,ACFstatus] = ACFilterBank(ACFcoef,ACFstatus,pGCout(:,nsmpl));
tomwalters@0 264 cGCout(:,nsmpl) = SigOut;
tomwalters@0 265
tomwalters@0 266 GCresp.Fr2(:,nsmpl) = Fr2Val;
tomwalters@0 267 GCresp.fratVal(:,nsmpl) = fratVal;
tomwalters@0 268
tomwalters@0 269 if nsmpl==1 | rem(nsmpl,nDisp)==0,
tomwalters@0 270 %%% [ 20*log10([max(LvlLin(:,1)) max(LvlLin(:,2)) max(LvlLinTtl) ])...
tomwalters@0 271 %%% + GCparam.LvlEst.RMStoSPLdB max(LvldB(:,nsmpl))]
tomwalters@0 272 disp(['Compressive GC: Time ' num2str(nsmpl/fs*1000,3) ...
tomwalters@0 273 ' (ms) / ' num2str(LenSnd/fs*1000) ' (ms). elapsed time = ' ...
tomwalters@0 274 num2str(fix(etime(clock,Tstart)*10)/10) ' (sec)']);
tomwalters@0 275 end;
tomwalters@0 276 end;
tomwalters@0 277
tomwalters@0 278
tomwalters@0 279 %%%% Signal path Normalization factor at Reference Level
tomwalters@0 280 fratRef = GCparam.frat(1,1) + GCparam.frat(1,2)*Ef(:) + ...
tomwalters@0 281 (GCparam.frat(2,1) + GCparam.frat(2,2)*Ef(:)).*GCparam.LvlRefdB;
tomwalters@0 282
tomwalters@0 283 cGCRef = CmprsGCFrsp(Fr1,fs,GCparam.n,b1,c1,fratRef,b2val,c2valRef);
tomwalters@0 284 GCresp.cGCRef = cGCRef;
tomwalters@0 285 GCresp.LvldB = LvldB;
tomwalters@0 286
tomwalters@0 287 %%%% Result
tomwalters@0 288 GainFactor = 10^(GCparam.GainCmpnstdB/20)*(cGCRef.NormFctFp2 * ones(1,LenSnd));
tomwalters@0 289 cGCout = GainFactor.*cGCout;
tomwalters@0 290
tomwalters@0 291 return
tomwalters@0 292
tomwalters@0 293