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