aboutsummaryrefslogtreecommitdiff
path: root/audio/softsynth/mt32
diff options
context:
space:
mode:
Diffstat (limited to 'audio/softsynth/mt32')
-rw-r--r--audio/softsynth/mt32/AReverbModel.cpp16
-rw-r--r--audio/softsynth/mt32/AReverbModel.h2
-rw-r--r--audio/softsynth/mt32/BReverbModel.cpp4
-rw-r--r--audio/softsynth/mt32/BReverbModel.h2
-rw-r--r--audio/softsynth/mt32/DelayReverb.cpp34
-rw-r--r--audio/softsynth/mt32/DelayReverb.h5
-rw-r--r--audio/softsynth/mt32/FreeverbModel.cpp4
-rw-r--r--audio/softsynth/mt32/FreeverbModel.h2
-rw-r--r--audio/softsynth/mt32/Part.cpp7
-rw-r--r--audio/softsynth/mt32/Partial.cpp9
-rw-r--r--audio/softsynth/mt32/ROMInfo.cpp112
-rw-r--r--audio/softsynth/mt32/ROMInfo.h77
-rw-r--r--audio/softsynth/mt32/Synth.cpp209
-rw-r--r--audio/softsynth/mt32/Synth.h122
-rw-r--r--audio/softsynth/mt32/TVA.cpp6
-rw-r--r--audio/softsynth/mt32/TVP.cpp5
-rw-r--r--audio/softsynth/mt32/Tables.h4
-rw-r--r--audio/softsynth/mt32/module.mk1
-rw-r--r--audio/softsynth/mt32/mt32emu.h3
19 files changed, 388 insertions, 236 deletions
diff --git a/audio/softsynth/mt32/AReverbModel.cpp b/audio/softsynth/mt32/AReverbModel.cpp
index ec24394e71..595b286a31 100644
--- a/audio/softsynth/mt32/AReverbModel.cpp
+++ b/audio/softsynth/mt32/AReverbModel.cpp
@@ -48,7 +48,7 @@ static const Bit32u MODE_0_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98};
-static const Bit32u MODE_0_LEVELS[] = {0, 10*3, 10*5, 10*7, 11*9, 11*12, 11*15, 13*15};
+static const Bit32u MODE_0_LEVELS[] = {10*1, 10*3, 10*5, 10*7, 11*9, 11*12, 11*15, 13*15};
static const Bit32u MODE_0_LPF_AMP = 6;
static const Bit32u MODE_1_ALLPASSES[] = {1324, 809, 176};
@@ -60,7 +60,7 @@ static const Bit32u MODE_1_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0x28, 0x48, 0x60, 0x70, 0x78, 0x80, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98,
0x28, 0x48, 0x60, 0x78, 0x80, 0x88, 0x90, 0x98};
-static const Bit32u MODE_1_LEVELS[] = {0, 10*3, 11*5, 11*7, 11*9, 11*12, 11*15, 14*15};
+static const Bit32u MODE_1_LEVELS[] = {10*1, 10*3, 11*5, 11*7, 11*9, 11*12, 11*15, 14*15};
static const Bit32u MODE_1_LPF_AMP = 6;
static const Bit32u MODE_2_ALLPASSES[] = {969, 644, 157};
@@ -72,7 +72,7 @@ static const Bit32u MODE_2_COMB_FEEDBACK[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00
0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0,
0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0,
0x30, 0x58, 0x78, 0x88, 0xA0, 0xB8, 0xC0, 0xD0};
-static const Bit32u MODE_2_LEVELS[] = {0, 10*3, 11*5, 11*7, 11*9, 11*12, 12*15, 14*15};
+static const Bit32u MODE_2_LEVELS[] = {10*1, 10*3, 11*5, 11*7, 11*9, 11*12, 12*15, 14*15};
static const Bit32u MODE_2_LPF_AMP = 8;
static const AReverbSettings REVERB_MODE_0_SETTINGS = {MODE_0_ALLPASSES, MODE_0_COMBS, MODE_0_OUTL, MODE_0_OUTR, MODE_0_COMB_FACTOR, MODE_0_COMB_FEEDBACK, MODE_0_LEVELS, MODE_0_LPF_AMP};
@@ -165,9 +165,7 @@ AReverbModel::~AReverbModel() {
close();
}
-void AReverbModel::open(unsigned int /*sampleRate*/) {
- // FIXME: filter sizes must be multiplied by sample rate to 32000Hz ratio
- // IIR filter values depend on sample rate as well
+void AReverbModel::open() {
allpasses = new AllpassFilter*[NUM_ALLPASSES];
for (Bit32u i = 0; i < NUM_ALLPASSES; i++) {
allpasses[i] = new AllpassFilter(currentSettings.allpassSizes[i]);
@@ -218,10 +216,12 @@ void AReverbModel::setParameters(Bit8u time, Bit8u level) {
// FIXME: wetLevel definitely needs ramping when changed
// Although, most games don't set reverb level during MIDI playback
if (combs == NULL) return;
+ level &= 7;
+ time &= 7;
for (Bit32u i = 0; i < NUM_COMBS; i++) {
- combs[i]->setFeedbackFactor(currentSettings.decayTimes[(i << 3) + (time & 7)] / 256.0f);
+ combs[i]->setFeedbackFactor(currentSettings.decayTimes[(i << 3) + time] / 256.0f);
}
- wetLevel = 0.5f * lpfAmp * currentSettings.wetLevels[(level & 7)] / 256.0f;
+ wetLevel = (level == 0 && time == 0) ? 0.0f : 0.5f * lpfAmp * currentSettings.wetLevels[level] / 256.0f;
}
bool AReverbModel::isActive() const {
diff --git a/audio/softsynth/mt32/AReverbModel.h b/audio/softsynth/mt32/AReverbModel.h
index d70e9ee14f..be1ca4916b 100644
--- a/audio/softsynth/mt32/AReverbModel.h
+++ b/audio/softsynth/mt32/AReverbModel.h
@@ -75,7 +75,7 @@ class AReverbModel : public ReverbModel {
public:
AReverbModel(const ReverbMode mode);
~AReverbModel();
- void open(unsigned int sampleRate);
+ void open();
void close();
void setParameters(Bit8u time, Bit8u level);
void process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples);
diff --git a/audio/softsynth/mt32/BReverbModel.cpp b/audio/softsynth/mt32/BReverbModel.cpp
index b5f4467c20..2570424187 100644
--- a/audio/softsynth/mt32/BReverbModel.cpp
+++ b/audio/softsynth/mt32/BReverbModel.cpp
@@ -241,9 +241,7 @@ BReverbModel::~BReverbModel() {
close();
}
-void BReverbModel::open(unsigned int /*sampleRate*/) {
- // FIXME: filter sizes must be multiplied by sample rate to 32000Hz ratio
- // IIR filter values depend on sample rate as well
+void BReverbModel::open() {
if (currentSettings.numberOfAllpasses > 0) {
allpasses = new AllpassFilter*[currentSettings.numberOfAllpasses];
for (Bit32u i = 0; i < currentSettings.numberOfAllpasses; i++) {
diff --git a/audio/softsynth/mt32/BReverbModel.h b/audio/softsynth/mt32/BReverbModel.h
index 7096ae04ae..f728d1a99c 100644
--- a/audio/softsynth/mt32/BReverbModel.h
+++ b/audio/softsynth/mt32/BReverbModel.h
@@ -100,7 +100,7 @@ class BReverbModel : public ReverbModel {
public:
BReverbModel(const ReverbMode mode);
~BReverbModel();
- void open(unsigned int sampleRate);
+ void open();
void close();
void setParameters(Bit8u time, Bit8u level);
void process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples);
diff --git a/audio/softsynth/mt32/DelayReverb.cpp b/audio/softsynth/mt32/DelayReverb.cpp
index 77521b4a01..bf925f8419 100644
--- a/audio/softsynth/mt32/DelayReverb.cpp
+++ b/audio/softsynth/mt32/DelayReverb.cpp
@@ -45,9 +45,10 @@ static const Bit32u REVERB_FEEDBACK67 = 0x60;
static const Bit32u REVERB_FEEDBACK = 0x68;
static const float LPF_VALUE = 0x68 / 256.0f;
+static const Bit32u BUFFER_SIZE = 16384;
+
DelayReverb::DelayReverb() {
buf = NULL;
- sampleRate = 0;
setParameters(0, 0);
}
@@ -55,27 +56,22 @@ DelayReverb::~DelayReverb() {
delete[] buf;
}
-void DelayReverb::open(unsigned int newSampleRate) {
- if (newSampleRate != sampleRate || buf == NULL) {
- sampleRate = newSampleRate;
-
+void DelayReverb::open() {
+ if (buf == NULL) {
delete[] buf;
- // If we ever need a speedup, set bufSize to EXP2F(ceil(log2(bufSize))) and use & instead of % to find buf indexes
- bufSize = 16384 * sampleRate / 32000;
- buf = new float[bufSize];
+ buf = new float[BUFFER_SIZE];
recalcParameters();
// mute buffer
bufIx = 0;
if (buf != NULL) {
- for (unsigned int i = 0; i < bufSize; i++) {
+ for (unsigned int i = 0; i < BUFFER_SIZE; i++) {
buf[i] = 0.0f;
}
}
}
- // FIXME: IIR filter value depends on sample rate as well
}
void DelayReverb::close() {
@@ -92,11 +88,11 @@ void DelayReverb::setParameters(Bit8u newTime, Bit8u newLevel) {
void DelayReverb::recalcParameters() {
// Number of samples between impulse and eventual appearance on the left channel
- delayLeft = REVERB_TIMINGS[time][0] * sampleRate / 32000;
+ delayLeft = REVERB_TIMINGS[time][0];
// Number of samples between impulse and eventual appearance on the right channel
- delayRight = REVERB_TIMINGS[time][1] * sampleRate / 32000;
+ delayRight = REVERB_TIMINGS[time][1];
// Number of samples between a response and that response feeding back/echoing
- delayFeedback = REVERB_TIMINGS[time][2] * sampleRate / 32000;
+ delayFeedback = REVERB_TIMINGS[time][2];
if (level < 3 || time < 6) {
feedback = REVERB_FEEDBACK / 256.0f;
@@ -113,10 +109,10 @@ void DelayReverb::process(const float *inLeft, const float *inRight, float *outL
for (unsigned int sampleIx = 0; sampleIx < numSamples; sampleIx++) {
// The ring buffer write index moves backwards; reads are all done with positive offsets.
- Bit32u bufIxPrev = (bufIx + 1) % bufSize;
- Bit32u bufIxLeft = (bufIx + delayLeft) % bufSize;
- Bit32u bufIxRight = (bufIx + delayRight) % bufSize;
- Bit32u bufIxFeedback = (bufIx + delayFeedback) % bufSize;
+ Bit32u bufIxPrev = (bufIx + 1) % BUFFER_SIZE;
+ Bit32u bufIxLeft = (bufIx + delayLeft) % BUFFER_SIZE;
+ Bit32u bufIxRight = (bufIx + delayRight) % BUFFER_SIZE;
+ Bit32u bufIxFeedback = (bufIx + delayFeedback) % BUFFER_SIZE;
// Attenuated input samples and feedback response are directly added to the current ring buffer location
float lpfIn = amp * (inLeft[sampleIx] + inRight[sampleIx]) + feedback * buf[bufIxFeedback];
@@ -127,7 +123,7 @@ void DelayReverb::process(const float *inLeft, const float *inRight, float *outL
outLeft[sampleIx] = buf[bufIxLeft];
outRight[sampleIx] = buf[bufIxRight];
- bufIx = (bufSize + bufIx - 1) % bufSize;
+ bufIx = (BUFFER_SIZE + bufIx - 1) % BUFFER_SIZE;
}
}
@@ -136,7 +132,7 @@ bool DelayReverb::isActive() const {
float *b = buf;
float max = 0.001f;
- for (Bit32u i = 0; i < bufSize; i++) {
+ for (Bit32u i = 0; i < BUFFER_SIZE; i++) {
if ((*b < -max) || (*b > max)) return true;
b++;
}
diff --git a/audio/softsynth/mt32/DelayReverb.h b/audio/softsynth/mt32/DelayReverb.h
index e967ddc49c..1abb49f128 100644
--- a/audio/softsynth/mt32/DelayReverb.h
+++ b/audio/softsynth/mt32/DelayReverb.h
@@ -25,10 +25,7 @@ private:
Bit8u time;
Bit8u level;
- unsigned int sampleRate;
- Bit32u bufSize;
Bit32u bufIx;
-
float *buf;
Bit32u delayLeft;
@@ -43,7 +40,7 @@ private:
public:
DelayReverb();
~DelayReverb();
- void open(unsigned int sampleRate);
+ void open();
void close();
void setParameters(Bit8u time, Bit8u level);
void process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples);
diff --git a/audio/softsynth/mt32/FreeverbModel.cpp b/audio/softsynth/mt32/FreeverbModel.cpp
index d9bd17e62e..2ed302fddc 100644
--- a/audio/softsynth/mt32/FreeverbModel.cpp
+++ b/audio/softsynth/mt32/FreeverbModel.cpp
@@ -35,9 +35,7 @@ FreeverbModel::~FreeverbModel() {
delete freeverb;
}
-void FreeverbModel::open(unsigned int /*sampleRate*/) {
- // FIXME: scaleTuning must be multiplied by sample rate to 32000Hz ratio
- // IIR filter values depend on sample rate as well
+void FreeverbModel::open() {
if (freeverb == NULL) {
freeverb = new revmodel(scaleTuning);
}
diff --git a/audio/softsynth/mt32/FreeverbModel.h b/audio/softsynth/mt32/FreeverbModel.h
index 925b2dbf96..bf1102b14a 100644
--- a/audio/softsynth/mt32/FreeverbModel.h
+++ b/audio/softsynth/mt32/FreeverbModel.h
@@ -32,7 +32,7 @@ class FreeverbModel : public ReverbModel {
public:
FreeverbModel(float useScaleTuning, float useFiltVal, float useWet, Bit8u useRoom, float useDamp);
~FreeverbModel();
- void open(unsigned int sampleRate);
+ void open();
void close();
void setParameters(Bit8u time, Bit8u level);
void process(const float *inLeft, const float *inRight, float *outLeft, float *outRight, unsigned long numSamples);
diff --git a/audio/softsynth/mt32/Part.cpp b/audio/softsynth/mt32/Part.cpp
index 88d42dbbd4..852319be70 100644
--- a/audio/softsynth/mt32/Part.cpp
+++ b/audio/softsynth/mt32/Part.cpp
@@ -209,6 +209,7 @@ void RhythmPart::setTimbre(TimbreParam * /*timbre*/) {
void Part::setTimbre(TimbreParam *timbre) {
*timbreTemp = *timbre;
+ synth->newTimbreSet(partNum, timbre->common.name);
}
unsigned int RhythmPart::getAbsTimbreNum() const {
@@ -537,6 +538,8 @@ void Part::playPoly(const PatchCache cache[4], const MemParams::RhythmTemp *rhyt
#if MT32EMU_MONITOR_PARTIALS > 1
synth->printPartialUsage();
#endif
+ synth->partStateChanged(partNum, true);
+ synth->polyStateChanged(partNum);
}
void Part::allNotesOff() {
@@ -619,6 +622,10 @@ void Part::partialDeactivated(Poly *poly) {
if (!poly->isActive()) {
activePolys.remove(poly);
freePolys.push_front(poly);
+ synth->polyStateChanged(partNum);
+ }
+ if (activePartialCount == 0) {
+ synth->partStateChanged(partNum, false);
}
}
diff --git a/audio/softsynth/mt32/Partial.cpp b/audio/softsynth/mt32/Partial.cpp
index a6d164f218..58878a3513 100644
--- a/audio/softsynth/mt32/Partial.cpp
+++ b/audio/softsynth/mt32/Partial.cpp
@@ -85,6 +85,7 @@ void Partial::deactivate() {
pair->pair = NULL;
}
}
+ synth->partialStateChanged(this, tva->getPhase(), TVA_PHASE_DEAD);
#if MT32EMU_MONITOR_PARTIALS > 2
synth->printDebug("[+%lu] [Partial %d] Deactivated", sampleNum, debugPartialNum);
synth->printPartialUsage(sampleNum);
@@ -232,12 +233,12 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
#if MT32EMU_ACCURATE_WG == 1
float amp = EXP2F((32772 - ampRampVal / 2048) / -2048.0f);
- float freq = EXP2F(pitch / 4096.0f - 16.0f) * 32000.0f;
+ float freq = EXP2F(pitch / 4096.0f - 16.0f) * SAMPLE_RATE;
#else
static const float ampFactor = EXP2F(32772 / -2048.0f);
float amp = EXP2I(ampRampVal >> 10) * ampFactor;
- static const float freqFactor = EXP2F(-16.0f) * 32000.0f;
+ static const float freqFactor = EXP2F(-16.0f) * SAMPLE_RATE;
float freq = EXP2I(pitch) * freqFactor;
#endif
@@ -251,7 +252,7 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
break;
}
Bit32u pcmAddr = pcmWave->addr;
- float positionDelta = freq * 2048.0f / synth->myProp.sampleRate;
+ float positionDelta = freq * 2048.0f / SAMPLE_RATE;
// Linear interpolation
float firstSample = synth->pcmROMData[pcmAddr + intPCMPosition];
@@ -296,7 +297,7 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length)
}
// Wave length in samples
- float waveLen = synth->myProp.sampleRate / freq;
+ float waveLen = SAMPLE_RATE / freq;
// Init cosineLen
float cosineLen = 0.5f * waveLen;
diff --git a/audio/softsynth/mt32/ROMInfo.cpp b/audio/softsynth/mt32/ROMInfo.cpp
new file mode 100644
index 0000000000..5735409655
--- /dev/null
+++ b/audio/softsynth/mt32/ROMInfo.cpp
@@ -0,0 +1,112 @@
+/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
+ * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//#include <cstring>
+#include "ROMInfo.h"
+
+namespace MT32Emu {
+
+// Known ROMs
+static const ROMInfo CTRL_MT32_V1_04 = {65536, "5a5cb5a77d7d55ee69657c2f870416daed52dea7", ROMInfo::Control, "ctrl_mt32_1_04", "MT-32 Control v1.04", ROMInfo::Full, NULL, NULL};
+static const ROMInfo CTRL_MT32_V1_05 = {65536, "e17a3a6d265bf1fa150312061134293d2b58288c", ROMInfo::Control, "ctrl_mt32_1_05", "MT-32 Control v1.05", ROMInfo::Full, NULL, NULL};
+static const ROMInfo CTRL_MT32_V1_06 = {65536, "a553481f4e2794c10cfe597fef154eef0d8257de", ROMInfo::Control, "ctrl_mt32_1_06", "MT-32 Control v1.06", ROMInfo::Full, NULL, NULL};
+static const ROMInfo CTRL_MT32_V1_07 = {65536, "b083518fffb7f66b03c23b7eb4f868e62dc5a987", ROMInfo::Control, "ctrl_mt32_1_07", "MT-32 Control v1.07", ROMInfo::Full, NULL, NULL};
+static const ROMInfo CTRL_MT32_BLUER = {65536, "7b8c2a5ddb42fd0732e2f22b3340dcf5360edf92", ROMInfo::Control, "ctrl_mt32_bluer", "MT-32 Control BlueRidge", ROMInfo::Full, NULL, NULL};
+
+static const ROMInfo CTRL_CM32L_V1_00 = {65536, "73683d585cd6948cc19547942ca0e14a0319456d", ROMInfo::Control, "ctrl_cm32l_1_00", "CM-32L/LAPC-I Control v1.00", ROMInfo::Full, NULL, NULL};
+static const ROMInfo CTRL_CM32L_V1_02 = {65536, "a439fbb390da38cada95a7cbb1d6ca199cd66ef8", ROMInfo::Control, "ctrl_cm32l_1_02", "CM-32L/LAPC-I Control v1.02", ROMInfo::Full, NULL, NULL};
+
+static const ROMInfo PCM_MT32 = {524288, "f6b1eebc4b2d200ec6d3d21d51325d5b48c60252", ROMInfo::PCM, "pcm_mt32", "MT-32 PCM ROM", ROMInfo::Full, NULL, NULL};
+static const ROMInfo PCM_CM32L = {1048576, "289cc298ad532b702461bfc738009d9ebe8025ea", ROMInfo::PCM, "pcm_cm32l", "CM-32L/CM-64/LAPC-I PCM ROM", ROMInfo::Full, NULL, NULL};
+
+static const ROMInfo * const ROM_INFOS[] = {
+ &CTRL_MT32_V1_04,
+ &CTRL_MT32_V1_05,
+ &CTRL_MT32_V1_06,
+ &CTRL_MT32_V1_07,
+ &CTRL_MT32_BLUER,
+ &CTRL_CM32L_V1_00,
+ &CTRL_CM32L_V1_02,
+ &PCM_MT32,
+ &PCM_CM32L,
+ NULL};
+
+const ROMInfo* ROMInfo::getROMInfo(Common::File *file) {
+ size_t fileSize = file->size();
+ // We haven't added the SHA1 checksum code in ScummVM, as the file size
+ // suffices for our needs for now.
+ //const char *fileDigest = file->getSHA1();
+ for (int i = 0; ROM_INFOS[i] != NULL; i++) {
+ const ROMInfo *romInfo = ROM_INFOS[i];
+ if (fileSize == romInfo->fileSize /*&& !strcmp(fileDigest, romInfo->sha1Digest)*/) {
+ return romInfo;
+ }
+ }
+ return NULL;
+}
+
+void ROMInfo::freeROMInfo(const ROMInfo *romInfo) {
+ (void) romInfo;
+}
+
+static int getROMCount() {
+ int count;
+ for(count = 0; ROM_INFOS[count] != NULL; count++) {
+ }
+ return count;
+}
+
+const ROMInfo** ROMInfo::getROMInfoList(unsigned int types, unsigned int pairTypes) {
+ const ROMInfo **romInfoList = new const ROMInfo*[getROMCount() + 1];
+ const ROMInfo **currentROMInList = romInfoList;
+ for(int i = 0; ROM_INFOS[i] != NULL; i++) {
+ const ROMInfo *romInfo = ROM_INFOS[i];
+ if ((types & (1 << romInfo->type)) && (pairTypes & (1 << romInfo->pairType))) {
+ *currentROMInList++ = romInfo;
+ }
+ }
+ *currentROMInList = NULL;
+ return romInfoList;
+}
+
+void ROMInfo::freeROMInfoList(const ROMInfo **romInfoList) {
+ delete[] romInfoList;
+}
+
+const ROMImage* ROMImage::makeROMImage(Common::File *file) {
+ ROMImage *romImage = new ROMImage;
+ romImage->file = file;
+ romImage->romInfo = ROMInfo::getROMInfo(romImage->file);
+ return romImage;
+}
+
+void ROMImage::freeROMImage(const ROMImage *romImage) {
+ ROMInfo::freeROMInfo(romImage->romInfo);
+ delete (romImage->file);
+ delete romImage;
+}
+
+
+Common::File* ROMImage::getFile() const {
+ return file;
+}
+
+const ROMInfo* ROMImage::getROMInfo() const {
+ return romInfo;
+}
+
+}
diff --git a/audio/softsynth/mt32/ROMInfo.h b/audio/softsynth/mt32/ROMInfo.h
new file mode 100644
index 0000000000..2ffd2b72c6
--- /dev/null
+++ b/audio/softsynth/mt32/ROMInfo.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
+ * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MT32EMU_ROMINFO_H
+#define MT32EMU_ROMINFO_H
+
+//#include <cstddef>
+#include "common/file.h"
+
+namespace MT32Emu {
+
+// Defines vital info about ROM file to be used by synth and applications
+
+struct ROMInfo {
+public:
+ size_t fileSize;
+ const char *sha1Digest;
+ enum Type {PCM, Control, Reverb} type;
+ const char *shortName;
+ const char *description;
+ enum PairType {Full, FirstHalf, SecondHalf, Mux0, Mux1} pairType;
+ ROMInfo *pairROMInfo;
+ void *controlROMInfo;
+
+ // Returns a ROMInfo struct by inspecting the size and the SHA1 hash
+ static const ROMInfo* getROMInfo(Common::File *file);
+
+ // Currently no-op
+ static void freeROMInfo(const ROMInfo *romInfo);
+
+ // Allows retrieving a NULL-terminated list of ROMInfos for a range of types and pairTypes
+ // (specified by bitmasks)
+ // Useful for GUI/console app to output information on what ROMs it supports
+ static const ROMInfo** getROMInfoList(unsigned int types, unsigned int pairTypes);
+
+ // Frees the list of ROMInfos given
+ static void freeROMInfoList(const ROMInfo **romInfos);
+};
+
+// Synth::open() is to require a full control ROMImage and a full PCM ROMImage to work
+
+class ROMImage {
+private:
+ Common::File *file;
+ const ROMInfo *romInfo;
+
+public:
+
+ // Creates a ROMImage object given a ROMInfo and a File. Keeps a reference
+ // to the File and ROMInfo given, which must be freed separately by the user
+ // after the ROMImage is freed
+ static const ROMImage* makeROMImage(Common::File *file);
+
+ // Must only be done after all Synths using the ROMImage are deleted
+ static void freeROMImage(const ROMImage *romImage);
+
+ Common::File *getFile() const;
+ const ROMInfo *getROMInfo() const;
+};
+
+}
+
+#endif
diff --git a/audio/softsynth/mt32/Synth.cpp b/audio/softsynth/mt32/Synth.cpp
index 9b5518b207..7f4ba44999 100644
--- a/audio/softsynth/mt32/Synth.cpp
+++ b/audio/softsynth/mt32/Synth.cpp
@@ -142,11 +142,19 @@ Bit8u Synth::calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum) {
return checksum;
}
-Synth::Synth() {
+Synth::Synth(ReportHandler *useReportHandler) {
isOpen = false;
reverbEnabled = true;
reverbOverridden = false;
+ if (useReportHandler == NULL) {
+ reportHandler = new ReportHandler;
+ isDefaultReportHandler = true;
+ } else {
+ reportHandler = useReportHandler;
+ isDefaultReportHandler = false;
+ }
+
#if MT32EMU_USE_REVERBMODEL == 1
reverbModels[REVERB_MODE_ROOM] = new AReverbModel(REVERB_MODE_ROOM);
reverbModels[REVERB_MODE_HALL] = new AReverbModel(REVERB_MODE_HALL);
@@ -178,31 +186,49 @@ Synth::~Synth() {
for (int i = 0; i < 4; i++) {
delete reverbModels[i];
}
+ if (isDefaultReportHandler) {
+ delete reportHandler;
+ }
}
-int Synth::report(ReportType type, const void *data) {
- if (myProp.report != NULL) {
- return myProp.report(myProp.userData, type, data);
+void ReportHandler::showLCDMessage(const char *data) {
+ printf("WRITE-LCD: %s", data);
+ printf("\n");
+}
+
+void ReportHandler::printDebug(const char *fmt, va_list list) {
+ vprintf(fmt, list);
+ printf("\n");
+}
+
+void Synth::partStateChanged(int partNum, bool isPartActive) {
+ reportHandler->onPartStateChanged(partNum, isPartActive);
+}
+
+void Synth::polyStateChanged(int partNum) {
+ reportHandler->onPolyStateChanged(partNum);
+}
+
+void Synth::partialStateChanged(const Partial * const partial, int oldPartialPhase, int newPartialPhase) {
+ for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
+ if (getPartial(i) == partial) {
+ reportHandler->onPartialStateChanged(i, oldPartialPhase, newPartialPhase);
+ break;
+ }
}
- return 0;
}
-unsigned int Synth::getSampleRate() const {
- return myProp.sampleRate;
+void Synth::newTimbreSet(int partNum, char patchName[]) {
+ reportHandler->onProgramChanged(partNum, patchName);
}
void Synth::printDebug(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
- if (myProp.printDebug != NULL) {
- myProp.printDebug(myProp.userData, fmt, ap);
- } else {
#if MT32EMU_DEBUG_SAMPLESTAMPS > 0
- printf("[%u] ", renderedSampleCount);
+ reportHandler->printDebug("[%u] ", renderedSampleCount);
#endif
- vprintf(fmt, ap);
- printf("\n");
- }
+ reportHandler->printDebug(fmt, ap);
va_end(ap);
}
@@ -252,80 +278,60 @@ void Synth::setReverbOutputGain(float newReverbOutputGain) {
reverbOutputGain = newReverbOutputGain;
}
-Common::File *Synth::openFile(const char *filename) {
- if (myProp.openFile != NULL) {
- return myProp.openFile(myProp.userData, filename);
- }
- char pathBuf[2048];
- if (myProp.baseDir != NULL) {
- strcpy(&pathBuf[0], myProp.baseDir);
- strcat(&pathBuf[0], filename);
- filename = pathBuf;
- }
- Common::File *file = new Common::File();
- if (!file->open(filename)) {
- delete file;
- return NULL;
- }
- return file;
-}
-
-void Synth::closeFile(Common::File *file) {
- if (myProp.closeFile != NULL) {
- myProp.closeFile(myProp.userData, file);
- } else {
- file->close();
- delete file;
- }
-}
-
-LoadResult Synth::loadControlROM(const char *filename) {
- Common::File *file = openFile(filename); // ROM File
- if (file == NULL) {
- return LoadResult_NotFound;
- }
- size_t fileSize = file->size();
- if (fileSize != CONTROL_ROM_SIZE) {
- printDebug("Control ROM file %s size mismatch: %i", filename, fileSize);
+bool Synth::loadControlROM(const ROMImage &controlROMImage) {
+ if (&controlROMImage == NULL) return false;
+ Common::File *file = controlROMImage.getFile();
+ const ROMInfo *controlROMInfo = controlROMImage.getROMInfo();
+ if ((controlROMInfo == NULL)
+ || (controlROMInfo->type != ROMInfo::Control)
+ || (controlROMInfo->pairType != ROMInfo::Full)) {
+ return false;
}
+#if MT32EMU_MONITOR_INIT
+ printDebug("Found Control ROM: %s, %s", controlROMInfo->shortName, controlROMInfo->description);
+#endif
file->read(controlROMData, CONTROL_ROM_SIZE);
- if (file->err()) {
- closeFile(file);
- return LoadResult_Unreadable;
- }
- closeFile(file);
// Control ROM successfully loaded, now check whether it's a known type
controlROMMap = NULL;
for (unsigned int i = 0; i < sizeof(ControlROMMaps) / sizeof(ControlROMMaps[0]); i++) {
if (memcmp(&controlROMData[ControlROMMaps[i].idPos], ControlROMMaps[i].idBytes, ControlROMMaps[i].idLen) == 0) {
controlROMMap = &ControlROMMaps[i];
- return LoadResult_OK;
+ return true;
}
}
- printDebug("%s does not match a known control ROM type", filename);
- return LoadResult_Invalid;
+#if MT32EMU_MONITOR_INIT
+ printDebug("Control ROM failed to load");
+#endif
+ return false;
}
-LoadResult Synth::loadPCMROM(const char *filename) {
- Common::File *file = openFile(filename); // ROM File
- if (file == NULL) {
- return LoadResult_NotFound;
+bool Synth::loadPCMROM(const ROMImage &pcmROMImage) {
+ if (&pcmROMImage == NULL) return false;
+ Common::File *file = pcmROMImage.getFile();
+ const ROMInfo *pcmROMInfo = pcmROMImage.getROMInfo();
+ if ((pcmROMInfo == NULL)
+ || (pcmROMInfo->type != ROMInfo::PCM)
+ || (pcmROMInfo->pairType != ROMInfo::Full)) {
+ return false;
}
+#if MT32EMU_MONITOR_INIT
+ printDebug("Found PCM ROM: %s, %s", pcmROMInfo->shortName, pcmROMInfo->description);
+#endif
size_t fileSize = file->size();
- if (fileSize < (size_t)(2 * pcmROMSize)) {
- printDebug("PCM ROM file is too short (expected %d, got %d)", 2 * pcmROMSize, fileSize);
- closeFile(file);
- return LoadResult_Invalid;
- }
- if (file->err()) {
- closeFile(file);
- return LoadResult_Unreadable;
+ if (fileSize != (2 * pcmROMSize)) {
+#if MT32EMU_MONITOR_INIT
+ printDebug("PCM ROM file has wrong size (expected %d, got %d)", 2 * pcmROMSize, fileSize);
+#endif
+ return false;
}
- LoadResult rc = LoadResult_OK;
- for (unsigned int i = 0; i < pcmROMSize; i++) {
- Bit8u s = file->readByte();
- Bit8u c = file->readByte();
+
+ byte *buffer = new byte[file->size()];
+ file->read(buffer, file->size());
+ const byte *fileData = buffer;
+ for (size_t i = 0; i < pcmROMSize; i++) {
+ Bit8u s = *(fileData++);
+ Bit8u c = *(fileData++);
int order[16] = {0, 9, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 8};
@@ -351,16 +357,18 @@ LoadResult Synth::loadPCMROM(const char *filename) {
pcmROMData[i] = lin;
}
- closeFile(file);
- return rc;
+
+ delete[] buffer;
+
+ return true;
}
bool Synth::initPCMList(Bit16u mapAddress, Bit16u count) {
ControlROMPCMStruct *tps = (ControlROMPCMStruct *)&controlROMData[mapAddress];
for (int i = 0; i < count; i++) {
- unsigned int rAddr = tps[i].pos * 0x800;
- int rLenExp = (tps[i].len & 0x70) >> 4;
- int rLen = 0x800 << rLenExp;
+ size_t rAddr = tps[i].pos * 0x800;
+ size_t rLenExp = (tps[i].len & 0x70) >> 4;
+ size_t rLen = 0x800 << rLenExp;
if (rAddr + rLen > pcmROMSize) {
printDebug("Control ROM error: Wave map entry %d points to invalid PCM address 0x%04X, length 0x%04X", i, rAddr, rLen);
return false;
@@ -422,12 +430,11 @@ bool Synth::initTimbres(Bit16u mapAddress, Bit16u offset, int count, int startTi
return true;
}
-bool Synth::open(SynthProperties &useProp) {
+bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage) {
if (isOpen) {
return false;
}
prerenderReadIx = prerenderWriteIx = 0;
- myProp = useProp;
#if MT32EMU_MONITOR_INIT
printDebug("Initialising Constant Tables");
#endif
@@ -436,11 +443,6 @@ bool Synth::open(SynthProperties &useProp) {
reverbModels[i]->open(useProp.sampleRate);
}
#endif
- if (useProp.baseDir != NULL) {
- char *baseDirCopy = new char[strlen(useProp.baseDir) + 1];
- strcpy(baseDirCopy, useProp.baseDir);
- myProp.baseDir = baseDirCopy;
- }
// This is to help detect bugs
memset(&mt32ram, '?', sizeof(mt32ram));
@@ -448,12 +450,10 @@ bool Synth::open(SynthProperties &useProp) {
#if MT32EMU_MONITOR_INIT
printDebug("Loading Control ROM");
#endif
- if (loadControlROM("CM32L_CONTROL.ROM") != LoadResult_OK) {
- if (loadControlROM("MT32_CONTROL.ROM") != LoadResult_OK) {
- printDebug("Init Error - Missing or invalid MT32_CONTROL.ROM");
- //report(ReportType_errorControlROM, &errno);
- return false;
- }
+ if (!loadControlROM(controlROMImage)) {
+ printDebug("Init Error - Missing or invalid Control ROM image");
+ reportHandler->onErrorControlROM();
+ return false;
}
initMemoryRegions();
@@ -467,12 +467,10 @@ bool Synth::open(SynthProperties &useProp) {
#if MT32EMU_MONITOR_INIT
printDebug("Loading PCM ROM");
#endif
- if (loadPCMROM("CM32L_PCM.ROM") != LoadResult_OK) {
- if (loadPCMROM("MT32_PCM.ROM") != LoadResult_OK) {
- printDebug("Init Error - Missing MT32_PCM.ROM");
- //report(ReportType_errorPCMROM, &errno);
- return false;
- }
+ if (!loadPCMROM(pcmROMImage)) {
+ printDebug("Init Error - Missing PCM ROM image");
+ reportHandler->onErrorPCMROM();
+ return false;
}
#if MT32EMU_MONITOR_INIT
@@ -601,9 +599,6 @@ void Synth::close() {
parts[i] = NULL;
}
- delete[] myProp.baseDir;
- myProp.baseDir = NULL;
-
delete[] pcmWaves;
delete[] pcmROMData;
@@ -1190,7 +1185,7 @@ void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u le
case MR_System:
region->write(0, off, data, len);
- report(ReportType_devReconfig, NULL);
+ reportHandler->onDeviceReconfig();
// FIXME: We haven't properly confirmed any of this behaviour
// In particular, we tend to reset things such as reverb even if the write contained
// the same parameters as were already set, which may be wrong.
@@ -1228,7 +1223,7 @@ void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u le
#if MT32EMU_MONITOR_SYSEX > 0
printDebug("WRITE-LCD: %s", buf);
#endif
- report(ReportType_lcdMessage, buf);
+ reportHandler->showLCDMessage(buf);
break;
case MR_Reset:
reset();
@@ -1256,9 +1251,9 @@ void Synth::refreshSystemReverbParameters() {
#endif
return;
}
- report(ReportType_newReverbMode, &mt32ram.system.reverbMode);
- report(ReportType_newReverbTime, &mt32ram.system.reverbTime);
- report(ReportType_newReverbLevel, &mt32ram.system.reverbLevel);
+ reportHandler->onNewReverbMode(mt32ram.system.reverbMode);
+ reportHandler->onNewReverbTime(mt32ram.system.reverbTime);
+ reportHandler->onNewReverbLevel(mt32ram.system.reverbLevel);
ReverbModel *newReverbModel = reverbModels[mt32ram.system.reverbMode];
#if MT32EMU_REDUCE_REVERB_MEMORY
@@ -1266,7 +1261,7 @@ void Synth::refreshSystemReverbParameters() {
if (reverbModel != NULL) {
reverbModel->close();
}
- newReverbModel->open(myProp.sampleRate);
+ newReverbModel->open();
}
#endif
reverbModel = newReverbModel;
@@ -1321,7 +1316,7 @@ void Synth::reset() {
#if MT32EMU_MONITOR_SYSEX > 0
printDebug("RESET");
#endif
- report(ReportType_devReset, NULL);
+ reportHandler->onDeviceReset();
partialManager->deactivateAll();
mt32ram = mt32default;
for (int i = 0; i < 9; i++) {
diff --git a/audio/softsynth/mt32/Synth.h b/audio/softsynth/mt32/Synth.h
index 2534b7af35..91375c0fc0 100644
--- a/audio/softsynth/mt32/Synth.h
+++ b/audio/softsynth/mt32/Synth.h
@@ -26,6 +26,7 @@ class TableInitialiser;
class Partial;
class PartialManager;
class Part;
+class ROMImage;
/**
* Methods for emulating the connection between the LA32 and the DAC, which involves
@@ -57,71 +58,6 @@ enum DACInputMode {
DACInputMode_GENERATION2
};
-enum ReportType {
- // Errors
- ReportType_errorControlROM = 1,
- ReportType_errorPCMROM,
- ReportType_errorSampleRate,
-
- // Progress
- ReportType_progressInit,
-
- // HW spec
- ReportType_availableSSE,
- ReportType_available3DNow,
- ReportType_usingSSE,
- ReportType_using3DNow,
-
- // General info
- ReportType_lcdMessage,
- ReportType_devReset,
- ReportType_devReconfig,
- ReportType_newReverbMode,
- ReportType_newReverbTime,
- ReportType_newReverbLevel
-};
-
-enum LoadResult {
- LoadResult_OK,
- LoadResult_NotFound,
- LoadResult_Unreadable,
- LoadResult_Invalid
-};
-
-struct SynthProperties {
- // Sample rate to use in mixing
- unsigned int sampleRate;
-
- // Deprecated - ignored. Use Synth::setReverbEnabled() instead.
- bool useReverb;
- // Deprecated - ignored. Use Synth::setReverbOverridden() instead.
- bool useDefaultReverb;
- // Deprecated - ignored. Use Synth::playSysex*() to configure reverb instead.
- unsigned char reverbType;
- // Deprecated - ignored. Use Synth::playSysex*() to configure reverb instead.
- unsigned char reverbTime;
- // Deprecated - ignored. Use Synth::playSysex*() to configure reverb instead.
- unsigned char reverbLevel;
- // The name of the directory in which the ROM and data files are stored (with trailing slash/backslash)
- // Not used if "openFile" is set. May be NULL in any case.
- const char *baseDir;
- // This is used as the first argument to all callbacks
- void *userData;
- // Callback for reporting various errors and information. May be NULL
- int (*report)(void *userData, ReportType type, const void *reportData);
- // Callback for debug messages, in vprintf() format
- void (*printDebug)(void *userData, const char *fmt, va_list list);
- // Callback for providing an implementation of File, opened and ready for use
- // May be NULL, in which case a default implementation will be used.
- Common::File *(*openFile)(void *userData, const char *filename);
- // Callback for closing a File. May be NULL, in which case the File will automatically be close()d/deleted.
- void (*closeFile)(void *userData, Common::File *file);
-};
-
-// This is the specification of the Callback routine used when calling the RecalcWaveforms
-// function
-typedef void (*recalcStatusCallback)(int percDone);
-
typedef void (*FloatToBit16sFunc)(Bit16s *target, const float *source, Bit32u len, float outputGain);
const Bit8u SYSEX_MANUFACTURER_ROLAND = 0x41;
@@ -285,7 +221,7 @@ class ReverbModel {
public:
virtual ~ReverbModel() {}
// After construction or a close(), open() will be called at least once before any other call (with the exception of close()).
- virtual void open(unsigned int sampleRate) = 0;
+ virtual void open() = 0;
// May be called multiple times without an open() in between.
virtual void close() = 0;
virtual void setParameters(Bit8u time, Bit8u level) = 0;
@@ -293,6 +229,32 @@ public:
virtual bool isActive() const = 0;
};
+class ReportHandler {
+friend class Synth;
+
+public:
+ virtual ~ReportHandler() {}
+
+protected:
+
+ // Callback for debug messages, in vprintf() format
+ virtual void printDebug(const char *fmt, va_list list);
+
+ // Callbacks for reporting various errors and information
+ virtual void onErrorControlROM() {}
+ virtual void onErrorPCMROM() {}
+ virtual void showLCDMessage(const char *message);
+ virtual void onDeviceReset() {}
+ virtual void onDeviceReconfig() {}
+ virtual void onNewReverbMode(Bit8u /* mode */) {}
+ virtual void onNewReverbTime(Bit8u /* time */) {}
+ virtual void onNewReverbLevel(Bit8u /* level */) {}
+ virtual void onPartStateChanged(int /* partNum */, bool /* isActive */) {}
+ virtual void onPolyStateChanged(int /* partNum */) {}
+ virtual void onPartialStateChanged(int /* partialNum */, int /* oldPartialPhase */, int /* newPartialPhase */) {}
+ virtual void onProgramChanged(int /* partNum */, char * /* patchName */) {}
+};
+
class Synth {
friend class Part;
friend class RhythmPart;
@@ -322,7 +284,7 @@ private:
const ControlROMMap *controlROMMap;
Bit8u controlROMData[CONTROL_ROM_SIZE];
float *pcmROMData;
- unsigned int pcmROMSize; // This is in 16-bit samples, therefore half the number of bytes in the ROM
+ size_t pcmROMSize; // This is in 16-bit samples, therefore half the number of bytes in the ROM
Bit8s chantable[32];
@@ -343,6 +305,9 @@ private:
bool isOpen;
+ bool isDefaultReportHandler;
+ ReportHandler *reportHandler;
+
PartialManager *partialManager;
Part *parts[9];
@@ -375,8 +340,6 @@ private:
int prerenderReadIx;
int prerenderWriteIx;
- SynthProperties myProp;
-
bool prerender();
void copyPrerender(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u pos, Bit32u len);
void checkPrerender(Bit16s *nonReverbLeft, Bit16s *nonReverbRight, Bit16s *reverbDryLeft, Bit16s *reverbDryRight, Bit16s *reverbWetLeft, Bit16s *reverbWetRight, Bit32u &pos, Bit32u &len);
@@ -390,8 +353,8 @@ private:
void writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, const Bit8u *data);
void readMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u len, Bit8u *data);
- LoadResult loadControlROM(const char *filename);
- LoadResult loadPCMROM(const char *filename);
+ bool loadControlROM(const ROMImage &controlROMImage);
+ bool loadPCMROM(const ROMImage &pcmROMImage);
bool initPCMList(Bit16u mapAddress, Bit16u count);
bool initTimbres(Bit16u mapAddress, Bit16u offset, int timbreCount, int startTimbre, bool compressed);
@@ -405,24 +368,25 @@ private:
void refreshSystem();
void reset();
- unsigned int getSampleRate() const;
-
void printPartialUsage(unsigned long sampleOffset = 0);
-protected:
- int report(ReportType type, const void *reportData);
- Common::File *openFile(const char *filename);
- void closeFile(Common::File *file);
+
+ void partStateChanged(int partNum, bool isPartActive);
+ void polyStateChanged(int partNum);
+ void partialStateChanged(const Partial * const partial, int oldPartialPhase, int newPartialPhase);
+ void newTimbreSet(int partNum, char patchName[]);
void printDebug(const char *fmt, ...);
public:
static Bit8u calcSysexChecksum(const Bit8u *data, Bit32u len, Bit8u checksum);
- Synth();
+ // Optionally sets callbacks for reporting various errors, information and debug messages
+ Synth(ReportHandler *useReportHandler = NULL);
~Synth();
// Used to initialise the MT-32. Must be called before any other function.
// Returns true if initialization was sucessful, otherwise returns false.
- bool open(SynthProperties &useProp);
+ // controlROMImage and pcmROMImage represent Control and PCM ROM images for use by synth.
+ bool open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage);
// Closes the MT-32 and deallocates any memory used by the synthesizer
void close(void);
diff --git a/audio/softsynth/mt32/TVA.cpp b/audio/softsynth/mt32/TVA.cpp
index c581259a38..fd442da905 100644
--- a/audio/softsynth/mt32/TVA.cpp
+++ b/audio/softsynth/mt32/TVA.cpp
@@ -34,6 +34,9 @@ TVA::TVA(const Partial *usePartial, LA32Ramp *useAmpRamp) :
}
void TVA::startRamp(Bit8u newTarget, Bit8u newIncrement, int newPhase) {
+ if (newPhase != phase) {
+ partial->getSynth()->partialStateChanged(partial, phase, newPhase);
+ }
target = newTarget;
phase = newPhase;
ampRamp->startRamp(newTarget, newIncrement);
@@ -43,6 +46,9 @@ void TVA::startRamp(Bit8u newTarget, Bit8u newIncrement, int newPhase) {
}
void TVA::end(int newPhase) {
+ if (newPhase != phase) {
+ partial->getSynth()->partialStateChanged(partial, phase, newPhase);
+ }
phase = newPhase;
playing = false;
#if MT32EMU_MONITOR_TVA >= 1
diff --git a/audio/softsynth/mt32/TVP.cpp b/audio/softsynth/mt32/TVP.cpp
index 32a6067841..5dc4ca6b66 100644
--- a/audio/softsynth/mt32/TVP.cpp
+++ b/audio/softsynth/mt32/TVP.cpp
@@ -47,12 +47,11 @@ static Bit16u keyToPitchTable[] = {
TVP::TVP(const Partial *usePartial) :
partial(usePartial), system_(&usePartial->getSynth()->mt32ram.system) {
- unsigned int sampleRate = usePartial->getSynth()->myProp.sampleRate;
// We want to do processing 4000 times per second. FIXME: This is pretty arbitrary.
- maxCounter = sampleRate / 4000;
+ maxCounter = SAMPLE_RATE / 4000;
// The timer runs at 500kHz. We only need to bother updating it every maxCounter samples, before we do processing.
// This is how much to increment it by every maxCounter samples.
- processTimerIncrement = 500000 * maxCounter / sampleRate;
+ processTimerIncrement = 500000 * maxCounter / SAMPLE_RATE;
}
static Bit16s keyToPitch(unsigned int key) {
diff --git a/audio/softsynth/mt32/Tables.h b/audio/softsynth/mt32/Tables.h
index a63eaf6d26..b353cf4c51 100644
--- a/audio/softsynth/mt32/Tables.h
+++ b/audio/softsynth/mt32/Tables.h
@@ -20,7 +20,9 @@
namespace MT32Emu {
-// Sample rate to use in mixing
+// Sample rate to use in mixing. With the progress of development, we've found way too many thing dependent.
+// In order to achieve further advance in emulation accuracy, sample rate made fixed throughout the emulator.
+// The output from the synth is supposed to be resampled to convert the sample rate.
const unsigned int SAMPLE_RATE = 32000;
const int MIDDLEC = 60;
diff --git a/audio/softsynth/mt32/module.mk b/audio/softsynth/mt32/module.mk
index c0ee363c04..ed6b0d33ed 100644
--- a/audio/softsynth/mt32/module.mk
+++ b/audio/softsynth/mt32/module.mk
@@ -10,6 +10,7 @@ MODULE_OBJS := \
Partial.o \
PartialManager.o \
Poly.o \
+ ROMInfo.o \
Synth.o \
TVA.o \
TVF.o \
diff --git a/audio/softsynth/mt32/mt32emu.h b/audio/softsynth/mt32/mt32emu.h
index a5a72b01ca..ae5f4955b1 100644
--- a/audio/softsynth/mt32/mt32emu.h
+++ b/audio/softsynth/mt32/mt32emu.h
@@ -71,8 +71,6 @@
// 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
-
// Configuration
// The maximum number of partials playing simultaneously
#define MT32EMU_MAX_PARTIALS 32
@@ -117,6 +115,7 @@ const unsigned int MAX_PRERENDER_SAMPLES = 1024;
#include "TVF.h"
#include "Partial.h"
#include "Part.h"
+#include "ROMInfo.h"
#include "Synth.h"
#endif