Mercurial > hg > camir-aes2014
comparison toolboxes/MIRtoolbox1.3.2/AuditoryToolbox/SeneffEarSetup.m @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:e9a9cd732c1e |
---|---|
1 function [SeneffPreemphasis, SeneffFilterBank, SeneffForward, SeneffBackward] ... | |
2 = SeneffEarSetup(fs) | |
3 | |
4 % This m-function is based on data from the following paper: | |
5 % Benjamin D. Bryant and John D. Gowdy, "Simulation of Stages | |
6 % I and II of Seneff's Auditory Model (SAM) Using Matlab", and | |
7 % published in the Proceedings of the 1993 Matlab User's Group | |
8 % Conference. | |
9 % Thanks to Benjamin Bryant for supplying us with his filter | |
10 % coefficients and the initial organization of this implementation. | |
11 | |
12 % (c) 1998 Interval Research Corporation | |
13 | |
14 % Set the following variable to a non-zero value to see a summary | |
15 % of the filter bank's behaviour. | |
16 plotTests = 0; | |
17 | |
18 % The following values were taken from Figure 2 of Bryant's paper. | |
19 PreemphasisRTheta = [0.86 3.1148863;0.99 0; 0.5 0; 0.95 3.14159]; | |
20 | |
21 % The following values were taken from Table 1 of Bryant's paper. | |
22 % They represent the cascade zeros (R-z and Theta-z), and the | |
23 % second order poles (radius and theta) and zeros (radius and theta/2). | |
24 % | |
25 % R-z Theta-z Radius Theta R-z2 | |
26 FilterBankRTheta = [ | |
27 0 3.14159 0.740055 2.633909 0.8 | |
28 0.86 2.997077 0.753637 2.178169 0.8 | |
29 0.86 2.879267 0.775569 1.856744 0.8 | |
30 0.86 2.761458 0.798336 1.617919 0.8 | |
31 0.86 2.643648 0.819169 1.433496 0.8 | |
32 0.86 2.525839 0.837158 1.286795 0.8 | |
33 0.8 2.964876 0.852598 1.167321 0.8 | |
34 0.86 2.408029 0.865429 1.068141 0.8 | |
35 0.86 2.29022 0.876208 0.984489 0.8 | |
36 0.86 2.17241 0.885329 0.912985 0.8 | |
37 0.86 2.054601 0.893116 0.851162 0.8 | |
38 0.86 1.936791 0.899823 0.797179 0.8 | |
39 0.8 2.788161 0.906118 0.749633 0.8 | |
40 0.86 1.818981 0.911236 0.70744 0.8 | |
41 0.86 1.701172 0.915747 0.669742 0.8 | |
42 0.86 1.583362 0.919753 0.635858 0.8 | |
43 0.86 1.465552 0.923335 0.605237 0.8 | |
44 0.86 1.347743 0.926565 0.57743 0.8 | |
45 0.8 2.611447 0.929914 0.552065 0.8 | |
46 0.86 1.229933 0.932576 0.528834 0.8 | |
47 0.86 1.112123 0.944589 0.487783 0.75 | |
48 0.86 0.994314 0.957206 0.452645 0.660714 | |
49 0.86 0.876504 0.956548 0.42223 0.672143 | |
50 0.86 0.758694 0.956653 0.395644 0.682143 | |
51 0.8 2.434732 0.956518 0.372208 0.690966 | |
52 0.86 0.640885 0.956676 0.351393 0.69881 | |
53 0.86 0.523075 0.956741 0.316044 0.712143 | |
54 0.8 2.258018 0.956481 0.287157 0.723052 | |
55 0.8 2.081304 0.956445 0.263108 0.732143 | |
56 0.8 1.904589 0.956481 0.242776 0.739835 | |
57 0.86 0.405265 0.958259 0.217558 0.749384 | |
58 0.8 1.727875 0.963083 0.197086 0.757143 | |
59 0.8 1.55116 0.969757 0.175115 0.769048 | |
60 0.8 1.374446 0.97003 0.153697 0.780662 | |
61 0.8 1.197732 0.970382 0.134026 0.791337 | |
62 0.8 1.021017 0.970721 0.118819 0.799596 | |
63 0.8 1.5 0.970985 0.106711 0.8 | |
64 0.8 1.2 0.971222 0.096843 0.8 | |
65 0.8 1 0.97144 0.088645 0.8 | |
66 0.8 0.9 0.971645 0.081727 0.8]; | |
67 | |
68 % Let's plot the cascade zero locations and the locations of the | |
69 % pole and zeros in the resonator. | |
70 if plotTests | |
71 clf; | |
72 subplot(3,3,1); | |
73 plot(FilterBankRTheta(:,1).*exp(i*FilterBankRTheta(:,2))) | |
74 axis([-1 1 0 1]) | |
75 title('Cascade Zero Locations') | |
76 | |
77 subplot(3,3,2); | |
78 plot([FilterBankRTheta(:,3).*exp(i*FilterBankRTheta(:,4)) ... | |
79 FilterBankRTheta(:,5).*exp(i*FilterBankRTheta(:,4)/2)],'+') | |
80 title('Resonator Pole/Zero') | |
81 drawnow; | |
82 end | |
83 | |
84 % Convert r-theta form, first into a list of roots, then a polynomial | |
85 roots=exp(i*PreemphasisRTheta(:,2)).*PreemphasisRTheta(:,1); | |
86 SeneffPreemphasis=real(poly([roots;conj(roots)])); | |
87 | |
88 % Plot the preemphasis filter response, if desired | |
89 if plotTests | |
90 subplot(3,3,3); | |
91 freqScale=(0:255)/256*8000; | |
92 freqresp = FreqResp(SeneffPreemphasis,[1], freqScale, 16000); | |
93 semilogx(freqScale,freqresp) | |
94 title('Preemphasis Response'); | |
95 axis([100 10000 -60 20]) | |
96 drawnow; | |
97 end | |
98 | |
99 % Now figure out the second order sections that make up the main | |
100 % filter bank cascade. We put the zeros into the numerator (b's) | |
101 % and there are no poles. Just to keep things simpler, we adjust | |
102 % the gain of each filter to keep it unity gain at DC. | |
103 [channels,width] = size(FilterBankRTheta); | |
104 roots=exp(i*FilterBankRTheta(:,2)).*FilterBankRTheta(:,1); | |
105 SeneffFilterBank = zeros(channels,5); | |
106 for j=1:channels | |
107 SeneffFilterBank(j,1:3) = poly([roots(j) conj(roots(j))]); | |
108 SeneffFilterBank(j,1:3) = SeneffFilterBank(j,1:3)/sum(SeneffFilterBank(j,1:3)); | |
109 end | |
110 | |
111 % Plot the cascade zero responses, if desired. | |
112 if plotTests | |
113 subplot(3,3,4); | |
114 y=soscascade([1 zeros(1,511)],SeneffFilterBank); | |
115 freqresp=20*log10(abs(fft(y(1:5:40,:)'))); | |
116 freqScale=(0:511)/512*16000; | |
117 semilogx(freqScale(1:256),freqresp(1:256,:)) | |
118 axis([100 10000 -150 0]); | |
119 title('Cascade Response'); | |
120 drawnow; | |
121 end | |
122 | |
123 % Now figure out the resonating filters. Each of these resonators | |
124 % is a double pole-zero pair. | |
125 zlocs = FilterBankRTheta(:,5).*exp(i*FilterBankRTheta(:,4)/2); | |
126 plocs = FilterBankRTheta(:,3).*exp(i*FilterBankRTheta(:,4)); | |
127 SeneffForward = zeros(5,channels); | |
128 SeneffBackward = zeros(5,channels); | |
129 | |
130 for j=1:channels | |
131 SeneffForward(:,j) = real(poly([zlocs(j) conj(zlocs(j)) ... | |
132 zlocs(j) conj(zlocs(j))]))'; | |
133 SeneffBackward(:,j) = real(poly([plocs(j) conj(plocs(j)) ... | |
134 plocs(j) conj(plocs(j))]))'; | |
135 end | |
136 | |
137 % Now plot the frequency response of just the resonating filters. | |
138 % These are all bandpass filters. | |
139 if plotTests | |
140 subplot(3,3,5); | |
141 impulse = [1 zeros(1,255)]; | |
142 y=zeros(256,channels); | |
143 for j=1:40 | |
144 y(:,j) = filter(SeneffForward(:,j),SeneffBackward(:,j),impulse)'; | |
145 end | |
146 freqresp=20*log10(abs(fft(y(:,1:5:40)))); | |
147 freqScale=(0:255)/256*16000; | |
148 semilogx(freqScale(1:128),freqresp(1:128,:)) | |
149 axis([100 10000 -30 40]); | |
150 title('Resonators Response') | |
151 drawnow; | |
152 end | |
153 | |
154 % The plot below shows the overall response of the preemphasis filters | |
155 % along with the just-designed cascade of zeros. | |
156 if plotTests | |
157 subplot(3,3,6); | |
158 impulse = [1 zeros(1,511)]; | |
159 y=soscascade(filter(SeneffPreemphasis, [1], impulse), ... | |
160 SeneffFilterBank); | |
161 freqresp=20*log10(abs(fft(y(1:5:40,:)'))); | |
162 freqScale=(0:511)/512*16000; | |
163 semilogx(freqScale(1:256),freqresp(1:256,:)) | |
164 axis([100 10000 -100 25]); | |
165 title('Preemphasis+Cascade'); | |
166 drawnow; | |
167 end | |
168 | |
169 % Now we need to normalize the gain of each channel. We run an impulse | |
170 % through the preemphasis filter, and then through the cascade of zeros. | |
171 % Finally, we run it through each of the resonator filters. | |
172 impulse = [1 zeros(1,255)]; | |
173 y=soscascade(filter(SeneffPreemphasis, [1], impulse), ... | |
174 SeneffFilterBank); | |
175 for j=1:channels | |
176 y(j,:) = filter(SeneffForward(:,j),SeneffBackward(:,j),y(j,:)); | |
177 end | |
178 | |
179 % Now we have impulse responses from each filter. We can find the FFT | |
180 % and then find the gain peak. We divide each forward polynomial by the | |
181 % maximum gain (to normalize) and then multiply by the desired low | |
182 % frequency roll-off. The Bryant paper says that the last 24 channels | |
183 % should be cut at 6dB per octave and that this occurs at 1600 Hz, but | |
184 % it looks to me like the gain change happens at 3200 Hz. | |
185 freqresp=abs(fft(y')); | |
186 gain = ones(1,channels)./max(freqresp); | |
187 cfs = FilterBankRTheta(:,4)/pi*fs/2; | |
188 rolloff = min(cfs/1600,1); | |
189 | |
190 for j=1:channels | |
191 SeneffForward(:,j)=SeneffForward(:,j)*gain(j)*rolloff(j); | |
192 end | |
193 | |
194 % All Done. The figure below should match Figure 3 of Bryant's paper. | |
195 if plotTests | |
196 subplot(3,3,8); | |
197 impulse = [1 zeros(1,511)]; | |
198 y=soscascade(filter(SeneffPreemphasis, [1], impulse), ... | |
199 SeneffFilterBank); | |
200 for j=1:channels | |
201 y(j,:) = filter(SeneffForward(:,j),SeneffBackward(:,j),y(j,:)); | |
202 end | |
203 | |
204 freqresp=20*log10(abs(fft(y(1:5:40,:)'))); | |
205 freqScale=(0:511)/512*16000; | |
206 plot(freqScale(1:256),freqresp(1:256,:)) | |
207 axis([100 10000 -120 0]); | |
208 title('Magnitude Response vs. Linear Frequency'); | |
209 drawnow; | |
210 end | |
211 | |
212 | |
213 function mag=FreqResp(b,a,f,fs) | |
214 cf = exp(i*2*pi*f/fs); | |
215 num = 0; | |
216 for i=1:length(b) | |
217 num = num + b(end-i+1)*cf.^i; | |
218 end | |
219 | |
220 denom = 0; | |
221 for i=1:length(a) | |
222 denom = denom + a(end-i+1)*cf.^i; | |
223 end | |
224 mag = 20*log10(abs(num./denom)); |