Make duplicate script compatible with Python 3
[wdl/wdl-ol.git] / WDL / verbengine.h
blob6524c87263f210458b2b194950d85618e5c93bd6
1 #ifndef _VERBENGINE_H_
2 #define _VERBENGINE_H_
5 /*
6 WDL - verbengine.h
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.
34 #include "heapbuf.h"
37 #include "denormal.h"
39 class WDL_ReverbAllpass
41 public:
42 WDL_ReverbAllpass() { feedback=0.5; setsize(1); }
43 ~WDL_ReverbAllpass() { }
45 void setsize(int size)
47 if (size<1)size=1;
48 if (buffer.GetSize()!=size)
50 bufidx=0;
51 buffer.Resize(size);
52 Reset();
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;
67 return output;
69 void Reset() { memset(buffer.Get(),0,buffer.GetSize()*sizeof(double)); }
70 void setfeedback(double val) { feedback=val; }
72 private:
73 double feedback;
74 WDL_TypedBuf<double> buffer;
75 int bufidx;
76 int __pad;
78 } WDL_FIXALIGN;
81 class WDL_ReverbComb
83 public:
84 WDL_ReverbComb() { feedback=0.5; damp=0.5; filterstore=0; setsize(1); }
85 ~WDL_ReverbComb() { }
87 void setsize(int size)
89 if (size<1)size=1;
90 if (buffer.GetSize()!=size)
92 bufidx=0;
93 buffer.Resize(size);
94 Reset();
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;
108 return output;
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; }
114 private:
116 double feedback;
117 double filterstore;
118 double damp;
119 WDL_TypedBuf<double> buffer;
120 int bufidx;
121 int __pad;
122 } WDL_FIXALIGN;
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
132 public:
133 WDL_ReverbEngine()
135 m_srate=44100.0;
136 m_roomsize=0.5;
137 m_damp=0.5;
138 SetWidth(1.0);
139 Reset(false);
141 ~WDL_ReverbEngine()
144 void SetSampleRate(double srate)
146 if (m_srate!=srate)
148 m_srate=srate;
149 Reset(true);
153 void ProcessSampleBlock(double *spl0, double *spl1, double *outp0, double *outp1, int ns)
155 int x;
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)
161 int i=ns;
162 double *p0=outp0,*p1=outp1,*i0=spl0,*i1=spl1;
163 while (i--)
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)
174 int i=ns;
175 double *p0=outp0,*p1=outp1;
176 while (i--)
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);
184 int i=ns;
185 double *p0=outp0,*p1=outp1;
186 while (i--)
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;
191 if (m_wid<0)
193 double m=-m_wid;
194 *p0 = b*m + a*(1.0-m);
195 *p1 = a*m + b*(1.0-m);
197 else
199 double m=m_wid;
200 *p0 = a*m + b*(1.0-m);
201 *p1 = b*m + a*(1.0-m);
203 p0++;
204 p1++;
209 void ProcessSample(double *spl0, double *spl1)
211 int x;
212 double in0=*spl0 * 0.015;
213 double in1=*spl1 * 0.015;
215 double out0=0.0;
216 double out1=0.0;
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);
228 if (m_wid<0)
230 double m=-m_wid;
231 *spl0 = out1*m + out0*(1.0-m);
232 *spl1 = out0*m + out1*(1.0-m);
234 else
236 double m=m_wid;
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
244 int x;
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);
252 if (doclear)
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);
266 if (doclear)
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)
279 if (wid<-1) wid=-1;
280 else if (wid>1) wid=1;
281 wid*=0.5;
282 if (wid>=0.0) wid+=0.5;
283 else wid-=0.5;
284 m_wid=wid;
285 } // -1..1
287 private:
288 double m_wid;
289 double m_roomsize;
290 double m_damp;
291 double m_srate;
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];
298 #endif