aboutsummaryrefslogtreecommitdiff
path: root/backends/midi
diff options
context:
space:
mode:
authorJerome Fisher2004-11-13 19:24:37 +0000
committerJerome Fisher2004-11-13 19:24:37 +0000
commit5e442766e533339c1e2f3389a2859601c6ab1127 (patch)
tree4df084b6b6756901508bb6c39d4125a6a150102f /backends/midi
parent2ae3166f2db47b7beb5225d57b5e271de33ab9cd (diff)
downloadscummvm-rg350-5e442766e533339c1e2f3389a2859601c6ab1127.tar.gz
scummvm-rg350-5e442766e533339c1e2f3389a2859601c6ab1127.tar.bz2
scummvm-rg350-5e442766e533339c1e2f3389a2859601c6ab1127.zip
MT32 MidiDriver:
- Channels now ignore effectLevel() and chorusLevel(), instead of sending unsupported control change messages to MT32Emu (they're not supported in a real MT-32, either, according to docs). - Implemented setPitchBendRange() by sending a sysex write command to adjust the patch. - _outputRate is now hard-coded at 32000, until tuning can be fixed for other sample rates. MT32EMu: - Extended File interface to deal with reading/writing 16/32-bit values endian-independently (they're always big-endian on file). - Improved usage of packing-related pragmas. - Should now be endian-agnostic (without depending on #defines for the endianness). svn-id: r15800
Diffstat (limited to 'backends/midi')
-rw-r--r--backends/midi/mt32.cpp83
-rw-r--r--backends/midi/mt32/mt32_file.cpp66
-rw-r--r--backends/midi/mt32/mt32_file.h27
-rw-r--r--backends/midi/mt32/mt32emu.h3
-rw-r--r--backends/midi/mt32/partial.cpp31
-rw-r--r--backends/midi/mt32/structures.h86
-rw-r--r--backends/midi/mt32/synth.cpp136
-rw-r--r--backends/midi/mt32/synth.h1
8 files changed, 256 insertions, 177 deletions
diff --git a/backends/midi/mt32.cpp b/backends/midi/mt32.cpp
index 6b2d576852..28f331e694 100644
--- a/backends/midi/mt32.cpp
+++ b/backends/midi/mt32.cpp
@@ -36,9 +36,14 @@
#include "common/file.h"
#include "common/config-manager.h"
+class MidiChannel_MT32 : public MidiChannel_MPU401 {
+ void effectLevel(byte value) { }
+ void chorusLevel(byte value) { }
+};
+
class MidiDriver_MT32 : public MidiDriver_Emulated {
private:
- MidiChannel_MPU401 _midiChannels[16];
+ MidiChannel_MT32 _midiChannels[16];
uint16 _channelMask;
MT32Emu::Synth *_synth;
@@ -54,6 +59,7 @@ public:
int open();
void close();
void send(uint32 b);
+ void setPitchBendRange (byte channel, uint range);
void sysEx(byte *msg, uint16 length);
uint32 property(int prop, uint32 param);
@@ -77,33 +83,32 @@ public:
void close() {
return file.close();
}
- size_t read(void *ptr, size_t size) {
- return file.read(ptr, size);
+ size_t read(void *in, size_t size) {
+ return file.read(in, size);
}
- bool readLine(char *ptr, size_t size) {
- return file.gets(ptr, size) != NULL;
+ bool readLine(char *in, size_t size) {
+ return file.gets(in, size) != NULL;
}
- size_t write(const void *ptr, size_t size) {
- return file.write(ptr, size);
- }
- int readByte() {
+ bool readBit8u(MT32Emu::Bit8u *in) {
byte b = file.readByte();
if (file.eof())
- return -1;
- return b;
- }
- bool writeByte(unsigned char out) {
- file.writeByte(out);
- if (file.ioFailed())
return false;
+ *in = b;
return true;
}
+ size_t write(const void *in, size_t size) {
+ return file.write(in, size);
+ }
+ bool writeBit8u(MT32Emu::Bit8u out) {
+ file.writeByte(out);
+ return !file.ioFailed();
+ }
bool isEOF() {
return file.eof();
}
};
-MT32Emu::File *MT32_OpenFile(void *userData, const char *filename, MT32Emu::File::OpenMode mode) {
+static MT32Emu::File *MT32_OpenFile(void *userData, const char *filename, MT32Emu::File::OpenMode mode) {
MT32File *file = new MT32File();
if (!file->open(filename, mode)) {
delete file;
@@ -112,13 +117,11 @@ MT32Emu::File *MT32_OpenFile(void *userData, const char *filename, MT32Emu::File
return file;
}
-////////////////////////////////////////
-//
-// MidiDriver_MT32
-//
-////////////////////////////////////////
+static void MT32_PrintDebug(void *userData, const char *fmt, va_list list) {
+ //vdebug(0, fmt, list); // FIXME: Use a higher debug level
+}
-static void report(void *userData, MT32Emu::ReportType type, void *reportData) {
+static void MT32_Report(void *userData, MT32Emu::ReportType type, void *reportData) {
switch(type) {
case MT32Emu::ReportType_lcdMessage:
g_system->displayMessageOnOSD((char *)reportData);
@@ -143,6 +146,12 @@ static void report(void *userData, MT32Emu::ReportType type, void *reportData) {
}
}
+////////////////////////////////////////
+//
+// MidiDriver_MT32
+//
+////////////////////////////////////////
+
MidiDriver_MT32::MidiDriver_MT32(SoundMixer *mixer) : MidiDriver_Emulated(mixer) {
_channelMask = 0xFFFF; // Permit all 16 channels by default
uint i;
@@ -153,7 +162,7 @@ MidiDriver_MT32::MidiDriver_MT32(SoundMixer *mixer) : MidiDriver_Emulated(mixer)
_baseFreq = 1000;
- _outputRate = _mixer->getOutputRate();
+ _outputRate = 32000; //_mixer->getOutputRate();
}
MidiDriver_MT32::~MidiDriver_MT32() {
@@ -161,10 +170,6 @@ MidiDriver_MT32::~MidiDriver_MT32() {
delete _synth;
}
-static void vdebug(void *data, const char *fmt, va_list list) {
- // do nothing here now
-}
-
int MidiDriver_MT32::open() {
MT32Emu::SynthProperties prop;
@@ -180,9 +185,8 @@ int MidiDriver_MT32::open() {
prop.RevType = 0;
prop.RevTime = 5;
prop.RevLevel = 3;
- prop.userData = (void *)1;
- prop.printDebug = &vdebug;
- prop.report = &report;
+ prop.printDebug = MT32_PrintDebug;
+ prop.report = MT32_Report;
prop.openFile = MT32_OpenFile;
_synth = new MT32Emu::Synth();
if (!_synth->open(prop))
@@ -197,6 +201,23 @@ void MidiDriver_MT32::send(uint32 b) {
_synth->playMsg(b);
}
+void MidiDriver_MT32::setPitchBendRange(byte channel, uint range) {
+ if (range > 24) {
+ printf("setPitchBendRange() called with range > 24: %d", range);
+ }
+ byte benderRangeSysex[9];
+ benderRangeSysex[0] = 0x41; // Roland
+ benderRangeSysex[1] = channel;
+ benderRangeSysex[2] = 0x16; // MT-32
+ benderRangeSysex[3] = 0x12; // Write
+ benderRangeSysex[4] = 0x00;
+ benderRangeSysex[5] = 0x00;
+ benderRangeSysex[6] = 0x04;
+ benderRangeSysex[7] = (byte)range;
+ benderRangeSysex[8] = MT32Emu::Synth::calcSysexChecksum(&benderRangeSysex[4], 4, 0);
+ sysEx(benderRangeSysex, 9);
+}
+
void MidiDriver_MT32::sysEx(byte *msg, uint16 length) {
if (msg[0] == 0xf0) {
_synth->playSysex(msg, length);
@@ -233,7 +254,7 @@ uint32 MidiDriver_MT32::property(int prop, uint32 param) {
}
MidiChannel *MidiDriver_MT32::allocateChannel() {
- MidiChannel_MPU401 *chan;
+ MidiChannel_MT32 *chan;
uint i;
for (i = 0; i < ARRAYSIZE(_midiChannels); ++i) {
diff --git a/backends/midi/mt32/mt32_file.cpp b/backends/midi/mt32/mt32_file.cpp
index 2a28194333..1537b734e7 100644
--- a/backends/midi/mt32/mt32_file.cpp
+++ b/backends/midi/mt32/mt32_file.cpp
@@ -21,7 +21,7 @@
#include <stdio.h>
-#include "mt32_file.h"
+#include "mt32emu.h"
namespace MT32Emu {
@@ -40,24 +40,70 @@ namespace MT32Emu {
fclose(fp);
}
- int ANSIFile::readByte() {
- return fgetc(fp);
+ size_t ANSIFile::read(void *in, size_t size) {
+ return fread(in, 1, size, fp);
}
- size_t ANSIFile::read(void *ptr, size_t size) {
- return fread(ptr, 1, size, fp);
+ bool ANSIFile::readLine(char *in, size_t size) {
+ return fgets(in, (int)size, fp) != NULL;
}
- bool ANSIFile::readLine(char *ptr, size_t size) {
- return fgets(ptr, (int)size, fp) != NULL;
+ bool ANSIFile::readBit8u(Bit8u *in) {
+ int c = fgetc(fp);
+ if (c == EOF)
+ return false;
+ *in = (Bit8u)c;
+ return true;
}
- bool ANSIFile::writeByte(unsigned char out) {
+ bool File::readBit16u(Bit16u *in) {
+ char b[2];
+ if (read(&b[0], 2) != 2)
+ return false;
+ *in = ((b[0] << 8) | b[1]);
+ return true;
+ }
+
+ bool File::readBit32u(Bit32u *in) {
+ char b[4];
+ if (read(&b[0], 4) != 4)
+ return false;
+ *in = ((b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]);
+ return true;
+ }
+
+ size_t ANSIFile::write(const void *out, size_t size) {
+ return fwrite(out, 1, size, fp);
+ }
+
+ bool ANSIFile::writeBit8u(Bit8u out) {
return fputc(out, fp) != EOF;
}
- size_t ANSIFile::write(const void *ptr, size_t size) {
- return fwrite(ptr, 1, size, fp);
+ bool File::writeBit16u(Bit16u out) {
+ if (!writeBit8u((Bit8u)((out >> 8) & 0xFF))) {
+ return false;
+ }
+ if (!writeBit8u((Bit8u)(out & 0xFF))) {
+ return false;
+ }
+ return true;
+ }
+
+ bool File::writeBit32u(Bit32u out) {
+ if (!writeBit8u((Bit8u)((out >> 24) & 0xFF))) {
+ return false;
+ }
+ if (!writeBit8u((Bit8u)((out >> 16) & 0xFF))) {
+ return false;
+ }
+ if (!writeBit8u((Bit8u)((out >> 8) & 0xFF))) {
+ return false;
+ }
+ if (!writeBit8u((Bit8u)(out & 0xFF))) {
+ return false;
+ }
+ return true;
}
bool ANSIFile::isEOF() {
diff --git a/backends/midi/mt32/mt32_file.h b/backends/midi/mt32/mt32_file.h
index 6c02712596..f5888db5e3 100644
--- a/backends/midi/mt32/mt32_file.h
+++ b/backends/midi/mt32/mt32_file.h
@@ -34,12 +34,17 @@ public:
};
virtual ~File() {}
virtual void close() = 0;
- virtual size_t read(void *ptr, size_t size) = 0;
- virtual bool readLine(char *ptr, size_t size) = 0;
- virtual size_t write(const void *ptr, size_t size) = 0;
- // Returns -1 in case of EOF or error
- virtual int readByte() = 0;
- virtual bool writeByte(unsigned char out) = 0;
+ virtual size_t read(void *in, size_t size) = 0;
+ virtual bool readLine(char *in, size_t size) = 0;
+ virtual bool readBit8u(Bit8u *in) = 0;
+ virtual bool readBit16u(Bit16u *in);
+ virtual bool readBit32u(Bit32u *in);
+ virtual size_t write(const void *out, size_t size) = 0;
+ virtual bool writeBit8u(Bit8u out) = 0;
+ // Note: May write some a single byte to the file before failing
+ virtual bool writeBit16u(Bit16u out);
+ // Note: May write some (<4) bytes to the file before failing
+ virtual bool writeBit32u(Bit32u out);
virtual bool isEOF() = 0;
};
@@ -49,11 +54,11 @@ private:
public:
bool open(const char *filename, OpenMode mode);
void close();
- size_t read(void *ptr, size_t size);
- bool readLine(char *ptr, size_t size);
- size_t write(const void *, size_t size);
- int readByte();
- bool writeByte(unsigned char out);
+ size_t read(void *in, size_t size);
+ bool readLine(char *in, size_t size);
+ bool readBit8u(Bit8u *in);
+ size_t write(const void *out, size_t size);
+ bool writeBit8u(unsigned char out);
bool isEOF();
};
diff --git a/backends/midi/mt32/mt32emu.h b/backends/midi/mt32/mt32emu.h
index ccf903ef8f..c31afee389 100644
--- a/backends/midi/mt32/mt32emu.h
+++ b/backends/midi/mt32/mt32emu.h
@@ -22,9 +22,6 @@
#ifndef MT32EMU_MT32EMU_H
#define MT32EMU_MT32EMU_H
-#include "stdafx.h"
-#include "common/scummsys.h"
-
#include "freeverb.h"
#include "structures.h"
diff --git a/backends/midi/mt32/partial.cpp b/backends/midi/mt32/partial.cpp
index 55daf7efbf..bc5151e565 100644
--- a/backends/midi/mt32/partial.cpp
+++ b/backends/midi/mt32/partial.cpp
@@ -149,7 +149,7 @@ void Partial::startPartial(dpoly *usePoly, PatchCache *useCache, Partial *pairPa
pitchEnvCache = 0;
pitchSustain = false;
loopPos = 0;
- partialOff.pcmabs = 0;
+ partialOff.pcmoffset = partialOff.pcmplace = 0;
pair = pairPartial;
useNoisePair = pairPartial == NULL && (mixType == 1 || mixType == 2);
age = 0;
@@ -238,9 +238,10 @@ Bit16s *Partial::generateSamples(long length) {
delta = wavtabler[tPCM->pcmnum][noteVal];
addr = tPCM->addr;
len = tPCM->len;
- if (partialOff.pcmoffs.pcmplace >= len) {
+ if (partialOff.pcmplace >= len) {
if (tPCM->loop) {
- partialOff.pcmabs = 0;
+ partialOff.pcmplace = partialOff.pcmoffset = 0;
+ // FIXME:KG: Use this?: partialOff.pcmplace %= len;
} else {
play = false;
deactivate();
@@ -252,11 +253,11 @@ Bit16s *Partial::generateSamples(long length) {
delta = looptabler[tPCM->aggSound][loopPos][noteVal];
addr = synth->PCM[tmppcm].addr;
len = synth->PCM[tmppcm].len;
- if (partialOff.pcmoffs.pcmplace >= len) {
+ if (partialOff.pcmplace >= len) {
loopPos++;
if (LoopPatterns[tPCM->aggSound][loopPos]==-1)
loopPos=0;
- partialOff.pcmabs = 0;
+ partialOff.pcmplace = partialOff.pcmoffset = 0;
}
}
@@ -265,7 +266,7 @@ Bit16s *Partial::generateSamples(long length) {
int taddr;
if (delta<0x10000) {
// Linear sound interpolation
- taddr = addr + partialOff.pcmoffs.pcmplace;
+ taddr = addr + partialOff.pcmplace;
if (taddr >= ROMSIZE) {
synth->printDebug("Overflow ROMSIZE!");
taddr = ROMSIZE - 1;
@@ -273,16 +274,15 @@ Bit16s *Partial::generateSamples(long length) {
ra = synth->romfile[taddr];
rb = synth->romfile[taddr+1];
dist = rb-ra;
- ptemp = (ra + ((dist * (Bit32s)(partialOff.pcmoffs.pcmoffset>>8)) >>8));
+ ptemp = (ra + ((dist * (Bit32s)(partialOff.pcmoffset >> 8)) >> 8));
} else {
- //r = romfile[addr + partialOff.pcmoffs.pcmplace];
// Sound decimation
// The right way to do it is to use a lowpass filter on the waveform before selecting
// a point. This is too slow. The following approximates this as fast as possible
int idelta = delta >> 16;
- taddr = addr + partialOff.pcmoffs.pcmplace;
+ taddr = addr + partialOff.pcmplace;
ra = 0;
- for (int ix=0;ix<idelta;ix++)
+ for (int ix = 0; ix < idelta; ix++)
ra += synth->romfile[taddr++];
ptemp = ra / idelta;
}
@@ -291,12 +291,12 @@ Bit16s *Partial::generateSamples(long length) {
// Synthesis partial
int divis = divtable[noteVal] >> 15;
- partialOff.pcmoffs.pcmplace %= (Bit16u)divis;
+ partialOff.pcmplace %= (Bit16u)divis;
if (ampval > 0) {
int wf = patchCache->waveform ;
- int toff = partialOff.pcmoffs.pcmplace;
- int minorplace = partialOff.pcmoffs.pcmoffset >> 14;
+ int toff = partialOff.pcmplace;
+ int minorplace = partialOff.pcmoffset >> 14;
int pa, pb;
@@ -381,7 +381,10 @@ Bit16s *Partial::generateSamples(long length) {
tdelta = (tdelta * *poly->bendptr)>>12;
// Add calculated delta to our waveform offset
- partialOff.pcmabs += (int)tdelta;
+ Bit32u absOff = ((partialOff.pcmplace << 16) | partialOff.pcmoffset);
+ absOff += (int)tdelta;
+ partialOff.pcmplace = (Bit16u)((absOff & 0xFFFF0000) >> 16);
+ partialOff.pcmoffset = (Bit16u)(absOff & 0xFFFF);
// Put volume envelope over generated sample
ptemp = (ptemp * ampval) >> 9;
diff --git a/backends/midi/mt32/structures.h b/backends/midi/mt32/structures.h
index 07b170cc89..5b1db5921b 100644
--- a/backends/midi/mt32/structures.h
+++ b/backends/midi/mt32/structures.h
@@ -36,12 +36,11 @@
namespace MT32Emu {
#ifdef _MSC_VER
-#define ALIGN_PACKED __declspec(align(1))
+#define MT32EMU_ALIGN_PACKED __declspec(align(1))
typedef unsigned __int64 Bit64u;
typedef signed __int64 Bit64s;
#else
-//#define ALIGN_PACKED __attribute__ ((__packed__))
-#define ALIGN_PACKED __attribute__ ((aligned (1)))
+#define MT32EMU_ALIGN_PACKED __attribute__((packed))
typedef unsigned long long Bit64u;
typedef signed long long Bit64s;
#endif
@@ -53,7 +52,16 @@ typedef signed short int Bit16s;
typedef unsigned char Bit8u;
typedef signed char Bit8s;
+// The following structures represent the MT-32's memory
+// Since sysex allows this memory to be written to in blocks of bytes,
+// we keep this packed so that we can copy data into the various
+// banks directly
+#ifdef __GNUC__
+#pragma pack(push, 1)
+#else
#pragma pack(1)
+#endif
+
struct TimbreParam {
struct commonParam {
char name[10];
@@ -61,19 +69,19 @@ struct TimbreParam {
char pstruct34; // #3&4 0-12 (1-13)
char pmute; // 0-15 (0000-1111)
char nosustain; // 0-1(Normal, No sustain)
- } ALIGN_PACKED common;
+ } MT32EMU_ALIGN_PACKED common;
struct partialParam {
struct wgParam {
char coarse; // 0-96 (C1,C#1-C9)
- char fine; // 0-100 (-50 - +50)
+ char fine; // 0-100 (-50 to +50 (cents?))
char keyfollow; // 0-16 (-1,-1/2,0,1,1/8,1/4,3/8,1/2,5/8,3/4,7/8,1,5/4,3/2,2.s1,s2)
char bender; // 0,1 (ON/OFF)
char waveform; // 0-1 (SQU/SAW)
char pcmwave; // 0-127 (1-128)
char pulsewid; // 0-100
char pwvelo; // 0-14 (-7 - +7)
- } ALIGN_PACKED wg;
+ } MT32EMU_ALIGN_PACKED wg;
struct envParam {
char depth; // 0-10
@@ -81,13 +89,13 @@ struct TimbreParam {
char timekeyfollow; // 0-4
char time[4]; // 1-100
char level[5]; // 1-100 (-50 - +50)
- } ALIGN_PACKED env;
+ } MT32EMU_ALIGN_PACKED env;
struct lfoParam {
char rate; // 0-100
char depth; // 0-100
char modsense; // 0-100
- } ALIGN_PACKED lfo;
+ } MT32EMU_ALIGN_PACKED lfo;
struct tvfParam {
char cutoff; // 0-100
@@ -101,7 +109,7 @@ struct TimbreParam {
char envtkf; // TIME KEY FOLLOW 0-4
char envtime[5]; // 1-100
char envlevel[4]; // 1-100
- } ALIGN_PACKED tvf;
+ } MT32EMU_ALIGN_PACKED tvf;
struct tvaParam {
char level; // 0-100
@@ -114,22 +122,20 @@ struct TimbreParam {
char envvkf; // VELOS KEY FOLL0W 0-4
char envtime[5]; // 1-100
char envlevel[4]; // 1-100
- } ALIGN_PACKED tva;
-
- } ALIGN_PACKED partial[4];
- //char dummy[20];
-} ALIGN_PACKED;
+ } MT32EMU_ALIGN_PACKED tva;
+ } MT32EMU_ALIGN_PACKED partial[4];
+} MT32EMU_ALIGN_PACKED;
struct PatchParam {
char timbreGroup; // TIMBRE GROUP 0-3 (group A, group B, Memory, Rhythm)
char timbreNum; // TIMBRE NUMBER 0-63
- char keyShift; // KEY SHIFT 0-48 (-24 - +24)
- char fineTune; // FINE TUNE 0-100 (-50 - +50)
+ char keyShift; // KEY SHIFT 0-48 (-24 - +24 semitones)
+ char fineTune; // FINE TUNE 0-100 (-50 - +50 cents)
char benderRange; // BENDER RANGE 0-24
char assignMode; // ASSIGN MODE 0-3 (POLY1, POLY2, POLY3, POLY4)
char reverbSwitch; // REVERB SWITCH 0-1 (OFF,ON)
char dummy; // (DUMMY)
-} ALIGN_PACKED;
+} MT32EMU_ALIGN_PACKED;
struct MemParams {
struct PatchTemp {
@@ -137,23 +143,23 @@ struct MemParams {
char outlevel; // OUTPUT LEVEL 0-100
char panpot; // PANPOT 0-14 (R-L)
char dummyv[6];
- } ALIGN_PACKED patchSettings[8];
+ } MT32EMU_ALIGN_PACKED patchSettings[8];
struct RhythmTemp {
char timbre; // TIMBRE 0-94 (M1-M64,R1-30,OFF)
char outlevel; // OUTPUT LEVEL 0-100
char panpot; // PANPOT 0-14 (R-L)
char reverbSwitch; // REVERB SWITCH 0-1 (OFF,ON)
- } ALIGN_PACKED rhythmSettings[64];
+ } MT32EMU_ALIGN_PACKED rhythmSettings[64];
- TimbreParam timbreSettings[8];
+ TimbreParam MT32EMU_ALIGN_PACKED timbreSettings[8];
- PatchParam patches[128];
+ PatchParam MT32EMU_ALIGN_PACKED patches[128];
struct PaddedTimbre {
TimbreParam timbre;
char padding[10];
- } ALIGN_PACKED timbres[64 + 64 + 64 + 30]; // Group A, Group B, Memory, Rhythm
+ } MT32EMU_ALIGN_PACKED timbres[64 + 64 + 64 + 30]; // Group A, Group B, Memory, Rhythm
struct SystemArea {
char masterTune; // MASTER TUNE 0-127 432.1-457.6Hz
@@ -163,8 +169,8 @@ struct MemParams {
char reserveSettings[9]; // PARTIAL RESERVE (PART 1) 0-32
char chanAssign[9]; // MIDI CHANNEL (PART1) 0-16 (1-16,OFF)
char masterVol; // MASTER VOLUME 0-100
- } ALIGN_PACKED system;
-} ALIGN_PACKED;
+ } MT32EMU_ALIGN_PACKED system;
+};
struct MemBanks {
char pTemp[8][sizeof(MemParams::PatchTemp)];
@@ -173,21 +179,21 @@ struct MemBanks {
char patchBank[128][sizeof(PatchParam)];
char timbreBank[64 + 64 + 64 + 30][sizeof(MemParams::PaddedTimbre)];
char systemBank[sizeof(MemParams::SystemArea)];
-} ALIGN_PACKED;
+ // System memory 0x100000
+ // Display 0x200000
+ // Reset 0x7F0000
+};
union MT32RAMFormat {
MemParams params;
MemBanks banks;
+} MT32EMU_ALIGN_PACKED;
- // System memory 10
-
- // Display 20
-
- // Reset 7F
-
-} ALIGN_PACKED;
-
+#ifdef __GNUC__
+#pragma pack(pop)
+#else
#pragma pack()
+#endif
struct sampleFormat {
Bit32u addr;
@@ -205,17 +211,9 @@ struct sampleTable {
Bit32s aggSound; // This variable is for the last 9 PCM samples, which are actually loop combinations
};
-union soundaddr {
- Bit32u pcmabs;
- struct offsets {
-#if defined(SCUMM_LITTLE_ENDIAN)
- Bit16u pcmoffset;
- Bit16u pcmplace;
-#else
- Bit16u pcmplace;
- Bit16u pcmoffset;
-#endif
- } pcmoffs;
+struct soundaddr {
+ Bit16u pcmplace;
+ Bit16u pcmoffset;
};
struct volset {
diff --git a/backends/midi/mt32/synth.cpp b/backends/midi/mt32/synth.cpp
index bd84ad076e..2647fdae85 100644
--- a/backends/midi/mt32/synth.cpp
+++ b/backends/midi/mt32/synth.cpp
@@ -35,10 +35,10 @@
// Used to dump drum patches to syx file for viewing
#define DUMPDRUMS 0
-#define SYSEX_SIZE 512
-
namespace MT32Emu {
+const int MAX_SYSEX_SIZE = 512;
+
iir_filter_type usefilter;
static const Bit8u InitPatches[8] = {
@@ -108,6 +108,16 @@ float iir_filter_normal(float input,float *hist1_ptr, float *coef_ptr, int revLe
return(output);
}
+Bit8u Synth::calcSysexChecksum(Bit8u *data, Bit32u len, Bit8u checksum) {
+ for (unsigned int i = 0; i < len; i++) {
+ checksum = checksum + data[i];
+ }
+ checksum = checksum & 0x7f;
+ if (checksum)
+ checksum = 0x80 - checksum;
+ return checksum;
+}
+
Synth::Synth() {
isOpen = false;
reverbModel = NULL;
@@ -208,44 +218,38 @@ bool Synth::loadPreset(const char *filename) {
return false;
}
bool inSys = false;
- Bit8u sysexBuf[SYSEX_SIZE];
+ Bit8u sysexBuf[MAX_SYSEX_SIZE];
Bit16u syslen = 0;
- int filePos = 0;
bool rc = true;
for (;;) {
- int fc = file->readByte();
- if (fc == -1) {
+ Bit8u c;
+ if (!file->readBit8u(&c)) {
if (!file->isEOF()) {
rc = false;
}
break;
}
- Bit8u c = (Bit8u)fc;
sysexBuf[syslen] = c;
- syslen++;
- filePos++;
- if (c==0xf0)
+ if (inSys) {
+ syslen++;
+ if (c == 0xF7) {
+ playSysex(&sysexBuf[0],syslen);
+ inSys = false;
+ syslen = 0;
+ } else if (syslen == MAX_SYSEX_SIZE) {
+ printDebug("MAX_SYSEX_SIZE (%d) exceeded while processing preset %s, ignoring message", MAX_SYSEX_SIZE, filename);
+ inSys = false;
+ syslen = 0;
+ }
+ } else if (c == 0xF0) {
+ syslen++;
inSys = true;
- if ((c==0xf7) && (inSys)) {
- playSysex(&sysexBuf[0],syslen);
- inSys = false;
- syslen = 0;
}
}
closeFile(file);
return rc;
}
-unsigned char calcChecksum(unsigned char *data, unsigned int len, unsigned char checksum) {
- for (unsigned int i = 0; i < len; i++) {
- checksum = checksum + data[i];
- }
- checksum = checksum & 0x7f;
- if (checksum)
- checksum = 0x80 - checksum;
- return checksum;
-}
-
bool Synth::loadDrums(const char *filename) {
File *file = openFile(filename, File::OpenMode_read);
if (file == NULL) {
@@ -288,15 +292,15 @@ void Synth::dumpDrums(const char *filename) {
memset(dumbtext,0,10);
for (int drumnum=0;drumnum<30;drumnum++) {
// Sysex header
- if (!file->writeByte(0xf0))
+ if (!file->writeBit8u(0xf0))
break;
- if (!file->writeByte(0x41))
+ if (!file->writeBit8u(0x41))
break;
- if (!file->writeByte(0x10))
+ if (!file->writeBit8u(0x10))
break;
- if (!file->writeByte(0x16))
+ if (!file->writeBit8u(0x16))
break;
- if (!file->writeByte(0x12))
+ if (!file->writeBit8u(0x12))
break;
int useaddr = drumnum * 256;
@@ -304,11 +308,11 @@ void Synth::dumpDrums(const char *filename) {
char isb = (char)((useaddr >> 7) & 0x7f);
char msb = (char)(((useaddr >> 14) & 0x7f) | 0x08);
//Address
- if (!file->writeByte(msb))
+ if (!file->writeBit8u(msb))
break;
- if (!file->writeByte(isb))
+ if (!file->writeBit8u(isb))
break;
- if (!file->writeByte(lsb))
+ if (!file->writeBit8u(lsb))
break;
TimbreParam *timbre = &mt32ram.params.timbres[192 + drumnum].timbre;
@@ -325,12 +329,12 @@ void Synth::dumpDrums(const char *filename) {
break;
//Checksum
unsigned char *dat = (unsigned char *)timbre;
- unsigned char checksum = calcChecksum(dat, 246, msb + isb + lsb);
- if (!file->writeByte(checksum))
+ unsigned char checksum = calcSysexChecksum(dat, 246, msb + isb + lsb);
+ if (!file->writeBit8u(checksum))
break;
//End of sysex
- if (!file->writeByte(0xf7))
+ if (!file->writeBit8u(0xf7))
break;
}
closeFile(file);
@@ -470,16 +474,15 @@ bool Synth::loadROM(const char *filename) {
#endif
bool rc = true;
for (int i = 0; ; i++) {
- int fc = file->readByte();
- if (fc == -1) {
+ Bit8u s;
+ if (!file->readBit8u(&s)) {
if (!file->isEOF()) {
rc = false;
}
break;
}
- Bit16s s = (Bit16s)fc;
- fc = file->readByte();
- if (fc == -1) {
+ Bit8u c;
+ if (!file->readBit8u(&c)) {
if (!file->isEOF()) {
rc = false;
} else {
@@ -487,7 +490,6 @@ bool Synth::loadROM(const char *filename) {
}
break;
}
- Bit16s c = (Bit16s)fc;
short e;
int bit;
@@ -515,8 +517,8 @@ bool Synth::loadROM(const char *filename) {
*/
#ifdef MT32OUT
- outFile->writeByte(e & 0xff);
- outFile->writeByte(((e >> 8) & 0x7f));
+ outFile->writeBit8u(e & 0xff);
+ outFile->writeBit8u(((e >> 8) & 0x7f));
#endif
// File is encoded in dB, convert to PCM
// MINDB = -96
@@ -533,8 +535,8 @@ bool Synth::loadROM(const char *filename) {
romfile[i] = (Bit16s)vol;
#ifdef MT32OUT
- outFileB->writeByte(romfile[i] & 0xff);
- outFileB->writeByte(romfile[i] >> 8);
+ outFileB->writeBit8u(romfile[i] & 0xff);
+ outFileB->writeBit8u(romfile[i] >> 8);
#endif
}
#ifdef MT32OUT
@@ -636,9 +638,11 @@ bool Synth::open(SynthProperties &useProp) {
if (available3DNow) {
printDebug("Detected and using SIMD (AMD 3DNow) extensions");
usefilter = &iir_filter_3dnow;
+ report(ReportType_using3DNow, NULL);
} else if (availableSSE) {
printDebug("Detected and using SIMD (Intel SSE) extensions");
usefilter = &iir_filter_sse;
+ report(ReportType_usingSSE, NULL);
}
#endif
@@ -695,13 +699,13 @@ void Synth::close(void) {
}
}
if (partialManager != NULL) {
- partialManager = NULL;
delete partialManager;
+ partialManager = NULL;
}
if (reverbModel != NULL) {
- reverbModel = NULL;
delete reverbModel;
+ reverbModel = NULL;
}
for (int i = 0; i < 9; i++) {
@@ -721,7 +725,7 @@ void Synth::playMsg(Bit32u msg) {
unsigned char velocity = (unsigned char)((msg & 0xff0000) >> 16);
isEnabled = true;
- //if (code!=0xf) printDebug("Playing chan %d, code 0x%01x note: 0x%02x", chan, code, note);
+ //printDebug("Playing chan %d, code 0x%01x note: 0x%02x", chan, code, note);
char part = chantable[chan];
if (part < 0 || part > 8) {
@@ -865,7 +869,7 @@ void Synth::playSysexWithoutHeader(unsigned char device, Bit8u *sysex, Bit32u le
printDebug("playSysexWithoutHeader: Message is too short (%d bytes)!", len);
return;
}
- unsigned char checksum = calcChecksum(sysex, len - 1, 0);
+ unsigned char checksum = calcSysexChecksum(sysex, len - 1, 0);
if (checksum != sysex[len - 1]) {
printDebug("playSysexWithoutHeader: Message checksum is incorrect (provided: %02x, expected: %02x)!", sysex[len - 1], checksum);
return;
@@ -875,7 +879,7 @@ void Synth::playSysexWithoutHeader(unsigned char device, Bit8u *sysex, Bit32u le
addr = MEMADDR(addr);
sysex += 3;
len -= 3;
- printDebug("Sysex addr: 0x%06x", SYSEXMEMADDR(addr));
+ //printDebug("Sysex addr: 0x%06x", SYSEXMEMADDR(addr));
// NOTE: Please keep both lower and upper bounds in each check, for ease of reading
if (device < 0x10) {
printDebug("WRITE-CHANNEL: Channel %d temp area 0x%06x", device, SYSEXMEMADDR(addr));
@@ -1108,10 +1112,14 @@ void Synth::playSysexWithoutHeader(unsigned char device, Bit8u *sysex, Bit32u le
printDebug(" Master volume: %d", mt32ram.params.system.masterVol);
mastervolume = (Bit16s)((float)mt32ram.params.system.masterVol * 327.0);
} else if (addr == MEMADDR(0x200000)) {
- char buf[SYSEX_SIZE];
- memset(&buf, 0, SYSEX_SIZE);
+ char buf[MAX_SYSEX_SIZE];
+ if (len > MAX_SYSEX_SIZE - 1) {
+ printDebug("WRITE-LCD sysex length (%d) exceeded MAX_SYSEX_SIZE (%d) - 1; truncating", len, MAX_SYSEX_SIZE);
+ len = MAX_SYSEX_SIZE - 1;
+ }
memcpy(&buf, &sysex[0], len);
- printDebug("LCD Display: %s", buf);
+ buf[len] = 0;
+ printDebug("WRITE-LCD: %s", buf);
report(ReportType_lcdMessage, buf);
} else if (addr >= MEMADDR(0x7f0000)) {
printDebug("Reset");
@@ -1136,15 +1144,15 @@ int Synth::dumpSysex(char *filename) {
int patchnum;
for (patchnum=0;patchnum<64;patchnum++) {
// Sysex header
- if (!file->writeByte(0xF0))
+ if (!file->writeBit8u(0xF0))
break;
- if (!file->writeByte(0x41))
+ if (!file->writeBit8u(0x41))
break;
- if (!file->writeByte(0x10))
+ if (!file->writeBit8u(0x10))
break;
- if (!file->writeByte(0x16))
+ if (!file->writeBit8u(0x16))
break;
- if (!file->writeByte(0x12))
+ if (!file->writeBit8u(0x12))
break;
int useaddr = patchnum * 256;
@@ -1152,11 +1160,11 @@ int Synth::dumpSysex(char *filename) {
char isb = (char)((useaddr >> 7) & 0x7f);
char msb = (char)(((useaddr >> 14) & 0x7f) | 0x08);
//Address
- if (!file->writeByte(msb))
+ if (!file->writeBit8u(msb))
break;
- if (!file->writeByte(isb))
+ if (!file->writeBit8u(isb))
break;
- if (!file->writeByte(lsb))
+ if (!file->writeBit8u(lsb))
break;
//Data
@@ -1172,13 +1180,13 @@ int Synth::dumpSysex(char *filename) {
break;
//Checksum
unsigned char *dat = (unsigned char *)&mt32ram.params.timbres[patchnum + 128].timbre;
- unsigned char checksum = calcChecksum(dat, 246, msb + isb + lsb);
+ unsigned char checksum = calcSysexChecksum(dat, 246, msb + isb + lsb);
- if (!file->writeByte(checksum))
+ if (!file->writeBit8u(checksum))
break;
//End of sysex
- if (!file->writeByte(0xF7))
+ if (!file->writeBit8u(0xF7))
break;
}
closeFile(file);
diff --git a/backends/midi/mt32/synth.h b/backends/midi/mt32/synth.h
index 8d3305e0d4..f2fc3ffae6 100644
--- a/backends/midi/mt32/synth.h
+++ b/backends/midi/mt32/synth.h
@@ -185,6 +185,7 @@ public:
// Sends a 4-byte MIDI message to the MT-32 for immediate playback
void playMsg(Bit32u msg);
+ static Bit8u calcSysexChecksum(Bit8u *data, Bit32u len, Bit8u checksum);
// Sends a string of Sysex commands to the MT-32 for immediate interpretation
// The length is in bytes
void playSysex(Bit8u *sysex, Bit32u len);