annotate aim-mat/modules/pcp/gm2002/ff_design.m @ 0:74dedb26614d

Initial checkin of AIM-MAT version 1.5 (6.4.2011).
author tomwalters
date Fri, 20 May 2011 12:32:31 +0100
parents
children
rev   line source
tomwalters@0 1 function fir_eq=genstonefir(fs,type)
tomwalters@0 2 % adapted version von S.Bleeck
tomwalters@0 3 %
tomwalters@0 4 %%% May 2001 M.A.Stone. To design FIR filters for fir_corr.c
tomwalters@0 5 %%% produces output on screen, and to file dummy.??k where ?? is clock freq in kHz
tomwalters@0 6 %%% select variables below, such as ntaps (output is ntaps +1) fs,
tomwalters@0 7 %%% and inverse =1 sets for inverse filter, 0 for normal filter.
tomwalters@0 8 %%% and eq characteristic is set by choosing appropriate variables:
tomwalters@0 9 %%%% function_str and dB corrn. Ff_ed , Df_ed, Midear, and Hz come
tomwalters@0 10 %%%% from a separate file [all_corrns.m]. Insert new characteristics
tomwalters@0 11 %%%% in there, eg ITU_erp_drp/ITU_Hz
tomwalters@0 12
tomwalters@0 13 %%% FORMAT for output file
tomwalters@0 14 %%% first line is comment
tomwalters@0 15 %%%% second line is number of taps (preferably odd)
tomwalters@0 16 %%%% third and subsequent lines are filter taps, one per line, floating point
tomwalters@0 17
tomwalters@0 18 all_corrns; %%%%%% external file for reference corrections, hz, midear, ff_ed, diffuse
tomwalters@0 19 %%%%%% NB, midear response has limit/flatten-off at lowest freqs to prevent enormous changes < 25 Hz
tomwalters@0 20 %%%%%%%% design parameters here
tomwalters@0 21 %%% NB sometomes for inverse, cannot have ntaps too high: claims index error in fir2.
tomwalters@0 22 % fs = 50000; %%%% sampling rate
tomwalters@0 23 ntaps = 1+2*(round(fs/24)); %% always odd
tomwalters@0 24 nFFT = 2.^(nextpow2(ntaps) + 1); %% FIR size is ntaps + 1, otherwise delay has extra half-sample
tomwalters@0 25 %% more taps require kaiser beta to be higher
tomwalters@0 26 inverse = 0; %% options 0/1 : whether to do forward or inverse filter
tomwalters@0 27
tomwalters@0 28 posh_print = 0; %%% just if we want publication figure, so no output file
tomwalters@0 29
tomwalters@0 30 beta = 6; %%% used to window INVERSE filter shape, and reduce ripple
tomwalters@0 31 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 32 %%%%%%%% Uncomment which of the three sections below you require
tomwalters@0 33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 34 switch type
tomwalters@0 35 case 1
tomwalters@0 36 %%%%%%% Section 1
tomwalters@0 37 function_str= sprintf(' Frontal free-field to cochlea correction,fs=%d',fs);
tomwalters@0 38 if fs <= 32000
tomwalters@0 39 dBcorrn = Ff_ed - Midear; %%%%% result in dB
tomwalters@0 40 else %% for high fs use truer version, without low freq fiddle
tomwalters@0 41 dBcorrn = Ff_ed - MidearAES; %%%%% result in dB
tomwalters@0 42 end
tomwalters@0 43 case 2
tomwalters@0 44 %%%%%%% Section 2
tomwalters@0 45 function_str= sprintf(' Diffuse-field to cochlea correction,fs=%d',fs);
tomwalters@0 46 if fs <= 32000
tomwalters@0 47 dBcorrn = Diffuse - Midear; %%%%% result in dB NB midear is inverted !!
tomwalters@0 48 else %% for high fs use truer version, without low freq fiddle
tomwalters@0 49 dBcorrn = Diffuse - MidearAES; %%%%% result in dB
tomwalters@0 50 end
tomwalters@0 51
tomwalters@0 52 case 3
tomwalters@0 53 %%%%%% Section 3
tomwalters@0 54 %%%%% ITU corrections for telephony.
tomwalters@0 55 function_str= sprintf(' ITU Ear Ref Pnt via Drum Ref Pnt to cochlea,fs=%d',fs);
tomwalters@0 56 ITU_on_Hz = interp1(ITU_Hz,ITU_erp_drp,Hz,'spline'); %%%% corrn on linear frequency spacing
tomwalters@0 57 dBcorrn = ITU_on_Hz - Midear; %%%%% result in dB. NB midear is inverted !!
tomwalters@0 58 end
tomwalters@0 59 %%%% END OF VARIABLE USER ENTRY/SET-UP
tomwalters@0 60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tomwalters@0 61 %%% rest is just calculations
tomwalters@0 62 if ~inverse
tomwalters@0 63 filename = sprintf('ff.%dk',floor(fs/1000));
tomwalters@0 64 else
tomwalters@0 65 filename = sprintf('iff.%dk',floor(fs/1000));
tomwalters@0 66 end
tomwalters@0 67 % if ~posh_print
tomwalters@0 68 % txt_file = fopen(filename,'wt');
tomwalters@0 69 % end
tomwalters@0 70 %%%% spacing for linear frequency design grid
tomwalters@0 71 deltaf = (fs)/nFFT;
tomwalters@0 72
tomwalters@0 73 linf = 0:deltaf:fs/2; %%%% frequencies of FFT bins (DC-nyq-1)
tomwalters@0 74
tomwalters@0 75 if inverse == 1
tomwalters@0 76 dBcorrn = -dBcorrn;
tomwalters@0 77 title_str = strcat('INVERSE',function_str);
tomwalters@0 78 else
tomwalters@0 79 title_str= function_str;
tomwalters@0 80 title_str=' ';
tomwalters@0 81 end
tomwalters@0 82
tomwalters@0 83 if Hz(end) < fs/2 %% handle interpolation of high fs data
tomwalters@0 84 dBcorrn_linf = interp1([Hz fs/2],[dBcorrn dBcorrn(end)],linf,'linear'); %%%% corrn on linear frequency spacing
tomwalters@0 85 else
tomwalters@0 86 dBcorrn_linf = interp1(Hz,dBcorrn,linf,'linear'); %%%% corrn on linear frequency spacing
tomwalters@0 87 end
tomwalters@0 88 %%%%%% limit/flatten-off at lowest freqs
tomwalters@0 89 dBcorrn_linf_orig = dBcorrn_linf;
tomwalters@0 90 %%%dBcorrn_linf(2) = dBcorrn_linf(3) - (dBcorrn_linf(3)-dBcorrn_linf(2))/2;
tomwalters@0 91 %%%dBcorrn_linf(1) = dBcorrn_linf(2);
tomwalters@0 92
tomwalters@0 93 [smth_b smth_a] = butter(4,.5); %% smooth to control roughness
tomwalters@0 94 eq_linf = filtfilt(smth_b,smth_a,dBcorrn_linf);
tomwalters@0 95
tomwalters@0 96 % if posh_print, figure(1); plot(linf,eq_linf,'r','linewidth',1.8); hold on; end
tomwalters@0 97
tomwalters@0 98 %%%%% design fir filter: NB taming of response by (gentle) Kaiser window
tomwalters@0 99 if inverse
tomwalters@0 100 halfwid = 10.^(eq_linf/20.);
tomwalters@0 101 npi = pi*mod((0:nFFT/2),2); %% include phase shift to put response in middle of aperture
tomwalters@0 102 phase_shift = exp(i*npi);
tomwalters@0 103 halfwid = halfwid .* phase_shift;
tomwalters@0 104 fullwid = [halfwid conj(halfwid(nFFT/2:-1:2))];
tomwalters@0 105 t_filt = real(ifft(fullwid));
tomwalters@0 106 %%%%%%%%figure(2); plot(real(t_filt)); figure(1);
tomwalters@0 107 ntaps2 = floor(ntaps/2); %% extract relevant portion
tomwalters@0 108 fir_eq = t_filt((nFFT/2+1)-ntaps2 : (nFFT/2+1)+ntaps2);
tomwalters@0 109 fir_eq = fir_eq.*kaiser(ntaps,beta)';
tomwalters@0 110 else
tomwalters@0 111 %TCW AIM 2006 naps -> ntaps+1 to remove error from fir2 which makes
tomwalters@0 112 %the filter order even anyway. (Ntaps is always odd, see line 23).
tomwalters@0 113 fir_eq = fir2(ntaps+1,linf./(fs/2),10.^(eq_linf/20.)); % f= 1 is Nyquist
tomwalters@0 114 end
tomwalters@0 115
tomwalters@0 116
tomwalters@0 117 %%%%% and plot response
tomwalters@0 118 if posh_print ~=0
tomwalters@0 119 [hz,fz] = freqz(fir_eq,1,16384,fs);
tomwalters@0 120
tomwalters@0 121 % GET AN OUTPUT FILE
tomwalters@0 122 % outfile=fopen('frq_res.ff','w');
tomwalters@0 123 % fprintf(outfile,'%.4f,%.4f\n',[fz,20*log10(abs(hz))]');
tomwalters@0 124 % fclose(outfile);
tomwalters@0 125 plot(fz,20*log10(abs(hz)),'b','linewidth',1.8);
tomwalters@0 126 set(gca,'box','on'); %%%% default with R12 is off
tomwalters@0 127 title(title_str,'fontsize',13); xlabel('Frequency (Hz)','fontsize',11); ylabel('Relative transmission (dB)','fontsize',11);
tomwalters@0 128 set(gca,'TickDirMode','manual','TickLength',[0 0]); %% turn off ticking
tomwalters@0 129
tomwalters@0 130 xfl = 20-.1; xfh = fs/2;
tomwalters@0 131 xticking = [20 50 100 200 500 1000 2000 5000 10000];
tomwalters@0 132 if fs/2 > 20e3, xticking = [xticking 20e3]; end
tomwalters@0 133 if fs/2 > 50e3, xticking = [xticking 50e3]; end % no point in any higher
tomwalters@0 134
tomwalters@0 135 set(gca,'xlim',[xfl xfh],'xscale','log');
tomwalters@0 136 set(gca,'xtickmode','manual','xtick',xticking,'xticklabel',xticking);
tomwalters@0 137
tomwalters@0 138 if inverse, dBl = -10; dBh = 40; else dBl = -40; dBh = 10; end
tomwalters@0 139 yticking = [dBl:5:dBh];
tomwalters@0 140 set(gca,'linewidth',1.3,'ylim',[dBl dBh],'fontsize',11);
tomwalters@0 141 set(gca,'ytickmode','manual','ytick',yticking,'yticklabel',yticking);
tomwalters@0 142
tomwalters@0 143 %% grid on ; set(gca,'GridLineStyle','-');
tomwalters@0 144 %%%%%% to overcome bugs in MATLAB with xscale producing extra ticks 20-06-2001
tomwalters@0 145 for ix = 1:length(xticking) %% draw ylines
tomwalters@0 146 line([xticking(ix) xticking(ix)],[min(yticking), max(yticking)],'linewidth',0.6,'linestyle','--');
tomwalters@0 147 end
tomwalters@0 148 for ix = 1:length(yticking) %% draw xlines
tomwalters@0 149 line([xfl xfh],[yticking(ix), yticking(ix)],'linewidth',0.6,'linestyle','--');
tomwalters@0 150 end
tomwalters@0 151
tomwalters@0 152 else
tomwalters@0 153 % freqz(fir_eq,1,8192,fs);
tomwalters@0 154 % subplot(2,1,1); set(gca,'xlim',[10 fs/2],'xscale','log');
tomwalters@0 155 % hold on ; grid on;
tomwalters@0 156 % semilogx(linf,dBcorrn_linf_orig,'r');
tomwalters@0 157 % title(title_str); xlabel('frequency (Hz)'); ylabel('dB (red=target, blue=actual)');
tomwalters@0 158 % subplot(2,1,1); hold off
tomwalters@0 159 % subplot(2,1,2); hold off
tomwalters@0 160 end
tomwalters@0 161
tomwalters@0 162 % hold off % for figure(1)
tomwalters@0 163
tomwalters@0 164 % %%%% print out design values to file (and was screen)
tomwalters@0 165 % if posh_print ~=0
tomwalters@0 166 % fprintf(1,'\nThis version has also created the file %s\n',filename);
tomwalters@0 167 % fprintf(1,'%s\n',function_str);
tomwalters@0 168 % fprintf(1,'%d\n',length(fir_eq));
tomwalters@0 169 % %% fprintf(1,'%11.8f\n',fir_eq);
tomwalters@0 170 % fprintf(txt_file,'%s\n',function_str);
tomwalters@0 171 % fprintf(txt_file,'%d\n',length(fir_eq));
tomwalters@0 172 % fprintf(txt_file,'%f\n',fir_eq);
tomwalters@0 173 % fclose(txt_file);
tomwalters@0 174 % end
tomwalters@0 175 %
tomwalters@0 176 % WriteDSAMFIRParFile(fir_eq, fs, inverse);