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