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