1 /*                                                     -*- linux-c -*-
2     Copyright (C) 2004 Tom Szilagyi
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18     $Id: tap_reverb.h,v 1.11 2009/08/17 11:16:19 tszilagyi Exp $
19 */
20 #ifndef _ISOC99_SOURCE
21 #define _ISOC99_SOURCE
22 #endif
23 
24 #include <inttypes.h>
25 
26 
27 
28 /* The Unique ID of the plugin: */
29 
30 #define ID_STEREO       2142
31 
32 /* The port numbers for the plugin: */
33 
34 #define DECAY       0
35 #define DRYLEVEL    1
36 #define WETLEVEL    2
37 #define COMBS_EN    3  /* comb filters on/off */
38 #define ALLPS_EN    4  /* allpass filters on/off */
39 #define BANDPASS_EN 5  /* bandpass filters on/off */
40 #define STEREO_ENH  6  /* stereo enhanced mode on/off */
41 #define MODE        7
42 
43 #define INPUT_L     8
44 #define OUTPUT_L    9
45 #define INPUT_R     10
46 #define OUTPUT_R    11
47 
48 /* Total number of ports */
49 
50 #define PORTCOUNT_STEREO 12
51 
52 /* Global constants (times in ms, bwidth in octaves) */
53 
54 #define MAX_COMBS         20
55 #define MAX_ALLPS         20
56 #define MAX_DECAY         10000.0f
57 #define MAX_COMB_DELAY    250.0f
58 #define MAX_ALLP_DELAY    20.0f
59 #define BANDPASS_BWIDTH   1.5f
60 #define FREQ_RESP_BWIDTH  3.0f
61 #define ENH_STEREO_RATIO  0.998f
62 
63 /* compensation ratio of freq_resp in fb_gain calc */
64 #define FR_R_COMP         0.75f
65 
66 
67 #ifndef M_PI
68 #define M_PI 3.14159265358979323846264338327
69 #endif
70 
71 
72 /* push a sample into a ringbuffer and return the sample falling out */
73 static inline
74 rev_t
push_buffer(rev_t insample,rev_t * buffer,unsigned long buflen,unsigned long * pos)75 push_buffer(rev_t insample, rev_t * buffer,
76             unsigned long buflen, unsigned long * pos) {
77 
78         rev_t outsample;
79 
80         outsample = buffer[*pos];
81         buffer[(*pos)++] = insample;
82 
83         if (*pos >= buflen)
84                 *pos = 0;
85 
86         return outsample;
87 }
88 
89 /* read a value from a ringbuffer.
90  * n == 0 returns the oldest sample from the buffer.
91  * n == buflen-1 returns the sample written to the buffer
92  *      at the last push_buffer call.
93  * n must not exceed buflen-1, or your computer will explode.
94  */
95 static inline
96 rev_t
read_buffer(rev_t * buffer,unsigned long buflen,unsigned long pos,unsigned long n)97 read_buffer(rev_t * buffer, unsigned long buflen,
98             unsigned long pos, unsigned long n) {
99 
100         while (n + pos >= buflen)
101                 n -= buflen;
102         return buffer[n + pos];
103 }
104 
105 
106 /* overwrites a value in a ringbuffer, but pos stays the same.
107  * n == 0 overwrites the oldest sample pushed in the buffer.
108  * n == buflen-1 overwrites the sample written to the buffer
109  *      at the last push_buffer call.
110  * n must not exceed buflen-1, or your computer... you know.
111  */
112 static inline
113 void
write_buffer(rev_t insample,rev_t * buffer,unsigned long buflen,unsigned long pos,unsigned long n)114 write_buffer(rev_t insample, rev_t * buffer, unsigned long buflen,
115              unsigned long pos, unsigned long n) {
116 
117         while (n + pos >= buflen)
118                 n -= buflen;
119         buffer[n + pos] = insample;
120 }
121 
122 #define db2lin(x) ((x) > -90.0f ? powf(10.0f, (x) * 0.05f) : 0.0f)
123 #define ABS(x)  (x)>0.0f?(x):-1.0f*(x)
124 #define LN_2_2 0.34657359f
125 #define LIMIT(v,l,u) ((v)<(l)?(l):((v)>(u)?(u):(v)))
126 
127 #define BIQUAD_TYPE float
128 typedef BIQUAD_TYPE bq_t;
129 
130 typedef struct {
131         bq_t a1;
132         bq_t a2;
133         bq_t b0;
134         bq_t b1;
135         bq_t b2;
136         rev_t x1;
137         rev_t x2;
138         rev_t y1;
139         rev_t y2;
140 } biquad;
141 
142 
biquad_init(biquad * f)143 static inline void biquad_init(biquad *f) {
144 
145         f->x1 = 0.0f;
146         f->x2 = 0.0f;
147         f->y1 = 0.0f;
148         f->y2 = 0.0f;
149 }
150 
151 static inline
152 void
eq_set_params(biquad * f,bq_t fc,bq_t gain,bq_t bw,bq_t fs)153 eq_set_params(biquad *f, bq_t fc, bq_t gain, bq_t bw, bq_t fs) {
154 
155         bq_t w = 2.0f * M_PI * LIMIT(fc, 1.0f, fs/2.0f) / fs;
156         bq_t cw = cosf(w);
157         bq_t sw = sinf(w);
158         bq_t J = pow(10.0f, gain * 0.025f);
159         bq_t g = sw * sinhf(LN_2_2 * LIMIT(bw, 0.0001f, 4.0f) * w / sw);
160         bq_t a0r = 1.0f / (1.0f + (g / J));
161 
162         f->b0 = (1.0f + (g * J)) * a0r;
163         f->b1 = (-2.0f * cw) * a0r;
164         f->b2 = (1.0f - (g * J)) * a0r;
165         f->a1 = -(f->b1);
166         f->a2 = ((g / J) - 1.0f) * a0r;
167 }
168 
lp_set_params(biquad * f,bq_t fc,bq_t bw,bq_t fs)169 static inline void lp_set_params(biquad *f, bq_t fc, bq_t bw, bq_t fs) {
170         bq_t omega = 2.0 * M_PI * fc/fs;
171         bq_t sn = sin(omega);
172         bq_t cs = cos(omega);
173         bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
174         const float a0r = 1.0 / (1.0 + alpha);
175         f->b0 = a0r * (1.0 - cs) * 0.5;
176         f->b1 = a0r * (1.0 - cs);
177         f->b2 = a0r * (1.0 - cs) * 0.5;
178         f->a1 = a0r * (2.0 * cs);
179         f->a2 = a0r * (alpha - 1.0);
180 }
181 
182 static inline
183 void
hp_set_params(biquad * f,bq_t fc,bq_t bw,bq_t fs)184 hp_set_params(biquad *f, bq_t fc, bq_t bw, bq_t fs)
185 {
186         bq_t omega = 2.0 * M_PI * fc/fs;
187         bq_t sn = sin(omega);
188         bq_t cs = cos(omega);
189         bq_t alpha = sn * sinh(M_LN2 / 2.0 * bw * omega / sn);
190         const float a0r = 1.0 / (1.0 + alpha);
191         f->b0 = a0r * (1.0 + cs) * 0.5;
192         f->b1 = a0r * -(1.0 + cs);
193         f->b2 = a0r * (1.0 + cs) * 0.5;
194         f->a1 = a0r * (2.0 * cs);
195         f->a2 = a0r * (alpha - 1.0);
196 }
197 
198 static inline
199 rev_t
biquad_run(biquad * f,rev_t x)200 biquad_run(biquad *f, rev_t x) {
201 
202 	union {
203 	  rev_t y;
204 	  uint32_t y_int;
205 	} u;
206 
207         u.y = f->b0 * x + f->b1 * f->x1 + f->b2 * f->x2
208 		        + f->a1 * f->y1 + f->a2 * f->y2;
209 #ifdef REVERB_CALC_FLOAT
210 	if ((u.y_int & 0x7f800000) == 0)
211 	  u.y = 0.0f;
212 #endif
213         f->x2 = f->x1;
214         f->x1 = x;
215         f->y2 = f->y1;
216         f->y1 = u.y;
217 
218         return u.y;
219 }
220 
221 
222 
223 typedef struct {
224 	float feedback;
225 	float fb_gain;
226 	float freq_resp;
227 	rev_t * ringbuffer;
228 	unsigned long buflen;
229 	unsigned long * buffer_pos;
230 	biquad * filter;
231 	rev_t last_out;
232 } COMB_FILTER;
233 
234 typedef struct {
235 	float feedback;
236 	float fb_gain;
237 	float in_gain;
238 	rev_t * ringbuffer;
239 	unsigned long buflen;
240 	unsigned long * buffer_pos;
241 	rev_t last_out;
242 } ALLP_FILTER;
243 
244 
245 /* The structure used to hold port connection information and state */
246 
247 typedef struct {
248 	unsigned long num_combs; /* total number of comb filters */
249 	unsigned long num_allps; /* total number of allpass filters */
250 	COMB_FILTER * combs;
251 	ALLP_FILTER * allps;
252 	biquad * low_pass; /* ptr to 2 low-pass filters */
253 	biquad * high_pass; /* ptr to 2 high-pass filters */
254 	unsigned long sample_rate;
255 
256 	LADSPA_Data * decay;
257 	LADSPA_Data * drylevel;
258 	LADSPA_Data * wetlevel;
259 	LADSPA_Data * combs_en; /* on/off */
260 	LADSPA_Data * allps_en; /* on/off */
261         LADSPA_Data * bandpass_en; /* on/off */
262 	LADSPA_Data * stereo_enh; /* on/off */
263 	LADSPA_Data * mode;
264 
265 	LADSPA_Data * input_L;
266 	LADSPA_Data * output_L;
267 	LADSPA_Data * input_R;
268 	LADSPA_Data * output_R;
269 
270 	LADSPA_Data old_decay;
271 	LADSPA_Data old_stereo_enh;
272 	LADSPA_Data old_mode;
273 
274 	LADSPA_Data run_adding_gain;
275 } Reverb;
276 
277 typedef struct {
278 	LADSPA_Data delay;
279 	LADSPA_Data feedback;
280 	LADSPA_Data freq_resp;
281 } COMB_DATA;
282 
283 typedef struct {
284 	LADSPA_Data delay;
285 	LADSPA_Data feedback;
286 } ALLP_DATA;
287 
288 typedef struct {
289 	unsigned long num_combs;
290 	unsigned long num_allps;
291 	COMB_DATA combs[MAX_COMBS];
292 	ALLP_DATA allps[MAX_ALLPS];
293 	LADSPA_Data bandpass_low;
294 	LADSPA_Data bandpass_high;
295 } REVERB_DATA;
296