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: phase.c tomwalters@0: ======= tomwalters@0: tomwalters@0: looks after phase compensation of all filter types tomwalters@0: tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: #include "stitch.h" tomwalters@0: #include "phase.h" tomwalters@0: tomwalters@0: tomwalters@0: PhaseCompensatorState *NewPhaseCompensator( filter_state, filter_module, sample_delay ) tomwalters@0: FilterState filter_state ; tomwalters@0: FilterModule filter_module ; tomwalters@0: double sample_delay ; tomwalters@0: { tomwalters@0: DeclareNew( PhaseCompensatorState *, compensator_state ) ; tomwalters@0: tomwalters@0: compensator_state->filter_state = filter_state ; tomwalters@0: compensator_state->filter_module = filter_module ; tomwalters@0: compensator_state->sample_delay = sample_delay + 0.5 ; tomwalters@0: tomwalters@0: compensator_state->delay_buffer = ( Pointer ) 0 ; tomwalters@0: tomwalters@0: return( compensator_state ) ; tomwalters@0: } tomwalters@0: tomwalters@0: PointCount PhaseCompensateFilter( compensator_state, input, output, points ) tomwalters@0: PhaseCompensatorState *compensator_state ; tomwalters@0: Pointer input ; tomwalters@0: Pointer output ; tomwalters@0: PointCount points ; tomwalters@0: { tomwalters@0: unsigned output_size ; tomwalters@0: int byte_delay, bytes ; tomwalters@0: PointCount process ; tomwalters@0: Pointer input_ptr ; tomwalters@0: static int zero = 0 ; tomwalters@0: tomwalters@0: /* support for new and old zero point transfers to get any remaining tomwalters@0: data from filters - in short a mess */ tomwalters@0: tomwalters@0: if( compensator_state->sample_delay < 0 && ( input == ( Pointer ) 0 || points == 0 ) ) { tomwalters@0: process = - ( int ) compensator_state->sample_delay ; tomwalters@0: tomwalters@0: if( process > points && points != 0 ) tomwalters@0: process = points ; tomwalters@0: tomwalters@0: compensator_state->sample_delay = ( int ) compensator_state->sample_delay + process ; tomwalters@0: tomwalters@0: input_ptr = ( Pointer ) 0 ; tomwalters@0: } tomwalters@0: else { tomwalters@0: process = points ; tomwalters@0: input_ptr = input ; tomwalters@0: } tomwalters@0: tomwalters@0: /* call filter pod */ tomwalters@0: tomwalters@0: output_size = compensator_state->filter_module( tomwalters@0: &compensator_state->filter_state, tomwalters@0: &zero, tomwalters@0: input_ptr, tomwalters@0: output, tomwalters@0: process, tomwalters@0: 1 tomwalters@0: ) ; tomwalters@0: tomwalters@0: byte_delay = ( int ) compensator_state->sample_delay * output_size ; tomwalters@0: bytes = points * output_size ; tomwalters@0: tomwalters@0: if( compensator_state->delay_buffer == ( Pointer ) 0 ) tomwalters@0: if( ( int ) compensator_state->sample_delay < 0 ) { tomwalters@0: stitch_bcopy( output - byte_delay, output, bytes - byte_delay ) ; tomwalters@0: compensator_state->delay_buffer = ( Pointer ) 0 + 1 ; tomwalters@0: tomwalters@0: return( points + ( int ) compensator_state->sample_delay ) ; tomwalters@0: } tomwalters@0: else tomwalters@0: compensator_state->delay_buffer = stitch_calloc( tomwalters@0: ( unsigned ) compensator_state->sample_delay * 2, tomwalters@0: output_size, "phase.c for delay buffer\n" ) ; tomwalters@0: tomwalters@0: if( byte_delay > bytes ) { tomwalters@0: stitch_bcopy( output, compensator_state->delay_buffer + byte_delay, bytes ) ; tomwalters@0: stitch_bcopy( compensator_state->delay_buffer, output, bytes ) ; tomwalters@0: stitch_bcopy( compensator_state->delay_buffer + bytes, compensator_state->delay_buffer, byte_delay ) ; tomwalters@0: } tomwalters@0: else if( byte_delay > 0 ) { tomwalters@0: stitch_bcopy( output + bytes - byte_delay, compensator_state->delay_buffer + byte_delay, byte_delay ) ; tomwalters@0: stitch_bcopy( output, output + byte_delay, bytes - byte_delay ) ; tomwalters@0: stitch_bcopy( compensator_state->delay_buffer, output, byte_delay ) ; tomwalters@0: stitch_bcopy( compensator_state->delay_buffer + byte_delay, compensator_state->delay_buffer, byte_delay ) ; tomwalters@0: } tomwalters@0: tomwalters@0: return( process ) ; tomwalters@0: } tomwalters@0: tomwalters@0: void FreeCompensatedFilter( compensator_state ) tomwalters@0: PhaseCompensatorState *compensator_state ; tomwalters@0: { tomwalters@0: stitch_free( compensator_state->filter_state ) ; tomwalters@0: stitch_free( ( Pointer ) compensator_state ) ; tomwalters@0: tomwalters@0: return ; tomwalters@0: } tomwalters@0: