comparison spandsp-0.0.6pre17/src/spandsp/fir.h @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * fir.h - General telephony FIR routines
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2002 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: fir.h,v 1.13 2008/04/17 14:27:00 steveu Exp $
26 */
27
28 /*! \page fir_page FIR filtering
29 \section fir_page_sec_1 What does it do?
30 ???.
31
32 \section fir_page_sec_2 How does it work?
33 ???.
34 */
35
36 #if !defined(_SPANDSP_FIR_H_)
37 #define _SPANDSP_FIR_H_
38
39 #if defined(USE_MMX) || defined(USE_SSE2)
40 #include "mmx.h"
41 #endif
42
43 /*!
44 16 bit integer FIR descriptor. This defines the working state for a single
45 instance of an FIR filter using 16 bit integer coefficients.
46 */
47 typedef struct
48 {
49 int taps;
50 int curr_pos;
51 const int16_t *coeffs;
52 int16_t *history;
53 } fir16_state_t;
54
55 /*!
56 32 bit integer FIR descriptor. This defines the working state for a single
57 instance of an FIR filter using 32 bit integer coefficients, and filtering
58 16 bit integer data.
59 */
60 typedef struct
61 {
62 int taps;
63 int curr_pos;
64 const int32_t *coeffs;
65 int16_t *history;
66 } fir32_state_t;
67
68 /*!
69 Floating point FIR descriptor. This defines the working state for a single
70 instance of an FIR filter using floating point coefficients and data.
71 */
72 typedef struct
73 {
74 int taps;
75 int curr_pos;
76 const float *coeffs;
77 float *history;
78 } fir_float_state_t;
79
80 #if defined(__cplusplus)
81 extern "C"
82 {
83 #endif
84
85 static __inline__ const int16_t *fir16_create(fir16_state_t *fir,
86 const int16_t *coeffs,
87 int taps)
88 {
89 fir->taps = taps;
90 fir->curr_pos = taps - 1;
91 fir->coeffs = coeffs;
92 #if defined(USE_MMX) || defined(USE_SSE2)
93 if ((fir->history = malloc(2*taps*sizeof(int16_t))))
94 memset(fir->history, 0, 2*taps*sizeof(int16_t));
95 #else
96 if ((fir->history = (int16_t *) malloc(taps*sizeof(int16_t))))
97 memset(fir->history, 0, taps*sizeof(int16_t));
98 #endif
99 return fir->history;
100 }
101 /*- End of function --------------------------------------------------------*/
102
103 static __inline__ void fir16_flush(fir16_state_t *fir)
104 {
105 #if defined(USE_MMX) || defined(USE_SSE2)
106 memset(fir->history, 0, 2*fir->taps*sizeof(int16_t));
107 #else
108 memset(fir->history, 0, fir->taps*sizeof(int16_t));
109 #endif
110 }
111 /*- End of function --------------------------------------------------------*/
112
113 static __inline__ void fir16_free(fir16_state_t *fir)
114 {
115 free(fir->history);
116 }
117 /*- End of function --------------------------------------------------------*/
118
119 static __inline__ int16_t fir16(fir16_state_t *fir, int16_t sample)
120 {
121 int i;
122 int32_t y;
123 #if defined(USE_MMX)
124 mmx_t *mmx_coeffs;
125 mmx_t *mmx_hist;
126
127 fir->history[fir->curr_pos] = sample;
128 fir->history[fir->curr_pos + fir->taps] = sample;
129
130 mmx_coeffs = (mmx_t *) fir->coeffs;
131 mmx_hist = (mmx_t *) &fir->history[fir->curr_pos];
132 i = fir->taps;
133 pxor_r2r(mm4, mm4);
134 /* 8 samples per iteration, so the filter must be a multiple of 8 long. */
135 while (i > 0)
136 {
137 movq_m2r(mmx_coeffs[0], mm0);
138 movq_m2r(mmx_coeffs[1], mm2);
139 movq_m2r(mmx_hist[0], mm1);
140 movq_m2r(mmx_hist[1], mm3);
141 mmx_coeffs += 2;
142 mmx_hist += 2;
143 pmaddwd_r2r(mm1, mm0);
144 pmaddwd_r2r(mm3, mm2);
145 paddd_r2r(mm0, mm4);
146 paddd_r2r(mm2, mm4);
147 i -= 8;
148 }
149 movq_r2r(mm4, mm0);
150 psrlq_i2r(32, mm0);
151 paddd_r2r(mm0, mm4);
152 movd_r2m(mm4, y);
153 emms();
154 #elif defined(USE_SSE2)
155 xmm_t *xmm_coeffs;
156 xmm_t *xmm_hist;
157
158 fir->history[fir->curr_pos] = sample;
159 fir->history[fir->curr_pos + fir->taps] = sample;
160
161 xmm_coeffs = (xmm_t *) fir->coeffs;
162 xmm_hist = (xmm_t *) &fir->history[fir->curr_pos];
163 i = fir->taps;
164 pxor_r2r(xmm4, xmm4);
165 /* 16 samples per iteration, so the filter must be a multiple of 16 long. */
166 while (i > 0)
167 {
168 movdqu_m2r(xmm_coeffs[0], xmm0);
169 movdqu_m2r(xmm_coeffs[1], xmm2);
170 movdqu_m2r(xmm_hist[0], xmm1);
171 movdqu_m2r(xmm_hist[1], xmm3);
172 xmm_coeffs += 2;
173 xmm_hist += 2;
174 pmaddwd_r2r(xmm1, xmm0);
175 pmaddwd_r2r(xmm3, xmm2);
176 paddd_r2r(xmm0, xmm4);
177 paddd_r2r(xmm2, xmm4);
178 i -= 16;
179 }
180 movdqa_r2r(xmm4, xmm0);
181 psrldq_i2r(8, xmm0);
182 paddd_r2r(xmm0, xmm4);
183 movdqa_r2r(xmm4, xmm0);
184 psrldq_i2r(4, xmm0);
185 paddd_r2r(xmm0, xmm4);
186 movd_r2m(xmm4, y);
187 #else
188 int offset1;
189 int offset2;
190
191 fir->history[fir->curr_pos] = sample;
192
193 offset2 = fir->curr_pos;
194 offset1 = fir->taps - offset2;
195 y = 0;
196 for (i = fir->taps - 1; i >= offset1; i--)
197 y += fir->coeffs[i]*fir->history[i - offset1];
198 for ( ; i >= 0; i--)
199 y += fir->coeffs[i]*fir->history[i + offset2];
200 #endif
201 if (fir->curr_pos <= 0)
202 fir->curr_pos = fir->taps;
203 fir->curr_pos--;
204 return (int16_t) (y >> 15);
205 }
206 /*- End of function --------------------------------------------------------*/
207
208 static __inline__ const int16_t *fir32_create(fir32_state_t *fir,
209 const int32_t *coeffs,
210 int taps)
211 {
212 fir->taps = taps;
213 fir->curr_pos = taps - 1;
214 fir->coeffs = coeffs;
215 fir->history = (int16_t *) malloc(taps*sizeof(int16_t));
216 if (fir->history)
217 memset(fir->history, '\0', taps*sizeof(int16_t));
218 return fir->history;
219 }
220 /*- End of function --------------------------------------------------------*/
221
222 static __inline__ void fir32_flush(fir32_state_t *fir)
223 {
224 memset(fir->history, 0, fir->taps*sizeof(int16_t));
225 }
226 /*- End of function --------------------------------------------------------*/
227
228 static __inline__ void fir32_free(fir32_state_t *fir)
229 {
230 free(fir->history);
231 }
232 /*- End of function --------------------------------------------------------*/
233
234 static __inline__ int16_t fir32(fir32_state_t *fir, int16_t sample)
235 {
236 int i;
237 int32_t y;
238 int offset1;
239 int offset2;
240
241 fir->history[fir->curr_pos] = sample;
242 offset2 = fir->curr_pos;
243 offset1 = fir->taps - offset2;
244 y = 0;
245 for (i = fir->taps - 1; i >= offset1; i--)
246 y += fir->coeffs[i]*fir->history[i - offset1];
247 for ( ; i >= 0; i--)
248 y += fir->coeffs[i]*fir->history[i + offset2];
249 if (fir->curr_pos <= 0)
250 fir->curr_pos = fir->taps;
251 fir->curr_pos--;
252 return (int16_t) (y >> 15);
253 }
254 /*- End of function --------------------------------------------------------*/
255
256 static __inline__ const float *fir_float_create(fir_float_state_t *fir,
257 const float *coeffs,
258 int taps)
259 {
260 fir->taps = taps;
261 fir->curr_pos = taps - 1;
262 fir->coeffs = coeffs;
263 fir->history = (float *) malloc(taps*sizeof(float));
264 if (fir->history)
265 memset(fir->history, '\0', taps*sizeof(float));
266 return fir->history;
267 }
268 /*- End of function --------------------------------------------------------*/
269
270 static __inline__ void fir_float_free(fir_float_state_t *fir)
271 {
272 free(fir->history);
273 }
274 /*- End of function --------------------------------------------------------*/
275
276 static __inline__ int16_t fir_float(fir_float_state_t *fir, int16_t sample)
277 {
278 int i;
279 float y;
280 int offset1;
281 int offset2;
282
283 fir->history[fir->curr_pos] = sample;
284
285 offset2 = fir->curr_pos;
286 offset1 = fir->taps - offset2;
287 y = 0;
288 for (i = fir->taps - 1; i >= offset1; i--)
289 y += fir->coeffs[i]*fir->history[i - offset1];
290 for ( ; i >= 0; i--)
291 y += fir->coeffs[i]*fir->history[i + offset2];
292 if (fir->curr_pos <= 0)
293 fir->curr_pos = fir->taps;
294 fir->curr_pos--;
295 return (int16_t) y;
296 }
297 /*- End of function --------------------------------------------------------*/
298
299 #if defined(__cplusplus)
300 }
301 #endif
302
303 #endif
304 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.