Mercurial > hg > aim92
diff wdf/upsample.c @ 0:5242703e91d3 tip
Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author | tomwalters |
---|---|
date | Fri, 20 May 2011 15:19:45 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wdf/upsample.c Fri May 20 15:19:45 2011 +0100 @@ -0,0 +1,203 @@ +/* + Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989 + =========================================================================== + + Permission to use, copy, modify, and distribute this software without fee + is hereby granted for research purposes, provided that this copyright + notice appears in all copies and in all supporting documentation, and that + the software is not redistributed for any fee (except for a nominal shipping + charge). Anyone wanting to incorporate all or part of this software in a + commercial product must obtain a license from the Medical Research Council. + + The MRC makes no representations about the suitability of this + software for any purpose. It is provided "as is" without express or implied + warranty. + + THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE + A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY + DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/* + Acknowledgment: + ============== + + The source code provided in this file was originally developed by + Christian Giguere as part of a Ph.D degree at the Department of + Engineering of the University of Cambridge from April 1990 to + November 1993. The code was subsequently adapted under a grant + from the Hearing Research Trust for full compatibility with + AIM Release 6.15. + + Christian Giguere 25/03/94 + +*/ + +/* + =========================================================== + upsample.c + =========================================================== + + Upsampling module (FIR filter interpolation method). + + Author : Christian Giguere + First written : 23rd November, 1990 + Last edited : 09th February, 1994 + + Reference: + (1) L.R.Rabiner and R.W.Schafer (1978). Digital Processing of + Speech Signals (Prentice-Hall), Section 2.4.2. + =========================================================== +*/ + +/***** includes *****/ + +#include <math.h> +#include <stdio.h> +#include "stitch.h" +#include "source.h" +#include "calc.h" +#include "calc_tl.h" +#include "fir.h" +#include "upsample.h" + + +/***** defines *****/ + +#define SEGMENT ( 2048 ) /* number of new points allocated and retained */ + /* on each call to input source */ + + +/***** functions *****/ + +/******************************************************************************* +* name: function: +* +* upsample_callback() Callable procedure returning pointer to upsampled data. +* +* UpSample() Setup and initialization function for the design of an +* FIR interpolation filter. Returns pointer to a new source. +********************************************************************************/ + +struct _upsample_state { + struct _fillable_source parent ; + Source source ; + Pointer input ; + int iptr, inout_size ; + int zerocount, upsample_factor, sample_delay, active ; + void (*proc)(), (*close)() ; + FIRfilterState *states ; + } ; + + +/************************* upsample_callback() ******************************/ + +static Pointer upsample_callback( state, bytes, buffer ) + struct _upsample_state *state ; + ByteCount *bytes ; + Pointer buffer ; +{ + register DataType *optr, *eptr, *pstart ; + register int last = *bytes == 0 ; + register int points, bytecount ; + + /***** process *****/ + if( !last ) { + + for( bytecount=0 ; bytecount<*bytes ; ) { + + /*** get input data ***/ + points = ( *bytes - bytecount ) / state->inout_size ; + points = MIN( points, state->upsample_factor * SEGMENT ) ; + + if( !state->active ) { + + if( state->sample_delay == 0 ) + state->active = 1 ; + + else if( state->sample_delay > points ) + state->sample_delay -= points ; + + else { + points = state->sample_delay ; + state->sample_delay = 0 ; + } + } + + if( state->iptr + ( points - 1 ) / state->upsample_factor >= SEGMENT ) { + state->input = Pull( state->source, SEGMENT * state->inout_size ) ; + state->iptr -= SEGMENT ; + } + + /*** fill output buffer with input points interspaced with zeros prior to FIR filtering ***/ + pstart = ( DataType * ) state->input ; + optr = ( DataType * ) ( buffer + bytecount ) ; + eptr = optr + points ; + + while( optr < eptr ) { + + if( ( state->zerocount %= state->upsample_factor ) > 0 ) + *optr++ = 0 ; + + else + *optr++ = pstart[state->iptr++] ; + + state->zerocount++ ; + } + + /*** filter data ***/ + state->proc( state->states, buffer+bytecount, points ) ; + + /*** loop counts ***/ + bytecount += points * state->inout_size * state->active ; + } + + return ( buffer ) ; + } + + + /***** close *****/ + else { + Pull( state->source, 0 ) ; + state->close( state->states ) ; + + return ( DeleteFillableSource( state ) ) ; + } + +} + + +/****************************** UpSample() **********************************/ + +Source UpSample( source, oldsamplerate, cutoff_freq, upsample_factor ) + Source source ; + double oldsamplerate, cutoff_freq ; + int upsample_factor ; +{ + DeclareNew( struct _upsample_state *, state ) ; + double filterGain, wc ; + + /***** initialise input-related parameters *****/ + state->inout_size = sizeof ( DataType ) ; + state->input = ( Pointer ) 0 ; + state->iptr = SEGMENT ; + state->source = NewRetainingSource( source, SEGMENT * state->inout_size ) ; + state->zerocount = 0 ; + state->upsample_factor = upsample_factor ; + + /***** Specify FIR filter design parameters *****/ + wc = cutoff_freq / ( state->upsample_factor * oldsamplerate ) * TwoPi ; + state->states = NewLpFIRfilter( wc, upsample_factor, &state->sample_delay ) ; + state->active = 0 ; + state->proc = DoFIRfilter ; + state->close = CloseFIRfilter ; + + /***** return *****/ + source = SetFillableSource( state, upsample_callback, "upsample buffering" ) ; + return ( source ) ; + +} +