-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfilter.c
More file actions
149 lines (134 loc) · 4.73 KB
/
Copy pathfilter.c
File metadata and controls
149 lines (134 loc) · 4.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
* filter.c
*
* Copyright (c) 2018 Disi A
*
* Author: Disi A
* Email: adis@live.cn
* https://www.mathworks.com/matlabcentral/profile/authors/3734620-disi-a
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "filter.h"
#include <stddef.h>
#if DOUBLE_PRECISION
#define COS cos
#define SIN sin
#define TAN tan
#define COSH cosh
#define SINH sinh
#define SQRT sqrt
#define LOG log
#else
#define COS cosf
#define SIN sinf
#define TAN tanf
#define COSH coshf
#define SINH sinhf
#define SQRT sqrtf
#define LOG logf
#endif
BWLowPass* create_bw_low_pass_filter(int order, FTR_PRECISION s, FTR_PRECISION f) {
BWLowPass* filter = (BWLowPass *) malloc(sizeof(BWLowPass));
filter -> n = order/2;
filter -> A = (FTR_PRECISION *)malloc(filter -> n*sizeof(FTR_PRECISION));
filter -> d1 = (FTR_PRECISION *)malloc(filter -> n*sizeof(FTR_PRECISION));
filter -> d2 = (FTR_PRECISION *)malloc(filter -> n*sizeof(FTR_PRECISION));
filter -> w0 = (FTR_PRECISION *)calloc(filter -> n, sizeof(FTR_PRECISION));
filter -> w1 = (FTR_PRECISION *)calloc(filter -> n, sizeof(FTR_PRECISION));
filter -> w2 = (FTR_PRECISION *)calloc(filter -> n, sizeof(FTR_PRECISION));
if (filter->d2 == NULL)
{
free_bw_low_pass(filter);
return NULL;
}
FTR_PRECISION a = TAN((FTR_PRECISION)(M_PI * f / s));
FTR_PRECISION a2 = a * a;
FTR_PRECISION r;
for(int i=0; i < filter -> n; ++i){
r = SIN((FTR_PRECISION)(M_PI * (2.0 * i + 1.0) / (4.0 * filter->n)));
s = (FTR_PRECISION) (a2 + 2.0 * a * r + 1.0);
filter->A[i] = a2 / s;
filter->d1[i] = (FTR_PRECISION) (2.0 * (1 - a2) / s);
filter->d2[i] = (FTR_PRECISION)(-(a2 - 2.0 * a * r + 1.0) / s);
}
return filter;
}
CHELowPass* create_che_low_pass_filter(int n, FTR_PRECISION epsilon, FTR_PRECISION s, FTR_PRECISION f){
CHELowPass* filter = (CHELowPass *) malloc(sizeof(CHELowPass));
filter -> m = n/2;
filter -> A = (FTR_PRECISION *)malloc(filter -> m*sizeof(FTR_PRECISION));
filter -> d1 = (FTR_PRECISION *)malloc(filter -> m*sizeof(FTR_PRECISION));
filter -> d2 = (FTR_PRECISION *)malloc(filter -> m*sizeof(FTR_PRECISION));
filter -> w0 = (FTR_PRECISION *)calloc(filter -> m, sizeof(FTR_PRECISION));
filter -> w1 = (FTR_PRECISION *)calloc(filter -> m, sizeof(FTR_PRECISION));
filter -> w2 = (FTR_PRECISION *)calloc(filter -> m, sizeof(FTR_PRECISION));
if (filter->d2 == NULL)
{
free_che_low_pass(filter);
return NULL;
}
FTR_PRECISION a = TAN((FTR_PRECISION) (M_PI * f/ s));
FTR_PRECISION a2 = a * a;
FTR_PRECISION u = LOG((FTR_PRECISION) (1.0 + SQRT((FTR_PRECISION) (1.0 + epsilon * epsilon)) / epsilon));
FTR_PRECISION su = SINH(u/(FTR_PRECISION)n);
FTR_PRECISION cu = COSH(u/(FTR_PRECISION)n);
FTR_PRECISION b,c;
int i;
for(i=0; i<filter->m; ++i){
b = SIN((FTR_PRECISION) (M_PI * (2.0 * i + 1.0) / (2.0 * n))) * su;
c = COS((FTR_PRECISION) (M_PI * (2.0 * i + 1.0) / (2.0 * n))) * cu;
c = b*b + c*c;
s = (FTR_PRECISION) (a2 * c + 2.0 * a * b + 1.0);
filter->A[i] = (FTR_PRECISION) (a2 / (4.0 * s));
filter->d1[i] = (FTR_PRECISION) (2.0 * (1 - a2 * c) / s);
filter->d2[i] = (FTR_PRECISION) (- (a2 * c - 2.0 * a * b + 1.0) / s);
}
filter->ep = (FTR_PRECISION) (2.0 / epsilon); // used to normalize
return filter;
}
FTR_PRECISION bw_low_pass(BWLowPass* filter, FTR_PRECISION x){
int i;
for(i=0; i<filter->n; ++i){
filter->w0[i] = filter->d1[i]*filter->w1[i] + filter->d2[i]*filter->w2[i] + x;
x = filter->A[i] * (filter->w0[i] + 2.0f * filter->w1[i] + filter->w2[i]);
filter->w2[i] = filter->w1[i];
filter->w1[i] = filter->w0[i];
}
return x;
}
FTR_PRECISION che_low_pass(CHELowPass* filter, FTR_PRECISION x){
int i;
for(i=0; i<filter->m; ++i){
filter->w0[i] = filter->d1[i]*filter->w1[i] + filter->d2[i]*filter->w2[i] + x;
x = filter->A[i] * (filter->w0[i] + 2.0f * filter->w1[i] + filter->w2[i]);
filter->w2[i] = filter->w1[i];
filter->w1[i] = filter->w0[i];
}
return x * filter->ep;
}
FTR_PRECISION softmax(FTR_PRECISION* data, int size, int target_ind){
FTR_PRECISION sum = 0;
for(int i = 0; i < size; i++) sum += data[i];
return data[target_ind]/sum;
}
void free_bw_low_pass(BWLowPass* filter){
free(filter -> A);
free(filter -> d1);
free(filter -> d2);
free(filter -> w0);
free(filter -> w1);
free(filter -> w2);
free(filter);
}
void free_che_low_pass(CHELowPass* filter){
free(filter -> A);
free(filter -> d1);
free(filter -> d2);
free(filter -> w0);
free(filter -> w1);
free(filter -> w2);
free(filter);
}