annotate aim-mat/modules/bmm/pzfc/gen_pzfc.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 20ada0af3d7d
children
rev   line source
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