DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/mt32/DelayReverb.cpp
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 }