DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/mt32/Synth.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 <cerrno>
00019 #include <cmath>
00020 #include <cstdlib>
00021 #include <cstring>
00022 #include <stdexcept>
00023 #include <exception>
00024 
00025 #include "mt32emu.h"
00026 #include "mmath.h"
00027 #include "PartialManager.h"
00028 
00029 #if MT32EMU_USE_REVERBMODEL == 1
00030 #include "AReverbModel.h"
00031 #elif MT32EMU_USE_REVERBMODEL == 2
00032 #include "BReverbModel.h"
00033 #else
00034 #include "FreeverbModel.h"
00035 #endif
00036 #include "DelayReverb.h"
00037 
00038 namespace MT32Emu {
00039 
00040 static const ControlROMMap ControlROMMaps[7] = {
00041     // ID    IDc IDbytes                     PCMmap  PCMc  tmbrA   tmbrAO, tmbrAC tmbrB   tmbrBO, tmbrBC tmbrR   trC  rhythm  rhyC  rsrv    panpot  prog    rhyMax  patMax  sysMax  timMax
00042     {0x4014, 22, "\000 ver1.04 14 July 87 ", 0x3000,  128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200,  30, 0x73A6,  85,  0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A},
00043     {0x4014, 22, "\000 ver1.05 06 Aug, 87 ", 0x3000,  128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200,  30, 0x7414,  85,  0x57C7, 0x57E2, 0x57D0, 0x5252, 0x525E, 0x526E, 0x520A},
00044     {0x4014, 22, "\000 ver1.06 31 Aug, 87 ", 0x3000,  128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200,  30, 0x7414,  85,  0x57D9, 0x57F4, 0x57E2, 0x5264, 0x5270, 0x5280, 0x521C},
00045     {0x4010, 22, "\000 ver1.07 10 Oct, 87 ", 0x3000,  128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200,  30, 0x73fe,  85,  0x57B1, 0x57CC, 0x57BA, 0x523C, 0x5248, 0x5258, 0x51F4}, // MT-32 revision 1
00046     {0x4010, 22, "\000verX.XX  30 Sep, 88 ", 0x3000,  128, 0x8000, 0x0000, false, 0xC000, 0x4000, false, 0x3200,  30, 0x741C,  85,  0x57E5, 0x5800, 0x57EE, 0x5270, 0x527C, 0x528C, 0x5228}, // MT-32 Blue Ridge mod
00047     {0x2205, 22, "\000CM32/LAPC1.00 890404", 0x8100,  256, 0x8000, 0x8000, false, 0x8080, 0x8000, false, 0x8500,  64, 0x8580,  85,  0x4F65, 0x4F80, 0x4F6E, 0x48A1, 0x48A5, 0x48BE, 0x48D5},
00048     {0x2205, 22, "\000CM32/LAPC1.02 891205", 0x8100,  256, 0x8000, 0x8000, true,  0x8080, 0x8000, true,  0x8500,  64, 0x8580,  85,  0x4F93, 0x4FAE, 0x4F9C, 0x48CB, 0x48CF, 0x48E8, 0x48FF}  // CM-32L
00049     // (Note that all but CM-32L ROM actually have 86 entries for rhythmTemp)
00050 };
00051 
00052 static inline Bit16s *streamOffset(Bit16s *stream, Bit32u pos) {
00053     return stream == NULL ? NULL : stream + pos;
00054 }
00055 
00056 static inline void clearIfNonNull(Bit16s *stream, Bit32u len) {
00057     if (stream != NULL) {
00058         memset(stream, 0, len * sizeof(Bit16s));
00059     }
00060 }
00061 
00062 static inline void mix(float *target, const float *stream, Bit32u len) {
00063     while (len--) {
00064         *target += *stream;
00065         stream++;
00066         target++;
00067     }
00068 }
00069 
00070 static inline void clearFloats(float *leftBuf, float *rightBuf, Bit32u len) {
00071     // FIXME: Use memset() where compatibility is guaranteed (if this turns out to be a win)
00072     while (len--) {
00073         *leftBuf++ = 0.0f;
00074         *rightBuf++ = 0.0f;
00075     }
00076 }
00077 
00078 static inline Bit16s clipBit16s(Bit32s a) {
00079     // Clamp values above 32767 to 32767, and values below -32768 to -32768
00080     if ((a + 32768) & ~65535) {
00081         return (a >> 31) ^ 32767;
00082     }
00083     return a;
00084 }
00085 
00086 static void floatToBit16s_nice(Bit16s *target, const float *source, Bit32u len, float outputGain) {
00087     float gain = outputGain * 16384.0f;
00088     while (len--) {
00089         // Since we're not shooting for accuracy here, don't worry about the rounding mode.
00090         *target = clipBit16s((Bit32s)(*source * gain));
00091         source++;
00092         target++;
00093     }
00094 }
00095 
00096 static void floatToBit16s_pure(Bit16s *target, const float *source, Bit32u len, float /*outputGain*/) {
00097     while (len--) {
00098         *target = clipBit16s((Bit32s)floor(*source * 8192.0f));
00099         source++;
00100         target++;
00101     }
00102 }
00103 
00104 static void floatToBit16s_reverb(Bit16s *target, const float *source, Bit32u len, float outputGain) {
00105     float gain = outputGain * 8192.0f;
00106     while (len--) {
00107         *target = clipBit16s((Bit32s)floor(*source * gain));
00108         source++;
00109         target++;
00110     }
00111 }
00112 
00113 static void floatToBit16s_generation1(Bit16s *target, const float *source, Bit32u len, float outputGain) {
00114     float gain = outputGain * 8192.0f;
00115     while (len--) {
00116         *target = clipBit16s((Bit32s)floor(*source * gain));
00117         *target = (*target & 0x8000) | ((*target << 1) & 0x7FFE);
00118         source++;
00119         target++;
00120     }
00121 }
00122 
00123 static void floatToBit16s_generation2(Bit16s *target, const float *source, Bit32u len, float outputGain) {
00124     float gain = outputGain * 8192.0f;
00125     while (len--) {
00126         *target = clipBit16s((Bit32s)floor(*source * gain));
00127         *target = (*target & 0x8000) | ((*target << 1) & 0x7FFE) | ((*target >> 14) & 0x0001);
00128         source++;
00129         target++;
00130     }
00131 }
00132 
00133 Bit8u Synth::calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum) {
00134     for (unsigned int i = 0; i < len; i++) {
00135         checksum = checksum + data[i];
00136     }
00137     checksum = checksum & 0x7f;
00138     if (checksum) {
00139         checksum = 0x80 - checksum;
00140     }
00141     return checksum;
00142 }
00143 
00144 Synth::Synth(ReportHandler *useReportHandler) {
00145     isOpen = false;
00146     reverbEnabled = true;
00147     reverbOverridden = false;
00148 
00149     if (useReportHandler == NULL) {
00150         reportHandler = new ReportHandler;
00151         isDefaultReportHandler = true;
00152     } else {
00153         reportHandler = useReportHandler;
00154         isDefaultReportHandler = false;
00155     }
00156 
00157 #if MT32EMU_USE_REVERBMODEL == 1
00158     reverbModels[REVERB_MODE_ROOM] = new AReverbModel(REVERB_MODE_ROOM);
00159     reverbModels[REVERB_MODE_HALL] = new AReverbModel(REVERB_MODE_HALL);
00160     reverbModels[REVERB_MODE_PLATE] = new AReverbModel(REVERB_MODE_PLATE);
00161     reverbModels[REVERB_MODE_TAP_DELAY] = new DelayReverb();
00162 #elif MT32EMU_USE_REVERBMODEL == 2
00163     reverbModels[REVERB_MODE_ROOM] = new BReverbModel(REVERB_MODE_ROOM);
00164     reverbModels[REVERB_MODE_HALL] = new BReverbModel(REVERB_MODE_HALL);
00165     reverbModels[REVERB_MODE_PLATE] = new BReverbModel(REVERB_MODE_PLATE);
00166     reverbModels[REVERB_MODE_TAP_DELAY] = new BReverbModel(REVERB_MODE_TAP_DELAY);
00167 #else
00168     reverbModels[REVERB_MODE_ROOM] = new FreeverbModel(0.76f, 0.687770909f, 0.63f, 0, 0.5f);
00169     reverbModels[REVERB_MODE_HALL] = new FreeverbModel(2.0f, 0.712025098f, 0.86f, 1, 0.5f);
00170     reverbModels[REVERB_MODE_PLATE] = new FreeverbModel(0.4f, 0.939522749f, 0.38f, 2, 0.05f);
00171     reverbModels[REVERB_MODE_TAP_DELAY] = new DelayReverb();
00172 #endif
00173 
00174     reverbModel = NULL;
00175     setDACInputMode(DACInputMode_NICE);
00176     setOutputGain(1.0f);
00177     setReverbOutputGain(0.68f);
00178     partialManager = NULL;
00179     memset(parts, 0, sizeof(parts));
00180     renderedSampleCount = 0;
00181 
00182     partialLimit = MT32EMU_MAX_PARTIALS;
00183 }
00184 
00185 Synth::~Synth() {
00186     close(); // Make sure we're closed and everything is freed
00187     for (int i = 0; i < 4; i++) {
00188         delete reverbModels[i];
00189     }
00190     if (isDefaultReportHandler) {
00191         delete reportHandler;
00192     }
00193 }
00194 
00195 void ReportHandler::showLCDMessage(const char *data) {
00196     printf("WRITE-LCD: %s", data);
00197     printf("\n");
00198 }
00199 
00200 void ReportHandler::printDebug(const char *fmt, va_list list) {
00201         vprintf(fmt, list);
00202         printf("\n");
00203 }
00204 
00205 void Synth::partStateChanged(int partNum, bool isPartActive) {
00206     reportHandler->onPartStateChanged(partNum, isPartActive);
00207 }
00208 
00209 void Synth::polyStateChanged(int partNum) {
00210     reportHandler->onPolyStateChanged(partNum);
00211 }
00212 
00213 void Synth::partialStateChanged(const Partial * const partial, int oldPartialPhase, int newPartialPhase) {
00214     for (unsigned int i = 0; i < getPartialLimit(); i++) {
00215         if (getPartial(i) == partial) {
00216             reportHandler->onPartialStateChanged(i, oldPartialPhase, newPartialPhase);
00217             break;
00218         }
00219     }
00220 }
00221 
00222 void Synth::newTimbreSet(int partNum, char patchName[]) {
00223     reportHandler->onProgramChanged(partNum, patchName);
00224 }
00225 
00226 void Synth::printDebug(const char *fmt, ...) {
00227     va_list ap;
00228     va_start(ap, fmt);
00229 #if MT32EMU_DEBUG_SAMPLESTAMPS > 0
00230     reportHandler->printDebug("[%u] ", renderedSampleCount);
00231 #endif
00232     reportHandler->printDebug(fmt, ap);
00233     va_end(ap);
00234 }
00235 
00236 void Synth::setReverbEnabled(bool newReverbEnabled) {
00237     reverbEnabled = newReverbEnabled;
00238 }
00239 
00240 bool Synth::isReverbEnabled() const {
00241     return reverbEnabled;
00242 }
00243 
00244 void Synth::setReverbOverridden(bool newReverbOverridden) {
00245     reverbOverridden = newReverbOverridden;
00246 }
00247 
00248 bool Synth::isReverbOverridden() const {
00249     return reverbOverridden;
00250 }
00251 
00252 void Synth::setDACInputMode(DACInputMode mode) {
00253     switch(mode) {
00254     case DACInputMode_GENERATION1:
00255         la32FloatToBit16sFunc = floatToBit16s_generation1;
00256         reverbFloatToBit16sFunc = floatToBit16s_reverb;
00257         break;
00258     case DACInputMode_GENERATION2:
00259         la32FloatToBit16sFunc = floatToBit16s_generation2;
00260         reverbFloatToBit16sFunc = floatToBit16s_reverb;
00261         break;
00262     case DACInputMode_PURE:
00263         la32FloatToBit16sFunc = floatToBit16s_pure;
00264         reverbFloatToBit16sFunc = floatToBit16s_pure;
00265         break;
00266     case DACInputMode_NICE:
00267     default:
00268         la32FloatToBit16sFunc = floatToBit16s_nice;
00269         reverbFloatToBit16sFunc = floatToBit16s_reverb;
00270         break;
00271     }
00272 }
00273 
00274 void Synth::setOutputGain(float newOutputGain) {
00275     outputGain = newOutputGain;
00276 }
00277 
00278 void Synth::setReverbOutputGain(float newReverbOutputGain) {
00279     reverbOutputGain = newReverbOutputGain;
00280 }
00281 
00282 bool Synth::loadControlROM(const ROMImage &controlROMImage) {
00283 //    if (&controlROMImage == NULL) return false;
00284     File *file = controlROMImage.getFile();
00285     const ROMInfo *controlROMInfo = controlROMImage.getROMInfo();
00286     if ((controlROMInfo == NULL)
00287             || (controlROMInfo->type != ROMInfo::Control)
00288             || (controlROMInfo->pairType != ROMInfo::Full)) {
00289         return false;
00290     }
00291 #if MT32EMU_MONITOR_INIT
00292     printDebug("Found Control ROM: %s, %s", controlROMInfo->shortName, controlROMInfo->description);
00293 #endif
00294     const Bit8u *fileData = file->getData();
00295     memcpy(controlROMData, fileData, CONTROL_ROM_SIZE);
00296 
00297     // Control ROM successfully loaded, now check whether it's a known type
00298     controlROMMap = NULL;
00299     for (unsigned int i = 0; i < sizeof(ControlROMMaps) / sizeof(ControlROMMaps[0]); i++) {
00300         if (memcmp(&controlROMData[ControlROMMaps[i].idPos], ControlROMMaps[i].idBytes, ControlROMMaps[i].idLen) == 0) {
00301             controlROMMap = &ControlROMMaps[i];
00302             return true;
00303         }
00304     }
00305 #if MT32EMU_MONITOR_INIT
00306     printDebug("Control ROM failed to load");
00307 #endif
00308     return false;
00309 }
00310 
00311 bool Synth::loadPCMROM(const ROMImage &pcmROMImage) {
00312 //    if (&pcmROMImage == NULL) return false;
00313     File *file = pcmROMImage.getFile();
00314     const ROMInfo *pcmROMInfo = pcmROMImage.getROMInfo();
00315     if ((pcmROMInfo == NULL)
00316             || (pcmROMInfo->type != ROMInfo::PCM)
00317             || (pcmROMInfo->pairType != ROMInfo::Full)) {
00318         return false;
00319     }
00320 #if MT32EMU_MONITOR_INIT
00321     printDebug("Found PCM ROM: %s, %s", pcmROMInfo->shortName, pcmROMInfo->description);
00322 #endif
00323     size_t fileSize = file->getSize();
00324     if (fileSize != (2 * pcmROMSize)) {
00325 #if MT32EMU_MONITOR_INIT
00326         printDebug("PCM ROM file has wrong size (expected %d, got %d)", 2 * pcmROMSize, fileSize);
00327 #endif
00328         return false;
00329     }
00330     const Bit8u *fileData = file->getData();
00331     for (size_t i = 0; i < pcmROMSize; i++) {
00332         Bit8u s = *(fileData++);
00333         Bit8u c = *(fileData++);
00334 
00335         int order[16] = {0, 9, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 8};
00336 
00337         signed short log = 0;
00338         for (int u = 0; u < 15; u++) {
00339             int bit;
00340             if (order[u] < 8) {
00341                 bit = (s >> (7 - order[u])) & 0x1;
00342             } else {
00343                 bit = (c >> (7 - (order[u] - 8))) & 0x1;
00344             }
00345             log = log | (short)(bit << (15 - u));
00346         }
00347         pcmROMData[i] = log;
00348     }
00349     return true;
00350 }
00351 
00352 bool Synth::initPCMList(Bit16u mapAddress, Bit16u count) {
00353     ControlROMPCMStruct *tps = (ControlROMPCMStruct *)&controlROMData[mapAddress];
00354     for (int i = 0; i < count; i++) {
00355         size_t rAddr = tps[i].pos * 0x800;
00356         size_t rLenExp = (tps[i].len & 0x70) >> 4;
00357         size_t rLen = 0x800 << rLenExp;
00358         if (rAddr + rLen > pcmROMSize) {
00359             printDebug("Control ROM error: Wave map entry %d points to invalid PCM address 0x%04X, length 0x%04X", i, rAddr, rLen);
00360             return false;
00361         }
00362         pcmWaves[i].addr = (Bit32u)rAddr;
00363         pcmWaves[i].len = (Bit32u)rLen;
00364         pcmWaves[i].loop = (tps[i].len & 0x80) != 0;
00365         pcmWaves[i].controlROMPCMStruct = &tps[i];
00366         //int pitch = (tps[i].pitchMSB << 8) | tps[i].pitchLSB;
00367         //bool unaffectedByMasterTune = (tps[i].len & 0x01) == 0;
00368         //printDebug("PCM %d: pos=%d, len=%d, pitch=%d, loop=%s, unaffectedByMasterTune=%s", i, rAddr, rLen, pitch, pcmWaves[i].loop ? "YES" : "NO", unaffectedByMasterTune ? "YES" : "NO");
00369     }
00370     return false;
00371 }
00372 
00373 bool Synth::initCompressedTimbre(int timbreNum, const Bit8u *src, unsigned int srcLen) {
00374     // "Compressed" here means that muted partials aren't present in ROM (except in the case of partial 0 being muted).
00375     // Instead the data from the previous unmuted partial is used.
00376     if (srcLen < sizeof(TimbreParam::CommonParam)) {
00377         return false;
00378     }
00379     TimbreParam *timbre = &mt32ram.timbres[timbreNum].timbre;
00380     timbresMemoryRegion->write(timbreNum, 0, src, sizeof(TimbreParam::CommonParam), true);
00381     unsigned int srcPos = sizeof(TimbreParam::CommonParam);
00382     unsigned int memPos = sizeof(TimbreParam::CommonParam);
00383     for (int t = 0; t < 4; t++) {
00384         if (t != 0 && ((timbre->common.partialMute >> t) & 0x1) == 0x00) {
00385             // This partial is muted - we'll copy the previously copied partial, then
00386             srcPos -= sizeof(TimbreParam::PartialParam);
00387         } else if (srcPos + sizeof(TimbreParam::PartialParam) >= srcLen) {
00388             return false;
00389         }
00390         timbresMemoryRegion->write(timbreNum, memPos, src + srcPos, sizeof(TimbreParam::PartialParam));
00391         srcPos += sizeof(TimbreParam::PartialParam);
00392         memPos += sizeof(TimbreParam::PartialParam);
00393     }
00394     return true;
00395 }
00396 
00397 bool Synth::initTimbres(Bit16u mapAddress, Bit16u offset, int count, int startTimbre, bool compressed) {
00398     const Bit8u *timbreMap = &controlROMData[mapAddress];
00399     for (Bit16u i = 0; i < count * 2; i += 2) {
00400         Bit16u address = (timbreMap[i + 1] << 8) | timbreMap[i];
00401         if (!compressed && (address + offset + sizeof(TimbreParam) > CONTROL_ROM_SIZE)) {
00402             printDebug("Control ROM error: Timbre map entry 0x%04x for timbre %d points to invalid timbre address 0x%04x", i, startTimbre, address);
00403             return false;
00404         }
00405         address += offset;
00406         if (compressed) {
00407             if (!initCompressedTimbre(startTimbre, &controlROMData[address], CONTROL_ROM_SIZE - address)) {
00408                 printDebug("Control ROM error: Timbre map entry 0x%04x for timbre %d points to invalid timbre at 0x%04x", i, startTimbre, address);
00409                 return false;
00410             }
00411         } else {
00412             timbresMemoryRegion->write(startTimbre, 0, &controlROMData[address], sizeof(TimbreParam), true);
00413         }
00414         startTimbre++;
00415     }
00416     return true;
00417 }
00418 
00419 bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage) {
00420     if (isOpen) {
00421         return false;
00422     }
00423     prerenderReadIx = prerenderWriteIx = 0;
00424 #if MT32EMU_MONITOR_INIT
00425     printDebug("Initialising Constant Tables");
00426 #endif
00427 #if !MT32EMU_REDUCE_REVERB_MEMORY
00428     for (int i = 0; i < 4; i++) {
00429         reverbModels[i]->open(useProp.sampleRate);
00430     }
00431 #endif
00432 
00433     // This is to help detect bugs
00434     memset(&mt32ram, '?', sizeof(mt32ram));
00435 
00436 #if MT32EMU_MONITOR_INIT
00437     printDebug("Loading Control ROM");
00438 #endif
00439     if (!loadControlROM(controlROMImage)) {
00440         printDebug("Init Error - Missing or invalid Control ROM image");
00441         reportHandler->onErrorControlROM();
00442         return false;
00443     }
00444 
00445     initMemoryRegions();
00446 
00447     // 512KB PCM ROM for MT-32, etc.
00448     // 1MB PCM ROM for CM-32L, LAPC-I, CM-64, CM-500
00449     // Note that the size below is given in samples (16-bit), not bytes
00450     pcmROMSize = controlROMMap->pcmCount == 256 ? 512 * 1024 : 256 * 1024;
00451     pcmROMData = new Bit16s[pcmROMSize];
00452 
00453 #if MT32EMU_MONITOR_INIT
00454     printDebug("Loading PCM ROM");
00455 #endif
00456     if (!loadPCMROM(pcmROMImage)) {
00457         printDebug("Init Error - Missing PCM ROM image");
00458         reportHandler->onErrorPCMROM();
00459         return false;
00460     }
00461 
00462 #if MT32EMU_MONITOR_INIT
00463     printDebug("Initialising Timbre Bank A");
00464 #endif
00465     if (!initTimbres(controlROMMap->timbreAMap, controlROMMap->timbreAOffset, 0x40, 0, controlROMMap->timbreACompressed)) {
00466         return false;
00467     }
00468 
00469 #if MT32EMU_MONITOR_INIT
00470     printDebug("Initialising Timbre Bank B");
00471 #endif
00472     if (!initTimbres(controlROMMap->timbreBMap, controlROMMap->timbreBOffset, 0x40, 64, controlROMMap->timbreBCompressed)) {
00473         return false;
00474     }
00475 
00476 #if MT32EMU_MONITOR_INIT
00477     printDebug("Initialising Timbre Bank R");
00478 #endif
00479     if (!initTimbres(controlROMMap->timbreRMap, 0, controlROMMap->timbreRCount, 192, true)) {
00480         return false;
00481     }
00482 
00483 #if MT32EMU_MONITOR_INIT
00484     printDebug("Initialising Timbre Bank M");
00485 #endif
00486     // CM-64 seems to initialise all bytes in this bank to 0.
00487     memset(&mt32ram.timbres[128], 0, sizeof(mt32ram.timbres[128]) * 64);
00488 
00489     partialManager = new PartialManager(this, parts);
00490 
00491     pcmWaves = new PCMWaveEntry[controlROMMap->pcmCount];
00492 
00493 #if MT32EMU_MONITOR_INIT
00494     printDebug("Initialising PCM List");
00495 #endif
00496     initPCMList(controlROMMap->pcmTable, controlROMMap->pcmCount);
00497 
00498 #if MT32EMU_MONITOR_INIT
00499     printDebug("Initialising Rhythm Temp");
00500 #endif
00501     memcpy(mt32ram.rhythmTemp, &controlROMData[controlROMMap->rhythmSettings], controlROMMap->rhythmSettingsCount * 4);
00502 
00503 #if MT32EMU_MONITOR_INIT
00504     printDebug("Initialising Patches");
00505 #endif
00506     for (Bit8u i = 0; i < 128; i++) {
00507         PatchParam *patch = &mt32ram.patches[i];
00508         patch->timbreGroup = i / 64;
00509         patch->timbreNum = i % 64;
00510         patch->keyShift = 24;
00511         patch->fineTune = 50;
00512         patch->benderRange = 12;
00513         patch->assignMode = 0;
00514         patch->reverbSwitch = 1;
00515         patch->dummy = 0;
00516     }
00517 
00518 #if MT32EMU_MONITOR_INIT
00519     printDebug("Initialising System");
00520 #endif
00521     // The MT-32 manual claims that "Standard pitch" is 442Hz.
00522     mt32ram.system.masterTune = 0x4A; // Confirmed on CM-64
00523     mt32ram.system.reverbMode = 0; // Confirmed
00524     mt32ram.system.reverbTime = 5; // Confirmed
00525     mt32ram.system.reverbLevel = 3; // Confirmed
00526     memcpy(mt32ram.system.reserveSettings, &controlROMData[controlROMMap->reserveSettings], 9); // Confirmed
00527     for (Bit8u i = 0; i < 9; i++) {
00528         // This is the default: {1, 2, 3, 4, 5, 6, 7, 8, 9}
00529         // An alternative configuration can be selected by holding "Master Volume"
00530         // and pressing "PART button 1" on the real MT-32's frontpanel.
00531         // The channel assignment is then {0, 1, 2, 3, 4, 5, 6, 7, 9}
00532         mt32ram.system.chanAssign[i] = i + 1;
00533     }
00534     mt32ram.system.masterVol = 100; // Confirmed
00535     refreshSystem();
00536 
00537     for (int i = 0; i < 9; i++) {
00538         MemParams::PatchTemp *patchTemp = &mt32ram.patchTemp[i];
00539 
00540         // Note that except for the rhythm part, these patch fields will be set in setProgram() below anyway.
00541         patchTemp->patch.timbreGroup = 0;
00542         patchTemp->patch.timbreNum = 0;
00543         patchTemp->patch.keyShift = 24;
00544         patchTemp->patch.fineTune = 50;
00545         patchTemp->patch.benderRange = 12;
00546         patchTemp->patch.assignMode = 0;
00547         patchTemp->patch.reverbSwitch = 1;
00548         patchTemp->patch.dummy = 0;
00549 
00550         patchTemp->outputLevel = 80;
00551         patchTemp->panpot = controlROMData[controlROMMap->panSettings + i];
00552         memset(patchTemp->dummyv, 0, sizeof(patchTemp->dummyv));
00553         patchTemp->dummyv[1] = 127;
00554 
00555         if (i < 8) {
00556             parts[i] = new Part(this, i);
00557             parts[i]->setProgram(controlROMData[controlROMMap->programSettings + i]);
00558         } else {
00559             parts[i] = new RhythmPart(this, i);
00560         }
00561     }
00562 
00563     // For resetting mt32 mid-execution
00564     mt32default = mt32ram;
00565 
00566     isOpen = true;
00567     isEnabled = false;
00568 
00569 #if MT32EMU_MONITOR_INIT
00570     printDebug("*** Initialisation complete ***");
00571 #endif
00572     return true;
00573 }
00574 
00575 void Synth::close() {
00576     if (!isOpen) {
00577         return;
00578     }
00579 
00580     delete partialManager;
00581     partialManager = NULL;
00582 
00583     for (int i = 0; i < 9; i++) {
00584         delete parts[i];
00585         parts[i] = NULL;
00586     }
00587 
00588     delete[] pcmWaves;
00589     delete[] pcmROMData;
00590 
00591     deleteMemoryRegions();
00592 
00593     for (int i = 0; i < 4; i++) {
00594         reverbModels[i]->close();
00595     }
00596     reverbModel = NULL;
00597     isOpen = false;
00598 }
00599 
00600 void Synth::playMsg(Bit32u msg) {
00601     // FIXME: Implement active sensing
00602     unsigned char code     = (unsigned char)((msg & 0x0000F0) >> 4);
00603     unsigned char chan     = (unsigned char)(msg & 0x00000F);
00604     unsigned char note     = (unsigned char)((msg & 0x00FF00) >> 8);
00605     unsigned char velocity = (unsigned char)((msg & 0xFF0000) >> 16);
00606     isEnabled = true;
00607 
00608     //printDebug("Playing chan %d, code 0x%01x note: 0x%02x", chan, code, note);
00609 
00610     char part = chantable[chan];
00611     if (part < 0 || part > 8) {
00612 #if MT32EMU_MONITOR_MIDI > 0
00613         printDebug("Play msg on unreg chan %d (%d): code=0x%01x, vel=%d", chan, part, code, velocity);
00614 #endif
00615         return;
00616     }
00617     playMsgOnPart(part, code, note, velocity);
00618 
00619     // This ensures minimum 1-sample delay between sequential MIDI events
00620     // Without this, a sequence of NoteOn and immediately succeeding NoteOff messages is always silent
00621     // Technically, it's also impossible to send events through the MIDI interface faster than about each millisecond
00622     prerender();
00623 }
00624 
00625 void Synth::playMsgOnPart(unsigned char part, unsigned char code, unsigned char note, unsigned char velocity) {
00626     Bit32u bend;
00627 
00628     //printDebug("Synth::playMsgOnPart(%02x, %02x, %02x, %02x)", part, code, note, velocity);
00629     switch (code) {
00630     case 0x8:
00631         //printDebug("Note OFF - Part %d", part);
00632         // The MT-32 ignores velocity for note off
00633         parts[part]->noteOff(note);
00634         break;
00635     case 0x9:
00636         //printDebug("Note ON - Part %d, Note %d Vel %d", part, note, velocity);
00637         if (velocity == 0) {
00638             // MIDI defines note-on with velocity 0 as being the same as note-off with velocity 40
00639             parts[part]->noteOff(note);
00640         } else {
00641             parts[part]->noteOn(note, velocity);
00642         }
00643         break;
00644     case 0xB: // Control change
00645         switch (note) {
00646         case 0x01:  // Modulation
00647             //printDebug("Modulation: %d", velocity);
00648             parts[part]->setModulation(velocity);
00649             break;
00650         case 0x06:
00651             parts[part]->setDataEntryMSB(velocity);
00652             break;
00653         case 0x07:  // Set volume
00654             //printDebug("Volume set: %d", velocity);
00655             parts[part]->setVolume(velocity);
00656             break;
00657         case 0x0A:  // Pan
00658             //printDebug("Pan set: %d", velocity);
00659             parts[part]->setPan(velocity);
00660             break;
00661         case 0x0B:
00662             //printDebug("Expression set: %d", velocity);
00663             parts[part]->setExpression(velocity);
00664             break;
00665         case 0x40: // Hold (sustain) pedal
00666             //printDebug("Hold pedal set: %d", velocity);
00667             parts[part]->setHoldPedal(velocity >= 64);
00668             break;
00669 
00670         case 0x62:
00671         case 0x63:
00672             parts[part]->setNRPN();
00673             break;
00674         case 0x64:
00675             parts[part]->setRPNLSB(velocity);
00676             break;
00677         case 0x65:
00678             parts[part]->setRPNMSB(velocity);
00679             break;
00680 
00681         case 0x79: // Reset all controllers
00682             //printDebug("Reset all controllers");
00683             parts[part]->resetAllControllers();
00684             break;
00685 
00686         case 0x7B: // All notes off
00687             //printDebug("All notes off");
00688             parts[part]->allNotesOff();
00689             break;
00690 
00691         case 0x7C:
00692         case 0x7D:
00693         case 0x7E:
00694         case 0x7F:
00695             // CONFIRMED:Mok: A real LAPC-I responds to these controllers as follows:
00696             parts[part]->setHoldPedal(false);
00697             parts[part]->allNotesOff();
00698             break;
00699 
00700         default:
00701 #if MT32EMU_MONITOR_MIDI > 0
00702             printDebug("Unknown MIDI Control code: 0x%02x - vel 0x%02x", note, velocity);
00703 #endif
00704             break;
00705         }
00706 
00707         break;
00708     case 0xC: // Program change
00709         //printDebug("Program change %01x", note);
00710         parts[part]->setProgram(note);
00711         break;
00712     case 0xE: // Pitch bender
00713         bend = (velocity << 7) | (note);
00714         //printDebug("Pitch bender %02x", bend);
00715         parts[part]->setBend(bend);
00716         break;
00717     default:
00718 #if MT32EMU_MONITOR_MIDI > 0
00719         printDebug("Unknown Midi code: 0x%01x - %02x - %02x", code, note, velocity);
00720 #endif
00721         break;
00722     }
00723 
00724     //midiOutShortMsg(m_out, msg);
00725 }
00726 
00727 void Synth::playSysex(const Bit8u *sysex, Bit32u len) {
00728     if (len < 2) {
00729         printDebug("playSysex: Message is too short for sysex (%d bytes)", len);
00730     }
00731     if (sysex[0] != 0xF0) {
00732         printDebug("playSysex: Message lacks start-of-sysex (0xF0)");
00733         return;
00734     }
00735     // Due to some programs (e.g. Java) sending buffers with junk at the end, we have to go through and find the end marker rather than relying on len.
00736     Bit32u endPos;
00737     for (endPos = 1; endPos < len; endPos++) {
00738         if (sysex[endPos] == 0xF7) {
00739             break;
00740         }
00741     }
00742     if (endPos == len) {
00743         printDebug("playSysex: Message lacks end-of-sysex (0xf7)");
00744         return;
00745     }
00746     playSysexWithoutFraming(sysex + 1, endPos - 1);
00747 }
00748 
00749 void Synth::playSysexWithoutFraming(const Bit8u *sysex, Bit32u len) {
00750     if (len < 4) {
00751         printDebug("playSysexWithoutFraming: Message is too short (%d bytes)!", len);
00752         return;
00753     }
00754     if (sysex[0] != SYSEX_MANUFACTURER_ROLAND) {
00755         printDebug("playSysexWithoutFraming: Header not intended for this device manufacturer: %02x %02x %02x %02x", (int)sysex[0], (int)sysex[1], (int)sysex[2], (int)sysex[3]);
00756         return;
00757     }
00758     if (sysex[2] == SYSEX_MDL_D50) {
00759         printDebug("playSysexWithoutFraming: Header is intended for model D-50 (not yet supported): %02x %02x %02x %02x", (int)sysex[0], (int)sysex[1], (int)sysex[2], (int)sysex[3]);
00760         return;
00761     } else if (sysex[2] != SYSEX_MDL_MT32) {
00762         printDebug("playSysexWithoutFraming: Header not intended for model MT-32: %02x %02x %02x %02x", (int)sysex[0], (int)sysex[1], (int)sysex[2], (int)sysex[3]);
00763         return;
00764     }
00765     playSysexWithoutHeader(sysex[1], sysex[3], sysex + 4, len - 4);
00766 }
00767 
00768 void Synth::playSysexWithoutHeader(unsigned char device, unsigned char command, const Bit8u *sysex, Bit32u len) {
00769     if (device > 0x10) {
00770         // We have device ID 0x10 (default, but changeable, on real MT-32), < 0x10 is for channels
00771         printDebug("playSysexWithoutHeader: Message is not intended for this device ID (provided: %02x, expected: 0x10 or channel)", (int)device);
00772         return;
00773     }
00774     // This is checked early in the real devices (before any sysex length checks or further processing)
00775     // FIXME: Response to SYSEX_CMD_DAT reset with partials active (and in general) is untested.
00776     if ((command == SYSEX_CMD_DT1 || command == SYSEX_CMD_DAT) && sysex[0] == 0x7F) {
00777         reset();
00778         return;
00779     }
00780     if (len < 4) {
00781         printDebug("playSysexWithoutHeader: Message is too short (%d bytes)!", len);
00782         return;
00783     }
00784     unsigned char checksum = calcSysexChecksum(sysex, len - 1, 0);
00785     if (checksum != sysex[len - 1]) {
00786         printDebug("playSysexWithoutHeader: Message checksum is incorrect (provided: %02x, expected: %02x)!", sysex[len - 1], checksum);
00787         return;
00788     }
00789     len -= 1; // Exclude checksum
00790     switch (command) {
00791     case SYSEX_CMD_DAT:
00792         if (hasActivePartials()) {
00793             printDebug("playSysexWithoutHeader: Got SYSEX_CMD_DAT but partials are active - ignoring");
00794             // FIXME: We should send SYSEX_CMD_RJC in this case
00795             break;
00796         }
00797         // Deliberate fall-through
00798     case SYSEX_CMD_DT1:
00799         writeSysex(device, sysex, len);
00800         break;
00801     case SYSEX_CMD_RQD:
00802         if (hasActivePartials()) {
00803             printDebug("playSysexWithoutHeader: Got SYSEX_CMD_RQD but partials are active - ignoring");
00804             // FIXME: We should send SYSEX_CMD_RJC in this case
00805             break;
00806         }
00807         // Deliberate fall-through
00808     case SYSEX_CMD_RQ1:
00809         readSysex(device, sysex, len);
00810         break;
00811     default:
00812         printDebug("playSysexWithoutHeader: Unsupported command %02x", command);
00813         return;
00814     }
00815 }
00816 
00817 void Synth::readSysex(unsigned char /*device*/, const Bit8u * /*sysex*/, Bit32u /*len*/) const {
00818     // NYI
00819 }
00820 
00821 void Synth::writeSysex(unsigned char device, const Bit8u *sysex, Bit32u len) {
00822     Bit32u addr = (sysex[0] << 16) | (sysex[1] << 8) | (sysex[2]);
00823     addr = MT32EMU_MEMADDR(addr);
00824     sysex += 3;
00825     len -= 3;
00826     //printDebug("Sysex addr: 0x%06x", MT32EMU_SYSEXMEMADDR(addr));
00827     // NOTE: Please keep both lower and upper bounds in each check, for ease of reading
00828 
00829     // Process channel-specific sysex by converting it to device-global
00830     if (device < 0x10) {
00831 #if MT32EMU_MONITOR_SYSEX > 0
00832         printDebug("WRITE-CHANNEL: Channel %d temp area 0x%06x", device, MT32EMU_SYSEXMEMADDR(addr));
00833 #endif
00834         if (/*addr >= MT32EMU_MEMADDR(0x000000) && */addr < MT32EMU_MEMADDR(0x010000)) {
00835             int offset;
00836             if (chantable[device] == -1) {
00837 #if MT32EMU_MONITOR_SYSEX > 0
00838                 printDebug(" (Channel not mapped to a part... 0 offset)");
00839 #endif
00840                 offset = 0;
00841             } else if (chantable[device] == 8) {
00842 #if MT32EMU_MONITOR_SYSEX > 0
00843                 printDebug(" (Channel mapped to rhythm... 0 offset)");
00844 #endif
00845                 offset = 0;
00846             } else {
00847                 offset = chantable[device] * sizeof(MemParams::PatchTemp);
00848 #if MT32EMU_MONITOR_SYSEX > 0
00849                 printDebug(" (Setting extra offset to %d)", offset);
00850 #endif
00851             }
00852             addr += MT32EMU_MEMADDR(0x030000) + offset;
00853         } else if (/*addr >= MT32EMU_MEMADDR(0x010000) && */ addr < MT32EMU_MEMADDR(0x020000)) {
00854             addr += MT32EMU_MEMADDR(0x030110) - MT32EMU_MEMADDR(0x010000);
00855         } else if (/*addr >= MT32EMU_MEMADDR(0x020000) && */ addr < MT32EMU_MEMADDR(0x030000)) {
00856             int offset;
00857             if (chantable[device] == -1) {
00858 #if MT32EMU_MONITOR_SYSEX > 0
00859                 printDebug(" (Channel not mapped to a part... 0 offset)");
00860 #endif
00861                 offset = 0;
00862             } else if (chantable[device] == 8) {
00863 #if MT32EMU_MONITOR_SYSEX > 0
00864                 printDebug(" (Channel mapped to rhythm... 0 offset)");
00865 #endif
00866                 offset = 0;
00867             } else {
00868                 offset = chantable[device] * sizeof(TimbreParam);
00869 #if MT32EMU_MONITOR_SYSEX > 0
00870                 printDebug(" (Setting extra offset to %d)", offset);
00871 #endif
00872             }
00873             addr += MT32EMU_MEMADDR(0x040000) - MT32EMU_MEMADDR(0x020000) + offset;
00874         } else {
00875 #if MT32EMU_MONITOR_SYSEX > 0
00876             printDebug(" Invalid channel");
00877 #endif
00878             return;
00879         }
00880     }
00881 
00882     // Process device-global sysex (possibly converted from channel-specific sysex above)
00883     for (;;) {
00884         // Find the appropriate memory region
00885         const MemoryRegion *region = findMemoryRegion(addr);
00886 
00887         if (region == NULL) {
00888             printDebug("Sysex write to unrecognised address %06x, len %d", MT32EMU_SYSEXMEMADDR(addr), len);
00889             break;
00890         }
00891         writeMemoryRegion(region, addr, region->getClampedLen(addr, len), sysex);
00892 
00893         Bit32u next = region->next(addr, len);
00894         if (next == 0) {
00895             break;
00896         }
00897         addr += next;
00898         sysex += next;
00899         len -= next;
00900     }
00901 }
00902 
00903 void Synth::readMemory(Bit32u addr, Bit32u len, Bit8u *data) {
00904     const MemoryRegion *region = findMemoryRegion(addr);
00905     if (region != NULL) {
00906         readMemoryRegion(region, addr, len, data);
00907     }
00908 }
00909 
00910 void Synth::initMemoryRegions() {
00911     // Timbre max tables are slightly more complicated than the others, which are used directly from the ROM.
00912     // The ROM (sensibly) just has maximums for TimbreParam.commonParam followed by just one TimbreParam.partialParam,
00913     // so we produce a table with all partialParams filled out, as well as padding for PaddedTimbre, for quick lookup.
00914     paddedTimbreMaxTable = new Bit8u[sizeof(MemParams::PaddedTimbre)];
00915     memcpy(&paddedTimbreMaxTable[0], &controlROMData[controlROMMap->timbreMaxTable], sizeof(TimbreParam::CommonParam) + sizeof(TimbreParam::PartialParam)); // commonParam and one partialParam
00916     int pos = sizeof(TimbreParam::CommonParam) + sizeof(TimbreParam::PartialParam);
00917     for (int i = 0; i < 3; i++) {
00918         memcpy(&paddedTimbreMaxTable[pos], &controlROMData[controlROMMap->timbreMaxTable + sizeof(TimbreParam::CommonParam)], sizeof(TimbreParam::PartialParam));
00919         pos += sizeof(TimbreParam::PartialParam);
00920     }
00921     memset(&paddedTimbreMaxTable[pos], 0, 10); // Padding
00922     patchTempMemoryRegion = new PatchTempMemoryRegion(this, (Bit8u *)&mt32ram.patchTemp[0], &controlROMData[controlROMMap->patchMaxTable]);
00923     rhythmTempMemoryRegion = new RhythmTempMemoryRegion(this, (Bit8u *)&mt32ram.rhythmTemp[0], &controlROMData[controlROMMap->rhythmMaxTable]);
00924     timbreTempMemoryRegion = new TimbreTempMemoryRegion(this, (Bit8u *)&mt32ram.timbreTemp[0], paddedTimbreMaxTable);
00925     patchesMemoryRegion = new PatchesMemoryRegion(this, (Bit8u *)&mt32ram.patches[0], &controlROMData[controlROMMap->patchMaxTable]);
00926     timbresMemoryRegion = new TimbresMemoryRegion(this, (Bit8u *)&mt32ram.timbres[0], paddedTimbreMaxTable);
00927     systemMemoryRegion = new SystemMemoryRegion(this, (Bit8u *)&mt32ram.system, &controlROMData[controlROMMap->systemMaxTable]);
00928     displayMemoryRegion = new DisplayMemoryRegion(this);
00929     resetMemoryRegion = new ResetMemoryRegion(this);
00930 }
00931 
00932 void Synth::deleteMemoryRegions() {
00933     delete patchTempMemoryRegion;
00934     patchTempMemoryRegion = NULL;
00935     delete rhythmTempMemoryRegion;
00936     rhythmTempMemoryRegion = NULL;
00937     delete timbreTempMemoryRegion;
00938     timbreTempMemoryRegion = NULL;
00939     delete patchesMemoryRegion;
00940     patchesMemoryRegion = NULL;
00941     delete timbresMemoryRegion;
00942     timbresMemoryRegion = NULL;
00943     delete systemMemoryRegion;
00944     systemMemoryRegion = NULL;
00945     delete displayMemoryRegion;
00946     displayMemoryRegion = NULL;
00947     delete resetMemoryRegion;
00948     resetMemoryRegion = NULL;
00949 
00950     delete[] paddedTimbreMaxTable;
00951     paddedTimbreMaxTable = NULL;
00952 }
00953 
00954 MemoryRegion *Synth::findMemoryRegion(Bit32u addr) {
00955     MemoryRegion *regions[] = {
00956         patchTempMemoryRegion,
00957         rhythmTempMemoryRegion,
00958         timbreTempMemoryRegion,
00959         patchesMemoryRegion,
00960         timbresMemoryRegion,
00961         systemMemoryRegion,
00962         displayMemoryRegion,
00963         resetMemoryRegion,
00964         NULL
00965     };
00966     for (int pos = 0; regions[pos] != NULL; pos++) {
00967         if (regions[pos]->contains(addr)) {
00968             return regions[pos];
00969         }
00970     }
00971     return NULL;
00972 }
00973 
00974 void Synth::readMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, Bit8u *data) {
00975     unsigned int first = region->firstTouched(addr);
00976     //unsigned int last = region->lastTouched(addr, len);
00977     unsigned int off = region->firstTouchedOffset(addr);
00978     len = region->getClampedLen(addr, len);
00979 
00980     unsigned int m;
00981 
00982     if (region->isReadable()) {
00983         region->read(first, off, data, len);
00984     } else {
00985         // FIXME: We might want to do these properly in future
00986         for (m = 0; m < len; m += 2) {
00987             data[m] = 0xff;
00988             if (m + 1 < len) {
00989                 data[m+1] = (Bit8u)region->type;
00990             }
00991         }
00992     }
00993 }
00994 
00995 void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, const Bit8u *data) {
00996     unsigned int first = region->firstTouched(addr);
00997     unsigned int last = region->lastTouched(addr, len);
00998     unsigned int off = region->firstTouchedOffset(addr);
00999     switch (region->type) {
01000     case MR_PatchTemp:
01001         region->write(first, off, data, len);
01002         //printDebug("Patch temp: Patch %d, offset %x, len %d", off/16, off % 16, len);
01003 
01004         for (unsigned int i = first; i <= last; i++) {
01005             int absTimbreNum = mt32ram.patchTemp[i].patch.timbreGroup * 64 + mt32ram.patchTemp[i].patch.timbreNum;
01006             char timbreName[11];
01007             memcpy(timbreName, mt32ram.timbres[absTimbreNum].timbre.common.name, 10);
01008             timbreName[10] = 0;
01009 #if MT32EMU_MONITOR_SYSEX > 0
01010             printDebug("WRITE-PARTPATCH (%d-%d@%d..%d): %d; timbre=%d (%s), outlevel=%d", first, last, off, off + len, i, absTimbreNum, timbreName, mt32ram.patchTemp[i].outputLevel);
01011 #endif
01012             if (parts[i] != NULL) {
01013                 if (i != 8) {
01014                     // Note: Confirmed on CM-64 that we definitely *should* update the timbre here,
01015                     // but only in the case that the sysex actually writes to those values
01016                     if (i == first && off > 2) {
01017 #if MT32EMU_MONITOR_SYSEX > 0
01018                         printDebug(" (Not updating timbre, since those values weren't touched)");
01019 #endif
01020                     } else {
01021                         parts[i]->setTimbre(&mt32ram.timbres[parts[i]->getAbsTimbreNum()].timbre);
01022                     }
01023                 }
01024                 parts[i]->refresh();
01025             }
01026         }
01027         break;
01028     case MR_RhythmTemp:
01029         region->write(first, off, data, len);
01030         for (unsigned int i = first; i <= last; i++) {
01031             int timbreNum = mt32ram.rhythmTemp[i].timbre;
01032             char timbreName[11];
01033             if (timbreNum < 94) {
01034                 memcpy(timbreName, mt32ram.timbres[128 + timbreNum].timbre.common.name, 10);
01035                 timbreName[10] = 0;
01036             } else {
01037                 strcpy(timbreName, "[None]");
01038             }
01039 #if MT32EMU_MONITOR_SYSEX > 0
01040             printDebug("WRITE-RHYTHM (%d-%d@%d..%d): %d; level=%02x, panpot=%02x, reverb=%02x, timbre=%d (%s)", first, last, off, off + len, i, mt32ram.rhythmTemp[i].outputLevel, mt32ram.rhythmTemp[i].panpot, mt32ram.rhythmTemp[i].reverbSwitch, mt32ram.rhythmTemp[i].timbre, timbreName);
01041 #endif
01042         }
01043         if (parts[8] != NULL) {
01044             parts[8]->refresh();
01045         }
01046         break;
01047     case MR_TimbreTemp:
01048         region->write(first, off, data, len);
01049         for (unsigned int i = first; i <= last; i++) {
01050             char instrumentName[11];
01051             memcpy(instrumentName, mt32ram.timbreTemp[i].common.name, 10);
01052             instrumentName[10] = 0;
01053 #if MT32EMU_MONITOR_SYSEX > 0
01054             printDebug("WRITE-PARTTIMBRE (%d-%d@%d..%d): timbre=%d (%s)", first, last, off, off + len, i, instrumentName);
01055 #endif
01056             if (parts[i] != NULL) {
01057                 parts[i]->refresh();
01058             }
01059         }
01060         break;
01061     case MR_Patches:
01062         region->write(first, off, data, len);
01063 #if MT32EMU_MONITOR_SYSEX > 0
01064         for (unsigned int i = first; i <= last; i++) {
01065             PatchParam *patch = &mt32ram.patches[i];
01066             int patchAbsTimbreNum = patch->timbreGroup * 64 + patch->timbreNum;
01067             char instrumentName[11];
01068             memcpy(instrumentName, mt32ram.timbres[patchAbsTimbreNum].timbre.common.name, 10);
01069             instrumentName[10] = 0;
01070             Bit8u *n = (Bit8u *)patch;
01071             printDebug("WRITE-PATCH (%d-%d@%d..%d): %d; timbre=%d (%s) %02X%02X%02X%02X%02X%02X%02X%02X", first, last, off, off + len, i, patchAbsTimbreNum, instrumentName, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]);
01072         }
01073 #endif
01074         break;
01075     case MR_Timbres:
01076         // Timbres
01077         first += 128;
01078         last += 128;
01079         region->write(first, off, data, len);
01080         for (unsigned int i = first; i <= last; i++) {
01081 #if MT32EMU_MONITOR_TIMBRES >= 1
01082             TimbreParam *timbre = &mt32ram.timbres[i].timbre;
01083             char instrumentName[11];
01084             memcpy(instrumentName, timbre->common.name, 10);
01085             instrumentName[10] = 0;
01086             printDebug("WRITE-TIMBRE (%d-%d@%d..%d): %d; name=\"%s\"", first, last, off, off + len, i, instrumentName);
01087 #if MT32EMU_MONITOR_TIMBRES >= 2
01088 #define DT(x) printDebug(" " #x ": %d", timbre->x)
01089             DT(common.partialStructure12);
01090             DT(common.partialStructure34);
01091             DT(common.partialMute);
01092             DT(common.noSustain);
01093 
01094 #define DTP(x) \
01095             DT(partial[x].wg.pitchCoarse); \
01096             DT(partial[x].wg.pitchFine); \
01097             DT(partial[x].wg.pitchKeyfollow); \
01098             DT(partial[x].wg.pitchBenderEnabled); \
01099             DT(partial[x].wg.waveform); \
01100             DT(partial[x].wg.pcmWave); \
01101             DT(partial[x].wg.pulseWidth); \
01102             DT(partial[x].wg.pulseWidthVeloSensitivity); \
01103             DT(partial[x].pitchEnv.depth); \
01104             DT(partial[x].pitchEnv.veloSensitivity); \
01105             DT(partial[x].pitchEnv.timeKeyfollow); \
01106             DT(partial[x].pitchEnv.time[0]); \
01107             DT(partial[x].pitchEnv.time[1]); \
01108             DT(partial[x].pitchEnv.time[2]); \
01109             DT(partial[x].pitchEnv.time[3]); \
01110             DT(partial[x].pitchEnv.level[0]); \
01111             DT(partial[x].pitchEnv.level[1]); \
01112             DT(partial[x].pitchEnv.level[2]); \
01113             DT(partial[x].pitchEnv.level[3]); \
01114             DT(partial[x].pitchEnv.level[4]); \
01115             DT(partial[x].pitchLFO.rate); \
01116             DT(partial[x].pitchLFO.depth); \
01117             DT(partial[x].pitchLFO.modSensitivity); \
01118             DT(partial[x].tvf.cutoff); \
01119             DT(partial[x].tvf.resonance); \
01120             DT(partial[x].tvf.keyfollow); \
01121             DT(partial[x].tvf.biasPoint); \
01122             DT(partial[x].tvf.biasLevel); \
01123             DT(partial[x].tvf.envDepth); \
01124             DT(partial[x].tvf.envVeloSensitivity); \
01125             DT(partial[x].tvf.envDepthKeyfollow); \
01126             DT(partial[x].tvf.envTimeKeyfollow); \
01127             DT(partial[x].tvf.envTime[0]); \
01128             DT(partial[x].tvf.envTime[1]); \
01129             DT(partial[x].tvf.envTime[2]); \
01130             DT(partial[x].tvf.envTime[3]); \
01131             DT(partial[x].tvf.envTime[4]); \
01132             DT(partial[x].tvf.envLevel[0]); \
01133             DT(partial[x].tvf.envLevel[1]); \
01134             DT(partial[x].tvf.envLevel[2]); \
01135             DT(partial[x].tvf.envLevel[3]); \
01136             DT(partial[x].tva.level); \
01137             DT(partial[x].tva.veloSensitivity); \
01138             DT(partial[x].tva.biasPoint1); \
01139             DT(partial[x].tva.biasLevel1); \
01140             DT(partial[x].tva.biasPoint2); \
01141             DT(partial[x].tva.biasLevel2); \
01142             DT(partial[x].tva.envTimeKeyfollow); \
01143             DT(partial[x].tva.envTimeVeloSensitivity); \
01144             DT(partial[x].tva.envTime[0]); \
01145             DT(partial[x].tva.envTime[1]); \
01146             DT(partial[x].tva.envTime[2]); \
01147             DT(partial[x].tva.envTime[3]); \
01148             DT(partial[x].tva.envTime[4]); \
01149             DT(partial[x].tva.envLevel[0]); \
01150             DT(partial[x].tva.envLevel[1]); \
01151             DT(partial[x].tva.envLevel[2]); \
01152             DT(partial[x].tva.envLevel[3]);
01153 
01154             DTP(0);
01155             DTP(1);
01156             DTP(2);
01157             DTP(3);
01158 #undef DTP
01159 #undef DT
01160 #endif
01161 #endif
01162             // FIXME:KG: Not sure if the stuff below should be done (for rhythm and/or parts)...
01163             // Does the real MT-32 automatically do this?
01164             for (unsigned int part = 0; part < 9; part++) {
01165                 if (parts[part] != NULL) {
01166                     parts[part]->refreshTimbre(i);
01167                 }
01168             }
01169         }
01170         break;
01171     case MR_System:
01172         region->write(0, off, data, len);
01173 
01174         reportHandler->onDeviceReconfig();
01175         // FIXME: We haven't properly confirmed any of this behaviour
01176         // In particular, we tend to reset things such as reverb even if the write contained
01177         // the same parameters as were already set, which may be wrong.
01178         // On the other hand, the real thing could be resetting things even when they aren't touched
01179         // by the write at all.
01180 #if MT32EMU_MONITOR_SYSEX > 0
01181         printDebug("WRITE-SYSTEM:");
01182 #endif
01183         if (off <= SYSTEM_MASTER_TUNE_OFF && off + len > SYSTEM_MASTER_TUNE_OFF) {
01184             refreshSystemMasterTune();
01185         }
01186         if (off <= SYSTEM_REVERB_LEVEL_OFF && off + len > SYSTEM_REVERB_MODE_OFF) {
01187             refreshSystemReverbParameters();
01188         }
01189         if (off <= SYSTEM_RESERVE_SETTINGS_END_OFF && off + len > SYSTEM_RESERVE_SETTINGS_START_OFF) {
01190             refreshSystemReserveSettings();
01191         }
01192         if (off <= SYSTEM_CHAN_ASSIGN_END_OFF && off + len > SYSTEM_CHAN_ASSIGN_START_OFF) {
01193             int firstPart = off - SYSTEM_CHAN_ASSIGN_START_OFF;
01194             if(firstPart < 0)
01195                 firstPart = 0;
01196             int lastPart = off + len - SYSTEM_CHAN_ASSIGN_START_OFF;
01197             if(lastPart > 9)
01198                 lastPart = 9;
01199             refreshSystemChanAssign(firstPart, lastPart);
01200         }
01201         if (off <= SYSTEM_MASTER_VOL_OFF && off + len > SYSTEM_MASTER_VOL_OFF) {
01202             refreshSystemMasterVol();
01203         }
01204         break;
01205     case MR_Display:
01206         char buf[MAX_SYSEX_SIZE];
01207         memcpy(&buf, &data[0], len);
01208         buf[len] = 0;
01209 #if MT32EMU_MONITOR_SYSEX > 0
01210         printDebug("WRITE-LCD: %s", buf);
01211 #endif
01212         reportHandler->showLCDMessage(buf);
01213         break;
01214     case MR_Reset:
01215         reset();
01216         break;
01217     }
01218 }
01219 
01220 void Synth::refreshSystemMasterTune() {
01221 #if MT32EMU_MONITOR_SYSEX > 0
01222     //FIXME:KG: This is just an educated guess.
01223     // The LAPC-I documentation claims a range of 427.5Hz-452.6Hz (similar to what we have here)
01224     // The MT-32 documentation claims a range of 432.1Hz-457.6Hz
01225     float masterTune = 440.0f * EXP2F((mt32ram.system.masterTune - 64.0f) / (128.0f * 12.0f));
01226     printDebug(" Master Tune: %f", masterTune);
01227 #endif
01228 }
01229 
01230 void Synth::refreshSystemReverbParameters() {
01231 #if MT32EMU_MONITOR_SYSEX > 0
01232     printDebug(" Reverb: mode=%d, time=%d, level=%d", mt32ram.system.reverbMode, mt32ram.system.reverbTime, mt32ram.system.reverbLevel);
01233 #endif
01234     if (reverbOverridden && reverbModel != NULL) {
01235 #if MT32EMU_MONITOR_SYSEX > 0
01236         printDebug(" (Reverb overridden - ignoring)");
01237 #endif
01238         return;
01239     }
01240     reportHandler->onNewReverbMode(mt32ram.system.reverbMode);
01241     reportHandler->onNewReverbTime(mt32ram.system.reverbTime);
01242     reportHandler->onNewReverbLevel(mt32ram.system.reverbLevel);
01243 
01244     ReverbModel *newReverbModel = reverbModels[mt32ram.system.reverbMode];
01245 #if MT32EMU_REDUCE_REVERB_MEMORY
01246     if (reverbModel != newReverbModel) {
01247         if (reverbModel != NULL) {
01248             reverbModel->close();
01249         }
01250         newReverbModel->open();
01251     }
01252 #endif
01253     reverbModel = newReverbModel;
01254     reverbModel->setParameters(mt32ram.system.reverbTime, mt32ram.system.reverbLevel);
01255 }
01256 
01257 void Synth::refreshSystemReserveSettings() {
01258     Bit8u *rset = mt32ram.system.reserveSettings;
01259 #if MT32EMU_MONITOR_SYSEX > 0
01260     printDebug(" Partial reserve: 1=%02d 2=%02d 3=%02d 4=%02d 5=%02d 6=%02d 7=%02d 8=%02d Rhythm=%02d", rset[0], rset[1], rset[2], rset[3], rset[4], rset[5], rset[6], rset[7], rset[8]);
01261 #endif
01262     partialManager->setReserve(rset);
01263 }
01264 
01265 void Synth::refreshSystemChanAssign(unsigned int firstPart, unsigned int lastPart) {
01266     memset(chantable, -1, sizeof(chantable));
01267 
01268     // CONFIRMED: In the case of assigning a channel to multiple parts, the lower part wins.
01269     for (unsigned int i = 0; i <= 8; i++) {
01270         if (parts[i] != NULL && i >= firstPart && i <= lastPart) {
01271             // CONFIRMED: Decay is started for all polys, and all controllers are reset, for every part whose assignment was touched by the sysex write.
01272             parts[i]->allSoundOff();
01273             parts[i]->resetAllControllers();
01274         }
01275         int chan = mt32ram.system.chanAssign[i];
01276         if (chan != 16 && chantable[chan] == -1) {
01277             chantable[chan] = i;
01278         }
01279     }
01280 
01281 #if MT32EMU_MONITOR_SYSEX > 0
01282     Bit8u *rset = mt32ram.system.chanAssign;
01283     printDebug(" Part assign:     1=%02d 2=%02d 3=%02d 4=%02d 5=%02d 6=%02d 7=%02d 8=%02d Rhythm=%02d", rset[0], rset[1], rset[2], rset[3], rset[4], rset[5], rset[6], rset[7], rset[8]);
01284 #endif
01285 }
01286 
01287 void Synth::refreshSystemMasterVol() {
01288 #if MT32EMU_MONITOR_SYSEX > 0
01289     printDebug(" Master volume: %d", mt32ram.system.masterVol);
01290 #endif
01291 }
01292 
01293 void Synth::refreshSystem() {
01294     refreshSystemMasterTune();
01295     refreshSystemReverbParameters();
01296     refreshSystemReserveSettings();
01297     refreshSystemChanAssign(0, 8);
01298     refreshSystemMasterVol();
01299 }
01300 
01301 void Synth::reset() {
01302 #if MT32EMU_MONITOR_SYSEX > 0
01303     printDebug("RESET");
01304 #endif
01305     reportHandler->onDeviceReset();
01306     partialManager->deactivateAll();
01307     mt32ram = mt32default;
01308     for (int i = 0; i < 9; i++) {
01309         parts[i]->reset();
01310         if (i != 8) {
01311             parts[i]->setProgram(controlROMData[controlROMMap->programSettings + i]);
01312         } else {
01313             parts[8]->refresh();
01314         }
01315     }
01316     refreshSystem();
01317     isEnabled = false;
01318 }
01319 
01320 void Synth::render(Bit16s *stream, Bit32u len) {
01321     if (!isEnabled) {
01322         memset(stream, 0, len * sizeof(Bit16s) * 2);
01323         return;
01324     }
01325     while (len > 0) {
01326         Bit32u thisLen = len > MAX_SAMPLES_PER_RUN ? MAX_SAMPLES_PER_RUN : len;
01327         renderStreams(tmpNonReverbLeft, tmpNonReverbRight, tmpReverbDryLeft, tmpReverbDryRight, tmpReverbWetLeft, tmpReverbWetRight, thisLen);
01328         for (Bit32u i = 0; i < thisLen; i++) {
01329             stream[0] = clipBit16s((Bit32s)tmpNonReverbLeft[i] + (Bit32s)tmpReverbDryLeft[i] + (Bit32s)tmpReverbWetLeft[i]);
01330             stream[1] = clipBit16s((Bit32s)tmpNonReverbRight[i] + (Bit32s)tmpReverbDryRight[i] + (Bit32s)tmpReverbWetRight[i]);
01331             stream += 2;
01332         }
01333         len -= thisLen;
01334     }
01335 }
01336 
01337 bool Synth::prerender() {
01338     int newPrerenderWriteIx = (prerenderWriteIx + 1) % MAX_PRERENDER_SAMPLES;
01339     if (newPrerenderWriteIx == prerenderReadIx) {
01340         // The prerender buffer is full
01341         return false;
01342     }
01343     doRenderStreams(
01344         prerenderNonReverbLeft + prerenderWriteIx,
01345         prerenderNonReverbRight + prerenderWriteIx,
01346         prerenderReverbDryLeft + prerenderWriteIx,
01347         prerenderReverbDryRight + prerenderWriteIx,
01348         prerenderReverbWetLeft + prerenderWriteIx,
01349         prerenderReverbWetRight + prerenderWriteIx,
01350         1);
01351     prerenderWriteIx = newPrerenderWriteIx;
01352     return true;
01353 }
01354 
01355 static inline void maybeCopy(Bit16s *out, Bit32u outPos, Bit16s *in, Bit32u inPos, Bit32u len) {
01356     if (out == NULL) {
01357         return;
01358     }
01359     memcpy(out + outPos, in + inPos, len * sizeof(Bit16s));
01360 }
01361 
01362 void Synth::copyPrerender(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u pos, Bit32u len) {
01363     maybeCopy(nonReverbLeft, pos, prerenderNonReverbLeft, prerenderReadIx, len);
01364     maybeCopy(nonReverbRight, pos, prerenderNonReverbRight, prerenderReadIx, len);
01365     maybeCopy(reverbDryLeft, pos, prerenderReverbDryLeft, prerenderReadIx, len);
01366     maybeCopy(reverbDryRight, pos, prerenderReverbDryRight, prerenderReadIx, len);
01367     maybeCopy(reverbWetLeft, pos, prerenderReverbWetLeft, prerenderReadIx, len);
01368     maybeCopy(reverbWetRight, pos, prerenderReverbWetRight, prerenderReadIx, len);
01369 }
01370 
01371 void Synth::checkPrerender(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u &pos, Bit32u &len) {
01372     if (prerenderReadIx > prerenderWriteIx) {
01373         // There's data in the prerender buffer, and the write index has wrapped.
01374         Bit32u prerenderCopyLen = MAX_PRERENDER_SAMPLES - prerenderReadIx;
01375         if (prerenderCopyLen > len) {
01376             prerenderCopyLen = len;
01377         }
01378         copyPrerender(nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, pos, prerenderCopyLen);
01379         len -= prerenderCopyLen;
01380         pos += prerenderCopyLen;
01381         prerenderReadIx = (prerenderReadIx + prerenderCopyLen) % MAX_PRERENDER_SAMPLES;
01382     }
01383     if (prerenderReadIx < prerenderWriteIx) {
01384         // There's data in the prerender buffer, and the write index is ahead of the read index.
01385         Bit32u prerenderCopyLen = prerenderWriteIx - prerenderReadIx;
01386         if (prerenderCopyLen > len) {
01387             prerenderCopyLen = len;
01388         }
01389         copyPrerender(nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, pos, prerenderCopyLen);
01390         len -= prerenderCopyLen;
01391         pos += prerenderCopyLen;
01392         prerenderReadIx += prerenderCopyLen;
01393     }
01394     if (prerenderReadIx == prerenderWriteIx) {
01395         // If the ring buffer's empty, reset it to start at 0 to minimise wrapping,
01396         // which requires two writes instead of one.
01397         prerenderReadIx = prerenderWriteIx = 0;
01398     }
01399 }
01400 
01401 void Synth::renderStreams(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u len) {
01402     if (!isEnabled) {
01403         clearIfNonNull(nonReverbLeft, len);
01404         clearIfNonNull(nonReverbRight, len);
01405         clearIfNonNull(reverbDryLeft, len);
01406         clearIfNonNull(reverbDryRight, len);
01407         clearIfNonNull(reverbWetLeft, len);
01408         clearIfNonNull(reverbWetRight, len);
01409         return;
01410     }
01411     Bit32u pos = 0;
01412 
01413     // First, check for data in the prerender buffer and spit that out before generating anything new.
01414     // Note that the prerender buffer is rarely used - see comments elsewhere for details.
01415     checkPrerender(nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, pos, len);
01416 
01417     while (len > 0) {
01418         Bit32u thisLen = len > MAX_SAMPLES_PER_RUN ? MAX_SAMPLES_PER_RUN : len;
01419         doRenderStreams(
01420             streamOffset(nonReverbLeft, pos),
01421             streamOffset(nonReverbRight, pos),
01422             streamOffset(reverbDryLeft, pos),
01423             streamOffset(reverbDryRight, pos),
01424             streamOffset(reverbWetLeft, pos),
01425             streamOffset(reverbWetRight, pos),
01426             thisLen);
01427         len -= thisLen;
01428         pos += thisLen;
01429     }
01430 }
01431 
01432 // FIXME: Using more temporary buffers than we need to
01433 void Synth::doRenderStreams(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u len) {
01434     clearFloats(&tmpBufMixLeft[0], &tmpBufMixRight[0], len);
01435     if (!reverbEnabled) {
01436         for (unsigned int i = 0; i < getPartialLimit(); i++) {
01437             if (partialManager->produceOutput(i, &tmpBufPartialLeft[0], &tmpBufPartialRight[0], len)) {
01438                 mix(&tmpBufMixLeft[0], &tmpBufPartialLeft[0], len);
01439                 mix(&tmpBufMixRight[0], &tmpBufPartialRight[0], len);
01440             }
01441         }
01442         if (nonReverbLeft != NULL) {
01443             la32FloatToBit16sFunc(nonReverbLeft, &tmpBufMixLeft[0], len, outputGain);
01444         }
01445         if (nonReverbRight != NULL) {
01446             la32FloatToBit16sFunc(nonReverbRight, &tmpBufMixRight[0], len, outputGain);
01447         }
01448         clearIfNonNull(reverbDryLeft, len);
01449         clearIfNonNull(reverbDryRight, len);
01450         clearIfNonNull(reverbWetLeft, len);
01451         clearIfNonNull(reverbWetRight, len);
01452     } else {
01453         for (unsigned int i = 0; i < getPartialLimit(); i++) {
01454             if (!partialManager->shouldReverb(i)) {
01455                 if (partialManager->produceOutput(i, &tmpBufPartialLeft[0], &tmpBufPartialRight[0], len)) {
01456                     mix(&tmpBufMixLeft[0], &tmpBufPartialLeft[0], len);
01457                     mix(&tmpBufMixRight[0], &tmpBufPartialRight[0], len);
01458                 }
01459             }
01460         }
01461         if (nonReverbLeft != NULL) {
01462             la32FloatToBit16sFunc(nonReverbLeft, &tmpBufMixLeft[0], len, outputGain);
01463         }
01464         if (nonReverbRight != NULL) {
01465             la32FloatToBit16sFunc(nonReverbRight, &tmpBufMixRight[0], len, outputGain);
01466         }
01467 
01468         clearFloats(&tmpBufMixLeft[0], &tmpBufMixRight[0], len);
01469         for (unsigned int i = 0; i < getPartialLimit(); i++) {
01470             if (partialManager->shouldReverb(i)) {
01471                 if (partialManager->produceOutput(i, &tmpBufPartialLeft[0], &tmpBufPartialRight[0], len)) {
01472                     mix(&tmpBufMixLeft[0], &tmpBufPartialLeft[0], len);
01473                     mix(&tmpBufMixRight[0], &tmpBufPartialRight[0], len);
01474                 }
01475             }
01476         }
01477         if (reverbDryLeft != NULL) {
01478             la32FloatToBit16sFunc(reverbDryLeft, &tmpBufMixLeft[0], len, outputGain);
01479         }
01480         if (reverbDryRight != NULL) {
01481             la32FloatToBit16sFunc(reverbDryRight, &tmpBufMixRight[0], len, outputGain);
01482         }
01483 
01484         // FIXME: Note that on the real devices, reverb input and output are signed linear 16-bit (well, kinda, there's some fudging) PCM, not float.
01485         reverbModel->process(&tmpBufMixLeft[0], &tmpBufMixRight[0], &tmpBufReverbOutLeft[0], &tmpBufReverbOutRight[0], len);
01486         if (reverbWetLeft != NULL) {
01487             reverbFloatToBit16sFunc(reverbWetLeft, &tmpBufReverbOutLeft[0], len, reverbOutputGain);
01488         }
01489         if (reverbWetRight != NULL) {
01490             reverbFloatToBit16sFunc(reverbWetRight, &tmpBufReverbOutRight[0], len, reverbOutputGain);
01491         }
01492     }
01493     partialManager->clearAlreadyOutputed();
01494     renderedSampleCount += len;
01495 }
01496 
01497 void Synth::printPartialUsage(unsigned long sampleOffset) {
01498     unsigned int partialUsage[9];
01499     partialManager->getPerPartPartialUsage(partialUsage);
01500     if (sampleOffset > 0) {
01501         printDebug("[+%lu] Partial Usage: 1:%02d 2:%02d 3:%02d 4:%02d 5:%02d 6:%02d 7:%02d 8:%02d R: %02d  TOTAL: %02d", sampleOffset, partialUsage[0], partialUsage[1], partialUsage[2], partialUsage[3], partialUsage[4], partialUsage[5], partialUsage[6], partialUsage[7], partialUsage[8], getPartialLimit() - partialManager->getFreePartialCount());
01502     } else {
01503         printDebug("Partial Usage: 1:%02d 2:%02d 3:%02d 4:%02d 5:%02d 6:%02d 7:%02d 8:%02d R: %02d  TOTAL: %02d", partialUsage[0], partialUsage[1], partialUsage[2], partialUsage[3], partialUsage[4], partialUsage[5], partialUsage[6], partialUsage[7], partialUsage[8], getPartialLimit() - partialManager->getFreePartialCount());
01504     }
01505 }
01506 
01507 bool Synth::hasActivePartials() const {
01508     if (prerenderReadIx != prerenderWriteIx) {
01509         // Data in the prerender buffer means that the current isActive() states are "in the future".
01510         // It also means that partials are definitely active at this render point.
01511         return true;
01512     }
01513     for (unsigned int partialNum = 0; partialNum < getPartialLimit(); partialNum++) {
01514         if (partialManager->getPartial(partialNum)->isActive()) {
01515             return true;
01516         }
01517     }
01518     return false;
01519 }
01520 
01521 bool Synth::isActive() const {
01522     if (hasActivePartials()) {
01523         return true;
01524     }
01525     if (reverbEnabled) {
01526         return reverbModel->isActive();
01527     }
01528     return false;
01529 }
01530 
01531 const Partial *Synth::getPartial(unsigned int partialNum) const {
01532     return partialManager->getPartial(partialNum);
01533 }
01534 
01535 const Part *Synth::getPart(unsigned int partNum) const {
01536     if (partNum > 8) {
01537         return NULL;
01538     }
01539     return parts[partNum];
01540 }
01541 
01542 void MemoryRegion::read(unsigned int entry, unsigned int off, Bit8u *dst, unsigned int len) const {
01543     off += entry * entrySize;
01544     // This method should never be called with out-of-bounds parameters,
01545     // or on an unsupported region - seeing any of this debug output indicates a bug in the emulator
01546     if (off > entrySize * entries - 1) {
01547 #if MT32EMU_MONITOR_SYSEX > 0
01548         synth->printDebug("read[%d]: parameters start out of bounds: entry=%d, off=%d, len=%d", type, entry, off, len);
01549 #endif
01550         return;
01551     }
01552     if (off + len > entrySize * entries) {
01553 #if MT32EMU_MONITOR_SYSEX > 0
01554         synth->printDebug("read[%d]: parameters end out of bounds: entry=%d, off=%d, len=%d", type, entry, off, len);
01555 #endif
01556         len = entrySize * entries - off;
01557     }
01558     Bit8u *src = getRealMemory();
01559     if (src == NULL) {
01560 #if MT32EMU_MONITOR_SYSEX > 0
01561         synth->printDebug("read[%d]: unreadable region: entry=%d, off=%d, len=%d", type, entry, off, len);
01562 #endif
01563         return;
01564     }
01565     memcpy(dst, src + off, len);
01566 }
01567 
01568 void MemoryRegion::write(unsigned int entry, unsigned int off, const Bit8u *src, unsigned int len, bool init) const {
01569     unsigned int memOff = entry * entrySize + off;
01570     // This method should never be called with out-of-bounds parameters,
01571     // or on an unsupported region - seeing any of this debug output indicates a bug in the emulator
01572     if (off > entrySize * entries - 1) {
01573 #if MT32EMU_MONITOR_SYSEX > 0
01574         synth->printDebug("write[%d]: parameters start out of bounds: entry=%d, off=%d, len=%d", type, entry, off, len);
01575 #endif
01576         return;
01577     }
01578     if (off + len > entrySize * entries) {
01579 #if MT32EMU_MONITOR_SYSEX > 0
01580         synth->printDebug("write[%d]: parameters end out of bounds: entry=%d, off=%d, len=%d", type, entry, off, len);
01581 #endif
01582         len = entrySize * entries - off;
01583     }
01584     Bit8u *dest = getRealMemory();
01585     if (dest == NULL) {
01586 #if MT32EMU_MONITOR_SYSEX > 0
01587         synth->printDebug("write[%d]: unwritable region: entry=%d, off=%d, len=%d", type, entry, off, len);
01588 #endif
01589     }
01590 
01591     for (unsigned int i = 0; i < len; i++) {
01592         Bit8u desiredValue = src[i];
01593         Bit8u maxValue = getMaxValue(memOff);
01594         // maxValue == 0 means write-protected unless called from initialisation code, in which case it really means the maximum value is 0.
01595         if (maxValue != 0 || init) {
01596             if (desiredValue > maxValue) {
01597 #if MT32EMU_MONITOR_SYSEX > 0
01598                 synth->printDebug("write[%d]: Wanted 0x%02x at %d, but max 0x%02x", type, desiredValue, memOff, maxValue);
01599 #endif
01600                 desiredValue = maxValue;
01601             }
01602             dest[memOff] = desiredValue;
01603         } else if (desiredValue != 0) {
01604 #if MT32EMU_MONITOR_SYSEX > 0
01605             // Only output debug info if they wanted to write non-zero, since a lot of things cause this to spit out a lot of debug info otherwise.
01606             synth->printDebug("write[%d]: Wanted 0x%02x at %d, but write-protected", type, desiredValue, memOff);
01607 #endif
01608         }
01609         memOff++;
01610     }
01611 }
01612 
01613 
01614 void Synth::setPartialLimit( unsigned int _partialLimit )
01615 {
01616     /* NTS: A memory leak can occur if we open the synth with the initial (max)
01617         number of partials, then allow DOSBox-X to call setPartialLimit()
01618         with an (often lower) partial count, because the PartialManager()
01619         will later free only that lower count of partials. To prevent this,
01620         we throw a C++ exception if an attempt is made while the synth is
01621         open to call this function. */
01622     if (isOpen) throw std::runtime_error("MT32 attempt to change partial limit while synth is open");
01623     partialLimit = _partialLimit;
01624 }
01625 
01626 
01627 unsigned int Synth::getPartialLimit() const
01628 {
01629     return partialLimit;
01630 }
01631 
01632 
01633 void Synth::findPart( const Part *src, Bit8u *index_out )
01634 {
01635     Bit8u part_idx;
01636 
01637 
01638     part_idx = 0xff;
01639     if( src != NULL ) {
01640 #ifdef WIN32_DEBUG
01641         bool stop = false;
01642 #endif
01643     
01644         part_idx = 0;
01645         for( unsigned int lcv=0; lcv<9; lcv++ ) {
01646             if( src == getPart(lcv) ) {
01647 #ifdef WIN32_DEBUG
01648                 stop = true;
01649 #endif
01650                 break;
01651             }
01652 
01653             part_idx++;
01654         }
01655 
01656 #ifdef WIN32_DEBUG
01657         // DEBUG
01658         if( stop == false ) __asm int 3
01659 #endif
01660     }
01661 
01662 
01663     *index_out = part_idx;
01664 }
01665 
01666 
01667 void Synth::findPartial( const Partial *src, Bit8u *index_out )
01668 {
01669     Bit8u partials_idx;
01670 
01671 
01672     partials_idx = 0xff;
01673     if( src != NULL ) {
01674 #ifdef WIN32_DEBUG
01675         bool stop = false;
01676 #endif
01677 
01678         partials_idx = 0;
01679         for( unsigned int lcv=0; lcv<getPartialLimit(); lcv++ ) {
01680             if( src == getPartial(lcv) ) {
01681 #ifdef WIN32_DEBUG
01682                 stop = true;
01683 #endif
01684                 break;
01685             }
01686 
01687             partials_idx++;
01688         }
01689 
01690 #ifdef WIN32_DEBUG
01691         // DEBUG
01692         if( stop == false ) __asm int 3
01693 #endif
01694     }
01695 
01696 
01697     *index_out = partials_idx;
01698 }
01699 
01700 
01701 void Synth::findPartialParam( const TimbreParam::PartialParam *src, Bit16u *index_out1, Bit16u *index_out2 )
01702 {
01703     Bit16u partialParam_idx1, partialParam_idx2;
01704     bool stop;
01705 
01706 
01707     stop = false;
01708 
01709     partialParam_idx1 = 0xffff;
01710     partialParam_idx2 = 0xffff;
01711 
01712 
01713     if( src != NULL ) {
01714         partialParam_idx1 = 0;
01715 
01716         // #1 = mt32ram.timbres[] - partial
01717         for( int lcv1=0; lcv1<256; lcv1++ ) {
01718             partialParam_idx2 = 0;
01719 
01720             for( int lcv2=0; lcv2<4; lcv2++ ) {
01721                 if( src == &mt32ram.timbres[lcv1].timbre.partial[lcv2] ) { stop = true; break; }
01722 
01723                 partialParam_idx2++;
01724             }
01725             if( stop == true ) break;
01726 
01727             partialParam_idx1++;
01728         }
01729 
01730 
01731         if( stop == false ) {
01732             partialParam_idx1 = 0x1000;
01733 
01734             // #2 = mt32ram.timbreTemp - partial[]
01735             for( int lcv1=0; lcv1<8; lcv1++ ) {
01736                 partialParam_idx2 = 0;
01737 
01738                 for( int lcv2=0; lcv2<4; lcv2++ ) {
01739                     if( src == &mt32ram.timbreTemp[lcv1].partial[lcv2] ) { stop = true; break; }
01740 
01741                     partialParam_idx2++;
01742                 }
01743                 if( stop == true ) break;
01744 
01745                 partialParam_idx1++;
01746             }
01747         }
01748 
01749 
01750         if( stop == false ) {
01751             partialParam_idx1 = 0x2000;
01752 
01753             // #3 = parts[0-7] - patchCache[0-3].srcPartial
01754             for( int lcv1=0; lcv1<8; lcv1++ ) {
01755                 partialParam_idx2 = 0;
01756 
01757                 for( int lcv2=0; lcv2<4; lcv2++ ) {
01758                     Part *part;
01759 
01760                     part = (Part *) getPart(lcv1);
01761                     if( src == &part->getPatchCache(lcv2)->srcPartial ) { stop = true; break; }
01762 
01763                     partialParam_idx2++;
01764                 }
01765                 if( stop == true ) break;
01766 
01767                 partialParam_idx1++;
01768             }
01769         }
01770 
01771 
01772         if( stop == false ) {
01773             partialParam_idx1 = 0x3000;
01774 
01775             // #4 = parts[8] - patchCache[0-3].srcPartial (Rhythm)
01776             for( int lcv1=0; lcv1<1; lcv1++ ) {
01777                 partialParam_idx2 = 0;
01778 
01779                 for( int lcv2=0; lcv2<4; lcv2++ ) {
01780                     RhythmPart *part;
01781 
01782                     part = (RhythmPart *) getPart(8);
01783                     if( src == &part->getPatchCache(lcv2)->srcPartial ) { stop = true; break; }
01784 
01785                     partialParam_idx2++;
01786                 }
01787                 if( stop == true ) break;
01788 
01789                 partialParam_idx1++;
01790             }
01791         }
01792 
01793 
01794         if( stop == false ) {
01795             partialParam_idx1 = 0x4000;
01796 
01797             // #5 = parts[8] - drumCache[][].srcPartial (Rhythm)
01798             for( int lcv1=0; lcv1<85; lcv1++ ) {
01799                 partialParam_idx2 = 0;
01800 
01801                 for( int lcv2=0; lcv2<4; lcv2++ ) {
01802                     RhythmPart *part;
01803 
01804                     part = (RhythmPart *) getPart(8);
01805                     if( src == &part->getDrumCache(lcv1,lcv2)->srcPartial ) { stop = true; break; }
01806 
01807                     partialParam_idx2++;
01808                 }
01809                 if( stop == true ) break;
01810 
01811                 partialParam_idx1++;
01812             }
01813         }
01814 
01815 
01816         if( stop == false ) {
01817             partialParam_idx1 = 0x5000;
01818 
01819             // #6 = partials[] - cacheBackup
01820             for( unsigned int lcv1=0; lcv1<getPartialLimit(); lcv1++ ) {
01821                 partialParam_idx2 = 0;
01822 
01823                 for( int lcv2=0; lcv2<1; lcv2++ ) {
01824                     if( src == &getPartial(lcv1)->cachebackup.srcPartial ) { stop = true; break; }
01825 
01826                     partialParam_idx2++;
01827                 }
01828                 if( stop == true ) break;
01829 
01830                 partialParam_idx1++;
01831             }
01832 
01833 
01834 #ifdef WIN32_DEBUG
01835             // DEBUG
01836             if( stop == false ) __asm int 3
01837 #endif
01838         }
01839     }
01840 
01841 
01842     *index_out1 = partialParam_idx1;
01843     *index_out2 = partialParam_idx2;
01844 }
01845 
01846 
01847 void Synth::findPatchCache( const PatchCache *src, Bit16u *index_out1, Bit16u *index_out2 )
01848 {
01849     Bit16u patchCache_idx1, patchCache_idx2;
01850     bool stop;
01851 
01852 
01853     stop = false;
01854 
01855     patchCache_idx1 = 0xffff;
01856     patchCache_idx2 = 0xffff;
01857 
01858 
01859     if( src != NULL ) {
01860         patchCache_idx1 = 0;
01861 
01862         // #1 = parts[0-7] - patchCache
01863         for( int lcv1=0; lcv1<8; lcv1++ ) {
01864             patchCache_idx2 = 0;
01865 
01866             for( int lcv2=0; lcv2<4; lcv2++ ) {
01867                 Part *part;
01868 
01869                 part = (Part *) getPart(lcv1);
01870                 if( src == part->getPatchCache(lcv2) ) { stop = true; break; }
01871 
01872                 patchCache_idx2++;
01873             }
01874             if( stop == true ) break;
01875 
01876             patchCache_idx1++;
01877         }
01878 
01879 
01880         if( stop == false ) {
01881             patchCache_idx1 = 0x1000;
01882 
01883             // #2 parts[8] - patchCache (Rhythm)
01884             for( int lcv1=0; lcv1<1; lcv1++ ) {
01885                 patchCache_idx2 = 0;
01886 
01887                 for( int lcv2=0; lcv2<4; lcv2++ ) {
01888                     RhythmPart *part;
01889 
01890                     part = (RhythmPart *) getPart(8);
01891                     if( src == part->getPatchCache(lcv2) ) { stop = true; break; }
01892 
01893                     patchCache_idx2++;
01894                 }
01895                 if( stop == true ) break;
01896 
01897                 patchCache_idx1++;
01898             }
01899         }
01900 
01901 
01902         if( stop == false ) {
01903             patchCache_idx1 = 0x2000;
01904 
01905             // #3 parts[8] - drumcache[][] (Rhythm)
01906             for( int lcv1=0; lcv1<85; lcv1++ ) {
01907                 patchCache_idx2 = 0;
01908 
01909                 for( int lcv2=0; lcv2<4; lcv2++ ) {
01910                     RhythmPart *part;
01911 
01912                     part = (RhythmPart *) getPart(8);
01913                     if( src == part->getDrumCache(lcv1,lcv2) ) { stop = true; break; }
01914 
01915                     patchCache_idx2++;
01916                 }
01917                 if( stop == true ) break;
01918 
01919                 patchCache_idx1++;
01920             }
01921         }
01922 
01923 
01924         if( stop == false ) {
01925             patchCache_idx1 = 0x3000;
01926 
01927             // #4 partials[] - cacheBackup
01928             for( unsigned int lcv1=0; lcv1<getPartialLimit(); lcv1++ ) {
01929                 patchCache_idx2 = 0;
01930 
01931                 for( int lcv2=0; lcv2<1; lcv2++ ) {
01932                     if( src == &getPartial(lcv1)->cachebackup ) { stop = true; break; }
01933 
01934                     patchCache_idx2++;
01935                 }
01936                 if( stop == true ) break;
01937 
01938                 patchCache_idx1++;
01939             }
01940 
01941 
01942 #ifdef WIN32_DEBUG
01943             // DEBUG
01944             if( stop == false ) __asm int 3
01945 #endif
01946         }
01947     }
01948 
01949 
01950     *index_out1 = patchCache_idx1;
01951     *index_out2 = patchCache_idx2;
01952 }
01953 
01954 
01955 void Synth::findPatchTemp( const MemParams::PatchTemp *src, Bit8u *index_out )
01956 {
01957     Bit8u patchTemp_idx;
01958 
01959 
01960     patchTemp_idx = 0xff;
01961     if( src != NULL ) {
01962 #ifdef WIN32_DEBUG
01963         bool stop = false;
01964 #endif
01965 
01966         patchTemp_idx = 0;
01967         for( int lcv=0; lcv<9; lcv++ ) {
01968             if( src == &mt32ram.patchTemp[lcv] ) {
01969 #ifdef WIN32_DEBUG
01970                 stop = true;
01971 #endif
01972                 break;
01973             }
01974 
01975             patchTemp_idx++;
01976         }
01977 
01978 
01979 #ifdef WIN32_DEBUG
01980         // DEBUG
01981         if( stop == false ) __asm int 3
01982 #endif
01983     }
01984 
01985 
01986     *index_out = patchTemp_idx;
01987 }
01988 
01989 
01990 void Synth::findPCMWaveEntry( const PCMWaveEntry *src, Bit16u *index_out )
01991 {
01992     Bit16u PCMWaveEntry_idx;
01993 
01994     PCMWaveEntry_idx = 0xffff;
01995     if( src != NULL ) {
01996 #ifdef WIN32_DEBUG
01997         bool stop = false;
01998 #endif
01999 
02000         PCMWaveEntry_idx = 0;
02001         for( int lcv=0; lcv<controlROMMap->pcmCount; lcv++ ) {
02002             if( src == &pcmWaves[lcv] ) {
02003 #ifdef WIN32_DEBUG
02004                 stop = true;
02005 #endif
02006                 break;
02007             }
02008 
02009             PCMWaveEntry_idx++;
02010         }
02011 
02012 
02013 #ifdef WIN32_DEBUG
02014         // DEBUG
02015         if( stop == false ) __asm int 3
02016 #endif
02017     }
02018 
02019 
02020     *index_out = PCMWaveEntry_idx;
02021 }
02022 
02023 // WE NEED TO REFRESH THIS
02024 void Synth::findPoly( const Poly *src, Bit16u *index_out1, Bit16u *index_out2 )
02025 {
02026     Bit16u poly_idx1, poly_idx2;
02027 
02028 
02029     poly_idx1 = 0xffff;
02030     poly_idx2 = 0xffff;
02031 
02032     if( src != NULL ) {
02033         bool stop;
02034 
02035         poly_idx1 = 0;
02036         stop = false;
02037 
02038         for( int lcv1=0; lcv1<9; lcv1++ ) {
02039             Part *part;
02040             part = (Part *) getPart(lcv1);
02041 
02042             poly_idx2 = 0;
02043 
02044             for( int lcv2=0; lcv2<part->getActivePolyCount(); lcv2++ ) {
02045                 if( src == part->getActivePoly(lcv2) ) { stop = true; break; }
02046 
02047                 poly_idx2++;
02048             }
02049             if( stop ) break;
02050 
02051             poly_idx1++;
02052         }
02053 
02054 
02055 #ifdef WIN32_DEBUG
02056         // DEBUG
02057         if( stop == false ) __asm int 3
02058 #endif
02059     }
02060 
02061     *index_out1 = poly_idx1;
02062     *index_out2 = poly_idx2;
02063 }
02064 
02065 
02066 
02067 void Synth::findRhythmTemp( const MemParams::RhythmTemp *src, Bit8u *index_out )
02068 {
02069     Bit8u rhythmTemp_idx;
02070 
02071     rhythmTemp_idx = 0xff;
02072     if( src != NULL ) {
02073 #ifdef WIN32_DEBUG
02074         bool stop = false;
02075 #endif
02076 
02077         rhythmTemp_idx = 0;
02078         for( int lcv=0; lcv<85; lcv++ ) {
02079             if( src == &mt32ram.rhythmTemp[lcv] ) {
02080 #ifdef WIN32_DEBUG
02081                 stop = true;
02082 #endif
02083                 break;
02084             }
02085 
02086             rhythmTemp_idx++;
02087         }
02088 
02089 #ifdef WIN32_DEBUG
02090         // DEBUG
02091         if( stop == false ) __asm int 3
02092 #endif
02093     }
02094 
02095 
02096     *index_out = rhythmTemp_idx;
02097 }
02098 
02099 
02100 void Synth::findTimbreParam( const TimbreParam *src, Bit8u *index_out )
02101 {
02102     Bit8u timbreParam_idx;
02103 
02104 
02105     timbreParam_idx = 0xff;
02106     if( src != NULL ) {
02107 #ifdef WIN32_DEBUG
02108         bool stop = false;
02109 #endif
02110 
02111         timbreParam_idx = 0;
02112         for( int lcv=0; lcv<8; lcv++ ) {
02113             if( src == &mt32ram.timbreTemp[lcv] ) {
02114 #ifdef WIN32_DEBUG
02115                 stop = true;
02116 #endif
02117                 break;
02118             }
02119 
02120             timbreParam_idx++;
02121         }
02122 
02123 #ifdef WIN32_DEBUG
02124         // DEBUG
02125         if( stop == false ) __asm int 3
02126 #endif
02127     }
02128 
02129 
02130     *index_out = timbreParam_idx;
02131 }
02132 
02133 
02134 Part *Synth::indexPart( Bit8u index )
02135 {
02136     Part *ptr;
02137 
02138     ptr = NULL;
02139     if( index != 0xff )
02140         ptr = (Part *) getPart(index);
02141 
02142     return ptr;
02143 }
02144 
02145 
02146 Partial *Synth::indexPartial( Bit8u index )
02147 {
02148     Partial *ptr;
02149 
02150     ptr = NULL;
02151     if( index != 0xff )
02152         ptr = (Partial *) getPartial(index);
02153 
02154     return ptr;
02155 }
02156 
02157 
02158 TimbreParam::PartialParam *Synth::indexPartialParam( Bit16u index1, Bit16u index2 )
02159 {
02160     TimbreParam::PartialParam *ptr;
02161 
02162 
02163     ptr = NULL;
02164     if( index1 < 0x1000 ) {
02165         index1 -= 0x0000;
02166 
02167         ptr = &mt32ram.timbres[index1].timbre.partial[index2];
02168     }
02169     else if( index1 < 0x2000 ) {
02170         index1 -= 0x1000;
02171 
02172         ptr = &mt32ram.timbreTemp[index1].partial[index2];
02173     }
02174     else if( index1 < 0x3000 ) {
02175         Part *part;
02176 
02177         index1 -= 0x2000;
02178 
02179         part = (Part *) getPart(index1);
02180         ptr = (TimbreParam::PartialParam *) &part->getPatchCache(index2)->srcPartial;
02181     }
02182     else if( index1 < 0x4000 ) {
02183         RhythmPart *part;
02184 
02185         index1 -= 0x3000;
02186 
02187         part = (RhythmPart *) getPart(8);
02188         ptr = (TimbreParam::PartialParam *) &part->getPatchCache(index2)->srcPartial;
02189     }
02190     else if( index1 < 0x5000 ) {
02191         RhythmPart *part;
02192 
02193         index1 -= 0x4000;
02194 
02195         part = (RhythmPart *) getPart(8);
02196         ptr = (TimbreParam::PartialParam *) &part->getDrumCache(index1,index2)->srcPartial;
02197     }
02198     else if( index1 < 0x6000 ) {
02199         index1 -= 0x5000;
02200 
02201         ptr = (TimbreParam::PartialParam *) &getPartial(index1)->cachebackup.srcPartial;
02202     }
02203 
02204 
02205     return ptr;
02206 }
02207 
02208 
02209 PatchCache *Synth::indexPatchCache( Bit16u index1, Bit16u index2 )
02210 {
02211     PatchCache *ptr;
02212 
02213 
02214     ptr = NULL;
02215     if( index1 < 0x1000 ) {
02216         Part *part;
02217 
02218         index1 -= 0x0000;
02219 
02220         part = (Part *) getPart(index1);
02221         ptr = (PatchCache *) part->getPatchCache(index2);
02222     }
02223     else if( index1 < 0x2000 ) {
02224         RhythmPart *part;
02225 
02226         index1 -= 0x1000;
02227 
02228         part = (RhythmPart *) getPart(8);
02229         ptr = (PatchCache *) part->getPatchCache(index2);
02230     }
02231     else if( index1 < 0x3000 ) {
02232         RhythmPart *part;
02233 
02234         index1 -= 0x2000;
02235 
02236         part = (RhythmPart *) getPart(8);
02237         ptr = (PatchCache *) part->getDrumCache(index1, index2);
02238     }
02239     else if( index1 < 0x4000 ) {
02240         index1 -= 0x3000;
02241 
02242         ptr = (PatchCache *) &getPartial(index1)->cachebackup;
02243     }
02244 
02245 
02246     return ptr;
02247 }
02248 
02249 
02250 MemParams::PatchTemp *Synth::indexPatchTemp( Bit8u index )
02251 {
02252     MemParams::PatchTemp *ptr;
02253 
02254     ptr = NULL;
02255     if( index != 0xff )
02256         ptr = &mt32ram.patchTemp[index];
02257 
02258     return ptr;
02259 }
02260 
02261 
02262 PCMWaveEntry *Synth::indexPCMWaveEntry( Bit16u index )
02263 {
02264     PCMWaveEntry *ptr;
02265 
02266     ptr = NULL;
02267     if( index != 0xffff ) {
02268         ptr = &pcmWaves[index];
02269     }
02270 
02271     return ptr;
02272 }
02273 
02274 // WE NEED TO REFRESH THIS
02275 Poly *Synth::indexPoly( Bit16u index1, Bit16u index2 )
02276 {
02277     Poly *ptr;
02278 
02279 
02280     ptr = NULL;
02281     if( index1 != 0xffff ) {
02282         Part *part;
02283         part = (Part *) getPart(index1);
02284 
02285         ptr = (Poly *) part->getActivePoly(index2);
02286     }
02287 
02288 
02289     return ptr;
02290 }
02291 
02292 
02293 MemParams::RhythmTemp *Synth::indexRhythmTemp( Bit8u index )
02294 {
02295     MemParams::RhythmTemp *ptr;
02296 
02297     ptr = NULL;
02298     if( index != 0xff ) {
02299         ptr = &mt32ram.rhythmTemp[index];
02300     }
02301 
02302     return ptr;
02303 }
02304 
02305 
02306 TimbreParam *Synth::indexTimbreParam( Bit8u index )
02307 {
02308     TimbreParam *ptr;
02309 
02310     ptr = NULL;
02311     if( index != 0xff )
02312         ptr = &mt32ram.timbreTemp[index];
02313 
02314     return ptr;
02315 }
02316 
02317 }
02318