1 /*
2     lp4pole_filter.h - Header for lp4pole_filter struct, and functions
3                        to run instance.
4 
5     Copyright (C) 2003  Mike Rawes
6 
7     Originally originally appeared in CSound as Timo Tossavainen's (sp?)
8     implementation from the Stilson/Smith CCRMA paper.
9 
10     See http://musicdsp.org/archive.php?classid=3#26
11 
12     Originally appeared in the arts softsynth by Stefan Westerfeld:
13     http://www.arts-project.org/
14 
15     First ported to LADSPA by Reiner Klenk (pdq808[at]t-online.de)
16 
17     Tuning and stability issues (output NaN) and additional audio-rate
18     variant added by Mike Rawes (mike_rawes[at]yahoo.co.uk)
19 
20     This program is free software; you can redistribute it and/or modify
21     it under the terms of the GNU General Public License as published by
22     the Free Software Foundation; either version 2 of the License, or
23     (at your option) any later version.
24 
25     This program is distributed in the hope that it will be useful,
26     but WITHOUT ANY WARRANTY; without even the implied warranty of
27     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28     GNU General Public License for more details.
29 
30     You should have received a copy of the GNU General Public License
31     along with this program; if not, write to the Free Software
32     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
33 */
34 
35 #ifndef blop_lp4pole_filter_h
36 #define blop_lp4pole_filter_h
37 
38 #include <ladspa.h>
39 #include "common.h"
40 
41 typedef struct {
42 	LADSPA_Data f;
43 	LADSPA_Data coeff;
44 	LADSPA_Data fb;
45 	LADSPA_Data in1;
46 	LADSPA_Data in2;
47 	LADSPA_Data in3;
48 	LADSPA_Data in4;
49 	LADSPA_Data inv_nyquist;
50 	LADSPA_Data out1;
51 	LADSPA_Data out2;
52 	LADSPA_Data out3;
53 	LADSPA_Data out4;
54 	LADSPA_Data max_abs_in;
55 } LP4PoleFilter;
56 
57 /*****************************************************************************
58  * Description: Allocate a new LP4PoleFilter instance
59  *
60  *   Arguments: sample_rate         Intended playback (DAC) rate
61  *
62  *     Returns: Allocated LP4PoleFilter instance
63  *****************************************************************************/
64 LP4PoleFilter *
65 lp4pole_new (unsigned long sample_rate);
66 
67 /*****************************************************************************
68  * Description: Cleanup an existing LP4PoleFilter instance
69  *
70  *   Arguments: lpf                 Pointer to LP4PoleFilter instance
71  *                                   allocated with initFilter
72  *****************************************************************************/
73 void
74 lp4pole_cleanup (LP4PoleFilter * lpf);
75 
76 /*****************************************************************************
77  * Description: Initialise filter
78  *
79  *   Arguments: lpf                 Pointer to LP4PoleFilter instance
80  *                                   allocated with initFilter
81  *****************************************************************************/
82 void
83 lp4pole_init (LP4PoleFilter * lpf);
84 
85 /*****************************************************************************
86  * Set up filter coefficients for given LP4Pole instance
87  *
88  *   Arguments: lpf                 Pointer to LP4PoleFilter instance
89  *              cutoff              Cutoff frequency in Hz
90  *              resonance           Resonance [Min=0.0, Max=4.0]
91  *****************************************************************************/
92 static inline void
lp4pole_set_params(LP4PoleFilter * lpf,LADSPA_Data cutoff,LADSPA_Data resonance)93 lp4pole_set_params (LP4PoleFilter *lpf,
94                     LADSPA_Data cutoff,
95                     LADSPA_Data resonance)
96 {
97 	LADSPA_Data fsqd;
98 	LADSPA_Data tuning;
99 
100 /* Normalise cutoff and find tuning - Magic numbers found empirically :) */
101 	lpf->f = cutoff * lpf->inv_nyquist;
102 	tuning = f_clip (3.13f - (lpf->f * 4.24703592f), 1.56503274f, 3.13f);
103 
104 /* Clip to bounds */
105 	lpf->f = f_clip (lpf->f * tuning, lpf->inv_nyquist, 1.16f);
106 
107 	fsqd = lpf->f * lpf->f;
108 	lpf->coeff = fsqd * fsqd * 0.35013f;
109 
110 	lpf->fb = f_clip (resonance, -1.3f, 4.0f) * (1.0f - 0.15f * fsqd);
111 
112 	lpf->f = 1.0f - lpf->f;
113 }
114 
115 /*****************************************************************************
116  * Description: Run given LP4PoleFilter instance for a single sample
117  *
118  *   Arguments: lpf                 Pointer to LP4PoleFilter instance
119  *              in                  Input sample
120  *
121  *     Returns: Filtered sample
122  *****************************************************************************/
123 static inline LADSPA_Data
lp4pole_run(LP4PoleFilter * lpf,LADSPA_Data in)124 lp4pole_run (LP4PoleFilter * lpf,
125              LADSPA_Data in)
126 {
127 	LADSPA_Data abs_in = fabsf (16.0f * in); /* ~24dB unclipped headroom */
128 
129 	lpf->max_abs_in = f_max (lpf->max_abs_in, abs_in);
130 
131 	in -= lpf->out4 * lpf->fb;
132 	in *= lpf->coeff;
133 
134 	lpf->out1 = in        + 0.3f * lpf->in1 + lpf->f * lpf->out1;  /* Pole 1 */
135 	lpf->in1  = in;
136 	lpf->out2 = lpf->out1 + 0.3f * lpf->in2 + lpf->f * lpf->out2;  /* Pole 2 */
137 	lpf->in2  = lpf->out1;
138 	lpf->out3 = lpf->out2 + 0.3f * lpf->in3 + lpf->f * lpf->out3;  /* Pole 3 */
139 	lpf->in3  = lpf->out2;
140 	lpf->out4 = lpf->out3 + 0.3f * lpf->in4 + lpf->f * lpf->out4;  /* Pole 4 */
141 	lpf->in4  = lpf->out3;
142 
143 /* Simple hard clip to prevent NaN */
144 	lpf->out4 = f_clip (lpf->out4, -lpf->max_abs_in, lpf->max_abs_in);
145 
146 	lpf->max_abs_in *= 0.999f;
147 
148 	return lpf->out4;
149 }
150 
151 #endif /* blop_lp4pole_filter_h */
152