7 Copyright (C) 2007 and later Cockos Incorporated
9 This is based on the public domain FreeVerb source:
10 by Jezar at Dreampoint, June 2000
11 http://www.dreampoint.co.uk
13 Filter tweaks and general guidance thanks to Thomas Scott Stillwell.
15 This software is provided 'as-is', without any express or implied
16 warranty. In no event will the authors be held liable for any damages
17 arising from the use of this software.
19 Permission is granted to anyone to use this software for any purpose,
20 including commercial applications, and to alter it and redistribute it
21 freely, subject to the following restrictions:
23 1. The origin of this software must not be misrepresented; you must not
24 claim that you wrote the original software. If you use this software
25 in a product, an acknowledgment in the product documentation would be
26 appreciated but is not required.
27 2. Altered source versions must be plainly marked as such, and must not be
28 misrepresented as being the original software.
29 3. This notice may not be removed or altered from any source distribution.
39 class WDL_ReverbAllpass
42 WDL_ReverbAllpass() { feedback
=0.5; setsize(1); }
43 ~WDL_ReverbAllpass() { }
45 void setsize(int size
)
48 if (buffer
.GetSize()!=size
)
56 double process(double inp
)
58 double *bptr
=buffer
.Get()+bufidx
;
60 double bufout
= *bptr
;
62 double output
= bufout
- inp
;
63 *bptr
= denormal_filter_double(inp
+ (bufout
*feedback
));
65 if(++bufidx
>=buffer
.GetSize()) bufidx
= 0;
69 void Reset() { memset(buffer
.Get(),0,buffer
.GetSize()*sizeof(double)); }
70 void setfeedback(double val
) { feedback
=val
; }
74 WDL_TypedBuf
<double> buffer
;
84 WDL_ReverbComb() { feedback
=0.5; damp
=0.5; filterstore
=0; setsize(1); }
87 void setsize(int size
)
90 if (buffer
.GetSize()!=size
)
98 double process(double inp
)
100 double *bptr
=buffer
.Get()+bufidx
;
101 double output
= *bptr
;
102 filterstore
= denormal_filter_double((output
*(1-damp
)) + (filterstore
*damp
));
104 *bptr
= inp
+ (filterstore
*feedback
);
106 if(++bufidx
>=buffer
.GetSize()) bufidx
= 0;
110 void Reset() { memset(buffer
.Get(),0,buffer
.GetSize()*sizeof(double)); }
111 void setdamp(double val
) { damp
=val
; }
112 void setfeedback(double val
) { feedback
=val
; }
119 WDL_TypedBuf
<double> buffer
;
124 // these represent lengths in samples at 44.1khz but are scaled accordingly
125 const int wdl_verb__stereospread
=23;
126 const short wdl_verb__combtunings
[]={1116,1188,1277,1356,1422,1491,1557,1617,1685,1748};
127 const short wdl_verb__allpasstunings
[]={556,441,341,225,180,153};
130 class WDL_ReverbEngine
144 void SetSampleRate(double srate
)
153 void ProcessSampleBlock(double *spl0
, double *spl1
, double *outp0
, double *outp1
, int ns
)
156 memset(outp0
,0,ns
*sizeof(double));
157 memset(outp1
,0,ns
*sizeof(double));
159 for (x
= 0; x
< sizeof(wdl_verb__combtunings
)/sizeof(wdl_verb__combtunings
[0]); x
+= 2)
162 double *p0
=outp0
,*p1
=outp1
,*i0
=spl0
,*i1
=spl1
;
165 double a
=*i0
++,b
=*i1
++;
166 *p0
+=m_combs
[x
][0].process(a
);
167 *p1
+=m_combs
[x
][1].process(b
);
168 *p0
+++=m_combs
[x
+1][0].process(a
);
169 *p1
+++=m_combs
[x
+1][1].process(b
);
172 for (x
= 0; x
< sizeof(wdl_verb__allpasstunings
)/sizeof(wdl_verb__allpasstunings
[0])-2; x
+= 2)
175 double *p0
=outp0
,*p1
=outp1
;
178 double tmp
=m_allpasses
[x
][0].process(*p0
);
179 double tmp2
=m_allpasses
[x
][1].process(*p1
);
180 *p0
++=m_allpasses
[x
+1][0].process(tmp
);
181 *p1
++=m_allpasses
[x
+1][1].process(tmp2
);
185 double *p0
=outp0
,*p1
=outp1
;
188 double a
=m_allpasses
[x
+1][0].process(m_allpasses
[x
][0].process(*p0
))*0.015;
189 double b
=m_allpasses
[x
+1][1].process(m_allpasses
[x
][1].process(*p1
))*0.015;
194 *p0
= b
*m
+ a
*(1.0-m
);
195 *p1
= a
*m
+ b
*(1.0-m
);
200 *p0
= a
*m
+ b
*(1.0-m
);
201 *p1
= b
*m
+ a
*(1.0-m
);
209 void ProcessSample(double *spl0
, double *spl1
)
212 double in0
=*spl0
* 0.015;
213 double in1
=*spl1
* 0.015;
217 for (x
= 0; x
< sizeof(wdl_verb__combtunings
)/sizeof(wdl_verb__combtunings
[0]); x
++)
219 out0
+=m_combs
[x
][0].process(in0
);
220 out1
+=m_combs
[x
][1].process(in1
);
222 for (x
= 0; x
< sizeof(wdl_verb__allpasstunings
)/sizeof(wdl_verb__allpasstunings
[0]); x
++)
224 out0
=m_allpasses
[x
][0].process(out0
);
225 out1
=m_allpasses
[x
][1].process(out1
);
231 *spl0
= out1
*m
+ out0
*(1.0-m
);
232 *spl1
= out0
*m
+ out1
*(1.0-m
);
237 *spl0
= out0
*m
+ out1
*(1.0-m
);
238 *spl1
= out1
*m
+ out0
*(1.0-m
);
242 void Reset(bool doclear
=false) // call this after changing roomsize or dampening
245 double sc
=m_srate
/ 44100.0;
246 for (x
= 0; x
< sizeof(wdl_verb__allpasstunings
)/sizeof(wdl_verb__allpasstunings
[0]); x
++)
248 m_allpasses
[x
][0].setsize((int) (wdl_verb__allpasstunings
[x
] * sc
));
249 m_allpasses
[x
][1].setsize((int) ((wdl_verb__allpasstunings
[x
]+wdl_verb__stereospread
) * sc
));
250 m_allpasses
[x
][0].setfeedback(0.5);
251 m_allpasses
[x
][1].setfeedback(0.5);
254 m_allpasses
[x
][0].Reset();
255 m_allpasses
[x
][1].Reset();
258 for (x
= 0; x
< sizeof(wdl_verb__combtunings
)/sizeof(wdl_verb__combtunings
[0]); x
++)
260 m_combs
[x
][0].setsize((int) (wdl_verb__combtunings
[x
] * sc
));
261 m_combs
[x
][1].setsize((int) ((wdl_verb__combtunings
[x
]+wdl_verb__stereospread
) * sc
));
262 m_combs
[x
][0].setfeedback(m_roomsize
);
263 m_combs
[x
][1].setfeedback(m_roomsize
);
264 m_combs
[x
][0].setdamp(m_damp
*0.4);
265 m_combs
[x
][1].setdamp(m_damp
*0.4);
268 m_combs
[x
][0].Reset();
269 m_combs
[x
][1].Reset();
275 void SetRoomSize(double sz
) { m_roomsize
=sz
;; } // 0.3..0.99 or so
276 void SetDampening(double dmp
) { m_damp
=dmp
; } // 0..1
277 void SetWidth(double wid
)
280 else if (wid
>1) wid
=1;
282 if (wid
>=0.0) wid
+=0.5;
292 WDL_ReverbAllpass m_allpasses
[sizeof(wdl_verb__allpasstunings
)/sizeof(wdl_verb__allpasstunings
[0])][2];
293 WDL_ReverbComb m_combs
[sizeof(wdl_verb__combtunings
)/sizeof(wdl_verb__combtunings
[0])][2];