tomwalters@0: /* tomwalters@0: Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989 tomwalters@0: =========================================================================== tomwalters@0: tomwalters@0: Permission to use, copy, modify, and distribute this software without fee tomwalters@0: is hereby granted for research purposes, provided that this copyright tomwalters@0: notice appears in all copies and in all supporting documentation, and that tomwalters@0: the software is not redistributed for any fee (except for a nominal shipping tomwalters@0: charge). Anyone wanting to incorporate all or part of this software in a tomwalters@0: commercial product must obtain a license from the Medical Research Council. tomwalters@0: tomwalters@0: The MRC makes no representations about the suitability of this tomwalters@0: software for any purpose. It is provided "as is" without express or implied tomwalters@0: warranty. tomwalters@0: tomwalters@0: THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING tomwalters@0: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE tomwalters@0: A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY tomwalters@0: DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN tomwalters@0: AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF tomwalters@0: OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. tomwalters@0: */ tomwalters@0: tomwalters@0: /* tomwalters@0: Acknowledgment: tomwalters@0: ============== tomwalters@0: tomwalters@0: The source code provided in this file was originally developed by tomwalters@0: Christian Giguere as part of a Ph.D degree at the Department of tomwalters@0: Engineering of the University of Cambridge from April 1990 to tomwalters@0: November 1993. The code was subsequently adapted under a grant tomwalters@0: from the Hearing Research Trust for full compatibility with tomwalters@0: AIM Release 6.15. tomwalters@0: tomwalters@0: Christian Giguere 25/03/94 tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: /* tomwalters@0: =========================================================== tomwalters@0: ear.c tomwalters@0: =========================================================== tomwalters@0: tomwalters@0: Design of outer and middle ear (EAR) filter. tomwalters@0: (uncoupled version) tomwalters@0: tomwalters@0: Author : Christian Giguere tomwalters@0: First written : 01st June, 1991 tomwalters@0: Last edited : 07th March, 1994 tomwalters@0: =========================================================== tomwalters@0: */ tomwalters@0: tomwalters@0: tomwalters@0: /***** includes *****/ tomwalters@0: tomwalters@0: #include tomwalters@0: #include tomwalters@0: #include "stitch.h" tomwalters@0: #include "source.h" tomwalters@0: #include "calc.h" tomwalters@0: #include "calc_tl.h" tomwalters@0: #include "wdf_ear.h" tomwalters@0: #include "ear.h" tomwalters@0: tomwalters@0: tomwalters@0: /***** defines *****/ tomwalters@0: tomwalters@0: #if 0 tomwalters@0: #define _DEBUG_ tomwalters@0: #endif tomwalters@0: tomwalters@0: /***** functions *****/ tomwalters@0: tomwalters@0: tomwalters@0: /************************************************************************** tomwalters@0: * name: function: tomwalters@0: * tomwalters@0: * ear_callback() Callable procedure returning pointer to filtered tomwalters@0: * data (stapes velocity). tomwalters@0: * tomwalters@0: * Ear() Set-up and initialization function for the design tomwalters@0: * of the outer and middle ear filter (this filter is tomwalters@0: * not coupled to the cochlea). Returns pointer to tomwalters@0: * a new source. tomwalters@0: ***************************************************************************/ tomwalters@0: tomwalters@0: struct _ear_state { tomwalters@0: struct _fillable_source parent ; tomwalters@0: Source source ; tomwalters@0: Pointer input ; tomwalters@0: int inout_size ; tomwalters@0: void (*proc)(), (*close)() ; tomwalters@0: int Ntube ; tomwalters@0: WaveWDFstate *wave_states ; tomwalters@0: EartubeWDFstate **eartube_states ; tomwalters@0: EarmiddleWDFstate *earmiddle_states ; tomwalters@0: } ; tomwalters@0: tomwalters@0: tomwalters@0: /******************************** ear_callback() *************************************/ tomwalters@0: tomwalters@0: static Pointer ear_callback( state, bytes, buffer ) tomwalters@0: struct _ear_state *state ; tomwalters@0: ByteCount *bytes ; tomwalters@0: Pointer buffer ; tomwalters@0: { tomwalters@0: register int last = *bytes == 0 ; tomwalters@0: register int points ; tomwalters@0: tomwalters@0: /***** process *****/ tomwalters@0: if( !last ) { tomwalters@0: tomwalters@0: /*** get input data ***/ tomwalters@0: Fill(state->source, *bytes, buffer ) ; tomwalters@0: tomwalters@0: /*** process data ***/ tomwalters@0: points = *bytes / state->inout_size ; tomwalters@0: state->proc( state->wave_states, state->eartube_states, state->earmiddle_states, tomwalters@0: state->Ntube, buffer, points ) ; tomwalters@0: tomwalters@0: return ( buffer ) ; tomwalters@0: } tomwalters@0: tomwalters@0: /***** close *****/ tomwalters@0: else { tomwalters@0: tomwalters@0: Fill( state->source, 0, buffer ) ; tomwalters@0: state->close( state->wave_states, state->eartube_states, state->earmiddle_states, state->Ntube ) ; tomwalters@0: tomwalters@0: return ( DeleteFillableSource( state ) ) ; tomwalters@0: } tomwalters@0: tomwalters@0: } tomwalters@0: tomwalters@0: tomwalters@0: /************************************ Ear() *******************************************/ tomwalters@0: tomwalters@0: Source Ear( source, samplerate, output_gain, concha, canal ) tomwalters@0: Source source ; tomwalters@0: double samplerate, output_gain ; tomwalters@0: TubeInfo *concha, *canal ; tomwalters@0: { tomwalters@0: DeclareNew( struct _ear_state *, state ) ; tomwalters@0: double length, diam, attn ; tomwalters@0: int segment ; tomwalters@0: tomwalters@0: /***** initialise input-related parameters *****/ tomwalters@0: state->inout_size = sizeof ( DataType ) ; tomwalters@0: state->input = ( Pointer ) 0 ; tomwalters@0: state->source = source ; tomwalters@0: tomwalters@0: /***** Specify WDF filter design parameters *****/ tomwalters@0: state->wave_states = FreefieldWDF( samplerate, RHO_air, C, As, concha->diameter/2. ) ; tomwalters@0: tomwalters@0: state->Ntube = canal->Nsegments + concha->Nsegments ; tomwalters@0: state->eartube_states = NewArray( EartubeWDFstate *, state->Ntube, "ear.c for eartube states" ) ; tomwalters@0: tomwalters@0: length = concha->length / concha->Nsegments ; tomwalters@0: diam = concha->diameter ; tomwalters@0: attn = concha->att_factor ; tomwalters@0: for( segment = 0 ; segment < concha->Nsegments ; segment++ ) tomwalters@0: state->eartube_states[ segment ] = EartubeWDF( samplerate, RHO_air, C, diam, length, attn ) ; tomwalters@0: tomwalters@0: length = canal->length / canal->Nsegments ; tomwalters@0: diam = canal->diameter ; tomwalters@0: attn = canal->att_factor ; tomwalters@0: for( ; segment < state->Ntube ; segment++ ) tomwalters@0: state->eartube_states[ segment ] = EartubeWDF( samplerate, RHO_air, C, diam, length, attn ) ; tomwalters@0: tomwalters@0: state->earmiddle_states = EarmiddleWDF( samplerate, 0.0, output_gain, 1.0 ) ; tomwalters@0: tomwalters@0: state->proc = DoEarWDF ; tomwalters@0: state->close = CloseEarWDF ; tomwalters@0: tomwalters@0: /***** return *****/ tomwalters@0: source = SetFillableSource( state, ear_callback, "ear filter stage" ) ; tomwalters@0: return ( source ) ; tomwalters@0: tomwalters@0: } tomwalters@0: