DOSBox-X
|
00001 /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher 00002 * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU Lesser General Public License as published by 00006 * the Free Software Foundation, either version 2.1 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #include <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 if (region->isReadable()) { 00981 region->read(first, off, data, len); 00982 } else { 00983 // FIXME: We might want to do these properly in future 00984 for (unsigned int m = 0; m < len; m += 2) { 00985 data[m] = 0xff; 00986 if (m + 1 < len) { 00987 data[m+1] = (Bit8u)region->type; 00988 } 00989 } 00990 } 00991 } 00992 00993 void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, const Bit8u *data) { 00994 unsigned int first = region->firstTouched(addr); 00995 unsigned int last = region->lastTouched(addr, len); 00996 unsigned int off = region->firstTouchedOffset(addr); 00997 switch (region->type) { 00998 case MR_PatchTemp: 00999 region->write(first, off, data, len); 01000 //printDebug("Patch temp: Patch %d, offset %x, len %d", off/16, off % 16, len); 01001 01002 for (unsigned int i = first; i <= last; i++) { 01003 int absTimbreNum = mt32ram.patchTemp[i].patch.timbreGroup * 64 + mt32ram.patchTemp[i].patch.timbreNum; 01004 char timbreName[11]; 01005 memcpy(timbreName, mt32ram.timbres[absTimbreNum].timbre.common.name, 10); 01006 timbreName[10] = 0; 01007 #if MT32EMU_MONITOR_SYSEX > 0 01008 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); 01009 #endif 01010 if (parts[i] != NULL) { 01011 if (i != 8) { 01012 // Note: Confirmed on CM-64 that we definitely *should* update the timbre here, 01013 // but only in the case that the sysex actually writes to those values 01014 if (i == first && off > 2) { 01015 #if MT32EMU_MONITOR_SYSEX > 0 01016 printDebug(" (Not updating timbre, since those values weren't touched)"); 01017 #endif 01018 } else { 01019 parts[i]->setTimbre(&mt32ram.timbres[parts[i]->getAbsTimbreNum()].timbre); 01020 } 01021 } 01022 parts[i]->refresh(); 01023 } 01024 } 01025 break; 01026 case MR_RhythmTemp: 01027 region->write(first, off, data, len); 01028 for (unsigned int i = first; i <= last; i++) { 01029 int timbreNum = mt32ram.rhythmTemp[i].timbre; 01030 char timbreName[11]; 01031 if (timbreNum < 94) { 01032 memcpy(timbreName, mt32ram.timbres[128 + timbreNum].timbre.common.name, 10); 01033 timbreName[10] = 0; 01034 } else { 01035 strcpy(timbreName, "[None]"); 01036 } 01037 #if MT32EMU_MONITOR_SYSEX > 0 01038 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); 01039 #endif 01040 } 01041 if (parts[8] != NULL) { 01042 parts[8]->refresh(); 01043 } 01044 break; 01045 case MR_TimbreTemp: 01046 region->write(first, off, data, len); 01047 for (unsigned int i = first; i <= last; i++) { 01048 char instrumentName[11]; 01049 memcpy(instrumentName, mt32ram.timbreTemp[i].common.name, 10); 01050 instrumentName[10] = 0; 01051 #if MT32EMU_MONITOR_SYSEX > 0 01052 printDebug("WRITE-PARTTIMBRE (%d-%d@%d..%d): timbre=%d (%s)", first, last, off, off + len, i, instrumentName); 01053 #endif 01054 if (parts[i] != NULL) { 01055 parts[i]->refresh(); 01056 } 01057 } 01058 break; 01059 case MR_Patches: 01060 region->write(first, off, data, len); 01061 #if MT32EMU_MONITOR_SYSEX > 0 01062 for (unsigned int i = first; i <= last; i++) { 01063 PatchParam *patch = &mt32ram.patches[i]; 01064 int patchAbsTimbreNum = patch->timbreGroup * 64 + patch->timbreNum; 01065 char instrumentName[11]; 01066 memcpy(instrumentName, mt32ram.timbres[patchAbsTimbreNum].timbre.common.name, 10); 01067 instrumentName[10] = 0; 01068 Bit8u *n = (Bit8u *)patch; 01069 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]); 01070 } 01071 #endif 01072 break; 01073 case MR_Timbres: 01074 // Timbres 01075 first += 128; 01076 last += 128; 01077 region->write(first, off, data, len); 01078 for (unsigned int i = first; i <= last; i++) { 01079 #if MT32EMU_MONITOR_TIMBRES >= 1 01080 TimbreParam *timbre = &mt32ram.timbres[i].timbre; 01081 char instrumentName[11]; 01082 memcpy(instrumentName, timbre->common.name, 10); 01083 instrumentName[10] = 0; 01084 printDebug("WRITE-TIMBRE (%d-%d@%d..%d): %d; name=\"%s\"", first, last, off, off + len, i, instrumentName); 01085 #if MT32EMU_MONITOR_TIMBRES >= 2 01086 #define DT(x) printDebug(" " #x ": %d", timbre->x) 01087 DT(common.partialStructure12); 01088 DT(common.partialStructure34); 01089 DT(common.partialMute); 01090 DT(common.noSustain); 01091 01092 #define DTP(x) \ 01093 DT(partial[x].wg.pitchCoarse); \ 01094 DT(partial[x].wg.pitchFine); \ 01095 DT(partial[x].wg.pitchKeyfollow); \ 01096 DT(partial[x].wg.pitchBenderEnabled); \ 01097 DT(partial[x].wg.waveform); \ 01098 DT(partial[x].wg.pcmWave); \ 01099 DT(partial[x].wg.pulseWidth); \ 01100 DT(partial[x].wg.pulseWidthVeloSensitivity); \ 01101 DT(partial[x].pitchEnv.depth); \ 01102 DT(partial[x].pitchEnv.veloSensitivity); \ 01103 DT(partial[x].pitchEnv.timeKeyfollow); \ 01104 DT(partial[x].pitchEnv.time[0]); \ 01105 DT(partial[x].pitchEnv.time[1]); \ 01106 DT(partial[x].pitchEnv.time[2]); \ 01107 DT(partial[x].pitchEnv.time[3]); \ 01108 DT(partial[x].pitchEnv.level[0]); \ 01109 DT(partial[x].pitchEnv.level[1]); \ 01110 DT(partial[x].pitchEnv.level[2]); \ 01111 DT(partial[x].pitchEnv.level[3]); \ 01112 DT(partial[x].pitchEnv.level[4]); \ 01113 DT(partial[x].pitchLFO.rate); \ 01114 DT(partial[x].pitchLFO.depth); \ 01115 DT(partial[x].pitchLFO.modSensitivity); \ 01116 DT(partial[x].tvf.cutoff); \ 01117 DT(partial[x].tvf.resonance); \ 01118 DT(partial[x].tvf.keyfollow); \ 01119 DT(partial[x].tvf.biasPoint); \ 01120 DT(partial[x].tvf.biasLevel); \ 01121 DT(partial[x].tvf.envDepth); \ 01122 DT(partial[x].tvf.envVeloSensitivity); \ 01123 DT(partial[x].tvf.envDepthKeyfollow); \ 01124 DT(partial[x].tvf.envTimeKeyfollow); \ 01125 DT(partial[x].tvf.envTime[0]); \ 01126 DT(partial[x].tvf.envTime[1]); \ 01127 DT(partial[x].tvf.envTime[2]); \ 01128 DT(partial[x].tvf.envTime[3]); \ 01129 DT(partial[x].tvf.envTime[4]); \ 01130 DT(partial[x].tvf.envLevel[0]); \ 01131 DT(partial[x].tvf.envLevel[1]); \ 01132 DT(partial[x].tvf.envLevel[2]); \ 01133 DT(partial[x].tvf.envLevel[3]); \ 01134 DT(partial[x].tva.level); \ 01135 DT(partial[x].tva.veloSensitivity); \ 01136 DT(partial[x].tva.biasPoint1); \ 01137 DT(partial[x].tva.biasLevel1); \ 01138 DT(partial[x].tva.biasPoint2); \ 01139 DT(partial[x].tva.biasLevel2); \ 01140 DT(partial[x].tva.envTimeKeyfollow); \ 01141 DT(partial[x].tva.envTimeVeloSensitivity); \ 01142 DT(partial[x].tva.envTime[0]); \ 01143 DT(partial[x].tva.envTime[1]); \ 01144 DT(partial[x].tva.envTime[2]); \ 01145 DT(partial[x].tva.envTime[3]); \ 01146 DT(partial[x].tva.envTime[4]); \ 01147 DT(partial[x].tva.envLevel[0]); \ 01148 DT(partial[x].tva.envLevel[1]); \ 01149 DT(partial[x].tva.envLevel[2]); \ 01150 DT(partial[x].tva.envLevel[3]); 01151 01152 DTP(0); 01153 DTP(1); 01154 DTP(2); 01155 DTP(3); 01156 #undef DTP 01157 #undef DT 01158 #endif 01159 #endif 01160 // FIXME:KG: Not sure if the stuff below should be done (for rhythm and/or parts)... 01161 // Does the real MT-32 automatically do this? 01162 for (unsigned int part = 0; part < 9; part++) { 01163 if (parts[part] != NULL) { 01164 parts[part]->refreshTimbre(i); 01165 } 01166 } 01167 } 01168 break; 01169 case MR_System: 01170 region->write(0, off, data, len); 01171 01172 reportHandler->onDeviceReconfig(); 01173 // FIXME: We haven't properly confirmed any of this behaviour 01174 // In particular, we tend to reset things such as reverb even if the write contained 01175 // the same parameters as were already set, which may be wrong. 01176 // On the other hand, the real thing could be resetting things even when they aren't touched 01177 // by the write at all. 01178 #if MT32EMU_MONITOR_SYSEX > 0 01179 printDebug("WRITE-SYSTEM:"); 01180 #endif 01181 if (off <= SYSTEM_MASTER_TUNE_OFF && off + len > SYSTEM_MASTER_TUNE_OFF) { 01182 refreshSystemMasterTune(); 01183 } 01184 if (off <= SYSTEM_REVERB_LEVEL_OFF && off + len > SYSTEM_REVERB_MODE_OFF) { 01185 refreshSystemReverbParameters(); 01186 } 01187 if (off <= SYSTEM_RESERVE_SETTINGS_END_OFF && off + len > SYSTEM_RESERVE_SETTINGS_START_OFF) { 01188 refreshSystemReserveSettings(); 01189 } 01190 if (off <= SYSTEM_CHAN_ASSIGN_END_OFF && off + len > SYSTEM_CHAN_ASSIGN_START_OFF) { 01191 int firstPart = off - SYSTEM_CHAN_ASSIGN_START_OFF; 01192 if(firstPart < 0) 01193 firstPart = 0; 01194 int lastPart = off + len - SYSTEM_CHAN_ASSIGN_START_OFF; 01195 if(lastPart > 9) 01196 lastPart = 9; 01197 refreshSystemChanAssign(firstPart, lastPart); 01198 } 01199 if (off <= SYSTEM_MASTER_VOL_OFF && off + len > SYSTEM_MASTER_VOL_OFF) { 01200 refreshSystemMasterVol(); 01201 } 01202 break; 01203 case MR_Display: 01204 char buf[MAX_SYSEX_SIZE]; 01205 memcpy(&buf, &data[0], len); 01206 buf[len] = 0; 01207 #if MT32EMU_MONITOR_SYSEX > 0 01208 printDebug("WRITE-LCD: %s", buf); 01209 #endif 01210 reportHandler->showLCDMessage(buf); 01211 break; 01212 case MR_Reset: 01213 reset(); 01214 break; 01215 } 01216 } 01217 01218 void Synth::refreshSystemMasterTune() { 01219 #if MT32EMU_MONITOR_SYSEX > 0 01220 //FIXME:KG: This is just an educated guess. 01221 // The LAPC-I documentation claims a range of 427.5Hz-452.6Hz (similar to what we have here) 01222 // The MT-32 documentation claims a range of 432.1Hz-457.6Hz 01223 float masterTune = 440.0f * EXP2F((mt32ram.system.masterTune - 64.0f) / (128.0f * 12.0f)); 01224 printDebug(" Master Tune: %f", masterTune); 01225 #endif 01226 } 01227 01228 void Synth::refreshSystemReverbParameters() { 01229 #if MT32EMU_MONITOR_SYSEX > 0 01230 printDebug(" Reverb: mode=%d, time=%d, level=%d", mt32ram.system.reverbMode, mt32ram.system.reverbTime, mt32ram.system.reverbLevel); 01231 #endif 01232 if (reverbOverridden && reverbModel != NULL) { 01233 #if MT32EMU_MONITOR_SYSEX > 0 01234 printDebug(" (Reverb overridden - ignoring)"); 01235 #endif 01236 return; 01237 } 01238 reportHandler->onNewReverbMode(mt32ram.system.reverbMode); 01239 reportHandler->onNewReverbTime(mt32ram.system.reverbTime); 01240 reportHandler->onNewReverbLevel(mt32ram.system.reverbLevel); 01241 01242 ReverbModel *newReverbModel = reverbModels[mt32ram.system.reverbMode]; 01243 #if MT32EMU_REDUCE_REVERB_MEMORY 01244 if (reverbModel != newReverbModel) { 01245 if (reverbModel != NULL) { 01246 reverbModel->close(); 01247 } 01248 newReverbModel->open(); 01249 } 01250 #endif 01251 reverbModel = newReverbModel; 01252 reverbModel->setParameters(mt32ram.system.reverbTime, mt32ram.system.reverbLevel); 01253 } 01254 01255 void Synth::refreshSystemReserveSettings() { 01256 Bit8u *rset = mt32ram.system.reserveSettings; 01257 #if MT32EMU_MONITOR_SYSEX > 0 01258 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]); 01259 #endif 01260 partialManager->setReserve(rset); 01261 } 01262 01263 void Synth::refreshSystemChanAssign(unsigned int firstPart, unsigned int lastPart) { 01264 memset(chantable, -1, sizeof(chantable)); 01265 01266 // CONFIRMED: In the case of assigning a channel to multiple parts, the lower part wins. 01267 for (unsigned int i = 0; i <= 8; i++) { 01268 if (parts[i] != NULL && i >= firstPart && i <= lastPart) { 01269 // CONFIRMED: Decay is started for all polys, and all controllers are reset, for every part whose assignment was touched by the sysex write. 01270 parts[i]->allSoundOff(); 01271 parts[i]->resetAllControllers(); 01272 } 01273 int chan = mt32ram.system.chanAssign[i]; 01274 if (chan != 16 && chantable[chan] == -1) { 01275 chantable[chan] = i; 01276 } 01277 } 01278 01279 #if MT32EMU_MONITOR_SYSEX > 0 01280 Bit8u *rset = mt32ram.system.chanAssign; 01281 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]); 01282 #endif 01283 } 01284 01285 void Synth::refreshSystemMasterVol() { 01286 #if MT32EMU_MONITOR_SYSEX > 0 01287 printDebug(" Master volume: %d", mt32ram.system.masterVol); 01288 #endif 01289 } 01290 01291 void Synth::refreshSystem() { 01292 refreshSystemMasterTune(); 01293 refreshSystemReverbParameters(); 01294 refreshSystemReserveSettings(); 01295 refreshSystemChanAssign(0, 8); 01296 refreshSystemMasterVol(); 01297 } 01298 01299 void Synth::reset() { 01300 #if MT32EMU_MONITOR_SYSEX > 0 01301 printDebug("RESET"); 01302 #endif 01303 reportHandler->onDeviceReset(); 01304 partialManager->deactivateAll(); 01305 mt32ram = mt32default; 01306 for (int i = 0; i < 9; i++) { 01307 parts[i]->reset(); 01308 if (i != 8) { 01309 parts[i]->setProgram(controlROMData[controlROMMap->programSettings + i]); 01310 } else { 01311 parts[8]->refresh(); 01312 } 01313 } 01314 refreshSystem(); 01315 isEnabled = false; 01316 } 01317 01318 void Synth::render(Bit16s *stream, Bit32u len) { 01319 if (!isEnabled) { 01320 memset(stream, 0, len * sizeof(Bit16s) * 2); 01321 return; 01322 } 01323 while (len > 0) { 01324 Bit32u thisLen = len > MAX_SAMPLES_PER_RUN ? MAX_SAMPLES_PER_RUN : len; 01325 renderStreams(tmpNonReverbLeft, tmpNonReverbRight, tmpReverbDryLeft, tmpReverbDryRight, tmpReverbWetLeft, tmpReverbWetRight, thisLen); 01326 for (Bit32u i = 0; i < thisLen; i++) { 01327 stream[0] = clipBit16s((Bit32s)tmpNonReverbLeft[i] + (Bit32s)tmpReverbDryLeft[i] + (Bit32s)tmpReverbWetLeft[i]); 01328 stream[1] = clipBit16s((Bit32s)tmpNonReverbRight[i] + (Bit32s)tmpReverbDryRight[i] + (Bit32s)tmpReverbWetRight[i]); 01329 stream += 2; 01330 } 01331 len -= thisLen; 01332 } 01333 } 01334 01335 bool Synth::prerender() { 01336 int newPrerenderWriteIx = (prerenderWriteIx + 1) % MAX_PRERENDER_SAMPLES; 01337 if (newPrerenderWriteIx == prerenderReadIx) { 01338 // The prerender buffer is full 01339 return false; 01340 } 01341 doRenderStreams( 01342 prerenderNonReverbLeft + prerenderWriteIx, 01343 prerenderNonReverbRight + prerenderWriteIx, 01344 prerenderReverbDryLeft + prerenderWriteIx, 01345 prerenderReverbDryRight + prerenderWriteIx, 01346 prerenderReverbWetLeft + prerenderWriteIx, 01347 prerenderReverbWetRight + prerenderWriteIx, 01348 1); 01349 prerenderWriteIx = newPrerenderWriteIx; 01350 return true; 01351 } 01352 01353 static inline void maybeCopy(Bit16s *out, Bit32u outPos, Bit16s *in, Bit32u inPos, Bit32u len) { 01354 if (out == NULL) { 01355 return; 01356 } 01357 memcpy(out + outPos, in + inPos, len * sizeof(Bit16s)); 01358 } 01359 01360 void Synth::copyPrerender(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u pos, Bit32u len) { 01361 maybeCopy(nonReverbLeft, pos, prerenderNonReverbLeft, prerenderReadIx, len); 01362 maybeCopy(nonReverbRight, pos, prerenderNonReverbRight, prerenderReadIx, len); 01363 maybeCopy(reverbDryLeft, pos, prerenderReverbDryLeft, prerenderReadIx, len); 01364 maybeCopy(reverbDryRight, pos, prerenderReverbDryRight, prerenderReadIx, len); 01365 maybeCopy(reverbWetLeft, pos, prerenderReverbWetLeft, prerenderReadIx, len); 01366 maybeCopy(reverbWetRight, pos, prerenderReverbWetRight, prerenderReadIx, len); 01367 } 01368 01369 void Synth::checkPrerender(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u &pos, Bit32u &len) { 01370 if (prerenderReadIx > prerenderWriteIx) { 01371 // There's data in the prerender buffer, and the write index has wrapped. 01372 Bit32u prerenderCopyLen = MAX_PRERENDER_SAMPLES - prerenderReadIx; 01373 if (prerenderCopyLen > len) { 01374 prerenderCopyLen = len; 01375 } 01376 copyPrerender(nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, pos, prerenderCopyLen); 01377 len -= prerenderCopyLen; 01378 pos += prerenderCopyLen; 01379 prerenderReadIx = (prerenderReadIx + prerenderCopyLen) % MAX_PRERENDER_SAMPLES; 01380 } 01381 if (prerenderReadIx < prerenderWriteIx) { 01382 // There's data in the prerender buffer, and the write index is ahead of the read index. 01383 Bit32u prerenderCopyLen = prerenderWriteIx - prerenderReadIx; 01384 if (prerenderCopyLen > len) { 01385 prerenderCopyLen = len; 01386 } 01387 copyPrerender(nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, pos, prerenderCopyLen); 01388 len -= prerenderCopyLen; 01389 pos += prerenderCopyLen; 01390 prerenderReadIx += prerenderCopyLen; 01391 } 01392 if (prerenderReadIx == prerenderWriteIx) { 01393 // If the ring buffer's empty, reset it to start at 0 to minimise wrapping, 01394 // which requires two writes instead of one. 01395 prerenderReadIx = prerenderWriteIx = 0; 01396 } 01397 } 01398 01399 void Synth::renderStreams(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u len) { 01400 if (!isEnabled) { 01401 clearIfNonNull(nonReverbLeft, len); 01402 clearIfNonNull(nonReverbRight, len); 01403 clearIfNonNull(reverbDryLeft, len); 01404 clearIfNonNull(reverbDryRight, len); 01405 clearIfNonNull(reverbWetLeft, len); 01406 clearIfNonNull(reverbWetRight, len); 01407 return; 01408 } 01409 Bit32u pos = 0; 01410 01411 // First, check for data in the prerender buffer and spit that out before generating anything new. 01412 // Note that the prerender buffer is rarely used - see comments elsewhere for details. 01413 checkPrerender(nonReverbLeft, nonReverbRight, reverbDryLeft, reverbDryRight, reverbWetLeft, reverbWetRight, pos, len); 01414 01415 while (len > 0) { 01416 Bit32u thisLen = len > MAX_SAMPLES_PER_RUN ? MAX_SAMPLES_PER_RUN : len; 01417 doRenderStreams( 01418 streamOffset(nonReverbLeft, pos), 01419 streamOffset(nonReverbRight, pos), 01420 streamOffset(reverbDryLeft, pos), 01421 streamOffset(reverbDryRight, pos), 01422 streamOffset(reverbWetLeft, pos), 01423 streamOffset(reverbWetRight, pos), 01424 thisLen); 01425 len -= thisLen; 01426 pos += thisLen; 01427 } 01428 } 01429 01430 // FIXME: Using more temporary buffers than we need to 01431 void Synth::doRenderStreams(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u len) { 01432 clearFloats(&tmpBufMixLeft[0], &tmpBufMixRight[0], len); 01433 if (!reverbEnabled) { 01434 for (unsigned int i = 0; i < getPartialLimit(); i++) { 01435 if (partialManager->produceOutput(i, &tmpBufPartialLeft[0], &tmpBufPartialRight[0], len)) { 01436 mix(&tmpBufMixLeft[0], &tmpBufPartialLeft[0], len); 01437 mix(&tmpBufMixRight[0], &tmpBufPartialRight[0], len); 01438 } 01439 } 01440 if (nonReverbLeft != NULL) { 01441 la32FloatToBit16sFunc(nonReverbLeft, &tmpBufMixLeft[0], len, outputGain); 01442 } 01443 if (nonReverbRight != NULL) { 01444 la32FloatToBit16sFunc(nonReverbRight, &tmpBufMixRight[0], len, outputGain); 01445 } 01446 clearIfNonNull(reverbDryLeft, len); 01447 clearIfNonNull(reverbDryRight, len); 01448 clearIfNonNull(reverbWetLeft, len); 01449 clearIfNonNull(reverbWetRight, len); 01450 } else { 01451 for (unsigned int i = 0; i < getPartialLimit(); i++) { 01452 if (!partialManager->shouldReverb(i)) { 01453 if (partialManager->produceOutput(i, &tmpBufPartialLeft[0], &tmpBufPartialRight[0], len)) { 01454 mix(&tmpBufMixLeft[0], &tmpBufPartialLeft[0], len); 01455 mix(&tmpBufMixRight[0], &tmpBufPartialRight[0], len); 01456 } 01457 } 01458 } 01459 if (nonReverbLeft != NULL) { 01460 la32FloatToBit16sFunc(nonReverbLeft, &tmpBufMixLeft[0], len, outputGain); 01461 } 01462 if (nonReverbRight != NULL) { 01463 la32FloatToBit16sFunc(nonReverbRight, &tmpBufMixRight[0], len, outputGain); 01464 } 01465 01466 clearFloats(&tmpBufMixLeft[0], &tmpBufMixRight[0], len); 01467 for (unsigned int i = 0; i < getPartialLimit(); i++) { 01468 if (partialManager->shouldReverb(i)) { 01469 if (partialManager->produceOutput(i, &tmpBufPartialLeft[0], &tmpBufPartialRight[0], len)) { 01470 mix(&tmpBufMixLeft[0], &tmpBufPartialLeft[0], len); 01471 mix(&tmpBufMixRight[0], &tmpBufPartialRight[0], len); 01472 } 01473 } 01474 } 01475 if (reverbDryLeft != NULL) { 01476 la32FloatToBit16sFunc(reverbDryLeft, &tmpBufMixLeft[0], len, outputGain); 01477 } 01478 if (reverbDryRight != NULL) { 01479 la32FloatToBit16sFunc(reverbDryRight, &tmpBufMixRight[0], len, outputGain); 01480 } 01481 01482 // 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. 01483 reverbModel->process(&tmpBufMixLeft[0], &tmpBufMixRight[0], &tmpBufReverbOutLeft[0], &tmpBufReverbOutRight[0], len); 01484 if (reverbWetLeft != NULL) { 01485 reverbFloatToBit16sFunc(reverbWetLeft, &tmpBufReverbOutLeft[0], len, reverbOutputGain); 01486 } 01487 if (reverbWetRight != NULL) { 01488 reverbFloatToBit16sFunc(reverbWetRight, &tmpBufReverbOutRight[0], len, reverbOutputGain); 01489 } 01490 } 01491 partialManager->clearAlreadyOutputed(); 01492 renderedSampleCount += len; 01493 } 01494 01495 void Synth::printPartialUsage(unsigned long sampleOffset) { 01496 unsigned int partialUsage[9]; 01497 partialManager->getPerPartPartialUsage(partialUsage); 01498 if (sampleOffset > 0) { 01499 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()); 01500 } else { 01501 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()); 01502 } 01503 } 01504 01505 bool Synth::hasActivePartials() const { 01506 if (prerenderReadIx != prerenderWriteIx) { 01507 // Data in the prerender buffer means that the current isActive() states are "in the future". 01508 // It also means that partials are definitely active at this render point. 01509 return true; 01510 } 01511 for (unsigned int partialNum = 0; partialNum < getPartialLimit(); partialNum++) { 01512 if (partialManager->getPartial(partialNum)->isActive()) { 01513 return true; 01514 } 01515 } 01516 return false; 01517 } 01518 01519 bool Synth::isActive() const { 01520 if (hasActivePartials()) { 01521 return true; 01522 } 01523 if (reverbEnabled) { 01524 return reverbModel->isActive(); 01525 } 01526 return false; 01527 } 01528 01529 const Partial *Synth::getPartial(unsigned int partialNum) const { 01530 return partialManager->getPartial(partialNum); 01531 } 01532 01533 const Part *Synth::getPart(unsigned int partNum) const { 01534 if (partNum > 8) { 01535 return NULL; 01536 } 01537 return parts[partNum]; 01538 } 01539 01540 void MemoryRegion::read(unsigned int entry, unsigned int off, Bit8u *dst, unsigned int len) const { 01541 off += entry * entrySize; 01542 // This method should never be called with out-of-bounds parameters, 01543 // or on an unsupported region - seeing any of this debug output indicates a bug in the emulator 01544 if (off > entrySize * entries - 1) { 01545 #if MT32EMU_MONITOR_SYSEX > 0 01546 synth->printDebug("read[%d]: parameters start out of bounds: entry=%d, off=%d, len=%d", type, entry, off, len); 01547 #endif 01548 return; 01549 } 01550 if (off + len > entrySize * entries) { 01551 #if MT32EMU_MONITOR_SYSEX > 0 01552 synth->printDebug("read[%d]: parameters end out of bounds: entry=%d, off=%d, len=%d", type, entry, off, len); 01553 #endif 01554 len = entrySize * entries - off; 01555 } 01556 Bit8u *src = getRealMemory(); 01557 if (src == NULL) { 01558 #if MT32EMU_MONITOR_SYSEX > 0 01559 synth->printDebug("read[%d]: unreadable region: entry=%d, off=%d, len=%d", type, entry, off, len); 01560 #endif 01561 return; 01562 } 01563 memcpy(dst, src + off, len); 01564 } 01565 01566 void MemoryRegion::write(unsigned int entry, unsigned int off, const Bit8u *src, unsigned int len, bool init) const { 01567 unsigned int memOff = entry * entrySize + off; 01568 // This method should never be called with out-of-bounds parameters, 01569 // or on an unsupported region - seeing any of this debug output indicates a bug in the emulator 01570 if (off > entrySize * entries - 1) { 01571 #if MT32EMU_MONITOR_SYSEX > 0 01572 synth->printDebug("write[%d]: parameters start out of bounds: entry=%d, off=%d, len=%d", type, entry, off, len); 01573 #endif 01574 return; 01575 } 01576 if (off + len > entrySize * entries) { 01577 #if MT32EMU_MONITOR_SYSEX > 0 01578 synth->printDebug("write[%d]: parameters end out of bounds: entry=%d, off=%d, len=%d", type, entry, off, len); 01579 #endif 01580 len = entrySize * entries - off; 01581 } 01582 Bit8u *dest = getRealMemory(); 01583 if (dest == NULL) { 01584 #if MT32EMU_MONITOR_SYSEX > 0 01585 synth->printDebug("write[%d]: unwritable region: entry=%d, off=%d, len=%d", type, entry, off, len); 01586 #endif 01587 } 01588 01589 for (unsigned int i = 0; i < len; i++) { 01590 Bit8u desiredValue = src[i]; 01591 Bit8u maxValue = getMaxValue(memOff); 01592 // maxValue == 0 means write-protected unless called from initialisation code, in which case it really means the maximum value is 0. 01593 if (maxValue != 0 || init) { 01594 if (desiredValue > maxValue) { 01595 #if MT32EMU_MONITOR_SYSEX > 0 01596 synth->printDebug("write[%d]: Wanted 0x%02x at %d, but max 0x%02x", type, desiredValue, memOff, maxValue); 01597 #endif 01598 desiredValue = maxValue; 01599 } 01600 dest[memOff] = desiredValue; 01601 } else if (desiredValue != 0) { 01602 #if MT32EMU_MONITOR_SYSEX > 0 01603 // 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. 01604 synth->printDebug("write[%d]: Wanted 0x%02x at %d, but write-protected", type, desiredValue, memOff); 01605 #endif 01606 } 01607 memOff++; 01608 } 01609 } 01610 01611 01612 void Synth::setPartialLimit( unsigned int _partialLimit ) 01613 { 01614 /* NTS: A memory leak can occur if we open the synth with the initial (max) 01615 number of partials, then allow DOSBox-X to call setPartialLimit() 01616 with an (often lower) partial count, because the PartialManager() 01617 will later free only that lower count of partials. To prevent this, 01618 we throw a C++ exception if an attempt is made while the synth is 01619 open to call this function. */ 01620 if (isOpen) throw std::runtime_error("MT32 attempt to change partial limit while synth is open"); 01621 partialLimit = _partialLimit; 01622 } 01623 01624 01625 unsigned int Synth::getPartialLimit() const 01626 { 01627 return partialLimit; 01628 } 01629 01630 01631 void Synth::findPart( const Part *src, Bit8u *index_out ) 01632 { 01633 Bit8u part_idx; 01634 01635 01636 part_idx = 0xff; 01637 if( src != NULL ) { 01638 #ifdef WIN32_DEBUG 01639 bool stop = false; 01640 #endif 01641 01642 part_idx = 0; 01643 for( unsigned int lcv=0; lcv<9; lcv++ ) { 01644 if( src == getPart(lcv) ) { 01645 #ifdef WIN32_DEBUG 01646 stop = true; 01647 #endif 01648 break; 01649 } 01650 01651 part_idx++; 01652 } 01653 01654 #ifdef WIN32_DEBUG 01655 // DEBUG 01656 if( stop == false ) __asm int 3 01657 #endif 01658 } 01659 01660 01661 *index_out = part_idx; 01662 } 01663 01664 01665 void Synth::findPartial( const Partial *src, Bit8u *index_out ) 01666 { 01667 Bit8u partials_idx; 01668 01669 01670 partials_idx = 0xff; 01671 if( src != NULL ) { 01672 #ifdef WIN32_DEBUG 01673 bool stop = false; 01674 #endif 01675 01676 partials_idx = 0; 01677 for( unsigned int lcv=0; lcv<getPartialLimit(); lcv++ ) { 01678 if( src == getPartial(lcv) ) { 01679 #ifdef WIN32_DEBUG 01680 stop = true; 01681 #endif 01682 break; 01683 } 01684 01685 partials_idx++; 01686 } 01687 01688 #ifdef WIN32_DEBUG 01689 // DEBUG 01690 if( stop == false ) __asm int 3 01691 #endif 01692 } 01693 01694 01695 *index_out = partials_idx; 01696 } 01697 01698 01699 void Synth::findPartialParam( const TimbreParam::PartialParam *src, Bit16u *index_out1, Bit16u *index_out2 ) 01700 { 01701 Bit16u partialParam_idx1, partialParam_idx2; 01702 01703 partialParam_idx1 = 0xffff; 01704 partialParam_idx2 = 0xffff; 01705 01706 if( src != NULL ) { 01707 bool stop = false; 01708 partialParam_idx1 = 0; 01709 01710 // #1 = mt32ram.timbres[] - partial 01711 for( int lcv1=0; lcv1<256; lcv1++ ) { 01712 partialParam_idx2 = 0; 01713 01714 for( int lcv2=0; lcv2<4; lcv2++ ) { 01715 if( src == &mt32ram.timbres[lcv1].timbre.partial[lcv2] ) { stop = true; break; } 01716 01717 partialParam_idx2++; 01718 } 01719 if( stop == true ) break; 01720 01721 partialParam_idx1++; 01722 } 01723 01724 01725 if( stop == false ) { 01726 partialParam_idx1 = 0x1000; 01727 01728 // #2 = mt32ram.timbreTemp - partial[] 01729 for( int lcv1=0; lcv1<8; lcv1++ ) { 01730 partialParam_idx2 = 0; 01731 01732 for( int lcv2=0; lcv2<4; lcv2++ ) { 01733 if( src == &mt32ram.timbreTemp[lcv1].partial[lcv2] ) { stop = true; break; } 01734 01735 partialParam_idx2++; 01736 } 01737 if( stop == true ) break; 01738 01739 partialParam_idx1++; 01740 } 01741 } 01742 01743 01744 if( stop == false ) { 01745 partialParam_idx1 = 0x2000; 01746 01747 // #3 = parts[0-7] - patchCache[0-3].srcPartial 01748 for( int lcv1=0; lcv1<8; lcv1++ ) { 01749 partialParam_idx2 = 0; 01750 01751 for( int lcv2=0; lcv2<4; lcv2++ ) { 01752 Part *part; 01753 01754 part = (Part *) getPart(lcv1); 01755 if( src == &part->getPatchCache(lcv2)->srcPartial ) { stop = true; break; } 01756 01757 partialParam_idx2++; 01758 } 01759 if( stop == true ) break; 01760 01761 partialParam_idx1++; 01762 } 01763 } 01764 01765 01766 if( stop == false ) { 01767 partialParam_idx1 = 0x3000; 01768 01769 // #4 = parts[8] - patchCache[0-3].srcPartial (Rhythm) 01770 for( int lcv1=0; lcv1<1; lcv1++ ) { 01771 partialParam_idx2 = 0; 01772 01773 for( int lcv2=0; lcv2<4; lcv2++ ) { 01774 RhythmPart *part; 01775 01776 part = (RhythmPart *) getPart(8); 01777 if( src == &part->getPatchCache(lcv2)->srcPartial ) { stop = true; break; } 01778 01779 partialParam_idx2++; 01780 } 01781 if( stop == true ) break; 01782 01783 partialParam_idx1++; 01784 } 01785 } 01786 01787 01788 if( stop == false ) { 01789 partialParam_idx1 = 0x4000; 01790 01791 // #5 = parts[8] - drumCache[][].srcPartial (Rhythm) 01792 for( int lcv1=0; lcv1<85; lcv1++ ) { 01793 partialParam_idx2 = 0; 01794 01795 for( int lcv2=0; lcv2<4; lcv2++ ) { 01796 RhythmPart *part; 01797 01798 part = (RhythmPart *) getPart(8); 01799 if( src == &part->getDrumCache(lcv1,lcv2)->srcPartial ) { stop = true; break; } 01800 01801 partialParam_idx2++; 01802 } 01803 if( stop == true ) break; 01804 01805 partialParam_idx1++; 01806 } 01807 } 01808 01809 01810 if( stop == false ) { 01811 partialParam_idx1 = 0x5000; 01812 01813 // #6 = partials[] - cacheBackup 01814 for( unsigned int lcv1=0; lcv1<getPartialLimit(); lcv1++ ) { 01815 partialParam_idx2 = 0; 01816 01817 for( int lcv2=0; lcv2<1; lcv2++ ) { 01818 if( src == &getPartial(lcv1)->cachebackup.srcPartial ) { stop = true; break; } 01819 01820 partialParam_idx2++; 01821 } 01822 if( stop == true ) break; 01823 01824 partialParam_idx1++; 01825 } 01826 01827 01828 #ifdef WIN32_DEBUG 01829 // DEBUG 01830 if( stop == false ) __asm int 3 01831 #endif 01832 } 01833 } 01834 01835 01836 *index_out1 = partialParam_idx1; 01837 *index_out2 = partialParam_idx2; 01838 } 01839 01840 01841 void Synth::findPatchCache( const PatchCache *src, Bit16u *index_out1, Bit16u *index_out2 ) 01842 { 01843 Bit16u patchCache_idx1, patchCache_idx2; 01844 01845 patchCache_idx1 = 0xffff; 01846 patchCache_idx2 = 0xffff; 01847 01848 if( src != NULL ) { 01849 bool stop = false; 01850 patchCache_idx1 = 0; 01851 01852 // #1 = parts[0-7] - patchCache 01853 for( int lcv1=0; lcv1<8; lcv1++ ) { 01854 patchCache_idx2 = 0; 01855 01856 for( int lcv2=0; lcv2<4; lcv2++ ) { 01857 Part *part; 01858 01859 part = (Part *) getPart(lcv1); 01860 if( src == part->getPatchCache(lcv2) ) { stop = true; break; } 01861 01862 patchCache_idx2++; 01863 } 01864 if( stop == true ) break; 01865 01866 patchCache_idx1++; 01867 } 01868 01869 01870 if( stop == false ) { 01871 patchCache_idx1 = 0x1000; 01872 01873 // #2 parts[8] - patchCache (Rhythm) 01874 for( int lcv1=0; lcv1<1; lcv1++ ) { 01875 patchCache_idx2 = 0; 01876 01877 for( int lcv2=0; lcv2<4; lcv2++ ) { 01878 RhythmPart *part; 01879 01880 part = (RhythmPart *) getPart(8); 01881 if( src == part->getPatchCache(lcv2) ) { stop = true; break; } 01882 01883 patchCache_idx2++; 01884 } 01885 if( stop == true ) break; 01886 01887 patchCache_idx1++; 01888 } 01889 } 01890 01891 01892 if( stop == false ) { 01893 patchCache_idx1 = 0x2000; 01894 01895 // #3 parts[8] - drumcache[][] (Rhythm) 01896 for( int lcv1=0; lcv1<85; lcv1++ ) { 01897 patchCache_idx2 = 0; 01898 01899 for( int lcv2=0; lcv2<4; lcv2++ ) { 01900 RhythmPart *part; 01901 01902 part = (RhythmPart *) getPart(8); 01903 if( src == part->getDrumCache(lcv1,lcv2) ) { stop = true; break; } 01904 01905 patchCache_idx2++; 01906 } 01907 if( stop == true ) break; 01908 01909 patchCache_idx1++; 01910 } 01911 } 01912 01913 01914 if( stop == false ) { 01915 patchCache_idx1 = 0x3000; 01916 01917 // #4 partials[] - cacheBackup 01918 for( unsigned int lcv1=0; lcv1<getPartialLimit(); lcv1++ ) { 01919 patchCache_idx2 = 0; 01920 01921 for( int lcv2=0; lcv2<1; lcv2++ ) { 01922 if( src == &getPartial(lcv1)->cachebackup ) { stop = true; break; } 01923 01924 patchCache_idx2++; 01925 } 01926 if( stop == true ) break; 01927 01928 patchCache_idx1++; 01929 } 01930 01931 01932 #ifdef WIN32_DEBUG 01933 // DEBUG 01934 if( stop == false ) __asm int 3 01935 #endif 01936 } 01937 } 01938 01939 01940 *index_out1 = patchCache_idx1; 01941 *index_out2 = patchCache_idx2; 01942 } 01943 01944 01945 void Synth::findPatchTemp( const MemParams::PatchTemp *src, Bit8u *index_out ) 01946 { 01947 Bit8u patchTemp_idx; 01948 01949 01950 patchTemp_idx = 0xff; 01951 if( src != NULL ) { 01952 #ifdef WIN32_DEBUG 01953 bool stop = false; 01954 #endif 01955 01956 patchTemp_idx = 0; 01957 for( int lcv=0; lcv<9; lcv++ ) { 01958 if( src == &mt32ram.patchTemp[lcv] ) { 01959 #ifdef WIN32_DEBUG 01960 stop = true; 01961 #endif 01962 break; 01963 } 01964 01965 patchTemp_idx++; 01966 } 01967 01968 01969 #ifdef WIN32_DEBUG 01970 // DEBUG 01971 if( stop == false ) __asm int 3 01972 #endif 01973 } 01974 01975 01976 *index_out = patchTemp_idx; 01977 } 01978 01979 01980 void Synth::findPCMWaveEntry( const PCMWaveEntry *src, Bit16u *index_out ) 01981 { 01982 Bit16u PCMWaveEntry_idx; 01983 01984 PCMWaveEntry_idx = 0xffff; 01985 if( src != NULL ) { 01986 #ifdef WIN32_DEBUG 01987 bool stop = false; 01988 #endif 01989 01990 PCMWaveEntry_idx = 0; 01991 for( int lcv=0; lcv<controlROMMap->pcmCount; lcv++ ) { 01992 if( src == &pcmWaves[lcv] ) { 01993 #ifdef WIN32_DEBUG 01994 stop = true; 01995 #endif 01996 break; 01997 } 01998 01999 PCMWaveEntry_idx++; 02000 } 02001 02002 02003 #ifdef WIN32_DEBUG 02004 // DEBUG 02005 if( stop == false ) __asm int 3 02006 #endif 02007 } 02008 02009 02010 *index_out = PCMWaveEntry_idx; 02011 } 02012 02013 // WE NEED TO REFRESH THIS 02014 void Synth::findPoly( const Poly *src, Bit16u *index_out1, Bit16u *index_out2 ) 02015 { 02016 Bit16u poly_idx1, poly_idx2; 02017 02018 02019 poly_idx1 = 0xffff; 02020 poly_idx2 = 0xffff; 02021 02022 if( src != NULL ) { 02023 bool stop; 02024 02025 poly_idx1 = 0; 02026 stop = false; 02027 02028 for( int lcv1=0; lcv1<9; lcv1++ ) { 02029 Part *part; 02030 part = (Part *) getPart(lcv1); 02031 02032 poly_idx2 = 0; 02033 02034 for( int lcv2=0; lcv2<part->getActivePolyCount(); lcv2++ ) { 02035 if( src == part->getActivePoly(lcv2) ) { stop = true; break; } 02036 02037 poly_idx2++; 02038 } 02039 if( stop ) break; 02040 02041 poly_idx1++; 02042 } 02043 02044 02045 #ifdef WIN32_DEBUG 02046 // DEBUG 02047 if( stop == false ) __asm int 3 02048 #endif 02049 } 02050 02051 *index_out1 = poly_idx1; 02052 *index_out2 = poly_idx2; 02053 } 02054 02055 02056 02057 void Synth::findRhythmTemp( const MemParams::RhythmTemp *src, Bit8u *index_out ) 02058 { 02059 Bit8u rhythmTemp_idx; 02060 02061 rhythmTemp_idx = 0xff; 02062 if( src != NULL ) { 02063 #ifdef WIN32_DEBUG 02064 bool stop = false; 02065 #endif 02066 02067 rhythmTemp_idx = 0; 02068 for( int lcv=0; lcv<85; lcv++ ) { 02069 if( src == &mt32ram.rhythmTemp[lcv] ) { 02070 #ifdef WIN32_DEBUG 02071 stop = true; 02072 #endif 02073 break; 02074 } 02075 02076 rhythmTemp_idx++; 02077 } 02078 02079 #ifdef WIN32_DEBUG 02080 // DEBUG 02081 if( stop == false ) __asm int 3 02082 #endif 02083 } 02084 02085 02086 *index_out = rhythmTemp_idx; 02087 } 02088 02089 02090 void Synth::findTimbreParam( const TimbreParam *src, Bit8u *index_out ) 02091 { 02092 Bit8u timbreParam_idx; 02093 02094 02095 timbreParam_idx = 0xff; 02096 if( src != NULL ) { 02097 #ifdef WIN32_DEBUG 02098 bool stop = false; 02099 #endif 02100 02101 timbreParam_idx = 0; 02102 for( int lcv=0; lcv<8; lcv++ ) { 02103 if( src == &mt32ram.timbreTemp[lcv] ) { 02104 #ifdef WIN32_DEBUG 02105 stop = true; 02106 #endif 02107 break; 02108 } 02109 02110 timbreParam_idx++; 02111 } 02112 02113 #ifdef WIN32_DEBUG 02114 // DEBUG 02115 if( stop == false ) __asm int 3 02116 #endif 02117 } 02118 02119 02120 *index_out = timbreParam_idx; 02121 } 02122 02123 02124 Part *Synth::indexPart( Bit8u index ) 02125 { 02126 Part *ptr; 02127 02128 ptr = NULL; 02129 if( index != 0xff ) 02130 ptr = (Part *) getPart(index); 02131 02132 return ptr; 02133 } 02134 02135 02136 Partial *Synth::indexPartial( Bit8u index ) 02137 { 02138 Partial *ptr; 02139 02140 ptr = NULL; 02141 if( index != 0xff ) 02142 ptr = (Partial *) getPartial(index); 02143 02144 return ptr; 02145 } 02146 02147 02148 TimbreParam::PartialParam *Synth::indexPartialParam( Bit16u index1, Bit16u index2 ) 02149 { 02150 TimbreParam::PartialParam *ptr; 02151 02152 02153 ptr = NULL; 02154 if( index1 < 0x1000 ) { 02155 index1 -= 0x0000; 02156 02157 ptr = &mt32ram.timbres[index1].timbre.partial[index2]; 02158 } 02159 else if( index1 < 0x2000 ) { 02160 index1 -= 0x1000; 02161 02162 ptr = &mt32ram.timbreTemp[index1].partial[index2]; 02163 } 02164 else if( index1 < 0x3000 ) { 02165 Part *part; 02166 02167 index1 -= 0x2000; 02168 02169 part = (Part *) getPart(index1); 02170 ptr = (TimbreParam::PartialParam *) &part->getPatchCache(index2)->srcPartial; 02171 } 02172 else if( index1 < 0x4000 ) { 02173 RhythmPart *part; 02174 02175 index1 -= 0x3000; 02176 02177 part = (RhythmPart *) getPart(8); 02178 ptr = (TimbreParam::PartialParam *) &part->getPatchCache(index2)->srcPartial; 02179 } 02180 else if( index1 < 0x5000 ) { 02181 RhythmPart *part; 02182 02183 index1 -= 0x4000; 02184 02185 part = (RhythmPart *) getPart(8); 02186 ptr = (TimbreParam::PartialParam *) &part->getDrumCache(index1,index2)->srcPartial; 02187 } 02188 else if( index1 < 0x6000 ) { 02189 index1 -= 0x5000; 02190 02191 ptr = (TimbreParam::PartialParam *) &getPartial(index1)->cachebackup.srcPartial; 02192 } 02193 02194 02195 return ptr; 02196 } 02197 02198 02199 PatchCache *Synth::indexPatchCache( Bit16u index1, Bit16u index2 ) 02200 { 02201 PatchCache *ptr; 02202 02203 02204 ptr = NULL; 02205 if( index1 < 0x1000 ) { 02206 Part *part; 02207 02208 index1 -= 0x0000; 02209 02210 part = (Part *) getPart(index1); 02211 ptr = (PatchCache *) part->getPatchCache(index2); 02212 } 02213 else if( index1 < 0x2000 ) { 02214 RhythmPart *part; 02215 02216 index1 -= 0x1000; 02217 02218 part = (RhythmPart *) getPart(8); 02219 ptr = (PatchCache *) part->getPatchCache(index2); 02220 } 02221 else if( index1 < 0x3000 ) { 02222 RhythmPart *part; 02223 02224 index1 -= 0x2000; 02225 02226 part = (RhythmPart *) getPart(8); 02227 ptr = (PatchCache *) part->getDrumCache(index1, index2); 02228 } 02229 else if( index1 < 0x4000 ) { 02230 index1 -= 0x3000; 02231 02232 ptr = (PatchCache *) &getPartial(index1)->cachebackup; 02233 } 02234 02235 02236 return ptr; 02237 } 02238 02239 02240 MemParams::PatchTemp *Synth::indexPatchTemp( Bit8u index ) 02241 { 02242 MemParams::PatchTemp *ptr; 02243 02244 ptr = NULL; 02245 if( index != 0xff ) 02246 ptr = &mt32ram.patchTemp[index]; 02247 02248 return ptr; 02249 } 02250 02251 02252 PCMWaveEntry *Synth::indexPCMWaveEntry( Bit16u index ) 02253 { 02254 PCMWaveEntry *ptr; 02255 02256 ptr = NULL; 02257 if( index != 0xffff ) { 02258 ptr = &pcmWaves[index]; 02259 } 02260 02261 return ptr; 02262 } 02263 02264 // WE NEED TO REFRESH THIS 02265 Poly *Synth::indexPoly( Bit16u index1, Bit16u index2 ) 02266 { 02267 Poly *ptr; 02268 02269 02270 ptr = NULL; 02271 if( index1 != 0xffff ) { 02272 Part *part; 02273 part = (Part *) getPart(index1); 02274 02275 ptr = (Poly *) part->getActivePoly(index2); 02276 } 02277 02278 02279 return ptr; 02280 } 02281 02282 02283 MemParams::RhythmTemp *Synth::indexRhythmTemp( Bit8u index ) 02284 { 02285 MemParams::RhythmTemp *ptr; 02286 02287 ptr = NULL; 02288 if( index != 0xff ) { 02289 ptr = &mt32ram.rhythmTemp[index]; 02290 } 02291 02292 return ptr; 02293 } 02294 02295 02296 TimbreParam *Synth::indexTimbreParam( Bit8u index ) 02297 { 02298 TimbreParam *ptr; 02299 02300 ptr = NULL; 02301 if( index != 0xff ) 02302 ptr = &mt32ram.timbreTemp[index]; 02303 02304 return ptr; 02305 } 02306 02307 } 02308