[Scummvm-cvs-logs] scummvm master -> 42b8f3db4d3fbddb2e59db761b8b1f488e279071
bluegr
bluegr at gmail.com
Thu Nov 15 13:32:22 CET 2012
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
3233edf9b8 MT32: Update the MT32 emulator to the latest munt revision
42b8f3db4d DREAMWEB: Add an extra line showing the available terminal commands
Commit: 3233edf9b843f16018b6142b344b08dedae74d67
https://github.com/scummvm/scummvm/commit/3233edf9b843f16018b6142b344b08dedae74d67
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2012-11-15T04:30:41-08:00
Commit Message:
MT32: Update the MT32 emulator to the latest munt revision
Previous munt revision was 189f607c88e7404ad99abcf4b90f23b103003ed1
(Feb 09, 2012).
Current munt revision is f969d2081d41b669c1bfebd0026b5419c09517ae
(Nov 15, 2012)
Changed paths:
audio/softsynth/mt32/AReverbModel.cpp
audio/softsynth/mt32/DelayReverb.cpp
audio/softsynth/mt32/FreeverbModel.cpp
audio/softsynth/mt32/LA32Ramp.cpp
audio/softsynth/mt32/Part.cpp
audio/softsynth/mt32/Partial.cpp
audio/softsynth/mt32/PartialManager.cpp
audio/softsynth/mt32/Poly.cpp
audio/softsynth/mt32/Synth.cpp
audio/softsynth/mt32/Synth.h
audio/softsynth/mt32/TVA.cpp
audio/softsynth/mt32/TVF.cpp
audio/softsynth/mt32/TVP.cpp
audio/softsynth/mt32/Tables.cpp
audio/softsynth/mt32/Tables.h
audio/softsynth/mt32/mmath.h
audio/softsynth/mt32/mt32emu.h
diff --git a/audio/softsynth/mt32/AReverbModel.cpp b/audio/softsynth/mt32/AReverbModel.cpp
index 4ee6c87..151f6c2 100644
--- a/audio/softsynth/mt32/AReverbModel.cpp
+++ b/audio/softsynth/mt32/AReverbModel.cpp
@@ -18,7 +18,7 @@
#include "mt32emu.h"
#include "AReverbModel.h"
-using namespace MT32Emu;
+namespace MT32Emu {
// Default reverb settings for modes 0-2
@@ -235,3 +235,5 @@ void AReverbModel::process(const float *inLeft, const float *inRight, float *out
outRight++;
}
}
+
+}
diff --git a/audio/softsynth/mt32/DelayReverb.cpp b/audio/softsynth/mt32/DelayReverb.cpp
index 89eebf0..bfb0666 100644
--- a/audio/softsynth/mt32/DelayReverb.cpp
+++ b/audio/softsynth/mt32/DelayReverb.cpp
@@ -20,7 +20,7 @@
#include "mt32emu.h"
#include "DelayReverb.h"
-using namespace MT32Emu;
+namespace MT32Emu {
// CONFIRMED: The values below are found via analysis of digital samples. Checked with all time and level combinations.
@@ -148,3 +148,5 @@ bool DelayReverb::isActive() const {
}
return false;
}
+
+}
diff --git a/audio/softsynth/mt32/FreeverbModel.cpp b/audio/softsynth/mt32/FreeverbModel.cpp
index c11fa85..d9bd17e 100644
--- a/audio/softsynth/mt32/FreeverbModel.cpp
+++ b/audio/softsynth/mt32/FreeverbModel.cpp
@@ -20,7 +20,7 @@
#include "freeverb.h"
-using namespace MT32Emu;
+namespace MT32Emu {
FreeverbModel::FreeverbModel(float useScaleTuning, float useFiltVal, float useWet, Bit8u useRoom, float useDamp) {
freeverb = NULL;
@@ -76,3 +76,5 @@ bool FreeverbModel::isActive() const {
// FIXME: Not bothering to do this properly since we'll be replacing Freeverb soon...
return false;
}
+
+}
diff --git a/audio/softsynth/mt32/LA32Ramp.cpp b/audio/softsynth/mt32/LA32Ramp.cpp
index 9f1f01c..4e4d6b4 100644
--- a/audio/softsynth/mt32/LA32Ramp.cpp
+++ b/audio/softsynth/mt32/LA32Ramp.cpp
@@ -79,11 +79,12 @@ LA32Ramp::LA32Ramp() :
void LA32Ramp::startRamp(Bit8u target, Bit8u increment) {
// CONFIRMED: From sample analysis, this appears to be very accurate.
- // FIXME: We could use a table for this in future
if (increment == 0) {
largeIncrement = 0;
} else {
- largeIncrement = (unsigned int)(EXP2F(((increment & 0x7F) + 24) / 8.0f) + 0.125f);
+ // Using integer argument here, no precision loss:
+ // (unsigned int)(EXP2F(((increment & 0x7F) + 24) / 8.0f) + 0.125f)
+ largeIncrement = (unsigned int)(EXP2I(((increment & 0x7F) + 24) << 9) + 0.125f);
}
descending = (increment & 0x80) != 0;
if (descending) {
diff --git a/audio/softsynth/mt32/Part.cpp b/audio/softsynth/mt32/Part.cpp
index 75912f3..88d42db 100644
--- a/audio/softsynth/mt32/Part.cpp
+++ b/audio/softsynth/mt32/Part.cpp
@@ -544,9 +544,12 @@ void Part::allNotesOff() {
// should treat the hold pedal as usual.
for (Common::List<Poly *>::iterator polyIt = activePolys.begin(); polyIt != activePolys.end(); polyIt++) {
Poly *poly = *polyIt;
- // FIXME: This has special handling of key 0 in NoteOff that Mok has not yet confirmed
- // applies to AllNotesOff.
- poly->noteOff(holdpedal);
+ // FIXME: This has special handling of key 0 in NoteOff that Mok has not yet confirmed applies to AllNotesOff.
+ // if (poly->canSustain() || poly->getKey() == 0) {
+ // FIXME: The real devices are found to be ignoring non-sustaining polys while processing AllNotesOff. Need to be confirmed.
+ if (poly->canSustain()) {
+ poly->noteOff(holdpedal);
+ }
}
}
diff --git a/audio/softsynth/mt32/Partial.cpp b/audio/softsynth/mt32/Partial.cpp
index 03bec56..a6d164f 100644
--- a/audio/softsynth/mt32/Partial.cpp
+++ b/audio/softsynth/mt32/Partial.cpp
@@ -22,7 +22,7 @@
#include "mt32emu.h"
#include "mmath.h"
-using namespace MT32Emu;
+namespace MT32Emu {
#ifdef INACCURATE_SMOOTH_PAN
// Mok wanted an option for smoother panning, and we love Mok.
@@ -133,6 +133,25 @@ void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *us
stereoVolume.leftVol = panVal / 7.0f;
stereoVolume.rightVol = 1.0f - stereoVolume.leftVol;
+ // SEMI-CONFIRMED: From sample analysis:
+ // Found that timbres with 3 or 4 partials (i.e. one using two partial pairs) are mixed in two different ways.
+ // Either partial pairs are added or subtracted, it depends on how the partial pairs are allocated.
+ // It seems that partials are grouped into quarters and if the partial pairs are allocated in different quarters the subtraction happens.
+ // Though, this matters little for the majority of timbres, it becomes crucial for timbres which contain several partials that sound very close.
+ // In this case that timbre can sound totally different depending of the way it is mixed up.
+ // Most easily this effect can be displayed with the help of a special timbre consisting of several identical square wave partials (3 or 4).
+ // Say, it is 3-partial timbre. Just play any two notes simultaneously and the polys very probably are mixed differently.
+ // 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.
+ // 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
+ // whole-quarter assignment or after some partials got aborted, even 4-partial timbres can be found sounding differently.
+ // This behaviour is also confirmed with two more special timbres: one with identical sawtooth partials, and one with PCM wave 02.
+ // For my personal taste, this behaviour rather enriches the sounding and should be emulated.
+ // Also, the current partial allocator model probably needs to be refined.
+ if (debugPartialNum & 8) {
+ stereoVolume.leftVol = -stereoVolume.leftVol;
+ stereoVolume.rightVol = -stereoVolume.rightVol;
+ }
+
if (patchCache->PCMPartial) {
pcmNum = patchCache->pcm;
if (synth->controlROMMap->pcmCount > 128) {
@@ -149,7 +168,7 @@ void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *us
}
// CONFIRMED: pulseWidthVal calculation is based on information from Mok
- pulseWidthVal = (poly->getVelocity() - 64) * (patchCache->srcPartial.wg.pulseWidthVeloSensitivity - 7) + synth->tables.pulseWidth100To255[patchCache->srcPartial.wg.pulseWidth];
+ pulseWidthVal = (poly->getVelocity() - 64) * (patchCache->srcPartial.wg.pulseWidthVeloSensitivity - 7) + Tables::getInstance().pulseWidth100To255[patchCache->srcPartial.wg.pulseWidth];
if (pulseWidthVal < 0) {
pulseWidthVal = 0;
} else if (pulseWidthVal > 255) {
@@ -175,6 +194,7 @@ float Partial::getPCMSample(unsigned int position) {
}
unsigned long Partial::generateSamples(float *partialBuf, unsigned long length) {
+ const Tables &tables = Tables::getInstance();
if (!isActive() || alreadyOutputed) {
return 0;
}
@@ -197,6 +217,9 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
deactivate();
break;
}
+
+ Bit16u pitch = tvp->nextPitch();
+
// SEMI-CONFIRMED: From sample analysis:
// (1) Tested with a single partial playing PCM wave 77 with pitchCoarse 36 and no keyfollow, velocity follow, etc.
// This gives results within +/- 2 at the output (before any DAC bitshifting)
@@ -206,10 +229,17 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
// positive amps, so negative still needs to be explored, as well as lower levels.
//
// Also still partially unconfirmed is the behaviour when ramping between levels, as well as the timing.
+
+#if MT32EMU_ACCURATE_WG == 1
float amp = EXP2F((32772 - ampRampVal / 2048) / -2048.0f);
+ float freq = EXP2F(pitch / 4096.0f - 16.0f) * 32000.0f;
+#else
+ static const float ampFactor = EXP2F(32772 / -2048.0f);
+ float amp = EXP2I(ampRampVal >> 10) * ampFactor;
- Bit16u pitch = tvp->nextPitch();
- float freq = synth->tables.pitchToFreq[pitch];
+ static const float freqFactor = EXP2F(-16.0f) * 32000.0f;
+ float freq = EXP2I(pitch) * freqFactor;
+#endif
if (patchCache->PCMPartial) {
// Render PCM waveform
@@ -225,8 +255,14 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
// Linear interpolation
float firstSample = synth->pcmROMData[pcmAddr + intPCMPosition];
- float nextSample = getPCMSample(intPCMPosition + 1);
- sample = firstSample + (nextSample - firstSample) * (pcmPosition - intPCMPosition);
+ // We observe that for partial structures with ring modulation the interpolation is not applied to the slave PCM partial.
+ // It's assumed that the multiplication circuitry intended to perform the interpolation on the slave PCM partial
+ // is borrowed by the ring modulation circuit (or the LA32 chip has a similar lack of resources assigned to each partial pair).
+ if (pair == NULL || mixType == 0 || structurePosition == 0) {
+ sample = firstSample + (getPCMSample(intPCMPosition + 1) - firstSample) * (pcmPosition - intPCMPosition);
+ } else {
+ sample = firstSample;
+ }
float newPCMPosition = pcmPosition + positionDelta;
if (pcmWave->loop) {
@@ -247,8 +283,8 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
// res corresponds to a value set in an LA32 register
Bit8u res = patchCache->srcPartial.tvf.resonance + 1;
- // EXP2F(1.0f - (32 - res) / 4.0f);
- float resAmp = synth->tables.resAmpMax[res];
+ // Using tiny exact table for computation of EXP2F(1.0f - (32 - res) / 4.0f)
+ float resAmp = tables.resAmpMax[res];
// The cutoffModifier may not be supposed to be directly added to the cutoff -
// it may for example need to be multiplied in some way.
@@ -268,7 +304,8 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
#if MT32EMU_ACCURATE_WG == 1
cosineLen *= EXP2F((cutoffVal - 128.0f) / -16.0f); // found from sample analysis
#else
- cosineLen *= synth->tables.cutoffToCosineLen[Bit32u((cutoffVal - 128.0f) * 8.0f)];
+ static const float cosineLenFactor = EXP2F(128.0f / -16.0f);
+ cosineLen *= EXP2I(Bit32u((256.0f - cutoffVal) * 256.0f)) * cosineLenFactor;
#endif
}
@@ -281,7 +318,7 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
float pulseLen = 0.5f;
if (pulseWidthVal > 128) {
- pulseLen += synth->tables.pulseLenFactor[pulseWidthVal - 128];
+ pulseLen += tables.pulseLenFactor[pulseWidthVal - 128];
}
pulseLen *= waveLen;
@@ -303,7 +340,7 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
#if MT32EMU_ACCURATE_WG == 1
resAmp *= sinf(FLOAT_PI * (cutoffVal - 128.0f) / 32.0f);
#else
- resAmp *= synth->tables.sinf10[Bit32u(64 * (cutoffVal - 128.0f))];
+ resAmp *= tables.sinf10[Bit32u(64 * (cutoffVal - 128.0f))];
#endif
}
@@ -314,7 +351,7 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
#if MT32EMU_ACCURATE_WG == 1
sample = -cosf(FLOAT_PI * relWavePos / cosineLen);
#else
- sample = -synth->tables.sinf10[Bit32u(2048.0f * relWavePos / cosineLen) + 1024];
+ sample = -tables.sinf10[Bit32u(2048.0f * relWavePos / cosineLen) + 1024];
#endif
} else
@@ -328,7 +365,7 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
#if MT32EMU_ACCURATE_WG == 1
sample = cosf(FLOAT_PI * (relWavePos - (cosineLen + hLen)) / cosineLen);
#else
- sample = synth->tables.sinf10[Bit32u(2048.0f * (relWavePos - (cosineLen + hLen)) / cosineLen) + 1024];
+ sample = tables.sinf10[Bit32u(2048.0f * (relWavePos - (cosineLen + hLen)) / cosineLen) + 1024];
#endif
} else {
@@ -343,7 +380,8 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
#if MT32EMU_ACCURATE_WG == 1
sample *= EXP2F(-0.125f * (128.0f - cutoffVal));
#else
- sample *= synth->tables.cutoffToFilterAmp[Bit32u(cutoffVal * 8.0f)];
+ static const float cutoffAttenuationFactor = EXP2F(-0.125f * 128.0f);
+ sample *= EXP2I(Bit32u(512.0f * cutoffVal)) * cutoffAttenuationFactor;
#endif
} else {
@@ -363,11 +401,17 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
#if MT32EMU_ACCURATE_WG == 1
resSample *= sinf(FLOAT_PI * relWavePos / cosineLen);
#else
- resSample *= synth->tables.sinf10[Bit32u(2048.0f * relWavePos / cosineLen) & 4095];
+ resSample *= tables.sinf10[Bit32u(2048.0f * relWavePos / cosineLen) & 4095];
#endif
// Resonance sine amp
- float resAmpFade = EXP2F(-synth->tables.resAmpFadeFactor[res >> 2] * (relWavePos / cosineLen)); // seems to be exact
+ float resAmpFadeLog2 = -tables.resAmpFadeFactor[res >> 2] * (relWavePos / cosineLen); // seems to be exact
+#if MT32EMU_ACCURATE_WG == 1
+ float resAmpFade = EXP2F(resAmpFadeLog2);
+#else
+ static const float resAmpFadeFactor = EXP2F(-30.0f);
+ float resAmpFade = (resAmpFadeLog2 < -30.0f) ? 0.0f : EXP2I(Bit32u((30.0f + resAmpFadeLog2) * 4096.0f)) * resAmpFadeFactor;
+#endif
// Now relWavePos set negative to the left from center of any cosine
relWavePos = wavePos;
@@ -388,7 +432,7 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
#if MT32EMU_ACCURATE_WG == 1
resAmpFade *= 0.5f * (1.0f - cosf(FLOAT_PI * relWavePos / (0.5f * cosineLen)));
#else
- resAmpFade *= 0.5f * (1.0f + synth->tables.sinf10[Bit32s(2048.0f * relWavePos / (0.5f * cosineLen)) + 3072]);
+ resAmpFade *= 0.5f * (1.0f + tables.sinf10[Bit32s(2048.0f * relWavePos / (0.5f * cosineLen)) + 3072]);
#endif
}
@@ -400,7 +444,7 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
#if MT32EMU_ACCURATE_WG == 1
sample *= cosf(FLOAT_2PI * wavePos / waveLen);
#else
- sample *= synth->tables.sinf10[(Bit32u(4096.0f * wavePos / waveLen) & 4095) + 1024];
+ sample *= tables.sinf10[(Bit32u(4096.0f * wavePos / waveLen) & 4095) + 1024];
#endif
}
@@ -516,10 +560,9 @@ bool Partial::produceOutput(float *leftBuf, float *rightBuf, unsigned long lengt
}
}
if (numGenerated > pairNumGenerated) {
- if (mixType == 1) {
- mixBuffersRingMix(partialBuf + pairNumGenerated, NULL, numGenerated - pairNumGenerated);
- } else {
- mixBuffersRing(partialBuf + pairNumGenerated, NULL, numGenerated - pairNumGenerated);
+ if (mixType == 2) {
+ numGenerated = pairNumGenerated;
+ deactivate();
}
}
}
@@ -555,3 +598,5 @@ void Partial::startDecayAll() {
tvp->startDecay();
tvf->startDecay();
}
+
+}
diff --git a/audio/softsynth/mt32/PartialManager.cpp b/audio/softsynth/mt32/PartialManager.cpp
index 0a6be82..f8c2dbc 100644
--- a/audio/softsynth/mt32/PartialManager.cpp
+++ b/audio/softsynth/mt32/PartialManager.cpp
@@ -20,7 +20,7 @@
#include "mt32emu.h"
#include "PartialManager.h"
-using namespace MT32Emu;
+namespace MT32Emu {
PartialManager::PartialManager(Synth *useSynth, Part **useParts) {
synth = useSynth;
@@ -248,3 +248,5 @@ const Partial *PartialManager::getPartial(unsigned int partialNum) const {
}
return partialTable[partialNum];
}
+
+}
diff --git a/audio/softsynth/mt32/Poly.cpp b/audio/softsynth/mt32/Poly.cpp
index a2f00db..c45391f 100644
--- a/audio/softsynth/mt32/Poly.cpp
+++ b/audio/softsynth/mt32/Poly.cpp
@@ -58,6 +58,9 @@ bool Poly::noteOff(bool pedalHeld) {
return false;
}
if (pedalHeld) {
+ if (state == POLY_Held) {
+ return false;
+ }
state = POLY_Held;
} else {
startDecay();
diff --git a/audio/softsynth/mt32/Synth.cpp b/audio/softsynth/mt32/Synth.cpp
index 7a1b5c2..d47d954 100644
--- a/audio/softsynth/mt32/Synth.cpp
+++ b/audio/softsynth/mt32/Synth.cpp
@@ -423,7 +423,6 @@ bool Synth::open(SynthProperties &useProp) {
#if MT32EMU_MONITOR_INIT
printDebug("Initialising Constant Tables");
#endif
- tables.init();
#if !MT32EMU_REDUCE_REVERB_MEMORY
for (int i = 0; i < 4; i++) {
reverbModels[i]->open(useProp.sampleRate);
@@ -627,6 +626,11 @@ void Synth::playMsg(Bit32u msg) {
return;
}
playMsgOnPart(part, code, note, velocity);
+
+ // This ensures minimum 1-sample delay between sequential MIDI events
+ // Without this, a sequence of NoteOn and immediately succeeding NoteOff messages is always silent
+ // Technically, it's also impossible to send events through the MIDI interface faster than about each millisecond
+ prerender();
}
void Synth::playMsgOnPart(unsigned char part, unsigned char code, unsigned char note, unsigned char velocity) {
diff --git a/audio/softsynth/mt32/Synth.h b/audio/softsynth/mt32/Synth.h
index ccabce7..a30df62 100644
--- a/audio/softsynth/mt32/Synth.h
+++ b/audio/softsynth/mt32/Synth.h
@@ -321,7 +321,6 @@ private:
Bit32u renderedSampleCount;
- Tables tables;
MemParams mt32ram, mt32default;
diff --git a/audio/softsynth/mt32/TVA.cpp b/audio/softsynth/mt32/TVA.cpp
index f3e3f7b..c581259 100644
--- a/audio/softsynth/mt32/TVA.cpp
+++ b/audio/softsynth/mt32/TVA.cpp
@@ -154,7 +154,7 @@ void TVA::reset(const Part *newPart, const TimbreParam::PartialParam *newPartial
playing = true;
- Tables *tables = &partial->getSynth()->tables;
+ const Tables *tables = &Tables::getInstance();
int key = partial->getPoly()->getKey();
int velocity = partial->getPoly()->getVelocity();
@@ -215,7 +215,7 @@ void TVA::recalcSustain() {
return;
}
// We're sustaining. Recalculate all the values
- Tables *tables = &partial->getSynth()->tables;
+ const Tables *tables = &Tables::getInstance();
int newTarget = calcBasicAmp(tables, partial, system_, partialParam, patchTemp, rhythmTemp, biasAmpSubtraction, veloAmpSubtraction, part->getExpression());
newTarget += partialParam->tva.envLevel[3];
// Since we're in TVA_PHASE_SUSTAIN at this point, we know that target has been reached and an interrupt fired, so we can rely on it being the current amp.
@@ -241,7 +241,7 @@ int TVA::getPhase() const {
}
void TVA::nextPhase() {
- Tables *tables = &partial->getSynth()->tables;
+ const Tables *tables = &Tables::getInstance();
if (phase >= TVA_PHASE_DEAD || !playing) {
partial->getSynth()->printDebug("TVA::nextPhase(): Shouldn't have got here with phase %d, playing=%s", phase, playing ? "true" : "false");
diff --git a/audio/softsynth/mt32/TVF.cpp b/audio/softsynth/mt32/TVF.cpp
index 80b592e..47c4917 100644
--- a/audio/softsynth/mt32/TVF.cpp
+++ b/audio/softsynth/mt32/TVF.cpp
@@ -117,7 +117,7 @@ void TVF::reset(const TimbreParam::PartialParam *newPartialParam, unsigned int b
unsigned int key = partial->getPoly()->getKey();
unsigned int velocity = partial->getPoly()->getVelocity();
- Tables *tables = &partial->getSynth()->tables;
+ const Tables *tables = &Tables::getInstance();
baseCutoff = calcBaseCutoff(newPartialParam, basePitch, key);
#if MT32EMU_MONITOR_TVF >= 1
@@ -179,7 +179,7 @@ void TVF::startDecay() {
}
void TVF::nextPhase() {
- Tables *tables = &partial->getSynth()->tables;
+ const Tables *tables = &Tables::getInstance();
int newPhase = phase + 1;
switch (newPhase) {
diff --git a/audio/softsynth/mt32/TVP.cpp b/audio/softsynth/mt32/TVP.cpp
index 0b339e8..32a6067 100644
--- a/audio/softsynth/mt32/TVP.cpp
+++ b/audio/softsynth/mt32/TVP.cpp
@@ -171,9 +171,14 @@ void TVP::updatePitch() {
if (newPitch < 0) {
newPitch = 0;
}
+
+// Note: Temporary #ifdef until we have proper "quirk" configuration
+// This is about right emulation of MT-32 GEN0 quirk exploited in Colonel's Bequest timbre "Lightning"
+#ifndef MT32EMU_QUIRK_PITCH_ENVELOPE_OVERFLOW_MT32
if (newPitch > 59392) {
newPitch = 59392;
}
+#endif
pitch = (Bit16u)newPitch;
// FIXME: We're doing this here because that's what the CM-32L does - we should probably move this somewhere more appropriate in future.
diff --git a/audio/softsynth/mt32/Tables.cpp b/audio/softsynth/mt32/Tables.cpp
index c9bd40b..b6e6384 100644
--- a/audio/softsynth/mt32/Tables.cpp
+++ b/audio/softsynth/mt32/Tables.cpp
@@ -22,18 +22,14 @@
#include "mt32emu.h"
#include "mmath.h"
-using namespace MT32Emu;
+namespace MT32Emu {
-Tables::Tables() {
- initialised = false;
+const Tables &Tables::getInstance() {
+ static const Tables instance;
+ return instance;
}
-void Tables::init() {
- if (initialised) {
- return;
- }
- initialised = true;
-
+Tables::Tables() {
int lf;
for (lf = 0; lf <= 100; lf++) {
// CONFIRMED:KG: This matches a ROM table found by Mok
@@ -83,19 +79,9 @@ void Tables::init() {
pulseLenFactor[i] = (1.241857812f - pt) * pt; // seems to be 2 ^ (5 / 16) = 1.241857812f
}
- for (int i = 0; i < 65536; i++) {
- // Aka (slightly slower): EXP2F(pitchVal / 4096.0f - 16.0f) * 32000.0f
- pitchToFreq[i] = EXP2F(i / 4096.0f - 1.034215715f);
- }
-
- // found from sample analysis
- for (int i = 0; i < 1024; i++) {
- cutoffToCosineLen[i] = EXP2F(i / -128.0f);
- }
-
- // found from sample analysis
- for (int i = 0; i < 1024; i++) {
- cutoffToFilterAmp[i] = EXP2F(-0.125f * (128.0f - i / 8.0f));
+ // The LA32 chip presumably has such a table inside as the internal computaions seem to be performed using fixed point math with 12-bit fractions
+ for (int i = 0; i < 4096; i++) {
+ exp2[i] = EXP2F(i / 4096.0f);
}
// found from sample analysis
@@ -117,3 +103,5 @@ void Tables::init() {
sinf10[i] = sin(FLOAT_PI * i / 2048.0f);
}
}
+
+}
diff --git a/audio/softsynth/mt32/Tables.h b/audio/softsynth/mt32/Tables.h
index a2b5ff5..a63eaf6 100644
--- a/audio/softsynth/mt32/Tables.h
+++ b/audio/softsynth/mt32/Tables.h
@@ -20,14 +20,21 @@
namespace MT32Emu {
+// Sample rate to use in mixing
+const unsigned int SAMPLE_RATE = 32000;
+
const int MIDDLEC = 60;
class Synth;
class Tables {
- bool initialised;
+private:
+ Tables();
+ Tables(Tables &);
public:
+ static const Tables &getInstance();
+
// Constant LUTs
// CONFIRMED: This is used to convert several parameters to amp-modifying values in the TVA envelope:
@@ -47,16 +54,11 @@ public:
// CONFIRMED:
Bit8u pulseWidth100To255[101];
+ float exp2[4096];
float pulseLenFactor[128];
- float pitchToFreq[65536];
- float cutoffToCosineLen[1024];
- float cutoffToFilterAmp[1024];
float resAmpMax[32];
float resAmpFadeFactor[8];
float sinf10[5120];
-
- Tables();
- void init();
};
}
diff --git a/audio/softsynth/mt32/mmath.h b/audio/softsynth/mt32/mmath.h
index 226d73e..25c79d5 100644
--- a/audio/softsynth/mt32/mmath.h
+++ b/audio/softsynth/mt32/mmath.h
@@ -52,6 +52,10 @@ static inline float EXP2F(float x) {
#endif
}
+static inline float EXP2I(unsigned int i) {
+ return float(1 << (i >> 12)) * Tables::getInstance().exp2[i & 0x0FFF];
+}
+
static inline float EXP10F(float x) {
return exp(FLOAT_LN_10 * x);
}
diff --git a/audio/softsynth/mt32/mt32emu.h b/audio/softsynth/mt32/mt32emu.h
index 091819b..f10bc1f 100644
--- a/audio/softsynth/mt32/mt32emu.h
+++ b/audio/softsynth/mt32/mt32emu.h
@@ -59,9 +59,16 @@
#define MT32EMU_MONITOR_TVA 0
#define MT32EMU_MONITOR_TVF 0
-
-// 0: Use LUTs to speedup WG
-// 1: Use precise float math
+// The WG algorithm involves dozens of transcendent maths, e.g. exponents and trigonometry.
+// Unfortunately, the majority of systems perform such computations inefficiently,
+// standard math libs and FPUs make no optimisations for single precision floats,
+// and use no LUTs to speedup computing internal taylor series. Though, there're rare exceptions,
+// and there's a hope it will become common soon.
+// So, this is the crucial point of speed optimisations. We have now eliminated all the transcendent maths
+// within the critical path and use LUTs instead.
+// Besides, since the LA32 chip is assumed to use similar LUTs inside, the overall emulation accuracy should be better.
+// 0: Use LUTs to speedup WG. Most common setting. You can expect about 50% performance boost.
+// 1: Use precise float math. Use this setting to achieve more accurate wave generator. If your system performs better with this setting, it is really notable. :)
#define MT32EMU_ACCURATE_WG 0
#define MT32EMU_USE_EXTINT 0
Commit: 42b8f3db4d3fbddb2e59db761b8b1f488e279071
https://github.com/scummvm/scummvm/commit/42b8f3db4d3fbddb2e59db761b8b1f488e279071
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2012-11-15T04:30:42-08:00
Commit Message:
DREAMWEB: Add an extra line showing the available terminal commands
This is possible, since the game is freeware now. It is very
helpful when playing the game in order to avoid referring to the
manual. The extra help text is shown when the player uses the
'help' command inside the game terminal.
Also, the list of games where copy protection is skipped has been
reordered alphabetically in the README
Changed paths:
NEWS
README
engines/dreamweb/dreamweb.cpp
engines/dreamweb/dreamweb.h
engines/dreamweb/monitor.cpp
diff --git a/NEWS b/NEWS
index 923844e..0ce1f06 100644
--- a/NEWS
+++ b/NEWS
@@ -15,6 +15,14 @@ For a more comprehensive changelog of the latest experimental code, see:
Now music fades out slowly instead of stopping immediately. Sound
effects are now properly panned, when requested by the game.
+ Dreamweb:
+ - Now that the game is freeware, there is a small extra help text showing
+ the available commands in the in-game terminals when the player uses the
+ 'help' command. Previously, players needed to consult the manual for the
+ available commands. Since this reference to the manual is a form of copy
+ protection, this extra line can be toggled by the ScummVM copy protection
+ command line option.
+
SCUMM:
- Implemented Monkey Island 2 Macintosh's audio driver. Now we properly
support its sample based audio output. The same output is also used for
diff --git a/README b/README
index 2b68876..3f506d3 100644
--- a/README
+++ b/README
@@ -384,21 +384,24 @@ entering any answer. Chances are that it will work.
ScummVM will skip copy protection in the following games:
- * Maniac Mansion
- * Zak McKracken and the Alien Mindbenders
- * Loom (EGA DOS)
- * The Secret of Monkey Island (VGA)
- * Monkey Island 2: LeChuck's Revenge
* Beneath a Steel Sky
-- bypassed with kind permission from Revolution Software.
+ * Dreamweb
+ -- a list of available commands in the in-game terminals is now shown
+ when the player uses the 'help' command
* Inherit the Earth: Quest for the Orb (Floppy version)
-- bypassed with kind permission from Wyrmkeep Entertainment,
since it was bypassed in all CD releases of the game.
+ * Loom (EGA DOS)
+ * Maniac Mansion
+ * Monkey Island 2: LeChuck's Revenge
* Simon the Sorcerer 1 (Floppy version)
* Simon the Sorcerer 2 (Floppy version)
-- bypassed with kind permission from Adventure Soft,
since it was bypassed in all CD releases of the game.
+ * The Secret of Monkey Island (VGA)
* Waxworks
+ * Zak McKracken and the Alien Mindbenders
3.2) Commodore64 games notes:
diff --git a/engines/dreamweb/dreamweb.cpp b/engines/dreamweb/dreamweb.cpp
index 5f5d627..cc9c9e6 100644
--- a/engines/dreamweb/dreamweb.cpp
+++ b/engines/dreamweb/dreamweb.cpp
@@ -374,6 +374,7 @@ Common::Error DreamWebEngine::run() {
ConfMan.registerDefault("bright_palette", true);
_hasSpeech = Common::File::exists(_speechDirName + "/r01c0000.raw") && !ConfMan.getBool("speech_mute");
_brightPalette = ConfMan.getBool("bright_palette");
+ _copyProtection = ConfMan.getBool("copy_protection");
_timer->installTimerProc(vSyncInterrupt, 1000000 / 70, this, "dreamwebVSync");
dreamweb();
diff --git a/engines/dreamweb/dreamweb.h b/engines/dreamweb/dreamweb.h
index a4597b1..8cb903a 100644
--- a/engines/dreamweb/dreamweb.h
+++ b/engines/dreamweb/dreamweb.h
@@ -316,6 +316,7 @@ public:
uint16 _charShift;
uint8 _kerning;
bool _brightPalette;
+ bool _copyProtection;
uint8 _roomLoaded;
uint8 _didZoom;
uint16 _lineSpacing;
diff --git a/engines/dreamweb/monitor.cpp b/engines/dreamweb/monitor.cpp
index 1886a80..83563c8 100644
--- a/engines/dreamweb/monitor.cpp
+++ b/engines/dreamweb/monitor.cpp
@@ -149,6 +149,13 @@ bool DreamWebEngine::execCommand() {
return true;
case 1:
monMessage(6);
+ // An extra addition in ScummVM: available commands.
+ // Since the reference to the game manual is a form of copy protection,
+ // this extra text is wrapped around the common copy protection check,
+ // to keep it faithful to the original, if requested.
+ if (!_copyProtection) {
+ monPrint("VALID COMMANDS ARE EXIT, HELP, LIST, READ, LOGON, KEYS");
+ }
break;
case 2:
dirCom();
More information about the Scummvm-git-logs
mailing list