DOSBox-X
|
00001 /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher 00002 * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU Lesser General Public License as published by 00006 * the Free Software Foundation, either version 2.1 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #include <cmath> 00019 #include <cstring> 00020 #include "mt32emu.h" 00021 #include "DelayReverb.h" 00022 #include "FileStream.h" 00023 00024 namespace MT32Emu { 00025 00026 // CONFIRMED: The values below are found via analysis of digital samples and tracing reverb RAM address / data lines. Checked with all time and level combinations. 00027 // Obviously: 00028 // rightDelay = (leftDelay - 2) * 2 + 2 00029 // echoDelay = rightDelay - 1 00030 // Leaving these separate in case it's useful for work on other reverb modes... 00031 static const Bit32u REVERB_TIMINGS[8][3]= { 00032 // {leftDelay, rightDelay, feedbackDelay} 00033 {402, 802, 801}, 00034 {626, 1250, 1249}, 00035 {962, 1922, 1921}, 00036 {1490, 2978, 2977}, 00037 {2258, 4514, 4513}, 00038 {3474, 6946, 6945}, 00039 {5282, 10562, 10561}, 00040 {8002, 16002, 16001} 00041 }; 00042 00043 // Reverb amp is found as dryAmp * wetAmp 00044 static const Bit32u REVERB_AMP[8] = {0x20*0x18, 0x50*0x18, 0x50*0x28, 0x50*0x40, 0x50*0x60, 0x50*0x80, 0x50*0xA8, 0x50*0xF8}; 00045 static const Bit32u REVERB_FEEDBACK67 = 0x60; 00046 static const Bit32u REVERB_FEEDBACK = 0x68; 00047 static const float LPF_VALUE = 0x68 / 256.0f; 00048 00049 static const Bit32u BUFFER_SIZE = 16384; 00050 00051 DelayReverb::DelayReverb() { 00052 buf = NULL; 00053 bufIx = 0; 00054 delayLeft = 0; 00055 delayRight = 0; 00056 delayFeedback = 0; 00057 amp = 0; 00058 feedback = 0; 00059 setParameters(0, 0); 00060 00061 00062 // loadstate init 00063 //bufSize = 0; 00064 } 00065 00066 DelayReverb::~DelayReverb() { 00067 delete[] buf; 00068 } 00069 00070 void DelayReverb::open() { 00071 if (buf == NULL) { 00072 delete[] buf; 00073 00074 buf = new float[BUFFER_SIZE]; 00075 00076 recalcParameters(); 00077 00078 // mute buffer 00079 bufIx = 0; 00080 if (buf != NULL) { 00081 for (unsigned int i = 0; i < BUFFER_SIZE; i++) { 00082 buf[i] = 0.0f; 00083 } 00084 } 00085 } 00086 } 00087 00088 void DelayReverb::close() { 00089 delete[] buf; 00090 buf = NULL; 00091 } 00092 00093 // This method will always trigger a flush of the buffer 00094 void DelayReverb::setParameters(Bit8u newTime, Bit8u newLevel) { 00095 time = newTime; 00096 level = newLevel; 00097 recalcParameters(); 00098 } 00099 00100 void DelayReverb::recalcParameters() { 00101 // Number of samples between impulse and eventual appearance on the left channel 00102 delayLeft = REVERB_TIMINGS[time][0]; 00103 // Number of samples between impulse and eventual appearance on the right channel 00104 delayRight = REVERB_TIMINGS[time][1]; 00105 // Number of samples between a response and that response feeding back/echoing 00106 delayFeedback = REVERB_TIMINGS[time][2]; 00107 00108 if (level < 3 || time < 6) { 00109 feedback = REVERB_FEEDBACK / 256.0f; 00110 } else { 00111 feedback = REVERB_FEEDBACK67 / 256.0f; 00112 } 00113 00114 // Overall output amp 00115 amp = (level == 0 && time == 0) ? 0.0f : REVERB_AMP[level] / 65536.0f; 00116 } 00117 00118 void DelayReverb::process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples) { 00119 if (buf == NULL) return; 00120 00121 for (unsigned int sampleIx = 0; sampleIx < numSamples; sampleIx++) { 00122 // The ring buffer write index moves backwards; reads are all done with positive offsets. 00123 Bit32u bufIxPrev = (bufIx + 1) % BUFFER_SIZE; 00124 Bit32u bufIxLeft = (bufIx + delayLeft) % BUFFER_SIZE; 00125 Bit32u bufIxRight = (bufIx + delayRight) % BUFFER_SIZE; 00126 Bit32u bufIxFeedback = (bufIx + delayFeedback) % BUFFER_SIZE; 00127 00128 // Attenuated input samples and feedback response are directly added to the current ring buffer location 00129 float lpfIn = amp * (inLeft[sampleIx] + inRight[sampleIx]) + feedback * buf[bufIxFeedback]; 00130 00131 // Single-pole IIR filter found on real devices 00132 buf[bufIx] = buf[bufIxPrev] * LPF_VALUE - lpfIn; 00133 00134 outLeft[sampleIx] = buf[bufIxLeft]; 00135 outRight[sampleIx] = buf[bufIxRight]; 00136 00137 bufIx = (BUFFER_SIZE + bufIx - 1) % BUFFER_SIZE; 00138 } 00139 } 00140 00141 bool DelayReverb::isActive() const { 00142 if (buf == NULL) return false; 00143 00144 float *b = buf; 00145 float max = 0.001f; 00146 for (Bit32u i = 0; i < BUFFER_SIZE; i++) { 00147 if ((*b < -max) || (*b > max)) return true; 00148 b++; 00149 } 00150 return false; 00151 } 00152 00153 00154 void DelayReverb::saveState( std::ostream &stream ) 00155 { 00156 stream.write(reinterpret_cast<const char*>(&time), sizeof(time) ); 00157 stream.write(reinterpret_cast<const char*>(&level), sizeof(level) ); 00158 //stream.write(reinterpret_cast<const char*>(&sampleRate), sizeof(sampleRate) ); 00159 //stream.write(reinterpret_cast<const char*>(&bufSize), sizeof(bufSize) ); 00160 stream.write(reinterpret_cast<const char*>(&bufIx), sizeof(bufIx) ); 00161 00162 if( buf ) 00163 stream.write(reinterpret_cast<const char*>(buf), sizeof(buf) * sizeof(float) ); 00164 00165 stream.write(reinterpret_cast<const char*>(&delayLeft), sizeof(delayLeft) ); 00166 stream.write(reinterpret_cast<const char*>(&delayRight), sizeof(delayRight) ); 00167 stream.write(reinterpret_cast<const char*>(&delayFeedback), sizeof(delayFeedback) ); 00168 //stream.write(reinterpret_cast<const char*>(&fade), sizeof(fade) ); 00169 stream.write(reinterpret_cast<const char*>(&feedback), sizeof(feedback) ); 00170 } 00171 00172 00173 void DelayReverb::loadState( std::istream &stream ) 00174 { 00175 stream.read(reinterpret_cast<char*>(&time), sizeof(time) ); 00176 stream.read(reinterpret_cast<char*>(&level), sizeof(level) ); 00177 //stream.read(reinterpret_cast<char*>(&sampleRate), sizeof(sampleRate) ); 00178 //stream.read(reinterpret_cast<char*>(&bufSize), sizeof(bufSize) ); 00179 stream.read(reinterpret_cast<char*>(&bufIx), sizeof(bufIx) ); 00180 00181 00182 if( buf ) delete[] buf; 00183 if( sizeof(buf) == 0 ) { 00184 buf = NULL; 00185 } 00186 else { 00187 buf = new float[ sizeof(buf) ]; 00188 stream.read(reinterpret_cast<char*>(buf), sizeof(buf) * sizeof(float) ); 00189 } 00190 00191 00192 stream.read(reinterpret_cast<char*>(&delayLeft), sizeof(delayLeft) ); 00193 stream.read(reinterpret_cast<char*>(&delayRight), sizeof(delayRight) ); 00194 stream.read(reinterpret_cast<char*>(&delayFeedback), sizeof(delayFeedback) ); 00195 //stream.read(reinterpret_cast<char*>(&fade), sizeof(fade) ); 00196 stream.read(reinterpret_cast<char*>(&feedback), sizeof(feedback) ); 00197 } 00198 00199 }