tomwalters@0
|
1 % Generating function for AIM-MAT
|
tomwalters@0
|
2 % Based on Dick Lyon's code for the Pole-Zero filter cascade
|
bleeck@3
|
3 % (c) 2011, University of Southampton
|
bleeck@3
|
4 % Maintained by Stefan Bleeck (bleeck@gmail.com)
|
bleeck@3
|
5 % download of current version is on the soundsoftware site:
|
bleeck@3
|
6 % http://code.soundsoftware.ac.uk/projects/aimmat
|
bleeck@3
|
7 % documentation and everything is on http://www.acousticscale.org
|
tomwalters@0
|
8 function fr=gen_pzfc(sig,options)
|
tomwalters@0
|
9
|
tomwalters@0
|
10 % Unpack the options and get the raw signal from the signal class
|
tomwalters@0
|
11 CFMin=options.lowest_frequency;
|
tomwalters@0
|
12 CFMax=options.highest_frequency;
|
tomwalters@0
|
13
|
tomwalters@0
|
14
|
tomwalters@0
|
15 % Default parameters (these defaults should be the same as in the parameter
|
tomwalters@0
|
16 % file)
|
tomwalters@0
|
17 if ~isfield(options,'segment_length')
|
tomwalters@0
|
18 segLength=200;
|
tomwalters@0
|
19 else
|
tomwalters@0
|
20 segLength=options.segment_length;
|
tomwalters@0
|
21 end
|
tomwalters@0
|
22
|
tomwalters@0
|
23 if ~isfield(options,'stepfactor')
|
tomwalters@0
|
24 stepfactor=1/3;
|
tomwalters@0
|
25 else
|
tomwalters@0
|
26 stepfactor=options.stepfactor;
|
tomwalters@0
|
27 end
|
tomwalters@0
|
28
|
tomwalters@0
|
29 if ~isfield(options,'pdamp')
|
tomwalters@0
|
30 pdamp=0.12;
|
tomwalters@0
|
31 else
|
tomwalters@0
|
32 pdamp=options.pdamp;
|
tomwalters@0
|
33 end
|
tomwalters@0
|
34
|
tomwalters@0
|
35 if ~isfield(options,'zdamp')
|
tomwalters@0
|
36 zdamp=0.2;
|
tomwalters@0
|
37 else
|
tomwalters@0
|
38 zdamp=options.zdamp;
|
tomwalters@0
|
39 end
|
tomwalters@0
|
40
|
tomwalters@0
|
41 if ~isfield(options,'zfactor')
|
tomwalters@0
|
42 zfactor=1.4;
|
tomwalters@0
|
43 else
|
tomwalters@0
|
44 zfactor=options.zfactor;
|
tomwalters@0
|
45 end
|
tomwalters@0
|
46
|
tomwalters@0
|
47 if ~isfield(options, 'bw_over_cf')
|
tomwalters@0
|
48 bwOverCF = 0.11;
|
tomwalters@0
|
49 else
|
tomwalters@0
|
50 bwOverCF = options.bw_over_cf;
|
tomwalters@0
|
51 end
|
tomwalters@0
|
52
|
tomwalters@0
|
53 if ~isfield(options, 'bw_min_hz');
|
tomwalters@0
|
54 bwMinHz = 27;
|
tomwalters@0
|
55 else
|
tomwalters@0
|
56 bwMinHz=options.bw_min_hz;
|
tomwalters@0
|
57 end
|
tomwalters@0
|
58
|
tomwalters@0
|
59 if ~isfield(options, 'use_fitted_params')
|
tomwalters@0
|
60 useFit=0;
|
tomwalters@0
|
61 else
|
tomwalters@0
|
62 useFit=options.use_fitted_params;
|
tomwalters@0
|
63 end
|
tomwalters@0
|
64
|
tomwalters@0
|
65 if ~isfield(options, 'agcfactor')
|
tomwalters@0
|
66 agcfactor=12;
|
tomwalters@0
|
67 else
|
tomwalters@0
|
68 agcfactor=options.agcfactor;
|
tomwalters@0
|
69 end
|
tomwalters@0
|
70
|
tomwalters@0
|
71 if ~isfield(options, 'do_agc')
|
tomwalters@0
|
72 doagcstep=1;
|
tomwalters@0
|
73 else
|
tomwalters@0
|
74 doagcstep=options.do_agc;
|
tomwalters@0
|
75 end
|
tomwalters@0
|
76
|
tomwalters@0
|
77 if ~isfield(options, 'pre_excite_with_noise')
|
tomwalters@0
|
78 do_pre_excite=0;
|
tomwalters@0
|
79 else
|
tomwalters@0
|
80 do_pre_excite=options.pre_excite_with_noise;
|
tomwalters@0
|
81 end
|
tomwalters@0
|
82
|
tomwalters@0
|
83 if ~isfield(options, 'pre_excite_time')
|
tomwalters@0
|
84 pre_excite_time=0.2; % 200ms
|
tomwalters@0
|
85 else
|
tomwalters@0
|
86 pre_excite_time=options.pre_excite_time;
|
tomwalters@0
|
87 end
|
tomwalters@0
|
88
|
tomwalters@0
|
89 if ~isfield(options, 'pre_excite_level_dB')
|
tomwalters@0
|
90 pre_excite_level_dB=-10;
|
tomwalters@0
|
91 else
|
tomwalters@0
|
92 pre_excite_level_dB=options.pre_excite_level_dB;
|
tomwalters@0
|
93 end
|
tomwalters@0
|
94
|
tomwalters@0
|
95 if ~isfield(options, 'doplot')
|
tomwalters@0
|
96 doplot=0;
|
tomwalters@0
|
97 else
|
tomwalters@0
|
98 doplot=options.doplot;
|
tomwalters@0
|
99 end
|
tomwalters@0
|
100
|
tomwalters@0
|
101 if useFit~=0
|
tomwalters@0
|
102 if isfield(options, 'fitted_params')
|
tomwalters@0
|
103 eval(options.fitted_params); % sets the varaible ValParam
|
tomwalters@0
|
104 if ~isvector('ValParam')
|
tomwalters@0
|
105 error('PZFC param file specified is not in the right format. Should set variable ValParam.');
|
tomwalters@0
|
106 end
|
tomwalters@0
|
107 else
|
tomwalters@0
|
108 error('If use_fitted_params is nonzero (i.e. true) then fitted_params must be a real filename');
|
tomwalters@0
|
109 end
|
tomwalters@0
|
110 end
|
tomwalters@0
|
111
|
tomwalters@0
|
112
|
tomwalters@0
|
113
|
tomwalters@0
|
114 fs=getsr(sig);
|
tomwalters@0
|
115 inputColumn=getvalues(sig);
|
tomwalters@0
|
116 Nt = length(inputColumn);
|
tomwalters@0
|
117
|
tomwalters@0
|
118 if useFit==0
|
tomwalters@0
|
119 if options.erb_scale == 0
|
tomwalters@0
|
120 [Coeffs Nch, freqs] = PZBankCoeffsHiLow(fs, CFMax, CFMin, pdamp, zdamp, zfactor, stepfactor, bwOverCF, bwMinHz);
|
tomwalters@0
|
121 else
|
tomwalters@0
|
122 [Coeffs Nch, freqs] = PZBankCoeffsERB(fs, CFMax, CFMin, pdamp, zdamp, zfactor, stepfactor);
|
tomwalters@0
|
123 end
|
tomwalters@0
|
124 else
|
tomwalters@0
|
125 % Use the parameters from the fit to set up the filterbank (using ERB scale)
|
tomwalters@0
|
126 [Coeffs, Nch, freqs] = PZBankCoeffsERBFitted(fs, CFMax, CFMin, ValParam);
|
tomwalters@0
|
127 end
|
tomwalters@0
|
128
|
tomwalters@0
|
129 deskewDelay = 0;
|
tomwalters@0
|
130 doStereo = 0; % no stereo option for AIM-MAT version
|
tomwalters@0
|
131 Ntracks=1; % ditto - don't try and make this any more than 1!
|
tomwalters@0
|
132
|
tomwalters@0
|
133 pfreqs = Coeffs(:,1);
|
tomwalters@0
|
134 pdamps = Coeffs(:,2);
|
tomwalters@0
|
135 za0 = Coeffs(:,3);
|
tomwalters@0
|
136 za1 = Coeffs(:,4);
|
tomwalters@0
|
137 za2 = Coeffs(:,5);
|
tomwalters@0
|
138 Nch = length(pfreqs);
|
tomwalters@0
|
139
|
tomwalters@0
|
140 mindamp = .18; % (Q = 3 max end of interp)
|
tomwalters@0
|
141 maxdamp = .4; % (Q = 1.25 min end of interp)
|
tomwalters@0
|
142 % min and max refer to the damping, not the x and r coordinates
|
tomwalters@0
|
143 rmin = exp(-mindamp*pfreqs);
|
tomwalters@0
|
144 rmax = exp(-maxdamp*pfreqs);
|
tomwalters@0
|
145 xmin = rmin.*cos(pfreqs.*(1-mindamp^2).^0.5);
|
tomwalters@0
|
146 xmax = rmax.*cos(pfreqs.*(1-maxdamp^2).^0.5);
|
tomwalters@0
|
147
|
tomwalters@0
|
148
|
tomwalters@0
|
149 agcepsilons = [0.0064, 0.0016, 0.0004, 0.0001]; % roughly 3 ms, 12 ms, 48 ms, 200 ms
|
tomwalters@0
|
150 agcgains = [1, 1.4, 2, 2.8];
|
tomwalters@0
|
151 agcgains = agcgains/mean(agcgains);
|
tomwalters@0
|
152 Nstages = length(agcepsilons);
|
tomwalters@0
|
153
|
tomwalters@0
|
154 outarray = []; %zeros(Nch*Ntracks,Nt);
|
tomwalters@0
|
155 for j = 1:Ntracks
|
tomwalters@0
|
156 inputColumn(:,j) = filter([0.5 0.5], 1, inputColumn(:,j)); % puts a zero in the TF
|
tomwalters@0
|
157 end
|
tomwalters@0
|
158
|
tomwalters@0
|
159 state1 = zeros(Nch,Ntracks);
|
tomwalters@0
|
160 state2 = zeros(Nch,Ntracks);
|
tomwalters@0
|
161 prevout = zeros(Nch,Ntracks);
|
tomwalters@0
|
162 agcstate = zeros(Nch, Nstages*Ntracks);
|
tomwalters@0
|
163 % initialize with double dampling:
|
tomwalters@0
|
164 [pdampsmod agcstate] = AGCdampStep([ ], pdamps, agcepsilons, agcgains, agcstate); % initialize pdampsmod, agcstate
|
tomwalters@0
|
165 % make safer place to start than full gain, in case input is abruptly loud:
|
tomwalters@0
|
166 pdampsmod = pdampsmod + 0.05;
|
tomwalters@0
|
167 agcstate = agcstate + 0.05;
|
tomwalters@0
|
168
|
tomwalters@0
|
169 % Noise pre-excitation
|
tomwalters@0
|
170 if do_pre_excite == 1
|
tomwalters@0
|
171 wbh=waitbar(0, 'Pre-calculating noise excitaiton for Pole-Zero filter cascade');
|
tomwalters@0
|
172 Nt_noise=pre_excite_time.*fs;
|
tomwalters@0
|
173 doagcstep_noise=1; % we want to run the AGC in this section, even if not in the main section.
|
tomwalters@0
|
174
|
tomwalters@0
|
175 nsegs = floor(Nt_noise/segLength);
|
tomwalters@0
|
176 %wbh=waitbar(0, 'Calculating Pole-Zero filter cascade');
|
tomwalters@0
|
177 for segno = 1:nsegs
|
tomwalters@0
|
178 inputSegment = rand(segLength,1);
|
tomwalters@0
|
179 inputSegment = inputSegment.*10.^(pre_excite_level_dB./20);
|
tomwalters@0
|
180
|
tomwalters@0
|
181 [outsegment, prevout, agcstate, state1, state2, pdampsmod] = ...
|
tomwalters@0
|
182 RunPZBankSegment(inputSegment, prevout, agcstate, state1, state2, pfreqs, pdamps, pdampsmod, ...
|
tomwalters@0
|
183 mindamp, maxdamp, xmin, xmax, rmin, rmax, za0, za1, za2, agcepsilons, agcgains, agcfactor, doagcstep_noise, doplot);
|
tomwalters@0
|
184
|
tomwalters@0
|
185 waitbar(segno/nsegs, wbh);
|
tomwalters@0
|
186
|
tomwalters@0
|
187
|
tomwalters@0
|
188 end
|
tomwalters@0
|
189 close(wbh);
|
tomwalters@0
|
190 end
|
tomwalters@0
|
191
|
tomwalters@0
|
192 % Reset the previous output of the filterbank
|
tomwalters@0
|
193 state1 = zeros(Nch,Ntracks);
|
tomwalters@0
|
194 state2 = zeros(Nch,Ntracks);
|
tomwalters@0
|
195 prevout = zeros(Nch,Ntracks);
|
tomwalters@0
|
196
|
tomwalters@0
|
197 nsegs = floor(Nt/segLength);
|
tomwalters@0
|
198 wbh=waitbar(0, 'Calculating Pole-Zero filter cascade');
|
tomwalters@0
|
199 for segno = 1:nsegs
|
tomwalters@0
|
200 inputSegment = inputColumn((segno-1)*segLength + (1:segLength), :);
|
tomwalters@0
|
201
|
tomwalters@0
|
202
|
tomwalters@0
|
203 [outsegment, prevout, agcstate, state1, state2, pdampsmod] = ...
|
tomwalters@0
|
204 RunPZBankSegment(inputSegment, prevout, agcstate, state1, state2, pfreqs, pdamps, pdampsmod, ...
|
tomwalters@0
|
205 mindamp, maxdamp, xmin, xmax, rmin, rmax, za0, za1, za2, agcepsilons, agcgains, agcfactor, doagcstep, doplot);
|
tomwalters@0
|
206
|
tomwalters@0
|
207 if isempty(outarray)
|
tomwalters@0
|
208 outarray=outsegment;
|
tomwalters@0
|
209 else
|
tomwalters@0
|
210 outarray = [outarray, outsegment]; % gather up the segments
|
tomwalters@0
|
211 end
|
tomwalters@0
|
212
|
tomwalters@0
|
213 waitbar(segno/nsegs, wbh);
|
tomwalters@0
|
214
|
tomwalters@0
|
215
|
tomwalters@0
|
216 end
|
tomwalters@0
|
217
|
tomwalters@0
|
218
|
tomwalters@0
|
219 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
tomwalters@0
|
220 % Convert all the stuff into the form that AIM-MAT wants it
|
tomwalters@0
|
221 outarray=flipdim(outarray, 1);
|
tomwalters@0
|
222 freqs=flipdim(freqs, 1);
|
tomwalters@0
|
223
|
tomwalters@0
|
224 fr=frame(outarray);
|
tomwalters@0
|
225 fr=setsr(fr,fs);
|
tomwalters@0
|
226 fr=setstarttime(fr,getminimumtime(sig));
|
tomwalters@0
|
227 fr=setcf(fr,freqs);
|
tomwalters@0
|
228 close(wbh);
|
tomwalters@0
|
229
|
tomwalters@0
|
230 return;
|
tomwalters@0
|
231
|