CSL  5.2
Freeverb.cpp
Go to the documentation of this file.
1 //
2 // Reverb.h -- The CSL port of the public domain Freeverb reverberator
3 // Freeverb was written by Jezar at Dreampoint, June 2000 -- http://www.dreampoint.co.uk
4 // See the copyright notice and acknowledgment of authors in the file COPYRIGHT
5 //
6 
7 #include "Freeverb.h"
8 
9 //#undef GCC_AUTO_VECTORIZATION
10 
11 using namespace csl;
12 
13 // These values assume 44.1KHz sample rate
14 // they will probably be OK for 48KHz sample rate
15 // but would need scaling for 96KHz (or other) sample rates.
16 // The values were obtained by listening tests.
17 
18 const int kNumCombs = 8;
19 const int kNumAllpasses = 4;
20 const float kMuted = 0.0f;
21 const float kFixedGain = 0.015f;
22 //const float kFixedGain = 1.0f;
23 const float kScaleWet = 3.0f;
24 const float kScaleDry = 2.0f;
25 const float kScaleDamp = 0.4f;
26 const float kScaleRoom = 0.28f;
27 const float kOffsetRoom = 0.7f;
28 const float kInitialRoom = 0.95;
29 const float kInitialDamp = 0.5f;
30 const float kInitialWet = 0.5;
31 const float kInitialDry = 0.5;
32 const float kInitialWidth = 1.0f;
33 const float kInitialMode = 0.0f;
34 const float kFreezeMode = 1.0f;
35 const int kStereoSpread = 23;
36 
37 const int kCombBufferSizes[] = { 1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617 };
38 const int kAllpassBufferSizes[] = { 556, 441, 341, 225 };
39 
40 // ~~~~~~ Comb implementation ~~~~~~~~~~ //
41 
42 void Comb::setBuffer(float *buf, int size) {
43  mBufferPtr = buf;
44  mBufSize = size;
45 }
46 
47 void Comb::mute() {
48  for (int i = 0; i < mBufSize; ++i)
49  mBufferPtr[i] = 0;
50 }
51 
52 void Comb::setDamp(float val) {
53  mDamp1 = val;
54  mDamp2 = 1 - val;
55 }
56 
57 // ~~~~~~ Allpass implementation ~~~~~~~~~~ //
58 
59 void FAllpass::setBuffer(float *buf, int size) {
60  mBufferPtr = buf;
61  mBufSize = size;
62 }
63 
65  for (int i = 0; i < mBufSize; i++)
66  mBufferPtr[i] = 0;
67 }
68 
69 // ~~~~~~~ Freeverb implementation ~~~~~~ //
70 
73 }
74 
76  for (unsigned i = 0; i < mCombFilters.size(); i++)
77  delete mCombBuffers[i];
78 
79  for (unsigned i = 0; i < mAllpassFilters.size(); i++)
80  delete mAllpassBuffers[i];
81 
82  std::vector<Comb*>::iterator iComb = mCombFilters.begin();
83  for (; iComb != mCombFilters.end(); ++iComb)
84  delete *iComb;
85 
86  std::vector<FAllpass*>::iterator iAllpass = mAllpassFilters.begin();
87  for (; iAllpass != mAllpassFilters.end(); ++iAllpass)
88  delete *iAllpass;
89 }
90 
92  int i, j;
93  int bufferSize;
94  sample * bufferPtr;
95  Comb *combFilter;
96  FAllpass *allpassFilter;
99 
100  // create buffers and combs
101  for (i = 0; i < kNumCombs; i++) {
102  bufferSize = kCombBufferSizes[i];
103  bufferPtr = new sample[bufferSize];
104  for (j = 0; j < bufferSize; j++)
105  bufferPtr[j] = 0.0f;
106  mCombBuffers[i] = bufferPtr;
107  combFilter = new Comb();
108  combFilter->setBuffer(bufferPtr, bufferSize);
109  mCombFilters.push_back(combFilter);
110  }
111  // create buffers and allpasses
112  for (i = 0; i < kNumAllpasses; i++) {
113  bufferSize = kAllpassBufferSizes[i];
114  bufferPtr = new sample[bufferSize];
115  for (j = 0; j < bufferSize; j++)
116  bufferPtr[j] = 0.0f;
117  mAllpassBuffers[i]= bufferPtr;
118  allpassFilter = new FAllpass();
119  allpassFilter->setBuffer(bufferPtr, bufferSize);
120  allpassFilter->setFeedback(0.5f);
121  mAllpassFilters.push_back(allpassFilter);
122  }
123  // Set default values
129  mGain = kFixedGain;
131 }
132 
134  for (std::vector<Comb*>::iterator iComb = mCombFilters.begin();
135  iComb != mCombFilters.end(); ++iComb) {
136  (*iComb)->setFeedback(mRoomSize);
137  (*iComb)->setDamp(mDampening);
138  }
139 }
140 
141 float Freeverb::roomSize() { return mRoomSize; }
142 
143 void Freeverb::setRoomSize(float size) {
144  mRoomSize = size * kScaleRoom + kOffsetRoom;
146 }
147 
148 float Freeverb::dampening() { return (mDampening * 100.0f) / kScaleDamp; }
149 
150 /// The "damp" parameter can be thought as setting the material of the room walls.
151 
152 void Freeverb::setDampening(float damp) {
153  mDampening = (damp * 0.01f) * kScaleDamp;
155 }
156 
157 float Freeverb::wetLevel() { return mWetLevel; }
158 
159 void Freeverb::setWetLevel(float level) {
160  mWetLevel = level;
162 }
163 
164 float Freeverb::dryLevel() { return mDryLevel; }
165 
166 /// Amount of the original "dry" signal in the output.
167 
168 void Freeverb::setDryLevel(float level) { mDryLevel = level; }
169 
170 float Freeverb::width() { return (mWidth*100.0f); }
171 
172 void Freeverb::setWidth(float twidth) {
173  mWidth = (twidth*0.01f);
175 }
176 
177 // Do the work
178 
179 void Freeverb::nextBuffer(Buffer &outputBuffer, unsigned outBufNum) throw (CException) {
180  unsigned numFrames = outputBuffer.mNumFrames;
181  sample * fp = outputBuffer.buffer(outBufNum);
182  this->pullInput(outputBuffer);
183  sample * inputBuf = mInputPtr;
184  float out, input;
185  unsigned i;
186 #ifdef CSL_DEBUG
187  logMsg("Freeverb nextBuffer");
188 #endif
189  for (i = 0; i < numFrames; i++) {
190  out = 0;
191  input = inputBuf[i] * mGain;
192  // Accumulate comb filters in parallel
193  std::vector<Comb*>::iterator iComb = mCombFilters.begin();
194  for (; iComb != mCombFilters.end(); ++iComb)
195  out += (*iComb)->process(input);
196  // Feed through allpasses in series
197  std::vector<FAllpass*>::iterator iAllpass = mAllpassFilters.begin();
198  for (; iAllpass != mAllpassFilters.end(); ++iAllpass)
199  out = (*iAllpass)->process(out);
200  *fp++ = out * mWetLevel + inputBuf[i] * mDryLevel; // Calculate output REPLACING anything already there
201  }
202 }
203 
204 //// Stereoverb ////////////////////////////////
205 
206 // Constructor sets up splitter/joiner network
207 
209  split = new Splitter(input);
210 
211  leftRev = new Freeverb(* split); // 2 mono reverbs
215 
216  rightRev = new Freeverb(* split);
220 
221  join = new Joiner (* leftRev, * rightRev); // mono-to-stereo joiner
222 }
223 
225  delete split;
226  delete leftRev;
227  delete rightRev;
228  delete join;
229 }
230 
232  return(split->isActive());
233 }
234 
235 void Stereoverb::setRoomSize(float size) {
236  leftRev->setRoomSize(size);
237  rightRev->setRoomSize(size);
238 }
239 
240 void Stereoverb::setDampening(float damp) {
241  leftRev->setDampening(damp);
242  rightRev->setDampening(damp);
243 }
244 
245 void Stereoverb::setWetLevel(float level) {
246  leftRev->setWetLevel(level);
247  rightRev->setWetLevel(level);
248 }
249 
250 void Stereoverb::setDryLevel(float level) {
251  leftRev->setDryLevel(level);
252  rightRev->setDryLevel(level);
253 }
254 
255 void Stereoverb::setWidth(float width) {
256  leftRev->setWidth(width);
257  rightRev->setWidth(width);
258 }
259 
260 // next_buffer work-horse method
261 
262 void Stereoverb::nextBuffer(Buffer &outputBuffer) throw (CException) {
263  join->nextBuffer(outputBuffer);
264 }