1 /* DSSI Plugin Framework
2  *
3  * Copyright (C) 2005 Sean Bolton and others.
4  *
5  * Most of this code comes from the Plate2x2 reverb in CAPS 0.2.3,
6  * copyright (c) 2002-4 Tim Goetze.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be
14  * useful, but WITHOUT ANY WARRANTY; without even the implied
15  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16  * PURPOSE.  See the GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public
19  * License along with this program; if not, write to the Free
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301 USA.
22  */
23 
24 #ifndef _EFFECT_REVERB_H
25 #define _EFFECT_REVERB_H
26 
27 #include <math.h>
28 
29 #include "whysynth_types.h"
30 
31 struct OnePoleLP
32 {
33     float a0, b1, y1;
34 };
35 
36 static inline void
OnePoleLP_reset(struct OnePoleLP * this)37 OnePoleLP_reset(struct OnePoleLP *this)
38 {
39     this->y1 = 0.0f;
40 }
41 
42 // static inline void
43 // OnePoleLP_set_f (struct OnePoleLP *this, double fc)
44 // {
45 //     OnePoleLP_set(this, exp (-2 * M_PI * fc));
46 // }
47 
48 static inline void
OnePoleLP_set(struct OnePoleLP * this,double d)49 OnePoleLP_set(struct OnePoleLP *this, double d)
50 {
51     this->a0 = (float)d;
52     this->b1 = (float)(1. - d);
53 }
54 
55 static inline float
OnePoleLP_process(struct OnePoleLP * this,float x)56 OnePoleLP_process(struct OnePoleLP *this, float x)
57 {
58     return this->y1 = this->a0 * x + this->b1 * this->y1;
59 }
60 
61 // static inline void
62 // OnePoleLP_decay (struct OnePoleLP *this, double d)
63 // {
64 //     this->a0 *= d;
65 //     this->b1 = 1. - this->a0;
66 // }
67 
68 static inline int
next_power_of_2(int n)69 next_power_of_2 (int n)
70 {
71     int m = 1;
72 
73     while (m < n)
74         m <<= 1;
75 
76     return m;
77 }
78 
79 struct Delay
80 {
81     int size;
82     float * data;
83     int read, write;
84 };
85 
86 static inline void
Delay_init(struct Delay * this,y_synth_t * synth,int n)87 Delay_init (struct Delay *this, y_synth_t *synth, int n)
88 {
89     this->size = next_power_of_2 (n);
90     this->data = (float *) effects_request_buffer(synth, this->size * sizeof(float));
91     this->size -= 1;
92     this->write = n;
93     this->read = 0;
94 }
95 
96 static inline void
Delay_reset(struct Delay * this)97 Delay_reset(struct Delay *this)
98 {
99     /* effect buffer should have been zeroed before we get here */
100     /* memset (this->data, 0, (this->size + 1) * sizeof (float)); */
101 }
102 
103 static inline float
Delay_peek(struct Delay * this,int i)104 Delay_peek(struct Delay *this, int i)
105 {
106     return this->data[(this->write - i) & this->size];
107 }
108 
109 static inline void
Delay_put(struct Delay * this,float x)110 Delay_put (struct Delay *this, float x)
111 {
112     this->data [this->write] = x;
113     this->write = (this->write + 1) & this->size;
114 }
115 
116 static inline float
Delay_get(struct Delay * this)117 Delay_get(struct Delay *this)
118 {
119     float x = this->data [this->read];
120     this->read = (this->read + 1) & this->size;
121     return x;
122 }
123 
124 static inline float
Delay_putget(struct Delay * this,float x)125 Delay_putget (struct Delay *this, float x)
126 {
127     Delay_put (this, x);
128     return Delay_get(this);
129 }
130 
131 /* fractional lookup, linear interpolation */
132 static inline float
Delay_get_at(struct Delay * this,float f)133 Delay_get_at (struct Delay *this, float f)
134 {
135     int n = lrintf(f - 0.5f);
136 
137     f -= (float)n;
138 
139     /* one multiply less, but slower on this 1.7 amd:
140      *   register d_sample xn = (*this) [n];
141      *   return xn + f * ((*this) [n + 1] - xn);
142      * rather like this ... */
143     return (1.0f - f) * Delay_peek(this, n) + f * Delay_peek(this, n + 1);
144 }
145 
146 /* fractional lookup, cubic interpolation */
147 // statis inline float
148 // Delay_get_cubic (struct Delay *this, float f)
149 // {
150 //     float x_1, x0, x1, x2;
151 //     register float a, b, c;
152 //     int n = lrintf(f - 0.5f);
153 //
154 //     f -= (float)n;
155 //
156 //     x_1 = Delay_peek(this, n - 1);
157 //     x0 = Delay_peek(this, n);
158 //     x1 = Delay_peek(this, n + 1);
159 //     x2 = Delay_peek(this, n + 2);
160 //
161 //     /* float quicker than double here */
162 //     a = (3 * (x0 - x1) - x_1 + x2) * .5;
163 //     b = 2 * x1 + x_1 - (5 * x0 + x2) * .5;
164 //     c = (x1 - x_1) * .5;
165 //
166 //     return x0 + (((a * f) + b) * f + c) * f;
167 // }
168 
169 static inline float
Lattice_process(struct Delay * delay,float x,double d)170 Lattice_process(struct Delay *delay, float x, double d)
171 {
172     float y = Delay_get(delay);
173     x -= d * y;
174     Delay_put(delay, x);
175     return d * x + y;
176 };
177 
178 struct Sine
179 {
180     int z;
181     float y[2];
182     float b;
183 };
184 
185 static inline void
Sine_set_f(struct Sine * this,double w,double phase)186 Sine_set_f (struct Sine *this, double w, double phase)
187 {
188     this->b = 2. * cos (w);
189     this->y[0] = sin (phase - w);
190     this->y[1] = sin (phase - w * 2.);
191     this->z = 0;
192 }
193 
194 static inline void
Sine_set_f3(struct Sine * this,double f,double fs,double phase)195 Sine_set_f3 (struct Sine *this, double f, double fs, double phase)
196 {
197     Sine_set_f (this, f * M_PI / fs, phase);
198 }
199 
200 /* advance and return 1 sample */
201 static inline double
Sine_get(struct Sine * this)202 Sine_get(struct Sine *this)
203 {
204     register double s = this->b * this->y[this->z];
205     this->z ^= 1;
206     s -= this->y[this->z];
207     return this->y[this->z] = s;
208 }
209 
210 struct ModLattice
211 {
212     float n0, width;
213 
214     struct Delay delay;
215     struct Sine lfo;
216 };
217 
218 static inline void
ModLattice_init(struct ModLattice * this,y_synth_t * synth,int n,int w)219 ModLattice_init (struct ModLattice *this, y_synth_t *synth, int n, int w)
220 {
221     this->n0 = n;
222     this->width = w;
223     Delay_init(&this->delay, synth, n + w);
224 }
225 
226 static inline void
ModLattice_reset(struct ModLattice * this)227 ModLattice_reset(struct ModLattice *this)
228 {
229     Delay_reset(&this->delay);
230 }
231 
232 static inline float
ModLattice_process(struct ModLattice * this,float x,double d)233 ModLattice_process (struct ModLattice *this, float x, double d)
234 {
235     /* TODO: try all-pass interpolation */
236     float y = Delay_get_at(&this->delay, this->n0 + this->width * Sine_get(&this->lfo));
237     x += d * y;
238     Delay_put(&this->delay, x);
239     return y - d * x; /* note sign */
240 }
241 
242 struct Plate
243 {
244     double fs;
245 
246     float indiff1, indiff2, dediff1, dediff2;
247 
248     struct {
249         struct OnePoleLP bandwidth;
250         struct Delay lattice[4];
251     } input;
252 
253     struct {
254         struct ModLattice mlattice[2];
255         struct Delay lattice[2];
256         struct Delay delay[4];
257         struct OnePoleLP damping[2];
258         int taps[12];
259     } tank;
260 };
261 
262 struct DualDelay
263 {
264     int max_delay;
265 
266     struct Delay delay_l,
267                  delay_r;
268     struct OnePoleLP damping_l,
269                      damping_r;
270 };
271 
272 #endif /* _EFFECT_REVERB_H */
273