DOSBox-X
|
00001 /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher 00002 * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU Lesser General Public License as published by 00006 * the Free Software Foundation, either version 2.1 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #include <cmath> 00019 #include <cstdlib> 00020 #include <cstring> 00021 00022 #include "mt32emu.h" 00023 #include "mmath.h" 00024 00025 namespace MT32Emu { 00026 00027 #ifdef INACCURATE_SMOOTH_PAN 00028 // Mok wanted an option for smoother panning, and we love Mok. 00029 static const float PAN_NUMERATOR_NORMAL[] = {0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 5.5f, 6.0f, 6.5f, 7.0f}; 00030 #else 00031 // CONFIRMED by Mok: These NUMERATOR values (as bytes, not floats, obviously) are sent exactly like this to the LA32. 00032 static const float PAN_NUMERATOR_NORMAL[] = {0.0f, 0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f, 7.0f}; 00033 #endif 00034 static const float PAN_NUMERATOR_MASTER[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}; 00035 static const float PAN_NUMERATOR_SLAVE[] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 7.0f, 7.0f, 7.0f, 7.0f, 7.0f, 7.0f, 7.0f}; 00036 00037 Partial::Partial(Synth *useSynth, int useDebugPartialNum) : 00038 synth(useSynth), debugPartialNum(useDebugPartialNum), sampleNum(0) { 00039 // Initialisation of tva, tvp and tvf uses 'this' pointer 00040 // and thus should not be in the initializer list to avoid a compiler warning 00041 tva = new TVA(this, &Ramp); 00042 tvp = new TVP(this); 00043 tvf = new TVF(this, &cutoffModifierRamp); 00044 ownerPart = -1; 00045 poly = NULL; 00046 pair = NULL; 00047 00048 00049 // init ptr warnings (load state crashes) 00050 pcmWave = NULL; 00051 patchCache = NULL; 00052 cachebackup.partialParam = NULL; 00053 } 00054 00055 Partial::~Partial() { 00056 delete tva; 00057 delete tvp; 00058 delete tvf; 00059 } 00060 00061 // Only used for debugging purposes 00062 int Partial::debugGetPartialNum() const { 00063 return debugPartialNum; 00064 } 00065 00066 // Only used for debugging purposes 00067 unsigned long Partial::debugGetSampleNum() const { 00068 return sampleNum; 00069 } 00070 00071 int Partial::getOwnerPart() const { 00072 return ownerPart; 00073 } 00074 00075 bool Partial::isActive() const { 00076 return ownerPart > -1; 00077 } 00078 00079 const Poly *Partial::getPoly() const { 00080 return poly; 00081 } 00082 00083 void Partial::activate(int part) { 00084 // This just marks the partial as being assigned to a part 00085 ownerPart = part; 00086 } 00087 00088 void Partial::deactivate() { 00089 if (!isActive()) { 00090 return; 00091 } 00092 ownerPart = -1; 00093 if (poly != NULL) { 00094 poly->partialDeactivated(this); 00095 } 00096 synth->partialStateChanged(this, tva->getPhase(), TVA_PHASE_DEAD); 00097 #if MT32EMU_MONITOR_PARTIALS > 2 00098 synth->printDebug("[+%lu] [Partial %d] Deactivated", sampleNum, debugPartialNum); 00099 synth->printPartialUsage(sampleNum); 00100 #endif 00101 if (isRingModulatingSlave()) { 00102 pair->la32Pair.deactivate(LA32PartialPair::SLAVE); 00103 } else { 00104 la32Pair.deactivate(LA32PartialPair::MASTER); 00105 if (hasRingModulatingSlave()) { 00106 pair->deactivate(); 00107 pair = NULL; 00108 } 00109 } 00110 00111 // loadstate ptr warnings (sometimes points to freePolys) 00112 poly = NULL; 00113 00114 if (pair != NULL) { 00115 pair->pair = NULL; 00116 } 00117 } 00118 00119 void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *usePatchCache, const MemParams::RhythmTemp *rhythmTemp, Partial *pairPartial) { 00120 if (usePoly == NULL || usePatchCache == NULL) { 00121 synth->printDebug("[Partial %d] *** Error: Starting partial for owner %d, usePoly=%s, usePatchCache=%s", debugPartialNum, ownerPart, usePoly == NULL ? "*** NULL ***" : "OK", usePatchCache == NULL ? "*** NULL ***" : "OK"); 00122 return; 00123 } 00124 patchCache = usePatchCache; 00125 poly = usePoly; 00126 mixType = patchCache->structureMix; 00127 structurePosition = patchCache->structurePosition; 00128 00129 Bit8u panSetting = rhythmTemp != NULL ? rhythmTemp->panpot : part->getPatchTemp()->panpot; 00130 float panVal; 00131 if (mixType == 3) { 00132 if (structurePosition == 0) { 00133 panVal = PAN_NUMERATOR_MASTER[panSetting]; 00134 } else { 00135 panVal = PAN_NUMERATOR_SLAVE[panSetting]; 00136 } 00137 // Do a normal mix independent of any pair partial. 00138 mixType = 0; 00139 pairPartial = NULL; 00140 } else { 00141 panVal = PAN_NUMERATOR_NORMAL[panSetting]; 00142 } 00143 00144 // FIXME: Sample analysis suggests that the use of panVal is linear, but there are some some quirks that still need to be resolved. 00145 stereoVolume.leftVol = panVal / 7.0f; 00146 stereoVolume.rightVol = 1.0f - stereoVolume.leftVol; 00147 00148 // SEMI-CONFIRMED: From sample analysis: 00149 // Found that timbres with 3 or 4 partials (i.e. one using two partial pairs) are mixed in two different ways. 00150 // Either partial pairs are added or subtracted, it depends on how the partial pairs are allocated. 00151 // It seems that partials are grouped into quarters and if the partial pairs are allocated in different quarters the subtraction happens. 00152 // Though, this matters little for the majority of timbres, it becomes crucial for timbres which contain several partials that sound very close. 00153 // In this case that timbre can sound totally different depending of the way it is mixed up. 00154 // Most easily this effect can be displayed with the help of a special timbre consisting of several identical square wave partials (3 or 4). 00155 // Say, it is 3-partial timbre. Just play any two notes simultaneously and the polys very probably are mixed differently. 00156 // Moreover, the partial allocator retains the last partial assignment it did and all the subsequent notes will sound the same as the last released one. 00157 // The situation is better with 4-partial timbres since then a whole quarter is assigned for each poly. However, if a 3-partial timbre broke the normal 00158 // whole-quarter assignment or after some partials got aborted, even 4-partial timbres can be found sounding differently. 00159 // This behaviour is also confirmed with two more special timbres: one with identical sawtooth partials, and one with PCM wave 02. 00160 // For my personal taste, this behaviour rather enriches the sounding and should be emulated. 00161 // Also, the current partial allocator model probably needs to be refined. 00162 if (debugPartialNum & 8) { 00163 stereoVolume.leftVol = -stereoVolume.leftVol; 00164 stereoVolume.rightVol = -stereoVolume.rightVol; 00165 } 00166 00167 if (patchCache->PCMPartial) { 00168 pcmNum = patchCache->pcm; 00169 if (synth->controlROMMap->pcmCount > 128) { 00170 // CM-32L, etc. support two "banks" of PCMs, selectable by waveform type parameter. 00171 if (patchCache->waveform > 1) { 00172 pcmNum += 128; 00173 } 00174 } 00175 pcmWave = &synth->pcmWaves[pcmNum]; 00176 } else { 00177 pcmWave = NULL; 00178 } 00179 00180 // CONFIRMED: pulseWidthVal calculation is based on information from Mok 00181 pulseWidthVal = (poly->getVelocity() - 64) * (patchCache->srcPartial.wg.pulseWidthVeloSensitivity - 7) + Tables::getInstance().pulseWidth100To255[patchCache->srcPartial.wg.pulseWidth]; 00182 if (pulseWidthVal < 0) { 00183 pulseWidthVal = 0; 00184 } else if (pulseWidthVal > 255) { 00185 pulseWidthVal = 255; 00186 } 00187 00188 pair = pairPartial; 00189 alreadyOutputed = false; 00190 tva->reset(part, patchCache->partialParam, rhythmTemp); 00191 tvp->reset(part, patchCache->partialParam); 00192 tvf->reset(patchCache->partialParam, tvp->getBasePitch()); 00193 00194 LA32PartialPair::PairType pairType; 00195 LA32PartialPair *useLA32Pair; 00196 if (isRingModulatingSlave()) { 00197 pairType = LA32PartialPair::SLAVE; 00198 useLA32Pair = &pair->la32Pair; 00199 } else { 00200 pairType = LA32PartialPair::MASTER; 00201 la32Pair.init(hasRingModulatingSlave(), mixType == 1); 00202 useLA32Pair = &la32Pair; 00203 } 00204 if (isPCM()) { 00205 useLA32Pair->initPCM(pairType, &synth->pcmROMData[pcmWave->addr], pcmWave->len, pcmWave->loop); 00206 } else { 00207 useLA32Pair->initSynth(pairType, (patchCache->waveform & 1) != 0, pulseWidthVal, patchCache->srcPartial.tvf.resonance + 1); 00208 } 00209 if (!hasRingModulatingSlave()) { 00210 la32Pair.deactivate(LA32PartialPair::SLAVE); 00211 } 00212 // Temporary integration hack 00213 stereoVolume.leftVol /= 8192.0f; 00214 stereoVolume.rightVol /= 8192.0f; 00215 } 00216 00217 Bit32u Partial::getAmpValue() { 00218 // SEMI-CONFIRMED: From sample analysis: 00219 // (1) Tested with a single partial playing PCM wave 77 with pitchCoarse 36 and no keyfollow, velocity follow, etc. 00220 // This gives results within +/- 2 at the output (before any DAC bitshifting) 00221 // when sustaining at levels 156 - 255 with no modifiers. 00222 // (2) Tested with a special square wave partial (internal capture ID tva5) at TVA envelope levels 155-255. 00223 // This gives deltas between -1 and 0 compared to the real output. Note that this special partial only produces 00224 // positive amps, so negative still needs to be explored, as well as lower levels. 00225 // 00226 // Also still partially unconfirmed is the behaviour when ramping between levels, as well as the timing. 00227 // TODO: The tests above were performed using the float model, to be refined 00228 Bit32u ampRampVal = 67117056 - ampRamp.nextValue(); 00229 if (ampRamp.checkInterrupt()) { 00230 tva->handleInterrupt(); 00231 } 00232 return ampRampVal; 00233 } 00234 00235 Bit32u Partial::getCutoffValue() { 00236 if (isPCM()) { 00237 return 0; 00238 } 00239 Bit32u cutoffModifierRampVal = cutoffModifierRamp.nextValue(); 00240 if (cutoffModifierRamp.checkInterrupt()) { 00241 tvf->handleInterrupt(); 00242 } 00243 return (tvf->getBaseCutoff() << 18) + cutoffModifierRampVal; 00244 } 00245 00246 unsigned long Partial::generateSamples(Bit16s *partialBuf, unsigned long length) { 00247 if (!isActive() || alreadyOutputed) { 00248 return 0; 00249 } 00250 if (poly == NULL) { 00251 synth->printDebug("[Partial %d] *** ERROR: poly is NULL at Partial::generateSamples()!", debugPartialNum); 00252 return 0; 00253 } 00254 alreadyOutputed = true; 00255 00256 for (sampleNum = 0; sampleNum < length; sampleNum++) { 00257 if (!tva->isPlaying() || !la32Pair.isActive(LA32PartialPair::MASTER)) { 00258 deactivate(); 00259 break; 00260 } 00261 la32Pair.generateNextSample(LA32PartialPair::MASTER, getAmpValue(), tvp->nextPitch(), getCutoffValue()); 00262 if (hasRingModulatingSlave()) { 00263 la32Pair.generateNextSample(LA32PartialPair::SLAVE, pair->getAmpValue(), pair->tvp->nextPitch(), pair->getCutoffValue()); 00264 if (!pair->tva->isPlaying() || !la32Pair.isActive(LA32PartialPair::SLAVE)) { 00265 pair->deactivate(); 00266 if (mixType == 2) { 00267 deactivate(); 00268 break; 00269 } 00270 } 00271 } 00272 *partialBuf++ = la32Pair.nextOutSample(); 00273 } 00274 unsigned long renderedSamples = sampleNum; 00275 sampleNum = 0; 00276 return renderedSamples; 00277 } 00278 00279 bool Partial::hasRingModulatingSlave() const { 00280 return pair != NULL && structurePosition == 0 && (mixType == 1 || mixType == 2); 00281 } 00282 00283 bool Partial::isRingModulatingSlave() const { 00284 return pair != NULL && structurePosition == 1 && (mixType == 1 || mixType == 2); 00285 } 00286 00287 bool Partial::isPCM() const { 00288 return pcmWave != NULL; 00289 } 00290 00291 const ControlROMPCMStruct *Partial::getControlROMPCMStruct() const { 00292 if (pcmWave != NULL) { 00293 return pcmWave->controlROMPCMStruct; 00294 } 00295 return NULL; 00296 } 00297 00298 Synth *Partial::getSynth() const { 00299 return synth; 00300 } 00301 00302 bool Partial::produceOutput(float *leftBuf, float *rightBuf, unsigned long length) { 00303 if (!isActive() || alreadyOutputed || isRingModulatingSlave()) { 00304 return false; 00305 } 00306 if (poly == NULL) { 00307 synth->printDebug("[Partial %d] *** ERROR: poly is NULL at Partial::produceOutput()!", debugPartialNum); 00308 return false; 00309 } 00310 unsigned long numGenerated = generateSamples(myBuffer, length); 00311 for (unsigned int i = 0; i < numGenerated; i++) { 00312 *leftBuf++ = myBuffer[i] * stereoVolume.leftVol; 00313 *rightBuf++ = myBuffer[i] * stereoVolume.rightVol; 00314 } 00315 for (; numGenerated < length; numGenerated++) { 00316 *leftBuf++ = 0.0f; 00317 *rightBuf++ = 0.0f; 00318 } 00319 return true; 00320 } 00321 00322 bool Partial::shouldReverb() { 00323 if (!isActive()) { 00324 return false; 00325 } 00326 return patchCache->reverb; 00327 } 00328 00329 void Partial::startAbort() { 00330 // This is called when the partial manager needs to terminate partials for re-use by a new Poly. 00331 tva->startAbort(); 00332 } 00333 00334 void Partial::startDecayAll() { 00335 tva->startDecay(); 00336 tvp->startDecay(); 00337 tvf->startDecay(); 00338 } 00339 00340 }