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
|