DOSBox-X
|
00001 // Reverb model implementation 00002 // 00003 // Written by Jezar at Dreampoint, June 2000 00004 // Modifications by Jerome Fisher, 2009, 2011 00005 // http://www.dreampoint.co.uk 00006 // This code is public domain 00007 00008 #include "revmodel.h" 00009 00010 revmodel::revmodel(float scaletuning) 00011 { 00012 int i; 00013 int bufsize; 00014 00015 // Allocate buffers for the components 00016 for (i = 0; i < numcombs; i++) { 00017 bufsize = int(scaletuning * combtuning[i]); 00018 combL[i].setbuffer(new float[bufsize], bufsize); 00019 bufsize += int(scaletuning * stereospread); 00020 combR[i].setbuffer(new float[bufsize], bufsize); 00021 } 00022 for (i = 0; i < numallpasses; i++) { 00023 bufsize = int(scaletuning * allpasstuning[i]); 00024 allpassL[i].setbuffer(new float[bufsize], bufsize); 00025 allpassL[i].setfeedback(0.5f); 00026 bufsize += int(scaletuning * stereospread); 00027 allpassR[i].setbuffer(new float[bufsize], bufsize); 00028 allpassR[i].setfeedback(0.5f); 00029 } 00030 00031 // Set default values 00032 dry = initialdry; 00033 wet = initialwet*scalewet; 00034 damp = initialdamp*scaledamp; 00035 roomsize = (initialroom*scaleroom) + offsetroom; 00036 width = initialwidth; 00037 mode = initialmode; 00038 filtval = 0; 00039 update(); 00040 00041 // Buffer will be full of rubbish - so we MUST mute them 00042 mute(); 00043 } 00044 00045 revmodel::~revmodel() 00046 { 00047 int i; 00048 00049 for (i = 0; i < numcombs; i++) { 00050 combL[i].deletebuffer(); 00051 combR[i].deletebuffer(); 00052 } 00053 for (i = 0; i < numallpasses; i++) { 00054 allpassL[i].deletebuffer(); 00055 allpassR[i].deletebuffer(); 00056 } 00057 } 00058 00059 void revmodel::mute() 00060 { 00061 int i; 00062 00063 if (getmode() >= freezemode) 00064 return; 00065 00066 for (i=0;i<numcombs;i++) 00067 { 00068 combL[i].mute(); 00069 combR[i].mute(); 00070 } 00071 for (i=0;i<numallpasses;i++) 00072 { 00073 allpassL[i].mute(); 00074 allpassR[i].mute(); 00075 } 00076 00077 // Init LPF history 00078 filtprev1 = 0; 00079 filtprev2 = 0; 00080 } 00081 00082 void revmodel::process(const float *inputL, const float *inputR, float *outputL, float *outputR, long numsamples) 00083 { 00084 while (numsamples-- > 0) 00085 { 00086 int i; 00087 00088 float outL = 0; 00089 float outR = 0; 00090 float input = (*inputL + *inputR) * gain; 00091 00092 // Implementation of 2-stage IIR single-pole low-pass filter 00093 // found at the entrance of reverb processing on real devices 00094 filtprev1 += (input - filtprev1) * filtval; 00095 filtprev2 += (filtprev1 - filtprev2) * filtval; 00096 input = filtprev2; 00097 00098 int s = -1; 00099 // Accumulate comb filters in parallel 00100 for (i=0; i<numcombs; i++) 00101 { 00102 outL += s * combL[i].process(input); 00103 outR += s * combR[i].process(input); 00104 s = -s; 00105 } 00106 00107 // Feed through allpasses in series 00108 for (i=0; i<numallpasses; i++) 00109 { 00110 outL = allpassL[i].process(outL); 00111 outR = allpassR[i].process(outR); 00112 } 00113 00114 // Calculate output REPLACING anything already there 00115 *outputL = outL*wet1 + outR*wet2; 00116 *outputR = outR*wet1 + outL*wet2; 00117 00118 inputL++; 00119 inputR++; 00120 outputL++; 00121 outputR++; 00122 } 00123 } 00124 00125 void revmodel::update() 00126 { 00127 // Recalculate internal values after parameter change 00128 00129 int i; 00130 00131 wet1 = wet*(width/2 + 0.5f); 00132 wet2 = wet*((1-width)/2); 00133 00134 if (mode >= freezemode) 00135 { 00136 roomsize1 = 1; 00137 damp1 = 0; 00138 gain = muted; 00139 } 00140 else 00141 { 00142 roomsize1 = roomsize; 00143 damp1 = damp; 00144 gain = fixedgain; 00145 } 00146 00147 for (i=0; i<numcombs; i++) 00148 { 00149 combL[i].setfeedback(roomsize1); 00150 combR[i].setfeedback(roomsize1); 00151 } 00152 00153 for (i=0; i<numcombs; i++) 00154 { 00155 combL[i].setdamp(damp1); 00156 combR[i].setdamp(damp1); 00157 } 00158 } 00159 00160 // The following get/set functions are not inlined, because 00161 // speed is never an issue when calling them, and also 00162 // because as you develop the reverb model, you may 00163 // wish to take dynamic action when they are called. 00164 00165 void revmodel::setroomsize(float value) 00166 { 00167 roomsize = (value*scaleroom) + offsetroom; 00168 update(); 00169 } 00170 00171 float revmodel::getroomsize() 00172 { 00173 return (roomsize-offsetroom)/scaleroom; 00174 } 00175 00176 void revmodel::setdamp(float value) 00177 { 00178 damp = value*scaledamp; 00179 update(); 00180 } 00181 00182 float revmodel::getdamp() 00183 { 00184 return damp/scaledamp; 00185 } 00186 00187 void revmodel::setwet(float value) 00188 { 00189 wet = value*scalewet; 00190 update(); 00191 } 00192 00193 float revmodel::getwet() 00194 { 00195 return wet/scalewet; 00196 } 00197 00198 void revmodel::setdry(float value) 00199 { 00200 dry = value*scaledry; 00201 } 00202 00203 float revmodel::getdry() 00204 { 00205 return dry/scaledry; 00206 } 00207 00208 void revmodel::setwidth(float value) 00209 { 00210 width = value; 00211 update(); 00212 } 00213 00214 float revmodel::getwidth() 00215 { 00216 return width; 00217 } 00218 00219 void revmodel::setmode(float value) 00220 { 00221 mode = value; 00222 update(); 00223 } 00224 00225 float revmodel::getmode() 00226 { 00227 if (mode >= freezemode) 00228 return 1; 00229 else 00230 return 0; 00231 } 00232 00233 void revmodel::setfiltval(float value) 00234 { 00235 filtval = value; 00236 } 00237 00238 00239 void revmodel::saveState( std::ostream &stream ) 00240 { 00241 stream.write(reinterpret_cast<const char*>(&gain), sizeof(gain) ); 00242 stream.write(reinterpret_cast<const char*>(&roomsize), sizeof(roomsize) ); 00243 stream.write(reinterpret_cast<const char*>(&roomsize1), sizeof(roomsize1) ); 00244 stream.write(reinterpret_cast<const char*>(&damp), sizeof(damp) ); 00245 stream.write(reinterpret_cast<const char*>(&damp1), sizeof(damp1) ); 00246 stream.write(reinterpret_cast<const char*>(&wet), sizeof(wet) ); 00247 stream.write(reinterpret_cast<const char*>(&wet1), sizeof(wet1) ); 00248 stream.write(reinterpret_cast<const char*>(&wet2), sizeof(wet2) ); 00249 stream.write(reinterpret_cast<const char*>(&dry), sizeof(dry) ); 00250 stream.write(reinterpret_cast<const char*>(&width), sizeof(width) ); 00251 stream.write(reinterpret_cast<const char*>(&mode), sizeof(mode) ); 00252 stream.write(reinterpret_cast<const char*>(&filtval), sizeof(filtval) ); 00253 stream.write(reinterpret_cast<const char*>(&filtprev1), sizeof(filtprev1) ); 00254 stream.write(reinterpret_cast<const char*>(&filtprev2), sizeof(filtprev2) ); 00255 00256 00257 for( int lcv=0; lcv<numcombs; lcv++ ) { 00258 combL[lcv].saveState(stream); 00259 combR[lcv].saveState(stream); 00260 } 00261 00262 for( int lcv=0; lcv<numallpasses; lcv++ ) { 00263 allpassL[lcv].saveState(stream); 00264 allpassR[lcv].saveState(stream); 00265 } 00266 } 00267 00268 00269 void revmodel::loadState( std::istream &stream ) 00270 { 00271 stream.read(reinterpret_cast<char*>(&gain), sizeof(gain) ); 00272 stream.read(reinterpret_cast<char*>(&roomsize), sizeof(roomsize) ); 00273 stream.read(reinterpret_cast<char*>(&roomsize1), sizeof(roomsize1) ); 00274 stream.read(reinterpret_cast<char*>(&damp), sizeof(damp) ); 00275 stream.read(reinterpret_cast<char*>(&damp1), sizeof(damp1) ); 00276 stream.read(reinterpret_cast<char*>(&wet), sizeof(wet) ); 00277 stream.read(reinterpret_cast<char*>(&wet1), sizeof(wet1) ); 00278 stream.read(reinterpret_cast<char*>(&wet2), sizeof(wet2) ); 00279 stream.read(reinterpret_cast<char*>(&dry), sizeof(dry) ); 00280 stream.read(reinterpret_cast<char*>(&width), sizeof(width) ); 00281 stream.read(reinterpret_cast<char*>(&mode), sizeof(mode) ); 00282 stream.read(reinterpret_cast<char*>(&filtval), sizeof(filtval) ); 00283 stream.read(reinterpret_cast<char*>(&filtprev1), sizeof(filtprev1) ); 00284 stream.read(reinterpret_cast<char*>(&filtprev2), sizeof(filtprev2) ); 00285 00286 00287 for( int lcv=0; lcv<numcombs; lcv++ ) { 00288 combL[lcv].loadState(stream); 00289 combR[lcv].loadState(stream); 00290 } 00291 00292 for( int lcv=0; lcv<numallpasses; lcv++ ) { 00293 allpassL[lcv].loadState(stream); 00294 allpassR[lcv].loadState(stream); 00295 } 00296 }