4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1992-2001 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
31 #include <sys/types.h>
35 char *bcopy(char *, char *, int);
36 char *memmove(char *, char *, int);
39 #define BCOPY(src, dest, num) memmove(dest, src, num)
43 * returns the convolution of coef[length] and in_buf[length]:
45 * convolution = coef[0] * in_buf[length - 1] +
46 * coef[1] * in_buf[length - 2] +
48 * coef[length - 1] * in_buf[0]
60 double sum
= *coefs
* *in_buf
;
62 sum
+= *++coefs
* *--in_buf
;
67 void // convert short to double
74 *out
++ = (double)*in
++;
78 double2short(double in
) // limit double to short
82 else if (in
>= 32767.0)
88 void Fir:: // update state with data[size]
94 memcpy(state
, data
+ size
- order
, order
* sizeof (double));
96 int old
= order
- size
;
97 BCOPY((char *)(state
+ size
), (char *)state
,
98 old
* sizeof (double));
99 memcpy(state
+ order
- size
, data
, size
* sizeof (double));
108 double *in_buf
= new double[size
];
109 short2double(in_buf
, in
, size
);
110 updateState(in_buf
, size
);
115 resetState(void) // reset state to all zero
117 for (int i
= 0; i
< order
; i
++)
127 Fir(int order_in
): order(order_in
) // construct Fir object
129 state
= new double[order
];
131 coef
= new double[order
+ 1];
132 delay
= (order
+ 1) >> 1; // assuming symmetric FIR
136 ~Fir() // destruct Fir object
143 getOrder(void) // returns filter order
149 getNumCoefs(void) // returns number of filter coefficients
155 putCoef(double *coef_in
) // copy coef_in in filter coefficients
157 memcpy(coef
, coef_in
, (order
+ 1) * sizeof (double));
161 getCoef(double *coef_out
) // returns filter coefs in coef_out
163 memcpy(coef_out
, coef
, (order
+ 1) * sizeof (double));
166 int Fir:: // filter in[size], and updates the state.
175 double *in_buf
= new double[size
];
176 short2double(in_buf
, in
, size
); // convert short input to double
178 int init_size
= (size
<= order
)? size
: order
;
179 int init_order
= order
;
180 double *state_ptr
= state
;
181 short *out_ptr
= out
;
183 // the first "order" outputs need state in convolution
184 for (i
= 1; i
<= init_size
; i
++)
185 *out_ptr
++ = double2short(convolve(coef
, in_buf
, i
) +
186 convolve(coef
+ i
, state_ptr
++, init_order
--));
188 // starting from "order + 1"th output, state is no longer needed
192 double2short(convolve(coef
, state_ptr
++, order
+ 1));
193 updateState(in_buf
, size
);
195 return (out_ptr
- out
);
201 int group_delay
= (order
+ 1) >> 1;
202 return ((delay
< group_delay
)? group_delay
- delay
: 0);
206 flush(short *out
) // zero input response of Fir
208 int num
= getFlushSize();
210 short *in
= new short[num
];
211 memset(in
, 0, num
* sizeof (short));
212 num
= filter_noadjust(in
, num
, out
);
219 * filter() filters in[size] with filter delay adjusted to 0
221 * All FIR filters introduce a delay of "order" samples between input and
222 * output sequences. Most FIR filters are symmetric filters to keep the
223 * linear phase responses. For those FIR fitlers the group delay is
224 * "(order + 1) / 2". So filter_nodelay adjusts the group delay in the
225 * output sequence such that the output is aligned with the input and
226 * direct comparison between them is possible.
228 * The first call of filter returns "size - group_delay" output samples.
229 * After all the input samples have been filtered, filter() needs
230 * to be called with size = 0 to get the residual output samples to make
231 * the output sequence the same length as the input.
241 if ((size
<= 0) || (in
== NULL
))
244 return (filter_noadjust(in
, size
, out
));
245 else if (size
<= delay
) {
246 update_short(in
, size
);
250 update_short(in
, delay
);
254 return (filter_noadjust(in
, size
, out
));