1 /*
2
3 Copyright (C) 1999 Juhana Sadeharju
4 kouhia at nic.funet.fi
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 */
21
22 #ifndef GVERB_H
23 #define GVERB_H
24
25 #include <stdlib.h>
26 #include <math.h>
27 #include <string.h>
28 #include "gverbdsp.h"
29 #include "gverb.h"
30 #include "../ladspa-util.h"
31
32 #define FDNORDER 4
33
34 typedef struct {
35 int rate;
36 float inputbandwidth;
37 float taillevel;
38 float earlylevel;
39 ty_damper *inputdamper;
40 float maxroomsize;
41 float roomsize;
42 float revtime;
43 float maxdelay;
44 float largestdelay;
45 ty_fixeddelay **fdndels;
46 float *fdngains;
47 int *fdnlens;
48 ty_damper **fdndamps;
49 float fdndamping;
50 ty_diffuser **ldifs;
51 ty_diffuser **rdifs;
52 ty_fixeddelay *tapdelay;
53 int *taps;
54 float *tapgains;
55 float *d;
56 float *u;
57 float *f;
58 double alpha;
59 } ty_gverb;
60
61
62 ty_gverb *gverb_new(int, float, float, float, float, float, float, float, float);
63 void gverb_free(ty_gverb *);
64 void gverb_flush(ty_gverb *);
65 static void gverb_do(ty_gverb *, float, float *, float *);
66 static void gverb_set_roomsize(ty_gverb *, float);
67 static void gverb_set_revtime(ty_gverb *, float);
68 static void gverb_set_damping(ty_gverb *, float);
69 static void gverb_set_inputbandwidth(ty_gverb *, float);
70 static void gverb_set_earlylevel(ty_gverb *, float);
71 static void gverb_set_taillevel(ty_gverb *, float);
72
73 /*
74 * This FDN reverb can be made smoother by setting matrix elements at the
75 * diagonal and near of it to zero or nearly zero. By setting diagonals to zero
76 * means we remove the effect of the parallel comb structure from the
77 * reverberation. A comb generates uniform impulse stream to the reverberation
78 * impulse response, and thus it is not good. By setting near diagonal elements
79 * to zero means we remove delay sequences having consequtive delays of the
80 * similar lenths, when the delays are in sorted in length with respect to
81 * matrix element index. The matrix described here could be generated by
82 * differencing Rocchesso's circulant matrix at max diffuse value and at low
83 * diffuse value (approaching parallel combs).
84 *
85 * Example 1:
86 * Set a(k,k), for all k, equal to 0.
87 *
88 * Example 2:
89 * Set a(k,k), a(k,k-1) and a(k,k+1) equal to 0.
90 *
91 * Example 3: The transition to zero gains could be smooth as well.
92 * a(k,k-1) and a(k,k+1) could be 0.3, and a(k,k-2) and a(k,k+2) could
93 * be 0.5, say.
94 */
95
gverb_fdnmatrix(float * a,float * b)96 static inline void gverb_fdnmatrix(float *a, float *b)
97 {
98 const float dl0 = a[0], dl1 = a[1], dl2 = a[2], dl3 = a[3];
99
100 b[0] = 0.5f*(+dl0 + dl1 - dl2 - dl3);
101 b[1] = 0.5f*(+dl0 - dl1 - dl2 + dl3);
102 b[2] = 0.5f*(-dl0 + dl1 - dl2 + dl3);
103 b[3] = 0.5f*(+dl0 + dl1 + dl2 + dl3);
104 }
105
gverb_do(ty_gverb * p,float x,float * yl,float * yr)106 static inline void gverb_do(ty_gverb *p, float x, float *yl, float *yr)
107 {
108 float z;
109 unsigned int i;
110 float lsum,rsum,sum,sign;
111
112 if (isnan(x) || fabsf(x) > 100000.0f) {
113 x = 0.0f;
114 }
115
116 z = damper_do(p->inputdamper, x);
117
118 z = diffuser_do(p->ldifs[0],z);
119
120 for(i = 0; i < FDNORDER; i++) {
121 p->u[i] = p->tapgains[i]*fixeddelay_read(p->tapdelay,p->taps[i]);
122 }
123 fixeddelay_write(p->tapdelay,z);
124
125 for(i = 0; i < FDNORDER; i++) {
126 p->d[i] = damper_do(p->fdndamps[i],
127 p->fdngains[i]*fixeddelay_read(p->fdndels[i],
128 p->fdnlens[i]));
129 }
130
131 sum = 0.0f;
132 sign = 1.0f;
133 for(i = 0; i < FDNORDER; i++) {
134 sum += sign*(p->taillevel*p->d[i] + p->earlylevel*p->u[i]);
135 sign = -sign;
136 }
137 sum += x*p->earlylevel;
138 lsum = sum;
139 rsum = sum;
140
141 gverb_fdnmatrix(p->d,p->f);
142
143 for(i = 0; i < FDNORDER; i++) {
144 fixeddelay_write(p->fdndels[i],p->u[i]+p->f[i]);
145 }
146
147 lsum = diffuser_do(p->ldifs[1],lsum);
148 lsum = diffuser_do(p->ldifs[2],lsum);
149 lsum = diffuser_do(p->ldifs[3],lsum);
150 rsum = diffuser_do(p->rdifs[1],rsum);
151 rsum = diffuser_do(p->rdifs[2],rsum);
152 rsum = diffuser_do(p->rdifs[3],rsum);
153
154 *yl = lsum;
155 *yr = rsum;
156 }
157
gverb_set_roomsize(ty_gverb * p,const float a)158 static inline void gverb_set_roomsize(ty_gverb *p, const float a)
159 {
160 unsigned int i;
161
162 if (a <= 1.0 || isnan(a)) {
163 p->roomsize = 1.0;
164 } else {
165 p->roomsize = a;
166 }
167 p->largestdelay = p->rate * p->roomsize * 0.00294f;
168
169 p->fdnlens[0] = f_round(1.000000f*p->largestdelay);
170 p->fdnlens[1] = f_round(0.816490f*p->largestdelay);
171 p->fdnlens[2] = f_round(0.707100f*p->largestdelay);
172 p->fdnlens[3] = f_round(0.632450f*p->largestdelay);
173 for(i = 0; i < FDNORDER; i++) {
174 p->fdngains[i] = -powf((float)p->alpha, p->fdnlens[i]);
175 }
176
177 p->taps[0] = 5+f_round(0.410f*p->largestdelay);
178 p->taps[1] = 5+f_round(0.300f*p->largestdelay);
179 p->taps[2] = 5+f_round(0.155f*p->largestdelay);
180 p->taps[3] = 5+f_round(0.000f*p->largestdelay);
181
182 for(i = 0; i < FDNORDER; i++) {
183 p->tapgains[i] = powf((float)p->alpha, p->taps[i]);
184 }
185
186 }
187
gverb_set_revtime(ty_gverb * p,float a)188 static inline void gverb_set_revtime(ty_gverb *p,float a)
189 {
190 float ga,gt;
191 double n;
192 unsigned int i;
193
194 p->revtime = a;
195
196 ga = 60.0;
197 gt = p->revtime;
198 ga = powf(10.0f,-ga/20.0f);
199 n = p->rate*gt;
200 p->alpha = (double)powf(ga,1.0f/n);
201
202 for(i = 0; i < FDNORDER; i++) {
203 p->fdngains[i] = -powf((float)p->alpha, p->fdnlens[i]);
204 }
205
206 }
207
gverb_set_damping(ty_gverb * p,float a)208 static inline void gverb_set_damping(ty_gverb *p,float a)
209 {
210 unsigned int i;
211
212 p->fdndamping = a;
213 for(i = 0; i < FDNORDER; i++) {
214 damper_set(p->fdndamps[i],p->fdndamping);
215 }
216 }
217
gverb_set_inputbandwidth(ty_gverb * p,float a)218 static inline void gverb_set_inputbandwidth(ty_gverb *p,float a)
219 {
220 p->inputbandwidth = a;
221 damper_set(p->inputdamper,1.0 - p->inputbandwidth);
222 }
223
gverb_set_earlylevel(ty_gverb * p,float a)224 static inline void gverb_set_earlylevel(ty_gverb *p,float a)
225 {
226 p->earlylevel = a;
227 }
228
gverb_set_taillevel(ty_gverb * p,float a)229 static inline void gverb_set_taillevel(ty_gverb *p,float a)
230 {
231 p->taillevel = a;
232 }
233
234 #endif
235