2
* SpanDSP - a series of DSP components for telephony
4
* filter_tools.c - A collection of routines used for filter design.
6
* Written by Steve Underwood <steveu@coppice.org>
8
* Copyright (C) 2008 Steve Underwood
10
* This includes some elements based on the mkfilter package by
11
* A.J. Fisher, University of York <fisher@minster.york.ac.uk>, November 1996
13
* All rights reserved.
15
* This program is free software; you can redistribute it and/or modify
16
* it under the terms of the GNU General Public License version 2, as
17
* published by the Free Software Foundation.
19
* This program is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU General Public License for more details.
24
* You should have received a copy of the GNU General Public License
25
* along with this program; if not, write to the Free Software
26
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28
* $Id: filter_tools.c,v 1.2 2008/01/10 14:06:21 steveu Exp $
38
#if defined(HAVE_TGMATH_H)
41
#if defined(HAVE_MATH_H)
50
#include "filter_tools.h"
58
static complex_t circle[SEQLEN/2];
60
static __inline__ complex_t expj(double theta)
62
return complex_set(cos(theta), sin(theta));
64
/*- End of function --------------------------------------------------------*/
66
static __inline__ double fix(double x)
69
return (x >= 0.0) ? floor(0.5 + x) : -floor(0.5 - x);
71
/*- End of function --------------------------------------------------------*/
73
static void fftx(complex_t data[], complex_t temp[], int n)
85
for (i = 0; i < h; i++)
88
temp[i] = data[i2]; /* Even */
89
temp[h + i] = data[i2 + 1]; /* Odd */
91
fftx(&temp[0], &data[0], h);
92
fftx(&temp[h], &data[h], h);
95
for (i = 0; i < h; i++)
97
wkt = complex_mul(&circle[p], &temp[h + i]);
98
data[i] = complex_add(&temp[i], &wkt);
99
data[h + i] = complex_sub(&temp[i], &wkt);
104
/*- End of function --------------------------------------------------------*/
106
void ifft(complex_t data[], int len)
110
complex_t temp[SEQLEN];
112
/* A very slow and clunky FFT, that's just fine for filter design. */
113
for (i = 0; i < SEQLEN/2; i++)
115
x = (2.0*3.1415926535*i)/(double) SEQLEN;
118
fftx(data, temp, len);
120
/*- End of function --------------------------------------------------------*/
122
void compute_raised_cosine_filter(double coeffs[],
134
complex_t vec[SEQLEN];
139
f1 = (1.0 - beta)*alpha;
140
f2 = (1.0 + beta)*alpha;
142
/* (Root) raised cosine */
143
for (i = 0; i <= SEQLEN/2; i++)
145
f = (double) i/(double) SEQLEN;
147
vec[i] = complex_set(1.0, 0.0);
149
vec[i] = complex_set(0.5*(1.0 + cos((3.1415926535*tau/beta) * (f - f1))), 0.0);
151
vec[i] = complex_set(0.0, 0.0);
155
for (i = 0; i <= SEQLEN/2; i++)
156
vec[i].re = sqrt(vec[i].re);
160
for (i = 1; i <= SEQLEN/2; i++)
162
x = 3.1415926535*(double) i/(double) SEQLEN;
163
vec[i].re *= (x/sin(x));
166
for (i = 0; i <= SEQLEN/2; i++)
168
for (i = 1; i < SEQLEN/2; i++)
169
vec[SEQLEN - i] = vec[i];
172
for (i = 0; i < len; i++)
174
j = (SEQLEN - h + i)%SEQLEN;
175
coeffs[i] = vec[j].re/(double) SEQLEN;
178
/*- End of function --------------------------------------------------------*/
180
void compute_hilbert_transform(double coeffs[], int len)
188
for (i = 1; i <= h; i++)
198
/*- End of function --------------------------------------------------------*/
200
void apply_hamming_window(double coeffs[], int len)
207
for (i = 1; i <= h; i++)
209
w = 0.53836 - 0.46164*cos(2.0*3.1415926535*(double) (h + i)/(double) (len - 1.0));
214
/*- End of function --------------------------------------------------------*/
216
void truncate_coeffs(double coeffs[], int len, int bits, int hilbert)
225
fac = pow(2.0, (double) (bits - 1.0));
227
max = (hilbert) ? coeffs[h - 1] : coeffs[h]; /* Max coeff */
228
scale = (fac - 1.0)/(fac*max);
229
for (i = 0; i < len; i++)
231
x = coeffs[i]*scale; /* Scale coeffs so max is (fac - 1.0)/fac */
232
coeffs[i] = fix(x*fac)/fac; /* Truncate */
235
/*- End of function --------------------------------------------------------*/
236
/*- End of file ------------------------------------------------------------*/