1 #include <stdlib.h>
2 #include <math.h>
3 #include <string.h>
4 
5 typedef struct {
6 
7 	int n_channels;
8 
9 	/* ... */
10 
11 } my_data_struct;
12 
13 /* par is an ascii string containing parameters given on the 'filter=' line
14  * in the configuration file
15  */
init_library(int bits_per_sample,int n_channels,int sample_rate,char * par)16 void * init_library(int bits_per_sample, int n_channels, int sample_rate, char *par)
17 {
18 	void *pnt;
19 
20 	/* init library */
21 
22 	/* you might allocate some datastructure here or so and then
23 	 * return a point to it which will be then given for each call
24 	 * to do_filter as the first parameter
25 	 */
26 
27 	pnt = malloc(sizeof(my_data_struct));
28 	if (!pnt)
29 		exit(1);
30 
31 	memset(pnt, 0x00, sizeof(my_data_struct));
32 
33 	((my_data_struct *)pnt) -> n_channels = n_channels;
34 
35 	return pnt;
36 }
37 
do_filter(void * lib_data,void * sample_data,int n_samples)38 void do_filter(void *lib_data, void *sample_data, int n_samples)
39 {
40 	my_data_struct *mds = (my_data_struct *)lib_data;
41 	short *pnt = (short *)sample_data;
42 	int channel;
43 
44 	/* do the filtering */
45 	/* warning: sample_data is n_samples * n_channels in size! */
46 
47 	/* code taken from http://musicdsp.org/archive.php?classid=3#28 */
48 	/* - Three one-poles combined in parallel
49 	 * - Output stays within input limits
50 	 * - 18 dB/oct (approx) frequency response rolloff
51 	 * - Quite fast, 2x3 parallel multiplications/sample, no internal buffers
52 	 * - Time-scalable, allowing use with different samplerates
53 	 * - Impulse and edge responses have continuous differential
54 	 * - Requires high internal numerical precision
55 	 */
56 
57 	/* Parameters */
58         /* Number of samples from start of edge to halfway to new value */
59         const double        scale = 100;
60         /* 0 < Smoothness < 1. High is better, but may cause precision problems */
61         const double        smoothness = 0.999;
62 
63         /* Precalc variables */
64         double                a = 1.0-(2.4/scale); /* Could also be set directly */
65         double                b = smoothness;      /*         -"-                */
66         double                acoef = a;
67         double                bcoef = a*b;
68         double                ccoef = a*b*b;
69         double                mastergain = 1.0 / (-1.0/(log(a)+2.0*log(b))+2.0/
70                         (log(a)+log(b))-1.0/log(a));
71         double                again = mastergain;
72         double                bgain = mastergain * (log(a*b*b)*(log(a)-log(a*b)) /
73                             ((log(a*b*b)-log(a*b))*log(a*b))
74                             - log(a)/log(a*b));
75         double                cgain = mastergain * (-(log(a)-log(a*b)) /
76                         (log(a*b*b)-log(a*b)));
77 
78         /* Runtime variables */
79         long                streamofs;
80         double                areg = 0;
81         double                breg = 0;
82         double                creg = 0;
83 
84 	/* Main loop */
85 	for(channel = 0; channel < mds -> n_channels; channel++)
86 	{
87 		for (streamofs = 0; streamofs < n_samples; streamofs++)
88 		{
89 			long temp;
90 
91 			/* Update filters */
92 			areg = acoef * areg + pnt[(streamofs * mds -> n_channels) + channel];
93 			breg = bcoef * breg + pnt[(streamofs * mds -> n_channels) + channel];
94 			creg = ccoef * creg + pnt[(streamofs * mds -> n_channels) + channel];
95 
96 			/* Combine filters in parallel */
97 			temp =  again * areg
98 			      + bgain * breg
99 			      + cgain * creg;
100 
101 			/* Check clipping */
102 			if (temp > 32767)
103 			{
104 				temp = 32767;
105 			}
106 			else if (temp < -32768)
107 			{
108 				temp = -32768;
109 			}
110 
111 			/* Store new value */
112 			pnt[(streamofs * mds -> n_channels) + channel] = temp;
113 		}
114 	}
115 }
116