2
Copyright (C) 2008-2011 Nicolas Bourdaud <nicolas.bourdaud@epfl.ch>
4
This file is part of the rtfilter library
6
The rtfilter library is free software: you can redistribute it and/or
7
modify it under the terms of the version 3 of the GNU Lesser General
8
Public License as published by the Free Software Foundation.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU Lesser General Public License for more details.
15
You should have received a copy of the GNU Lesser General Public License
16
along with this program. If not, see <http://www.gnu.org/licenses/>.
27
#include "rtf_common.h"
29
#define PId 3.1415926535897932384626433832795L
30
#define PIf 3.1415926535897932384626433832795f
32
/***************************************************************
36
***************************************************************/
38
void apply_window(double *fir, unsigned int length, KernelWindow window)
41
double M = length - 1;
45
for (i = 0; i < length; i++)
46
fir[i] *= 0.54 + 0.46 * cos(2.0 * PIf * ((double)i / M - 0.5));
50
for (i = 0; i < length; i++)
53
0.5 * cos(2.0 * PIf * ((double) i / M - 0.5)) +
54
0.08 * cos(4.0 * PIf * ((double) i / M - 0.5));
64
void normalize_fir(double *fir, unsigned int length)
69
for (i = 0; i < length; i++)
72
for (i = 0; i < length; i++)
77
void compute_convolution(double *product, double *sig1, unsigned int len1,
78
double *sig2, unsigned int len2)
82
memset(product, 0, (len1 + len2 - 1) * sizeof(*product));
84
for (i = 0; i < len1; i++)
85
for (j = 0; j < len2; j++)
86
product[i + j] += sig1[i] * sig2[j];
90
void FFT(complex double *X, double *t, unsigned int length){
94
for(i=0; i<length; i++){
96
for(j=0; j<length; j++){
97
X[i]=X[i] + t[j]*cexp((-2.0*I*M_PI)*(j)*(i)/length);
104
void compute_fir_lowpass(double *fir, unsigned int length, double fc)
107
double half_len = (double) ((unsigned int) (length / 2));
109
for (i = 0; i < length; i++)
112
sin(2.0 * PIf * (double) fc *
113
((double) i - half_len)) / ((double) i -
116
fir[i] = 2.0 * PIf * fc;
120
void reverse_fir(double *fir, unsigned int length)
124
// compute delay minus lowpass fir
125
for (i = 0; i < length; i++)
126
fir[i] = -1.0 * fir[i];
127
fir[length - 1] += 1.0;
130
/* Algorithm taken form:
132
"Introduction to Digital Filters with Audio Applications",
133
by Julius O. Smith III, (September 2007 Edition).
134
https://ccrma.stanford.edu/~jos/filters/Numerical_Computation_Group_Delay.html
137
double compute_IIR_filter_delay(double *num, double *den,
140
unsigned int i,length_c;
142
complex double *X,*Y;
143
double Delay = 0.0, d = 0.0;
147
a = malloc( (length)*sizeof(*a));
148
b = malloc( (length)*sizeof(*b));
149
c = malloc( (length_c)*sizeof(*c));
150
cr = malloc( (length_c)*sizeof(*cr));
151
X = malloc( (length_c)*sizeof(*X));
152
Y = malloc( (length_c)*sizeof(*Y));
153
if (!a || !b || !c || !cr|| !X || !Y){
158
for(i=0;i<length;i++){
159
b[i]=den[length-i-1];
162
compute_convolution(c,b,length,a,length);
164
for (i=0;i<length_c;i++)
170
for (i=0;i<length_c;i++) {
171
d = creal(X[i]/Y[i]);
188
/******************************
189
* inspired by DSP guide ch33 *
190
******************************/
192
void get_pole_coefs(double p, double np, double fc, double r, int highpass, double a[3], double b[3])
194
double rp, ip, es, vx, kx, t, w, m, d, x0, x1, x2, y1, y2, k;
196
// calculate pole locate on the unit circle
197
rp = -cos(PId / (np * 2.0) + (p - 1.0) * PId / np);
198
ip = sin(PId / (np * 2.0) + (p - 1.0) * PId / np);
200
// Warp from a circle to an ellipse
202
/* es = sqrt(pow(1.0 / (1.0 - r), 2) - 1.0);
203
vx = (1.0 / np) * log((1.0 / es) +
204
sqrt((1.0 / (es * es)) +
206
kx = (1.0 / np) * log((1.0 / es) +
207
sqrt((1.0 / (es * es)) -
209
kx = (exp(kx) + exp(-kx)) / 2.0;
210
rp = rp * ((exp(vx) - exp(-vx)) / 2.0) / kx;
211
ip = ip * ((exp(vx) + exp(-vx)) / 2.0) / kx;
213
es = sqrt(pow(1.0 / (1.0 - r), 2) - 1.0);
214
vx = asinh(1.0/es) / np;
215
kx = acosh(1.0/es) / np;
222
// s to z domains conversion
226
d = 4.0 - 4.0*rp*t + m*t*t;
230
y1 = (8.0 - 2.0*m*t*t)/d;
231
y2 = (-4.0 - 4.0*rp*t - m*t*t)/d;
233
// LP(s) to LP(z) or LP(s) to HP(z)
235
k = -cos(w/2.0 + 0.5)/cos(w/2.0 - 0.5);
237
k = sin(0.5 - w/2.0)/sin(0.5 + w/2.0);
238
d = 1.0 + y1*k - y2*k*k;
239
a[0] = (x0 - x1*k + x2*k*k)/d;
240
a[1] = (-2.0*x0*k + x1 + x1*k*k - 2.0*x2*k)/d;
241
a[2] = (x0*k*k - x1*k + x2)/d;
242
b[1] = (2.0*k + y1 + y1*k*k - 2.0*y2*k)/d;
243
b[2] = (-k*k - y1*k + y2)/d;
250
/******************************
251
* inspired by DSP guide ch33 *
252
******************************/
254
int compute_cheby_iir(double *num, double *den, unsigned int num_pole,
255
int highpass, double ripple, double cutoff_freq)
257
double *a, *b, *ta, *tb;
263
// Allocate temporary arrays
264
a = malloc((num_pole + 3) * sizeof(*a));
265
b = malloc((num_pole + 3) * sizeof(*b));
266
ta = malloc((num_pole + 3) * sizeof(*ta));
267
tb = malloc((num_pole + 3) * sizeof(*tb));
268
if (!a || !b || !ta || !tb) {
272
memset(a, 0, (num_pole + 3) * sizeof(*a));
273
memset(b, 0, (num_pole + 3) * sizeof(*b));
278
for (p = 1; p <= num_pole / 2; p++) {
279
// Compute the coefficients for this pole
280
get_pole_coefs(p, num_pole, cutoff_freq, ripple, highpass, ap, bp);
282
// Add coefficients to the cascade
283
memcpy(ta, a, (num_pole + 3) * sizeof(*a));
284
memcpy(tb, b, (num_pole + 3) * sizeof(*b));
285
for (i = 2; i <= num_pole + 2; i++) {
286
a[i] = ap[0]*ta[i] + ap[1]*ta[i-1] + ap[2]*ta[i-2];
287
b[i] = tb[i] - bp[1]*tb[i-1] - bp[2]*tb[i-2];
291
// Finish combining coefficients
293
for (i = 0; i <= num_pole; i++) {
298
// Normalize the gain
300
for (i = 0; i <= num_pole; i++) {
301
sa += a[i] * ((highpass && i % 2) ? -1.0 : 1.0);
302
sb += b[i] * ((highpass && i % 2) ? -1.0 : 1.0);
304
gain = sa / (1.0 - sb);
305
for (i = 0; i <= num_pole; i++)
308
// Copy the results to the num and den
309
for (i = 0; i <= num_pole; i++) {
313
// den[0] must be 1.0
324
/** compute_bandpass_complex_filter:
325
* \param fl normalized lowest cutoff freq of the bandpass filter. (the normal frequency divided by the sampling freq)
326
* \param fh normalized highest cutoff freq of the bandpass filter. (the normal frequency divided by the sampling freq)
327
* \param num_pole The number of pole the z-transform of the filter should possess
329
This function creates a complex bandpass filter from a Chebyshev low pass filter.
332
int compute_bandpass_complex_filter(complex double *num,
334
unsigned int num_pole,
335
double fl, double fh)
337
double *a=NULL, *b=NULL;
338
complex double *ac,*bc;
339
double ripple,fc,alpha,Delay;
340
unsigned int i,retval=1;
342
// Allocate temporary arrays
343
a = malloc( (num_pole+1)*sizeof(*a));
344
b = malloc( (num_pole+1)*sizeof(*b));
345
ac = malloc((num_pole+1)*sizeof(*ac));
346
bc = malloc( (num_pole+1)*sizeof(*bc));
347
if (!a || !b || !ac || !bc){
352
alpha = M_PI*(fl+fh); // Rotation angle in radians to produces
353
// the desired analitic filter
354
fc = (fh-fl)/2.0; // Normalized cutoff frequency
355
// of the low pass filter
358
// prepare the z-transform of low pass filter
359
if (!compute_cheby_iir(b, a, num_pole, 0, ripple, fc)){
364
// Compute the low pass filter delay; the complex filter
365
Delay=compute_IIR_filter_delay(b, a,num_pole+1);
367
/* Note: The complex filter introduces a delay equal to
368
e^(j*alpha*D) (D: Delay low pass filter).To get rid of the
369
undesired frequency independent phase factor, the filter with
370
rotated poles and zeros should be multiplied by
371
the constant e^(-j*alpha*D).*/
374
// compute complex coefficients (rotating poles and zeros).
375
for(i=0;i<num_pole + 1; i++) {
377
ac[i]= 2.0*cexp(-1.0*I*alpha*Delay)
378
*b[i]*cexp(1.0*I*alpha*(i+1));
380
// complex denominator
381
bc[i]= a[i]*cexp(1.0*I*alpha*(i+1));
384
for(i=0;i<num_pole + 1; i++){
398
/**************************************************************************
400
* Create particular filters *
402
**************************************************************************/
404
* \param nchann number of channels the filter will process
405
* \param type type of data the filter will process (\c RTF_FLOAT or \c RTF_DOUBLE)
406
* \param fir_length number of sample used to compute the mean
407
* \return the handle of the newly created filter in case of success, \c NULL otherwise.
410
hfilter rtf_create_fir_mean(unsigned int nchann, int proctype,
411
unsigned int fir_length)
417
// Alloc temporary fir
418
fir = malloc(fir_length*sizeof(*fir));
422
// prepare the finite impulse response
423
for (i = 0; i < fir_length; i++)
424
fir[i] = 1.0f / (double) fir_length;
426
filt = rtf_create_filter(nchann, proctype,
427
fir_length, fir, 0, NULL,
435
* \param nchann number of channels the filter will process
436
* \param proctype type of data the filter will process (\c RTF_FLOAT or \c RTF_DOUBLE)
437
* \param fc Normalized cutoff frequency (the normal frequency divided by the sampling frequency)
438
* \param half_length the half size of the impulse response (in number of samples)
439
* \param window The type of the kernel wondow to use for designing the filter
440
* \return the handle of the newly created filter in case of success, \c NULL otherwise.
443
hfilter rtf_create_fir_lowpass(unsigned int nchann, int proctype,
444
double fc, unsigned int half_length,
449
unsigned int fir_length = 2 * half_length + 1;
451
// Alloc temporary fir
452
fir = malloc(fir_length*sizeof(*fir));
456
// prepare the finite impulse response
457
compute_fir_lowpass(fir, fir_length, fc);
458
apply_window(fir, fir_length, window);
459
normalize_fir(fir, fir_length);
461
filt = rtf_create_filter(nchann, proctype,
462
fir_length, fir, 0, NULL,
471
* \param nchann number of channels the filter will process
472
* \param proctype type of data the filter will process (\c RTF_FLOAT or \c RTF_DOUBLE)
473
* \param fc Normalized cutoff frequency (the normal frequency divided by the sampling frequency)
474
* \param half_length the half size of the impulse response (in number of samples)
475
* \param window The type of the kernel wondow to use for designing the filter
476
* \return the handle of the newly created filter in case of success, \c NULL otherwise.
479
hfilter rtf_create_fir_highpass(unsigned int nchann, int proctype,
480
double fc, unsigned int half_length,
485
unsigned int fir_length = 2 * half_length + 1;
487
// Alloc temporary fir
488
fir = malloc(fir_length*sizeof(*fir));
492
// prepare the finite impulse response
493
compute_fir_lowpass(fir, fir_length, fc);
494
apply_window(fir, fir_length, window);
495
normalize_fir(fir, fir_length);
496
reverse_fir(fir, fir_length);
498
filt = rtf_create_filter(nchann, proctype,
499
fir_length, fir, 0, NULL,
508
* \param nchann number of channels the filter will process
509
* \param proctype type of data the filter will process (\c datatype_float or \c datatype_double)
510
* \param fc_low normalized cutoff frequency of the lowpass part (the normal frequency divided by the sampling frequency)
511
* \param fc_high normalized cutoff frequency of the highpass part (the normal frequency divided by the sampling frequency)
512
* \param half_length the half size of the impulse response (in number of samples)
513
* \param window the type of the kernel wondow to use for designing the filter
514
* \return the handle of the newly created filter in case of success, \c null otherwise.
517
hfilter rtf_create_fir_bandpass(unsigned int nchann, int proctype,
518
double fc_low, double fc_high,
519
unsigned int half_length,
522
unsigned int len = 2 * (half_length / 2) + 1;
523
double fir_low[len], fir_high[len];
526
unsigned int fir_length = 2 * half_length + 1;
528
// Alloc temporary fir
529
fir = malloc(fir_length*sizeof(*fir));
533
// Create the lowpass finite impulse response
534
compute_fir_lowpass(fir_low, len, fc_low);
535
apply_window(fir_low, len, window);
536
normalize_fir(fir_low, len);
538
// Create the highpass finite impulse response
539
compute_fir_lowpass(fir_high, len, fc_high);
540
apply_window(fir_high, len, window);
541
normalize_fir(fir_high, len);
542
reverse_fir(fir_high, len);
544
// compute the convolution product of the two FIR
545
compute_convolution(fir, fir_low, len, fir_high, len);
547
filt = rtf_create_filter(nchann, proctype,
548
fir_length, fir, 0, NULL,
557
* \param nchann number of channels the filter will process
558
* \param proctype type of data the filter will process (\c datatype_float or \c datatype_double)
559
* \param fc normalized cutoff frequency (the normal frequency divided by the sampling frequency)
560
* \param num_pole The number of pole the z-transform of the filter should possess
561
* \param highpass flag to specify the type of filter (0 for a lowpass, 1 for a highpass)
562
* \param ripple ripple
563
* \return the handle of the newly created filter in case of success, \c null otherwise.
566
hfilter rtf_create_chebychev(unsigned int nchann, int proctype,
567
double fc, unsigned int num_pole,
568
int highpass, double ripple)
570
double *num = NULL, *den = NULL;
573
if (num_pole % 2 != 0)
576
num = malloc( (num_pole+1)*sizeof(*num));
577
den = malloc( (num_pole+1)*sizeof(*den));
581
// prepare the z-transform of the filter
582
if (!compute_cheby_iir(num, den, num_pole, highpass, ripple, fc))
585
filt = rtf_create_filter(nchann, proctype,
586
num_pole+1, num, num_pole+1, den,
596
* \param nchann number of channels the filter will process
597
* \param proctype type of data the filter will process (\c datatype_float or \c datatype_double)
598
* \param fc normalized cutoff frequency (the normal frequency divided by the sampling frequency)
599
* \param num_pole The number of pole the z-transform of the filter should possess
600
* \param highpass flag to specify the type of filter (0 for a lowpass, 1 for a highpass)
601
* \return the handle of the newly created filter in case of success, \c null otherwise.
604
hfilter rtf_create_butterworth(unsigned int nchann, int proctype,
605
double fc, unsigned int num_pole,
608
return rtf_create_chebychev(nchann, proctype,
609
fc, num_pole, highpass, 0.0);
613
* \param nchann number of channels the filter will process
614
* \param type type of data the filter will process (\c datatype_float or \c datatype_double)
615
* \param fs sampling frequency in Hz
616
* \return the handle of the newly created filter in case of success, \c null otherwise.
619
hfilter rtf_create_integral(unsigned int nchann, int type, double fs)
622
double a = 1.0/fs, b[2] = {1.0, -1.0};
624
filt = rtf_create_filter(nchann, type, 1, &a, 2, &b, RTF_DOUBLE);
630
rtf_create_bandpass_analytic:
632
Analytic filter: Is a complex filter generating a signal whose spectrum equals the positive spectrum from a (real) input signal. The resulting signal is said to be “analytic".
633
The technique relies on the rotation of the pole-zero plot of a low pass filter.
635
* \param nchann number of channels the filter will process.
636
* \param proctype type of data the filter will process (\c datatype_float or \c datatype_double).
637
* \param fl normalized low bandpass cutoff frequency (the normal frequency divided by the sampling frequency).
638
* \param fh normalized hihg bandpass cutoff frequency (the normal frequency divided by the sampling frequency).
639
* \param num_pole The number of pole the z-transform of the filter should possess.
640
* \return The handle of the newly created filter in case of success, \c null otherwise.
643
hfilter rtf_create_bandpass_analytic(unsigned int nchann,
645
double fl, double fh,
646
unsigned int num_pole)
648
complex double *a = NULL, *b = NULL;
651
if (num_pole % 2 != 0)
654
a = malloc((num_pole+1)*sizeof(*a));
655
b = malloc((num_pole+1)*sizeof(*b));
659
// prepare the z-transform of the complex bandpass filter
660
if (!compute_bandpass_complex_filter(b,a,num_pole,fl,fh))
663
filt = rtf_create_filter(nchann, proctype,
664
num_pole+1, b, num_pole+1, a,