Anklang 0.3.0-460-gc4ef46ba
ASE — Anklang Sound Engine (C++)

« « « Anklang Documentation
Loading...
Searching...
No Matches
revmodel.cpp
Go to the documentation of this file.
1 // Reverb model implementation
2//
3// Written by Jezar at Dreampoint, June 2000
4// http://www.dreampoint.co.uk
5// This code is public domain
6
7#include "revmodel.hpp"
8
9revmodel::revmodel()
10{
11 // Tie the components to their buffers
12 combL[0].setbuffer(bufcombL1,combtuningL1);
13 combR[0].setbuffer(bufcombR1,combtuningR1);
14 combL[1].setbuffer(bufcombL2,combtuningL2);
15 combR[1].setbuffer(bufcombR2,combtuningR2);
16 combL[2].setbuffer(bufcombL3,combtuningL3);
17 combR[2].setbuffer(bufcombR3,combtuningR3);
18 combL[3].setbuffer(bufcombL4,combtuningL4);
19 combR[3].setbuffer(bufcombR4,combtuningR4);
20 combL[4].setbuffer(bufcombL5,combtuningL5);
21 combR[4].setbuffer(bufcombR5,combtuningR5);
22 combL[5].setbuffer(bufcombL6,combtuningL6);
23 combR[5].setbuffer(bufcombR6,combtuningR6);
24 combL[6].setbuffer(bufcombL7,combtuningL7);
25 combR[6].setbuffer(bufcombR7,combtuningR7);
26 combL[7].setbuffer(bufcombL8,combtuningL8);
27 combR[7].setbuffer(bufcombR8,combtuningR8);
28 allpassL[0].setbuffer(bufallpassL1,allpasstuningL1);
29 allpassR[0].setbuffer(bufallpassR1,allpasstuningR1);
30 allpassL[1].setbuffer(bufallpassL2,allpasstuningL2);
31 allpassR[1].setbuffer(bufallpassR2,allpasstuningR2);
32 allpassL[2].setbuffer(bufallpassL3,allpasstuningL3);
33 allpassR[2].setbuffer(bufallpassR3,allpasstuningR3);
34 allpassL[3].setbuffer(bufallpassL4,allpasstuningL4);
35 allpassR[3].setbuffer(bufallpassR4,allpasstuningR4);
36
37 // Set default values
38 allpassL[0].setfeedback(0.5f);
39 allpassR[0].setfeedback(0.5f);
40 allpassL[1].setfeedback(0.5f);
41 allpassR[1].setfeedback(0.5f);
42 allpassL[2].setfeedback(0.5f);
43 allpassR[2].setfeedback(0.5f);
44 allpassL[3].setfeedback(0.5f);
45 allpassR[3].setfeedback(0.5f);
46 setwet(initialwet);
47 setroomsize(initialroom);
48 setdry(initialdry);
49 setdamp(initialdamp, +1);
50 setwidth(initialwidth);
51 setmode(initialmode);
52
53 // Buffer will be full of rubbish - so we MUST mute them
54 mute();
55}
56
57void revmodel::mute()
58{
59 if (getmode() >= freezemode)
60 return;
61
62 for (int i=0;i<numcombs;i++)
63 {
64 combL[i].mute();
65 combR[i].mute();
66 }
67 for (int i=0;i<numallpasses;i++)
68 {
69 allpassL[i].mute();
70 allpassR[i].mute();
71 }
72}
73
74void revmodel::processreplace(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip)
75{
76 float outL,outR,input;
77
78 while(numsamples-- > 0)
79 {
80 outL = outR = 0;
81 input = (*inputL + *inputR) * gain;
82
83 // Accumulate comb filters in parallel
84 for(int i=0; i<numcombs; i++)
85 {
86 outL += combL[i].process(input);
87 outR += combR[i].process(input);
88 }
89
90 // Feed through allpasses in series
91 for(int i=0; i<numallpasses; i++)
92 {
93 outL = allpassL[i].process(outL);
94 outR = allpassR[i].process(outR);
95 }
96
97 // Calculate output REPLACING anything already there
98 *outputL = outL*wet1 + outR*wet2 + *inputL*dry;
99 *outputR = outR*wet1 + outL*wet2 + *inputR*dry;
100
101 // Increment sample pointers, allowing for interleave (if any)
102 inputL += skip;
103 inputR += skip;
104 outputL += skip;
105 outputR += skip;
106 }
107}
108
109void revmodel::processmix(float *inputL, float *inputR, float *outputL, float *outputR, long numsamples, int skip)
110{
111 float outL,outR,input;
112
113 while(numsamples-- > 0)
114 {
115 outL = outR = 0;
116 input = (*inputL + *inputR) * gain;
117
118 // Accumulate comb filters in parallel
119 for(int i=0; i<numcombs; i++)
120 {
121 outL += combL[i].process(input);
122 outR += combR[i].process(input);
123 }
124
125 // Feed through allpasses in series
126 for(int i=0; i<numallpasses; i++)
127 {
128 outL = allpassL[i].process(outL);
129 outR = allpassR[i].process(outR);
130 }
131
132 // Calculate output MIXING with anything already there
133 *outputL += outL*wet1 + outR*wet2 + *inputL*dry;
134 *outputR += outR*wet1 + outL*wet2 + *inputR*dry;
135
136 // Increment sample pointers, allowing for interleave (if any)
137 inputL += skip;
138 inputR += skip;
139 outputL += skip;
140 outputR += skip;
141 }
142}
143
144void revmodel::update()
145{
146// Recalculate internal values after parameter change
147
148 int i;
149
150 wet1 = wet*(width/2 + 0.5f);
151 wet2 = wet*((1-width)/2);
152
153 if (mode >= freezemode)
154 {
155 roomsize1 = 1;
156 damp1 = 0;
157 gain = muted;
158 }
159 else
160 {
161 roomsize1 = roomsize;
162 damp1 = damp;
163 gain = fixedgain;
164 }
165
166 for(i=0; i<numcombs; i++)
167 {
168 combL[i].setfeedback(roomsize1);
169 combR[i].setfeedback(roomsize1);
170 }
171
172 for(i=0; i<numcombs; i++)
173 {
174 combL[i].setdamp(damp1, dampmode);
175 combR[i].setdamp(damp1, dampmode);
176 }
177}
178
179// The following get/set functions are not inlined, because
180// speed is never an issue when calling them, and also
181// because as you develop the reverb model, you may
182// wish to take dynamic action when they are called.
183
184void revmodel::setroomsize(float value)
185{
186 roomsize = (value*scaleroom) + offsetroom;
187 update();
188}
189
190float revmodel::getroomsize()
191{
192 return (roomsize-offsetroom)/scaleroom;
193}
194
195void revmodel::setdamp(float value, int mode)
196{
197 damp = value*scaledamp;
198 dampmode = mode;
199 update();
200}
201
202float revmodel::getdamp()
203{
204 return damp/scaledamp;
205}
206
207void revmodel::setwet(float value)
208{
209 wet = value*scalewet;
210 update();
211}
212
213float revmodel::getwet()
214{
215 return wet/scalewet;
216}
217
218void revmodel::setdry(float value)
219{
220 dry = value*scaledry;
221}
222
223float revmodel::getdry()
224{
225 return dry/scaledry;
226}
227
228void revmodel::setwidth(float value)
229{
230 width = value;
231 update();
232}
233
234float revmodel::getwidth()
235{
236 return width;
237}
238
239void revmodel::setmode(float value)
240{
241 mode = value;
242 update();
243}
244
245float revmodel::getmode()
246{
247 if (mode >= freezemode)
248 return 1;
249 else
250 return 0;
251}
252
253//ends