tomwalters@0
|
1 /*
|
tomwalters@0
|
2 Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
|
tomwalters@0
|
3 ===========================================================================
|
tomwalters@0
|
4
|
tomwalters@0
|
5 Permission to use, copy, modify, and distribute this software without fee
|
tomwalters@0
|
6 is hereby granted for research purposes, provided that this copyright
|
tomwalters@0
|
7 notice appears in all copies and in all supporting documentation, and that
|
tomwalters@0
|
8 the software is not redistributed for any fee (except for a nominal shipping
|
tomwalters@0
|
9 charge). Anyone wanting to incorporate all or part of this software in a
|
tomwalters@0
|
10 commercial product must obtain a license from the Medical Research Council.
|
tomwalters@0
|
11
|
tomwalters@0
|
12 The MRC makes no representations about the suitability of this
|
tomwalters@0
|
13 software for any purpose. It is provided "as is" without express or implied
|
tomwalters@0
|
14 warranty.
|
tomwalters@0
|
15
|
tomwalters@0
|
16 THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
tomwalters@0
|
17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
|
tomwalters@0
|
18 A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
|
tomwalters@0
|
19 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
tomwalters@0
|
20 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
tomwalters@0
|
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
tomwalters@0
|
22 */
|
tomwalters@0
|
23
|
tomwalters@0
|
24 /*
|
tomwalters@0
|
25 Acknowledgment:
|
tomwalters@0
|
26 ==============
|
tomwalters@0
|
27
|
tomwalters@0
|
28 The source code provided in this file was originally developed by
|
tomwalters@0
|
29 Christian Giguere as part of a Ph.D degree at the Department of
|
tomwalters@0
|
30 Engineering of the University of Cambridge from April 1990 to
|
tomwalters@0
|
31 November 1993. The code was subsequently adapted under a grant
|
tomwalters@0
|
32 from the Hearing Research Trust for full compatibility with
|
tomwalters@0
|
33 AIM Release 6.15.
|
tomwalters@0
|
34
|
tomwalters@0
|
35 Christian Giguere 25/03/94
|
tomwalters@0
|
36
|
tomwalters@0
|
37 */
|
tomwalters@0
|
38
|
tomwalters@0
|
39 /*
|
tomwalters@0
|
40 ===========================================================
|
tomwalters@0
|
41 wdf_ear.c
|
tomwalters@0
|
42 ===========================================================
|
tomwalters@0
|
43
|
tomwalters@0
|
44 Wave digital filter (WDF) implementation of the outer and
|
tomwalters@0
|
45 middle ear (EAR) electroacoustic networks.
|
tomwalters@0
|
46
|
tomwalters@0
|
47 Author : Christian Giguere
|
tomwalters@0
|
48 First written : 01st June, 1991
|
tomwalters@0
|
49 Last edited : 18th February, 1994
|
tomwalters@0
|
50
|
tomwalters@0
|
51 References:
|
tomwalters@0
|
52 (1) C.Giguere and P.C.Woodland (1992). Technical Report
|
tomwalters@0
|
53 CUED/F-INFENG/TR.93, University of Cambridge.
|
tomwalters@0
|
54 (2) C.Giguere and P.C.Woodland (1994). JASA 95(1): 331-342.
|
tomwalters@0
|
55 (3) M.E.Lutman and A.M.Martin (1979). J.Sound.Vib. 64(1): 133-157
|
tomwalters@0
|
56 (4) A.Fettweis (1986). Proceedings IEEE 74(2): 270-327.
|
tomwalters@0
|
57
|
tomwalters@0
|
58 Note: Ref (1) describes an implementation where the outer
|
tomwalters@0
|
59 ear and middle ear module is _UNCOUPLED_ to the cochlea.
|
tomwalters@0
|
60 In this case, the middle ear network is that of Lutman
|
tomwalters@0
|
61 and Martin (1979) unmodified.
|
tomwalters@0
|
62
|
tomwalters@0
|
63 Ref (2) describes an implementation where the outer
|
tomwalters@0
|
64 ear and middle ear module is _COUPLED_ to the cochlea.
|
tomwalters@0
|
65 In this case, the middle ear network is a modified
|
tomwalters@0
|
66 version of Lutman and Martin (1979) network (See Fig.2)
|
tomwalters@0
|
67 ===========================================================
|
tomwalters@0
|
68 */
|
tomwalters@0
|
69
|
tomwalters@0
|
70
|
tomwalters@0
|
71 /***** includes *****/
|
tomwalters@0
|
72
|
tomwalters@0
|
73 #include <math.h>
|
tomwalters@0
|
74 #include <stdio.h>
|
tomwalters@0
|
75 #include "stitch.h"
|
tomwalters@0
|
76 #include "calc.h"
|
tomwalters@0
|
77 #include "calc_tl.h"
|
tomwalters@0
|
78 #include "wdf_ear.h"
|
tomwalters@0
|
79
|
tomwalters@0
|
80 /***** defines *****/
|
tomwalters@0
|
81
|
tomwalters@0
|
82 #define N_OF_FREEFIELD_STATES ( 12 )
|
tomwalters@0
|
83 #define N_OF_EARTUBE_STATES ( 16 ) /* per segment */
|
tomwalters@0
|
84 #define N_OF_EARMIDDLE_STATES ( 48 )
|
tomwalters@0
|
85
|
tomwalters@0
|
86 #if 0
|
tomwalters@0
|
87 #define _DEBUG_
|
tomwalters@0
|
88 #define _OVERFLOW_
|
tomwalters@0
|
89 #endif
|
tomwalters@0
|
90
|
tomwalters@0
|
91 #if 0
|
tomwalters@0
|
92 #define _IMPULSE_ /* bypasses input wave with a delta impulse */
|
tomwalters@0
|
93 #endif
|
tomwalters@0
|
94
|
tomwalters@0
|
95 #if 0
|
tomwalters@0
|
96 #define _EARDRUM_ /* outputs eardrum pressure instead of stapes velocity */
|
tomwalters@0
|
97 #endif
|
tomwalters@0
|
98
|
tomwalters@0
|
99 /* Middle ear circuit elements in CGS units (From Lutman and Martin (1979) */
|
tomwalters@0
|
100
|
tomwalters@0
|
101 #define La ( 14.0e-03 ) /* Middle ear cavities */
|
tomwalters@0
|
102 #define Cp ( 5.1e-06 )
|
tomwalters@0
|
103 #define Ra ( 10.0 )
|
tomwalters@0
|
104 #define Rm ( 390.0 )
|
tomwalters@0
|
105 #define Ct ( 0.35e-06 )
|
tomwalters@0
|
106 #define Rd1 ( 200.0 ) /* Eardrum losses */
|
tomwalters@0
|
107 #define Cd1 ( 0.8e-06 )
|
tomwalters@0
|
108 #define Cd2 ( 0.4e-06 )
|
tomwalters@0
|
109 #define Rd2 ( 220.0 )
|
tomwalters@0
|
110 #define Ld ( 15.0e-03 )
|
tomwalters@0
|
111 #define Rd3 ( 5900.0 )
|
tomwalters@0
|
112 #define Cd3 ( 0.2e-06 )
|
tomwalters@0
|
113 #define Lo ( 40.0e-03 ) /* Eardrum, mallus, incus */
|
tomwalters@0
|
114 #define Co ( 1.4e-06 )
|
tomwalters@0
|
115 #define Ro ( 70.0 )
|
tomwalters@0
|
116 #define Cs ( 0.25e-06 ) /* Incudo-stapedial joint */
|
tomwalters@0
|
117 #define Rs ( 3000.0 )
|
tomwalters@0
|
118 #define Lc ( 45.0e-03 ) /* Stapes and cochlea */
|
tomwalters@0
|
119 #define Cc ( 0.6e-06 )
|
tomwalters@0
|
120 #define Rc ( 550.0 )
|
tomwalters@0
|
121
|
tomwalters@0
|
122 /* Additional middle ear circuit elements in CGS units (From Giguere and Woodland (1994) */
|
tomwalters@0
|
123
|
tomwalters@0
|
124 #define Ral ( 100.0 ) /* annular ligaments */
|
tomwalters@0
|
125 #define Kst_max ( 1./0.1e-06 ) /* max. Stapedius stiffness */
|
tomwalters@0
|
126 #define Kst_min_ratio ( 0.0001 ) /* min value of Kst_ratio */
|
tomwalters@0
|
127
|
tomwalters@0
|
128
|
tomwalters@0
|
129 /***** external variables *****/
|
tomwalters@0
|
130
|
tomwalters@0
|
131 double Kst_ratio = Kst_min_ratio ; /* initial fraction of Kst_max */
|
tomwalters@0
|
132 /* updated by feedback module */
|
tomwalters@0
|
133 static double rn_1 ;
|
tomwalters@0
|
134
|
tomwalters@0
|
135
|
tomwalters@0
|
136 /***** functions *****/
|
tomwalters@0
|
137
|
tomwalters@0
|
138 /******************************* WDF set-up functions ************************************
|
tomwalters@0
|
139 * name: function:
|
tomwalters@0
|
140 *
|
tomwalters@0
|
141 * FreefieldWDF() Set-up function for the WDF implementation of the external ear network
|
tomwalters@0
|
142 * (Giguere and Woodland, 1994, Figs. 1 and 8). It generates the multiplier
|
tomwalters@0
|
143 * coefficients and initializes the states of the filter.
|
tomwalters@0
|
144 *
|
tomwalters@0
|
145 * In the case of the _UNCOUPLED_ ear version, it is called by the
|
tomwalters@0
|
146 * function ``Ear()'' in file ``ear.c''.
|
tomwalters@0
|
147 * In the case of the _COUPLED_ ear version, it is called by the
|
tomwalters@0
|
148 * function ``TLF_GenBank()'' in file ``bank_tl.c''.
|
tomwalters@0
|
149 *
|
tomwalters@0
|
150 * It returns a pointer to a structure containing all the relevant
|
tomwalters@0
|
151 * information for the computation of the whole filter.
|
tomwalters@0
|
152 *
|
tomwalters@0
|
153 * EartubeWDF() Set-up function for the WDF implementation of the concha and auditory
|
tomwalters@0
|
154 * canal transmission lines (Giguere and Woodland, 1994, Figs. 1 and 8).
|
tomwalters@0
|
155 * It generates the multiplier coefficients and initializes the states
|
tomwalters@0
|
156 * of the filter.
|
tomwalters@0
|
157 *
|
tomwalters@0
|
158 * In the case of the _UNCOUPLED_ ear version, it is called by the
|
tomwalters@0
|
159 * function ``Ear()'' in file ``ear.c'' once for each segment of the
|
tomwalters@0
|
160 * transmission lines starting from the outermost segment.
|
tomwalters@0
|
161 * In the case of the _COUPLED_ ear version, it is called by the
|
tomwalters@0
|
162 * function ``TLF_GenBank()'' in file ``bank_tl.c'' once for each segment
|
tomwalters@0
|
163 * of the transmission lines starting from the outermost segment.
|
tomwalters@0
|
164 *
|
tomwalters@0
|
165 * It returns a pointer to a structure containing all the relevant
|
tomwalters@0
|
166 * information for the current filter segment.
|
tomwalters@0
|
167 *
|
tomwalters@0
|
168 * EarmiddleWDF() Set-up function for the WDF implementation of the middle ear network
|
tomwalters@0
|
169 * (Giguere and Woodland, 1994, Figs. 2 and 9). It generates the multiplier
|
tomwalters@0
|
170 * coefficients and initializes the states of the filter.
|
tomwalters@0
|
171 *
|
tomwalters@0
|
172 * In the case of the _UNCOUPLED_ ear version, it is called by the
|
tomwalters@0
|
173 * function ``Ear()'' in file ``ear.c''.
|
tomwalters@0
|
174 * In the case of the _COUPLED_ ear version, it is called by the
|
tomwalters@0
|
175 * function ``TLF_GenBank()'' in file ``bank_tl.c''.
|
tomwalters@0
|
176 *
|
tomwalters@0
|
177 * It returns a pointer to a structure containing all the relevant
|
tomwalters@0
|
178 * information for the computation of the whole filter.
|
tomwalters@0
|
179 ******************************************************************************************/
|
tomwalters@0
|
180
|
tomwalters@0
|
181 /************************** FreefieldWDF() *****************************/
|
tomwalters@0
|
182
|
tomwalters@0
|
183 WaveWDFstate *FreefieldWDF( samplerate, rho, velocity, diffraction_radius, radiation_radius )
|
tomwalters@0
|
184 double samplerate ;
|
tomwalters@0
|
185 double rho, velocity ;
|
tomwalters@0
|
186 double diffraction_radius, radiation_radius ;
|
tomwalters@0
|
187 {
|
tomwalters@0
|
188 DeclareNew( WaveWDFstate *, filter_state ) ;
|
tomwalters@0
|
189 double fs2 ;
|
tomwalters@0
|
190 double r1, r2, r3, g1, g2, g3 ;
|
tomwalters@0
|
191 double zh, zr ;
|
tomwalters@0
|
192 double Lh, Rh, Lr, Rr ;
|
tomwalters@0
|
193
|
tomwalters@0
|
194 /*** electrical circuit elements (CGS) ***/
|
tomwalters@0
|
195 Rh = rho * velocity / ( Pi * diffraction_radius * diffraction_radius ) ;
|
tomwalters@0
|
196 Lh = 0.5 * rho / ( Pi * diffraction_radius ) ;
|
tomwalters@0
|
197 Rr = rho * velocity / ( Pi * radiation_radius * radiation_radius ) ;
|
tomwalters@0
|
198 Lr = 0.7 * rho / ( Pi * radiation_radius ) ;
|
tomwalters@0
|
199
|
tomwalters@0
|
200 /*** sampling frequency ***/
|
tomwalters@0
|
201 fs2 = samplerate * 2. ;
|
tomwalters@0
|
202
|
tomwalters@0
|
203 /*** WDF-port resistances and multiplier coefficients ***/
|
tomwalters@0
|
204
|
tomwalters@0
|
205 /* Adaptor 0 */
|
tomwalters@0
|
206 g1 = 1. / ( fs2 * Lh ) ; /* (1 / Zlh) */
|
tomwalters@0
|
207 g2 = 1. / Rh ; /* (1 / Zrh) */
|
tomwalters@0
|
208 g3 = g1 + g2 ;
|
tomwalters@0
|
209 zh = 1. / g3 ;
|
tomwalters@0
|
210 filter_state->gamma01 = g1 / g3 ;
|
tomwalters@0
|
211
|
tomwalters@0
|
212 /* Adaptor 2 */
|
tomwalters@0
|
213 g1 = 1. / ( fs2 * Lr ) ; /* (1 / Zlr) */
|
tomwalters@0
|
214 g2 = 1. / Rr ; /* (1 / Zrr) */
|
tomwalters@0
|
215 g3 = g1 + g2 ;
|
tomwalters@0
|
216 zr = 1. / g3 ;
|
tomwalters@0
|
217 filter_state->gamma21 = g1 / g3 ;
|
tomwalters@0
|
218
|
tomwalters@0
|
219 /* Adaptor 1 */
|
tomwalters@0
|
220 r1 = zh ;
|
tomwalters@0
|
221 r2 = zr ;
|
tomwalters@0
|
222 r3 = rn_1 = r1 + r2 ;
|
tomwalters@0
|
223 filter_state->gamma11 = r1 / r3 ;
|
tomwalters@0
|
224
|
tomwalters@0
|
225 #ifdef _DEBUG_
|
tomwalters@0
|
226 fprintf( stderr, "Rh=%e Lh=%e Rr=%e Lr=%e\n", Rh, Lh, Rr, Lr ) ;
|
tomwalters@0
|
227 fprintf( stderr, "gamma01=%f\n", filter_state->gamma01 ) ;
|
tomwalters@0
|
228 fprintf( stderr, "gamma11=%f\n", filter_state->gamma11 ) ;
|
tomwalters@0
|
229 fprintf( stderr, "gamma21=%f\n", filter_state->gamma21 ) ;
|
tomwalters@0
|
230 #endif
|
tomwalters@0
|
231
|
tomwalters@0
|
232 /*** initialise filter states ***/
|
tomwalters@0
|
233 filter_state->Nstates = N_OF_FREEFIELD_STATES ;
|
tomwalters@0
|
234 filter_state->states = ( char * ) NewZeroedArray( StateType, filter_state->Nstates,
|
tomwalters@0
|
235 "wdf_ear.c for freefield states\n" ) ;
|
tomwalters@0
|
236
|
tomwalters@0
|
237 /*** return ***/
|
tomwalters@0
|
238 return( filter_state ) ;
|
tomwalters@0
|
239 }
|
tomwalters@0
|
240
|
tomwalters@0
|
241 /************************** EartubeWDF() *****************************/
|
tomwalters@0
|
242
|
tomwalters@0
|
243 EartubeWDFstate *EartubeWDF( samplerate, rho, velocity, diam, seglength, attn )
|
tomwalters@0
|
244 double samplerate ;
|
tomwalters@0
|
245 double rho, velocity ;
|
tomwalters@0
|
246 double diam, seglength ;
|
tomwalters@0
|
247 double attn ;
|
tomwalters@0
|
248 {
|
tomwalters@0
|
249 DeclareNew( EartubeWDFstate *, filter_state ) ;
|
tomwalters@0
|
250 double an, d, c, k, alpha, fs2 ;
|
tomwalters@0
|
251 double Ln, Cn, Gn, Zn ;
|
tomwalters@0
|
252 double r1, r2, r3, g1, g2, g3, r33, g43, g53 ;
|
tomwalters@0
|
253
|
tomwalters@0
|
254 /*** acoustic tube parameters for current segment ***/
|
tomwalters@0
|
255 an = Pi * diam * diam / 4. ; /* cross-sectional area of tube (cm2) */
|
tomwalters@0
|
256 d = seglength; /* length of tube (cm) */
|
tomwalters@0
|
257 c = velocity ; /* sound velocity in air (cm/s) */
|
tomwalters@0
|
258 alpha = attn ; /* attenuation constant of travelling waves (1/cm) */
|
tomwalters@0
|
259
|
tomwalters@0
|
260 /*** sampling frequency ***/
|
tomwalters@0
|
261 fs2 = samplerate * 2. ;
|
tomwalters@0
|
262
|
tomwalters@0
|
263 /*** electrical circuit elements (CGS units) for current segment ***/
|
tomwalters@0
|
264 Ln = ( rho * d ) / an ; /* series inductor (either Lch or Lcl) */
|
tomwalters@0
|
265 Cn = ( an * d ) / ( rho * c * c ) ; /* shunt capacitor (either Cch or Ccl) */
|
tomwalters@0
|
266 Zn = sqrt( Ln / Cn ) ; /* characteristic impedance ( either Zch or Zcl) */
|
tomwalters@0
|
267 Gn = 2. / Zn * alpha * d ; /* shunt conductance (either Gch or Gcl) */
|
tomwalters@0
|
268
|
tomwalters@0
|
269 /*** WDF multiplier coefficients for current tube segment ***/
|
tomwalters@0
|
270
|
tomwalters@0
|
271 /* Adaptor 3 */
|
tomwalters@0
|
272 r1 = fs2 * Ln / 2. ; /* 0.5 Zl */
|
tomwalters@0
|
273 r2 = rn_1 ;
|
tomwalters@0
|
274 r3 = r33 = r1 + r2 ;
|
tomwalters@0
|
275 filter_state->gamma31 = r1 / r3 ;
|
tomwalters@0
|
276
|
tomwalters@0
|
277 /* Adaptor 5 */
|
tomwalters@0
|
278 g1 = Gn ; /* (1 / Zg ) */
|
tomwalters@0
|
279 g2 = fs2 * Cn ; /* (1 / Zc ) */
|
tomwalters@0
|
280 g3 = g53 = g1 + g2 ;
|
tomwalters@0
|
281 filter_state->gamma51 = g1 / g3 ;
|
tomwalters@0
|
282
|
tomwalters@0
|
283 /* Adaptor 4 */
|
tomwalters@0
|
284 g1 = 1 / r33 ;
|
tomwalters@0
|
285 g2 = g53 ;
|
tomwalters@0
|
286 g3 = g43 = g1 + g2 ;
|
tomwalters@0
|
287 filter_state->gamma41 = g1 / g3 ;
|
tomwalters@0
|
288
|
tomwalters@0
|
289 /* Adaptor 6 */
|
tomwalters@0
|
290 r1 = 1 / g43 ;
|
tomwalters@0
|
291 r2 = fs2 * Ln / 2. ; /* 0.5 Zl */
|
tomwalters@0
|
292 r3 = rn_1 = r1 + r2 ;
|
tomwalters@0
|
293 filter_state->gamma61 = r1 / r3 ;
|
tomwalters@0
|
294
|
tomwalters@0
|
295 #ifdef _DEBUG_
|
tomwalters@0
|
296 fprintf( stderr, "gamma31=%f ", filter_state->gamma31 ) ;
|
tomwalters@0
|
297 fprintf( stderr, "gamma41=%f ", filter_state->gamma41 ) ;
|
tomwalters@0
|
298 fprintf( stderr, "gamma51=%f ", filter_state->gamma51 ) ;
|
tomwalters@0
|
299 fprintf( stderr, "gamma61=%f\n", filter_state->gamma61 ) ;
|
tomwalters@0
|
300 #endif
|
tomwalters@0
|
301
|
tomwalters@0
|
302 /*** initialise filter states ***/
|
tomwalters@0
|
303 filter_state->Nstates = N_OF_EARTUBE_STATES ;
|
tomwalters@0
|
304 filter_state->states = ( char * ) NewZeroedArray( StateType, filter_state->Nstates,
|
tomwalters@0
|
305 "wdf_ear.c for earcanal states\n" ) ;
|
tomwalters@0
|
306
|
tomwalters@0
|
307 /*** return ***/
|
tomwalters@0
|
308 return( filter_state ) ;
|
tomwalters@0
|
309 }
|
tomwalters@0
|
310
|
tomwalters@0
|
311
|
tomwalters@0
|
312 /********************** EarmiddleWDF() ***************************/
|
tomwalters@0
|
313
|
tomwalters@0
|
314 EarmiddleWDFstate *EarmiddleWDF( samplerate, zov, output_scale, ratio )
|
tomwalters@0
|
315 double samplerate, zov, output_scale, ratio ;
|
tomwalters@0
|
316 {
|
tomwalters@0
|
317 DeclareNew( EarmiddleWDFstate *, filter_state ) ;
|
tomwalters@0
|
318 double fs2 ;
|
tomwalters@0
|
319 double r1, r2, r3, r4, g1, g2, g3, g4 ;
|
tomwalters@0
|
320 double r73, r84, r94, r103, r114, r123, r133, r143, r153 ;
|
tomwalters@0
|
321 double r163, r174, r183, r193, r204, r214 ;
|
tomwalters@0
|
322 void update_earmiddle_init(), update_earmiddle() ;
|
tomwalters@0
|
323
|
tomwalters@0
|
324 /*** sampling frequency ***/
|
tomwalters@0
|
325 fs2 = samplerate * 2. ;
|
tomwalters@0
|
326
|
tomwalters@0
|
327 /*** WDF-port resistances and multiplier coefficients ***/
|
tomwalters@0
|
328
|
tomwalters@0
|
329 /* Adaptor 9 */
|
tomwalters@0
|
330 r1 = 1. / ( fs2 * Cp ) ; /* Zcp */
|
tomwalters@0
|
331 r2 = Ra ; /* Zra */
|
tomwalters@0
|
332 r3 = fs2 * La ; /* Zla */
|
tomwalters@0
|
333 r4 = r94 = r1 + r2 + r3 ;
|
tomwalters@0
|
334 filter_state->gamma91 = r1 / r4 ;
|
tomwalters@0
|
335 filter_state->gamma92 = r2 / r4 ;
|
tomwalters@0
|
336
|
tomwalters@0
|
337 /* Adaptor 8 */
|
tomwalters@0
|
338 g1 = 1. / r94 ;
|
tomwalters@0
|
339 g2 = 1. / Rm ; /* (1 / Zrm) */
|
tomwalters@0
|
340 g3 = fs2 * Ct ; /* (1 / Zct) */
|
tomwalters@0
|
341 g4 = g1 + g2 + g3 ;
|
tomwalters@0
|
342 r84 = 1. /g4 ;
|
tomwalters@0
|
343 filter_state->gamma81 = g1 / g4 ;
|
tomwalters@0
|
344 filter_state->gamma82 = g2 / g4 ;
|
tomwalters@0
|
345
|
tomwalters@0
|
346 /* Adaptor 7 */
|
tomwalters@0
|
347 r1 = r84 ;
|
tomwalters@0
|
348 r2 = rn_1 ;
|
tomwalters@0
|
349 r3 = r73 = r1 + r2 ;
|
tomwalters@0
|
350 filter_state->gamma71 = r1 / r3 ;
|
tomwalters@0
|
351
|
tomwalters@0
|
352 /* Adaptor 13 */
|
tomwalters@0
|
353 r1 = 1. / ( fs2 * Cd2 ) ; /* Zcd2 */
|
tomwalters@0
|
354 r2 = Rd2 ; /* Zrd2 */
|
tomwalters@0
|
355 r3 = r133 = r1 + r2 ;
|
tomwalters@0
|
356 filter_state->gamma131 = r1 / r3 ;
|
tomwalters@0
|
357
|
tomwalters@0
|
358 /* Adaptor 12 */
|
tomwalters@0
|
359 g1 = 1. / ( fs2 * Ld ) ; /* (1 / Zld) */
|
tomwalters@0
|
360 g2 = 1. / r133 ;
|
tomwalters@0
|
361 g3 = g1 + g2 ;
|
tomwalters@0
|
362 r123 = 1. / g3 ;
|
tomwalters@0
|
363 filter_state->gamma121 = g1 / g3 ;
|
tomwalters@0
|
364
|
tomwalters@0
|
365 /* Adaptor 14 */
|
tomwalters@0
|
366 g1 = 1. / Rd3 ; /* (1 / Zrd3) */
|
tomwalters@0
|
367 g2 = fs2 * Cd3 ; /* (1 / Zcd3) */
|
tomwalters@0
|
368 g3 = g1 + g2 ;
|
tomwalters@0
|
369 r143 = 1. / g3 ;
|
tomwalters@0
|
370 filter_state->gamma141 = g1 / g3 ;
|
tomwalters@0
|
371
|
tomwalters@0
|
372 /* Adaptor 15 */
|
tomwalters@0
|
373 r1 = 1. / ( fs2 * Cd1 ) ; /* Zcd1 */
|
tomwalters@0
|
374 r2 = Rd1 ; /* Zrd1 */
|
tomwalters@0
|
375 r3 = r153 = r1 + r2 ;
|
tomwalters@0
|
376 filter_state->gamma151 = r1 / r3 ;
|
tomwalters@0
|
377
|
tomwalters@0
|
378 /* Adaptor 11 */
|
tomwalters@0
|
379 r1 = r143 ;
|
tomwalters@0
|
380 r2 = r123 ;
|
tomwalters@0
|
381 r3 = r153 ;
|
tomwalters@0
|
382 r4 = r114 = r1 + r2 + r3 ;
|
tomwalters@0
|
383 filter_state->gamma111 = r1 / r4 ;
|
tomwalters@0
|
384 filter_state->gamma112 = r2 / r4 ;
|
tomwalters@0
|
385
|
tomwalters@0
|
386 /* Adaptor 10 */
|
tomwalters@0
|
387 g1 = 1. / r114 ;
|
tomwalters@0
|
388 g2 = 1. / r73 ;
|
tomwalters@0
|
389 g3 = g1 + g2 ;
|
tomwalters@0
|
390 r103 = 1. /g3 ;
|
tomwalters@0
|
391 filter_state->gamma101 = g1 / g3 ;
|
tomwalters@0
|
392
|
tomwalters@0
|
393 /* Adaptor 17 */
|
tomwalters@0
|
394 r1 = 1. / ( fs2 * Co ) ; /* Zco */
|
tomwalters@0
|
395 r2 = Ro ; /* Zro */
|
tomwalters@0
|
396 r3 = fs2 * Lo ; /* Zlo */
|
tomwalters@0
|
397 r4 = r174 = r1 + r2 + r3 ;
|
tomwalters@0
|
398 filter_state->gamma171 = r1 / r4 ;
|
tomwalters@0
|
399 filter_state->gamma172 = r2 / r4 ;
|
tomwalters@0
|
400
|
tomwalters@0
|
401 /* Adaptor 16 */
|
tomwalters@0
|
402 r1 = r103 ;
|
tomwalters@0
|
403 r2 = r174 ;
|
tomwalters@0
|
404 r3 = r163 = r1 + r2 ;
|
tomwalters@0
|
405 filter_state->gamma161 = r1 / r3 ;
|
tomwalters@0
|
406
|
tomwalters@0
|
407 /* Adaptor 19 */
|
tomwalters@0
|
408 r1 = 1. / ( fs2 * Cs ) ; /* Zcs */
|
tomwalters@0
|
409 r2 = Rs ; /* Zrs */
|
tomwalters@0
|
410 r3 = r193 = r1 + r2 ;
|
tomwalters@0
|
411 filter_state->gamma191 = r1 / r3 ;
|
tomwalters@0
|
412
|
tomwalters@0
|
413 /* Adaptor 18 */
|
tomwalters@0
|
414 g1 = 1. / r163 ;
|
tomwalters@0
|
415 g2 = 1. / r193 ;
|
tomwalters@0
|
416 g3 = g1 + g2 ;
|
tomwalters@0
|
417 r183 = 1. / g3 ;
|
tomwalters@0
|
418 filter_state->gamma181 = g1 / g3 ;
|
tomwalters@0
|
419
|
tomwalters@0
|
420 /* Adaptor 20 */
|
tomwalters@0
|
421 #ifdef _DEBUG_
|
tomwalters@0
|
422 fprintf( stderr, "Zov=%e\n", zov ) ;
|
tomwalters@0
|
423 #endif
|
tomwalters@0
|
424 if( zov != 0. ) { /* coupled version ? */
|
tomwalters@0
|
425 r1 = Ral ; /* Zral */
|
tomwalters@0
|
426 r2 = zov / ( ratio * ratio ) ; /* Zov / (r*r) */
|
tomwalters@0
|
427 }
|
tomwalters@0
|
428 else { /* uncoupled version */
|
tomwalters@0
|
429 r1 = 0.0 ;
|
tomwalters@0
|
430 r2 = Rc ; /* Zrc */
|
tomwalters@0
|
431 }
|
tomwalters@0
|
432 r3 = r183 ;
|
tomwalters@0
|
433 r4 = r204 = r1 + r2 +r3 ;
|
tomwalters@0
|
434 filter_state->gamma201 = r1 / r4 ;
|
tomwalters@0
|
435 filter_state->gamma202 = r2 / r4 ;
|
tomwalters@0
|
436 filter_state->ratio = ratio ;
|
tomwalters@0
|
437
|
tomwalters@0
|
438 /* Adaptor 21 */
|
tomwalters@0
|
439 r1 = 1. / ( fs2 * Cc ) ; /* Zcc */
|
tomwalters@0
|
440 r2 = r204 ;
|
tomwalters@0
|
441 if( zov != 0. ) /* coupled version ? */
|
tomwalters@0
|
442 r3 = 0.0 ;
|
tomwalters@0
|
443 else /* uncoupled version */
|
tomwalters@0
|
444 r3 = fs2 * Lc ; /* Zlc */
|
tomwalters@0
|
445 r4 = r214 = r1 + r2 + r3 ;
|
tomwalters@0
|
446 filter_state->gamma211 = r1 / r4 ;
|
tomwalters@0
|
447 filter_state->gamma212 = r2 / r4 ;
|
tomwalters@0
|
448
|
tomwalters@0
|
449 /* Adaptor 22 */
|
tomwalters@0
|
450 r1 = Kst_ratio * Kst_max / fs2 ; /* Zcst (initial value only) */
|
tomwalters@0
|
451 r2 = r214 ;
|
tomwalters@0
|
452 r3 = r1 + r2 ;
|
tomwalters@0
|
453 filter_state->gamma221 = 2. * r1 / r3 ;
|
tomwalters@0
|
454
|
tomwalters@0
|
455 #ifdef _DEBUG_
|
tomwalters@0
|
456 fprintf ( stderr, "gamma71 =%f \n", filter_state->gamma71 ) ;
|
tomwalters@0
|
457 fprintf ( stderr, "gamma81 =%f gamma82 =%f\n", filter_state->gamma81
|
tomwalters@0
|
458 , filter_state->gamma82 ) ;
|
tomwalters@0
|
459 fprintf ( stderr, "gamma91 =%f gamma92 =%f\n", filter_state->gamma91
|
tomwalters@0
|
460 , filter_state->gamma92 ) ;
|
tomwalters@0
|
461 fprintf ( stderr, "gamma101=%f \n", filter_state->gamma101 ) ;
|
tomwalters@0
|
462 fprintf ( stderr, "gamma111=%f gamma112=%f\n", filter_state->gamma111
|
tomwalters@0
|
463 , filter_state->gamma112 ) ;
|
tomwalters@0
|
464 fprintf ( stderr, "gamma121=%f \n", filter_state->gamma121 ) ;
|
tomwalters@0
|
465 fprintf ( stderr, "gamma131=%f \n", filter_state->gamma131 ) ;
|
tomwalters@0
|
466 fprintf ( stderr, "gamma141=%f \n", filter_state->gamma141 ) ;
|
tomwalters@0
|
467 fprintf ( stderr, "gamma151=%f \n", filter_state->gamma151 ) ;
|
tomwalters@0
|
468 fprintf ( stderr, "gamma161=%f \n", filter_state->gamma161 ) ;
|
tomwalters@0
|
469 fprintf ( stderr, "gamma171=%f gamma172=%f\n", filter_state->gamma171
|
tomwalters@0
|
470 , filter_state->gamma172 ) ;
|
tomwalters@0
|
471 fprintf ( stderr, "gamma181=%f \n", filter_state->gamma181 ) ;
|
tomwalters@0
|
472 fprintf ( stderr, "gamma191=%f \n", filter_state->gamma191 ) ;
|
tomwalters@0
|
473 fprintf ( stderr, "gamma201=%f gamma202=%f\n", filter_state->gamma201
|
tomwalters@0
|
474 , filter_state->gamma202 ) ;
|
tomwalters@0
|
475 fprintf ( stderr, "gamma211=%f gamma212=%f\n", filter_state->gamma211
|
tomwalters@0
|
476 , filter_state->gamma212 ) ;
|
tomwalters@0
|
477 fprintf ( stderr, "gamma221=%f \n", filter_state->gamma221 ) ;
|
tomwalters@0
|
478 #endif
|
tomwalters@0
|
479
|
tomwalters@0
|
480 /*** specify and initialise coefficient update procedure ***/
|
tomwalters@0
|
481 filter_state->update_proc = update_earmiddle ;
|
tomwalters@0
|
482 ( void ) update_earmiddle_init( fs2, r214 ) ;
|
tomwalters@0
|
483
|
tomwalters@0
|
484 /*** output scaling ***/
|
tomwalters@0
|
485 filter_state->out_scale = output_scale ;
|
tomwalters@0
|
486
|
tomwalters@0
|
487 /*** initialise filter states ***/
|
tomwalters@0
|
488 filter_state->Nstates = N_OF_EARMIDDLE_STATES ;
|
tomwalters@0
|
489 filter_state->states = ( char * ) NewZeroedArray( StateType, filter_state->Nstates,
|
tomwalters@0
|
490 "wdf_ear.c for middle ear states\n" ) ;
|
tomwalters@0
|
491
|
tomwalters@0
|
492 /*** return ***/
|
tomwalters@0
|
493 return( filter_state ) ;
|
tomwalters@0
|
494 }
|
tomwalters@0
|
495
|
tomwalters@0
|
496
|
tomwalters@0
|
497 /*********************************** WDF procedures ***************************************
|
tomwalters@0
|
498 * name: function:
|
tomwalters@0
|
499 *
|
tomwalters@0
|
500 * DoEarWDF() WDF realization of the _UNCOUPLED_ version of the outer ear and
|
tomwalters@0
|
501 * middle ear networks. It is called by function ``ear_callback()''
|
tomwalters@0
|
502 * in file ``ear.c'' once for a specified number of input points.
|
tomwalters@0
|
503 * It computes the stapes velocity for each input point and keeps
|
tomwalters@0
|
504 * track of the filter states.
|
tomwalters@0
|
505 *
|
tomwalters@0
|
506 * Note: The code for the realization of the _COUPLED_ ear version
|
tomwalters@0
|
507 * is located in file ``wdf_tl.c''.
|
tomwalters@0
|
508 *
|
tomwalters@0
|
509 *
|
tomwalters@0
|
510 * CloseEarWDF() Deletes all private data structures and arrays of the outer and
|
tomwalters@0
|
511 * middle ear filter upon completion of filtering.
|
tomwalters@0
|
512 * In the case of the _UNCOUPLED_ ear version, it is called by the
|
tomwalters@0
|
513 * function ``ear_callback()'' in file ``ear.c''.
|
tomwalters@0
|
514 * In the case of the _COUPLED_ ear version, it is called by the
|
tomwalters@0
|
515 * function ``tlf_bank_callbank()'' in file ``bank_tl.c''.
|
tomwalters@0
|
516 ******************************************************************************************/
|
tomwalters@0
|
517
|
tomwalters@0
|
518 /******************************* DoEarWDF() **************************************/
|
tomwalters@0
|
519
|
tomwalters@0
|
520 void DoEarWDF( ws, eartube_states, ms, tube_segments, inout_ptr, points )
|
tomwalters@0
|
521 register WaveWDFstate *ws ;
|
tomwalters@0
|
522 register EartubeWDFstate **eartube_states ;
|
tomwalters@0
|
523 register EarmiddleWDFstate *ms ;
|
tomwalters@0
|
524 register int tube_segments ;
|
tomwalters@0
|
525 register DataType *inout_ptr ;
|
tomwalters@0
|
526 register int points ;
|
tomwalters@0
|
527 {
|
tomwalters@0
|
528 register EartubeWDFstate *ts ;
|
tomwalters@0
|
529 register StateType *st, in, out ;
|
tomwalters@0
|
530 register StateType a0, an_1, b1, b2, b3, b161, b202, b212, bn ;
|
tomwalters@0
|
531 register int tube_segment = -1 ;
|
tomwalters@0
|
532 #ifdef _IMPULSE_
|
tomwalters@0
|
533 static int impulse = 10000 ;
|
tomwalters@0
|
534 #endif
|
tomwalters@0
|
535
|
tomwalters@0
|
536
|
tomwalters@0
|
537 /***** update stapedial muscle state *****/
|
tomwalters@0
|
538
|
tomwalters@0
|
539 ( void ) ms->update_proc( ms ) ;
|
tomwalters@0
|
540
|
tomwalters@0
|
541 /***** for all points *****/
|
tomwalters@0
|
542
|
tomwalters@0
|
543 while( points-- > 0 ) {
|
tomwalters@0
|
544
|
tomwalters@0
|
545 /*** input point ***/
|
tomwalters@0
|
546
|
tomwalters@0
|
547 in = ( StateType ) *inout_ptr ;
|
tomwalters@0
|
548
|
tomwalters@0
|
549 #ifdef _IMPULSE_
|
tomwalters@0
|
550 if( impulse != 0 ) {
|
tomwalters@0
|
551 in = ( StateType ) impulse ;
|
tomwalters@0
|
552 impulse = 0 ;
|
tomwalters@0
|
553 }
|
tomwalters@0
|
554 else
|
tomwalters@0
|
555 in = ( StateType ) 0 ;
|
tomwalters@0
|
556 #endif
|
tomwalters@0
|
557
|
tomwalters@0
|
558 /*** computation in FORWARD direction for current input point ***/
|
tomwalters@0
|
559
|
tomwalters@0
|
560 /* freefield - external ear */
|
tomwalters@0
|
561
|
tomwalters@0
|
562 /* get states */
|
tomwalters@0
|
563 st = ( StateType * ) ws->states ;
|
tomwalters@0
|
564
|
tomwalters@0
|
565 /* Adaptor 0 */
|
tomwalters@0
|
566 st[4] = ws->gamma01 * ( st[3] - in ) ; /* b00 */
|
tomwalters@0
|
567 st[5] = st[4] + in + in ; /* b03 = -a11 */
|
tomwalters@0
|
568
|
tomwalters@0
|
569 /* Adaptor 2 */
|
tomwalters@0
|
570 st[1] = -ws->gamma21 * st[0] ; /* b20 */
|
tomwalters@0
|
571 st[2] = st[1] ; /* b23 = a12 */
|
tomwalters@0
|
572
|
tomwalters@0
|
573 /* Adaptor 1 */
|
tomwalters@0
|
574 st[6] = st[5] - st[2] ; /* b13 = a32 */
|
tomwalters@0
|
575 an_1 = st[6] ;
|
tomwalters@0
|
576
|
tomwalters@0
|
577 /* concha and auditory canal */
|
tomwalters@0
|
578
|
tomwalters@0
|
579 while( ++tube_segment < tube_segments ) {
|
tomwalters@0
|
580
|
tomwalters@0
|
581 /* get states */
|
tomwalters@0
|
582 ts = *eartube_states++ ;
|
tomwalters@0
|
583 st = ( StateType * ) ts->states ;
|
tomwalters@0
|
584
|
tomwalters@0
|
585 /* Adaptor 3 */
|
tomwalters@0
|
586 st[3] = st[4] - an_1 ; /* b33 = a41 */
|
tomwalters@0
|
587
|
tomwalters@0
|
588 /* Adaptor 5 */
|
tomwalters@0
|
589 st[0] = -ts->gamma51 * st[1] ; /* b50 */
|
tomwalters@0
|
590 st[2] = st[0] + st[1] ; /* b53 = a42 */
|
tomwalters@0
|
591
|
tomwalters@0
|
592 /* Adaptor 4 */
|
tomwalters@0
|
593 st[5] = st[3] - st[2] ; /* -a42+a41 */
|
tomwalters@0
|
594 st[6] = ts->gamma41 * st[5] ; /* b40 */
|
tomwalters@0
|
595 st[7] = st[6] + st[2] ; /* b43 = a61 */
|
tomwalters@0
|
596
|
tomwalters@0
|
597 /* Adaptor 6 */
|
tomwalters@0
|
598 st[8] = st[9] - st[7] ; /* b63 = a32 */
|
tomwalters@0
|
599 an_1 = st[8] ;
|
tomwalters@0
|
600 }
|
tomwalters@0
|
601
|
tomwalters@0
|
602 /* middle ear */
|
tomwalters@0
|
603
|
tomwalters@0
|
604 /* get states */
|
tomwalters@0
|
605 st = ( StateType * ) ms->states ;
|
tomwalters@0
|
606
|
tomwalters@0
|
607 /* Adaptor 9 */
|
tomwalters@0
|
608 st[31] = st[30] - st[29] ; /* b94 = a81 */
|
tomwalters@0
|
609
|
tomwalters@0
|
610 /* Adaptor 8 */
|
tomwalters@0
|
611 st[32] = st[35] - st[31] ; /* a83-a81 */
|
tomwalters@0
|
612 st[33] = -ms->gamma81 * st[32] - ms->gamma82 * st[35] ; /* b80 */
|
tomwalters@0
|
613 st[34] = st[33] + st[35] ; /* b84 = a71 */
|
tomwalters@0
|
614
|
tomwalters@0
|
615 /* Adaptor 7 */
|
tomwalters@0
|
616 st[36] = -st[34] - an_1 ; /* b73 = a102 */
|
tomwalters@0
|
617
|
tomwalters@0
|
618 /* Adaptor 13 */
|
tomwalters@0
|
619 st[15] = -st[14] ; /* b133 = a122 */
|
tomwalters@0
|
620
|
tomwalters@0
|
621 /* Adaptor 12 */
|
tomwalters@0
|
622 st[16] = st[15] + st[18] ; /* a122-a121 */
|
tomwalters@0
|
623 st[17] = -ms->gamma121 * st[16] ; /* b120 */
|
tomwalters@0
|
624 st[19] = st[17] + st[15] ; /* b123 = a112 */
|
tomwalters@0
|
625
|
tomwalters@0
|
626 /* Adaptor 14 */
|
tomwalters@0
|
627 st[21] = -ms->gamma141 * st[20] ; /* b140 */
|
tomwalters@0
|
628 st[22] = st[21] + st[20] ; /* b143 = a111 */
|
tomwalters@0
|
629
|
tomwalters@0
|
630 /* Adaptor 15 */
|
tomwalters@0
|
631 st[23] = -st[24] ; /* b153 = a113 */
|
tomwalters@0
|
632
|
tomwalters@0
|
633 /* Adaptor 11 */
|
tomwalters@0
|
634 st[25] = -st[22] - st[19] - st[23] ; /* b114 = a101 */
|
tomwalters@0
|
635
|
tomwalters@0
|
636 /* Adaptor 10 */
|
tomwalters@0
|
637 st[26] = st[25] - st[36] ; /* -a102+a101 */
|
tomwalters@0
|
638 st[27] = ms->gamma101 * st[26] ; /* b100 */
|
tomwalters@0
|
639 st[28] = st[27] + st[36] ; /* b103 = a161 */
|
tomwalters@0
|
640
|
tomwalters@0
|
641 /* Adaptor 17 */
|
tomwalters@0
|
642 st[10] = st[12] - st[11] ; /* b174 = a162 */
|
tomwalters@0
|
643
|
tomwalters@0
|
644 /* Adaptor 16 */
|
tomwalters@0
|
645 st[13] = -st[28] - st[10] ; /* b163 = a181 */
|
tomwalters@0
|
646
|
tomwalters@0
|
647 /* Adaptor 19 */
|
tomwalters@0
|
648 st[5] = -st[6] ; /* b193 = a182 */
|
tomwalters@0
|
649
|
tomwalters@0
|
650 /* Adaptor 18 */
|
tomwalters@0
|
651 st[7] = st[13] - st[5] ; /* -a182+a181 */
|
tomwalters@0
|
652 st[8] = ms->gamma181 * st[7] ; /* b180 */
|
tomwalters@0
|
653 st[9] = st[8] + st[5] ; /* b183 = a203 */
|
tomwalters@0
|
654
|
tomwalters@0
|
655 /* Adaptor 20 */
|
tomwalters@0
|
656 st[3] = -st[9] ; /* b204 = a212 */
|
tomwalters@0
|
657
|
tomwalters@0
|
658 /* Adaptor 21 */
|
tomwalters@0
|
659 st[0] = st[2] - st[1] - st[3] ; /* b214 = a222 */
|
tomwalters@0
|
660
|
tomwalters@0
|
661
|
tomwalters@0
|
662 /*** computation in BACKWARD direction for current input point ***/
|
tomwalters@0
|
663
|
tomwalters@0
|
664 /* middle ear */
|
tomwalters@0
|
665
|
tomwalters@0
|
666 /* Adaptor 22 */
|
tomwalters@0
|
667 a0 = st[4] + st[0] ; /* a220 */
|
tomwalters@0
|
668 st[4] = st[4] - ms->gamma221 * a0 ; /* b221 */
|
tomwalters@0
|
669 b2 = -st[4] - a0 ; /* b222 = a214 */
|
tomwalters@0
|
670
|
tomwalters@0
|
671 /* Adaptor 21 */
|
tomwalters@0
|
672 a0 = b2 - st[0] ; /* a210 */
|
tomwalters@0
|
673 st[1] = st[1] - ms->gamma211 * a0 ; /* b211 */
|
tomwalters@0
|
674 b212 = st[3] - ms->gamma212 * a0 ; /* b212 = a204 */
|
tomwalters@0
|
675 st[2] = -st[1] - b212 - b2 ; /* b213 */
|
tomwalters@0
|
676
|
tomwalters@0
|
677 /* Adaptor 20 */
|
tomwalters@0
|
678 a0 = b212 - st[3] ; /* a200 */
|
tomwalters@0
|
679 b202 = - ms->gamma202 * a0 ; /* b202 */
|
tomwalters@0
|
680 b3 = ms->gamma201 * a0 - b202 - b212 ; /* b203 = a183 */
|
tomwalters@0
|
681
|
tomwalters@0
|
682 /* Adaptor 18 */
|
tomwalters@0
|
683 b2 = st[8] + b3 ; /* b182 = a193 */
|
tomwalters@0
|
684 b1 = b2 - st[7] ; /* b181 = a163 */
|
tomwalters@0
|
685
|
tomwalters@0
|
686 /* Adaptor 19 */
|
tomwalters@0
|
687 st[6] = st[6] + ms->gamma191 * ( st[5] - b2 ) ; /* b191 */
|
tomwalters@0
|
688
|
tomwalters@0
|
689 /* Adaptor 16 */
|
tomwalters@0
|
690 b161 = st[28] + ms->gamma161 * ( st[13] - b1 ) ; /* b161 = a103 */
|
tomwalters@0
|
691 b2 = -b161 - b1 ; /* b162 = a174 */
|
tomwalters@0
|
692
|
tomwalters@0
|
693 /* Adaptor 17 */
|
tomwalters@0
|
694 a0 = b2 - st[10] ; /* a170 */
|
tomwalters@0
|
695 st[11] = st[11] - ms->gamma171 * a0 ; /* b171 */
|
tomwalters@0
|
696 st[12] = ms->gamma172 * a0 - b2 - st[11] ; /* b173 */
|
tomwalters@0
|
697
|
tomwalters@0
|
698 /* Adaptor 10 */
|
tomwalters@0
|
699 st[37] = st[27] + b161 ; /* b102 = a73 */
|
tomwalters@0
|
700 st[38] = st[37] - st[26] ; /* b101 = a114 */
|
tomwalters@0
|
701
|
tomwalters@0
|
702 /* Adaptor 11 */
|
tomwalters@0
|
703 a0 = st[38] - st[25] ; /* a110 */
|
tomwalters@0
|
704 b1 = st[22] - ms->gamma111 * a0 ; /* b111 = a143 */
|
tomwalters@0
|
705 b2 = st[19] - ms->gamma112 * a0 ; /* b112 = a123 */
|
tomwalters@0
|
706 b3 = -b1 -b2 - st[38] ; /* b113 = a153 */
|
tomwalters@0
|
707
|
tomwalters@0
|
708 /* Adaptor 15 */
|
tomwalters@0
|
709 st[24] = st[24] + ms->gamma151 * ( st[23] - b3 ) ; /* b151 */
|
tomwalters@0
|
710
|
tomwalters@0
|
711 /* Adaptor 14 */
|
tomwalters@0
|
712 st[20] = st[21] + b1 ; /* b142 */
|
tomwalters@0
|
713
|
tomwalters@0
|
714 /* Adaptor 12 */
|
tomwalters@0
|
715 b2 = st[17] + b2 ; /* b122 = a133 */
|
tomwalters@0
|
716 st[18] = b2 + st[16] ; /* b121 */
|
tomwalters@0
|
717
|
tomwalters@0
|
718 /* Adaptor 13 */
|
tomwalters@0
|
719 st[14] = st[14] + ms->gamma131 * ( st[15] - b2 ) ; /* b131 */
|
tomwalters@0
|
720
|
tomwalters@0
|
721 /* Adaptor 7 */
|
tomwalters@0
|
722 b1 = st[34] + ms->gamma71 * ( st[36] - st[37] ) ; /* b71 = a84 */
|
tomwalters@0
|
723 st[39] = -b1 - st[37] ; /* b72 = a63 */
|
tomwalters@0
|
724
|
tomwalters@0
|
725 /* Adaptor 8 */
|
tomwalters@0
|
726 st[35] = st[33] + b1 ; /* b83 */
|
tomwalters@0
|
727 b1 = st[35] + st[32] ; /* b81 = a94 */
|
tomwalters@0
|
728
|
tomwalters@0
|
729 /* Adaptor 9 */
|
tomwalters@0
|
730 a0 = b1 - st[31] ; /* a90 */
|
tomwalters@0
|
731 st[29] = st[29] - ms->gamma91 * a0 ; /* b91 */
|
tomwalters@0
|
732 st[30] = -st[29] + ms->gamma92 * a0 - b1 ; /* b93 */
|
tomwalters@0
|
733
|
tomwalters@0
|
734 bn = st[39] ;
|
tomwalters@0
|
735
|
tomwalters@0
|
736 /* concha and auditory canal */
|
tomwalters@0
|
737
|
tomwalters@0
|
738 while( tube_segment-- > 0 ) {
|
tomwalters@0
|
739
|
tomwalters@0
|
740 /* get states */
|
tomwalters@0
|
741 ts = *--eartube_states ;
|
tomwalters@0
|
742 st = ( StateType * ) ts->states ;
|
tomwalters@0
|
743
|
tomwalters@0
|
744 /* Adaptor 6 */
|
tomwalters@0
|
745 b1 = st[7] - ts->gamma61 * ( bn - st[8] ) ; /* b61 = a43 */
|
tomwalters@0
|
746 st[9] = -b1 - bn ; /* b62 */
|
tomwalters@0
|
747
|
tomwalters@0
|
748 /* Adaptor 4 */
|
tomwalters@0
|
749 b2 = st[6] + b1 ; /* b42 = a53 */
|
tomwalters@0
|
750 b1 = b2 - st[5] ; /* b41 = a33 */
|
tomwalters@0
|
751
|
tomwalters@0
|
752 /* Adaptor 5 */
|
tomwalters@0
|
753 st[1] = st[0] + b2 ; /* b52 */
|
tomwalters@0
|
754
|
tomwalters@0
|
755 /* Adaptor 3 */
|
tomwalters@0
|
756 st[4] = ts->gamma31 * ( st[3] - b1 ) - st[4] ; /* b31 */
|
tomwalters@0
|
757 bn = -st[4] - b1 ; /* b32 = a63 */
|
tomwalters@0
|
758 }
|
tomwalters@0
|
759
|
tomwalters@0
|
760 /* freefield - external ear */
|
tomwalters@0
|
761
|
tomwalters@0
|
762 /* get states */
|
tomwalters@0
|
763 st = ( StateType * ) ws->states ;
|
tomwalters@0
|
764
|
tomwalters@0
|
765 /* Adaptor 1 */
|
tomwalters@0
|
766 b1 = ws->gamma11 * ( st[6] - bn ) - st[5] ; /* b11 = -a03 */
|
tomwalters@0
|
767 b2 = -b1 - bn ; /* b12 = a23 */
|
tomwalters@0
|
768
|
tomwalters@0
|
769 /* Adaptor 2 */
|
tomwalters@0
|
770 st[0] = st[1] + b2 + st[0] ; /* b61 */
|
tomwalters@0
|
771
|
tomwalters@0
|
772 /* Adaptor 0 */
|
tomwalters@0
|
773 st[3] = b1 - st[4] + st[3] ; /* -b01 + p */
|
tomwalters@0
|
774
|
tomwalters@0
|
775 /*** output ***/
|
tomwalters@0
|
776 #ifdef _EARDRUM_
|
tomwalters@0
|
777 st = ( StateType * ) ms->states ;
|
tomwalters@0
|
778 out = 0.5 * ( st[39] + an_1 ) * ms->out_scale ;
|
tomwalters@0
|
779 #else
|
tomwalters@0
|
780 out = -0.5 * b202 * ms->out_scale ;
|
tomwalters@0
|
781 #endif
|
tomwalters@0
|
782
|
tomwalters@0
|
783 #ifdef _OVERFLOW_
|
tomwalters@0
|
784 if( out > _MaxOutput_ || out < _MinOutput_ )
|
tomwalters@0
|
785 fprintf( stderr, "Overflow error in Outer/Middle ear output=%e\n", ( double ) out ) ;
|
tomwalters@0
|
786 #endif
|
tomwalters@0
|
787 *inout_ptr++ = out ;
|
tomwalters@0
|
788
|
tomwalters@0
|
789 }
|
tomwalters@0
|
790 return ;
|
tomwalters@0
|
791 }
|
tomwalters@0
|
792
|
tomwalters@0
|
793
|
tomwalters@0
|
794 /******************************* CloseEarWDF() *************************************/
|
tomwalters@0
|
795
|
tomwalters@0
|
796 void CloseEarWDF( wave_states, eartube_states, earmiddle_states, tube_segments )
|
tomwalters@0
|
797 register WaveWDFstate *wave_states ;
|
tomwalters@0
|
798 register EartubeWDFstate **eartube_states ;
|
tomwalters@0
|
799 register EarmiddleWDFstate *earmiddle_states ;
|
tomwalters@0
|
800 register int tube_segments ;
|
tomwalters@0
|
801 {
|
tomwalters@0
|
802 Delete( earmiddle_states->states ) ;
|
tomwalters@0
|
803 Delete( earmiddle_states ) ;
|
tomwalters@0
|
804
|
tomwalters@0
|
805 for( ; --tube_segments < 0 ; ) {
|
tomwalters@0
|
806 Delete( eartube_states[ tube_segments ]->states ) ;
|
tomwalters@0
|
807 Delete( eartube_states[ tube_segments ] ) ;
|
tomwalters@0
|
808 }
|
tomwalters@0
|
809 Delete( eartube_states ) ;
|
tomwalters@0
|
810
|
tomwalters@0
|
811 Delete( wave_states->states ) ;
|
tomwalters@0
|
812 Delete( wave_states ) ;
|
tomwalters@0
|
813
|
tomwalters@0
|
814 return ;
|
tomwalters@0
|
815
|
tomwalters@0
|
816 }
|
tomwalters@0
|
817
|
tomwalters@0
|
818 /************** low level functions **************/
|
tomwalters@0
|
819
|
tomwalters@0
|
820 static double den221 ;
|
tomwalters@0
|
821 static double Kst_old_ratio ;
|
tomwalters@0
|
822
|
tomwalters@0
|
823 void update_earmiddle_init( rate, z )
|
tomwalters@0
|
824 double rate, z ;
|
tomwalters@0
|
825 {
|
tomwalters@0
|
826 Kst_old_ratio = Kst_ratio ;
|
tomwalters@0
|
827 den221 = rate * z / Kst_max ;
|
tomwalters@0
|
828 return ;
|
tomwalters@0
|
829 }
|
tomwalters@0
|
830
|
tomwalters@0
|
831 void update_earmiddle( ms )
|
tomwalters@0
|
832 EarmiddleWDFstate *ms ;
|
tomwalters@0
|
833 {
|
tomwalters@0
|
834 if( Kst_ratio < Kst_min_ratio )
|
tomwalters@0
|
835 Kst_ratio = Kst_min_ratio ;
|
tomwalters@0
|
836
|
tomwalters@0
|
837 ms->gamma221 = 2. * Kst_ratio / ( Kst_ratio + den221 ) ;
|
tomwalters@0
|
838 ms->states[4] = ms->states[4] * Kst_ratio / Kst_old_ratio ;
|
tomwalters@0
|
839
|
tomwalters@0
|
840 Kst_old_ratio = Kst_ratio ;
|
tomwalters@0
|
841
|
tomwalters@0
|
842 return ;
|
tomwalters@0
|
843 }
|
tomwalters@0
|
844
|