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 upsample.c
|
tomwalters@0
|
42 ===========================================================
|
tomwalters@0
|
43
|
tomwalters@0
|
44 Upsampling module (FIR filter interpolation method).
|
tomwalters@0
|
45
|
tomwalters@0
|
46 Author : Christian Giguere
|
tomwalters@0
|
47 First written : 23rd November, 1990
|
tomwalters@0
|
48 Last edited : 09th February, 1994
|
tomwalters@0
|
49
|
tomwalters@0
|
50 Reference:
|
tomwalters@0
|
51 (1) L.R.Rabiner and R.W.Schafer (1978). Digital Processing of
|
tomwalters@0
|
52 Speech Signals (Prentice-Hall), Section 2.4.2.
|
tomwalters@0
|
53 ===========================================================
|
tomwalters@0
|
54 */
|
tomwalters@0
|
55
|
tomwalters@0
|
56 /***** includes *****/
|
tomwalters@0
|
57
|
tomwalters@0
|
58 #include <math.h>
|
tomwalters@0
|
59 #include <stdio.h>
|
tomwalters@0
|
60 #include "stitch.h"
|
tomwalters@0
|
61 #include "source.h"
|
tomwalters@0
|
62 #include "calc.h"
|
tomwalters@0
|
63 #include "calc_tl.h"
|
tomwalters@0
|
64 #include "fir.h"
|
tomwalters@0
|
65 #include "upsample.h"
|
tomwalters@0
|
66
|
tomwalters@0
|
67
|
tomwalters@0
|
68 /***** defines *****/
|
tomwalters@0
|
69
|
tomwalters@0
|
70 #define SEGMENT ( 2048 ) /* number of new points allocated and retained */
|
tomwalters@0
|
71 /* on each call to input source */
|
tomwalters@0
|
72
|
tomwalters@0
|
73
|
tomwalters@0
|
74 /***** functions *****/
|
tomwalters@0
|
75
|
tomwalters@0
|
76 /*******************************************************************************
|
tomwalters@0
|
77 * name: function:
|
tomwalters@0
|
78 *
|
tomwalters@0
|
79 * upsample_callback() Callable procedure returning pointer to upsampled data.
|
tomwalters@0
|
80 *
|
tomwalters@0
|
81 * UpSample() Setup and initialization function for the design of an
|
tomwalters@0
|
82 * FIR interpolation filter. Returns pointer to a new source.
|
tomwalters@0
|
83 ********************************************************************************/
|
tomwalters@0
|
84
|
tomwalters@0
|
85 struct _upsample_state {
|
tomwalters@0
|
86 struct _fillable_source parent ;
|
tomwalters@0
|
87 Source source ;
|
tomwalters@0
|
88 Pointer input ;
|
tomwalters@0
|
89 int iptr, inout_size ;
|
tomwalters@0
|
90 int zerocount, upsample_factor, sample_delay, active ;
|
tomwalters@0
|
91 void (*proc)(), (*close)() ;
|
tomwalters@0
|
92 FIRfilterState *states ;
|
tomwalters@0
|
93 } ;
|
tomwalters@0
|
94
|
tomwalters@0
|
95
|
tomwalters@0
|
96 /************************* upsample_callback() ******************************/
|
tomwalters@0
|
97
|
tomwalters@0
|
98 static Pointer upsample_callback( state, bytes, buffer )
|
tomwalters@0
|
99 struct _upsample_state *state ;
|
tomwalters@0
|
100 ByteCount *bytes ;
|
tomwalters@0
|
101 Pointer buffer ;
|
tomwalters@0
|
102 {
|
tomwalters@0
|
103 register DataType *optr, *eptr, *pstart ;
|
tomwalters@0
|
104 register int last = *bytes == 0 ;
|
tomwalters@0
|
105 register int points, bytecount ;
|
tomwalters@0
|
106
|
tomwalters@0
|
107 /***** process *****/
|
tomwalters@0
|
108 if( !last ) {
|
tomwalters@0
|
109
|
tomwalters@0
|
110 for( bytecount=0 ; bytecount<*bytes ; ) {
|
tomwalters@0
|
111
|
tomwalters@0
|
112 /*** get input data ***/
|
tomwalters@0
|
113 points = ( *bytes - bytecount ) / state->inout_size ;
|
tomwalters@0
|
114 points = MIN( points, state->upsample_factor * SEGMENT ) ;
|
tomwalters@0
|
115
|
tomwalters@0
|
116 if( !state->active ) {
|
tomwalters@0
|
117
|
tomwalters@0
|
118 if( state->sample_delay == 0 )
|
tomwalters@0
|
119 state->active = 1 ;
|
tomwalters@0
|
120
|
tomwalters@0
|
121 else if( state->sample_delay > points )
|
tomwalters@0
|
122 state->sample_delay -= points ;
|
tomwalters@0
|
123
|
tomwalters@0
|
124 else {
|
tomwalters@0
|
125 points = state->sample_delay ;
|
tomwalters@0
|
126 state->sample_delay = 0 ;
|
tomwalters@0
|
127 }
|
tomwalters@0
|
128 }
|
tomwalters@0
|
129
|
tomwalters@0
|
130 if( state->iptr + ( points - 1 ) / state->upsample_factor >= SEGMENT ) {
|
tomwalters@0
|
131 state->input = Pull( state->source, SEGMENT * state->inout_size ) ;
|
tomwalters@0
|
132 state->iptr -= SEGMENT ;
|
tomwalters@0
|
133 }
|
tomwalters@0
|
134
|
tomwalters@0
|
135 /*** fill output buffer with input points interspaced with zeros prior to FIR filtering ***/
|
tomwalters@0
|
136 pstart = ( DataType * ) state->input ;
|
tomwalters@0
|
137 optr = ( DataType * ) ( buffer + bytecount ) ;
|
tomwalters@0
|
138 eptr = optr + points ;
|
tomwalters@0
|
139
|
tomwalters@0
|
140 while( optr < eptr ) {
|
tomwalters@0
|
141
|
tomwalters@0
|
142 if( ( state->zerocount %= state->upsample_factor ) > 0 )
|
tomwalters@0
|
143 *optr++ = 0 ;
|
tomwalters@0
|
144
|
tomwalters@0
|
145 else
|
tomwalters@0
|
146 *optr++ = pstart[state->iptr++] ;
|
tomwalters@0
|
147
|
tomwalters@0
|
148 state->zerocount++ ;
|
tomwalters@0
|
149 }
|
tomwalters@0
|
150
|
tomwalters@0
|
151 /*** filter data ***/
|
tomwalters@0
|
152 state->proc( state->states, buffer+bytecount, points ) ;
|
tomwalters@0
|
153
|
tomwalters@0
|
154 /*** loop counts ***/
|
tomwalters@0
|
155 bytecount += points * state->inout_size * state->active ;
|
tomwalters@0
|
156 }
|
tomwalters@0
|
157
|
tomwalters@0
|
158 return ( buffer ) ;
|
tomwalters@0
|
159 }
|
tomwalters@0
|
160
|
tomwalters@0
|
161
|
tomwalters@0
|
162 /***** close *****/
|
tomwalters@0
|
163 else {
|
tomwalters@0
|
164 Pull( state->source, 0 ) ;
|
tomwalters@0
|
165 state->close( state->states ) ;
|
tomwalters@0
|
166
|
tomwalters@0
|
167 return ( DeleteFillableSource( state ) ) ;
|
tomwalters@0
|
168 }
|
tomwalters@0
|
169
|
tomwalters@0
|
170 }
|
tomwalters@0
|
171
|
tomwalters@0
|
172
|
tomwalters@0
|
173 /****************************** UpSample() **********************************/
|
tomwalters@0
|
174
|
tomwalters@0
|
175 Source UpSample( source, oldsamplerate, cutoff_freq, upsample_factor )
|
tomwalters@0
|
176 Source source ;
|
tomwalters@0
|
177 double oldsamplerate, cutoff_freq ;
|
tomwalters@0
|
178 int upsample_factor ;
|
tomwalters@0
|
179 {
|
tomwalters@0
|
180 DeclareNew( struct _upsample_state *, state ) ;
|
tomwalters@0
|
181 double filterGain, wc ;
|
tomwalters@0
|
182
|
tomwalters@0
|
183 /***** initialise input-related parameters *****/
|
tomwalters@0
|
184 state->inout_size = sizeof ( DataType ) ;
|
tomwalters@0
|
185 state->input = ( Pointer ) 0 ;
|
tomwalters@0
|
186 state->iptr = SEGMENT ;
|
tomwalters@0
|
187 state->source = NewRetainingSource( source, SEGMENT * state->inout_size ) ;
|
tomwalters@0
|
188 state->zerocount = 0 ;
|
tomwalters@0
|
189 state->upsample_factor = upsample_factor ;
|
tomwalters@0
|
190
|
tomwalters@0
|
191 /***** Specify FIR filter design parameters *****/
|
tomwalters@0
|
192 wc = cutoff_freq / ( state->upsample_factor * oldsamplerate ) * TwoPi ;
|
tomwalters@0
|
193 state->states = NewLpFIRfilter( wc, upsample_factor, &state->sample_delay ) ;
|
tomwalters@0
|
194 state->active = 0 ;
|
tomwalters@0
|
195 state->proc = DoFIRfilter ;
|
tomwalters@0
|
196 state->close = CloseFIRfilter ;
|
tomwalters@0
|
197
|
tomwalters@0
|
198 /***** return *****/
|
tomwalters@0
|
199 source = SetFillableSource( state, upsample_callback, "upsample buffering" ) ;
|
tomwalters@0
|
200 return ( source ) ;
|
tomwalters@0
|
201
|
tomwalters@0
|
202 }
|
tomwalters@0
|
203
|