aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWalter van Niftrik2010-01-21 16:24:47 +0000
committerWalter van Niftrik2010-01-21 16:24:47 +0000
commitc5409b2d7b1480934d4622b9b7e83928f53abc3a (patch)
treee9c18bdbd3c474fe7b142370ae8bcaa9f539cd04
parentd5dfb7ef0a9132ce4041f10c30883a2fb0584963 (diff)
downloadscummvm-rg350-c5409b2d7b1480934d4622b9b7e83928f53abc3a.tar.gz
scummvm-rg350-c5409b2d7b1480934d4622b9b7e83928f53abc3a.tar.bz2
scummvm-rg350-c5409b2d7b1480934d4622b9b7e83928f53abc3a.zip
SCI: Add MT-32 to GM mapping
svn-id: r47416
-rw-r--r--engines/sci/sound/softseq/map-mt32-to-gm.h552
-rw-r--r--engines/sci/sound/softseq/midi.cpp224
2 files changed, 768 insertions, 8 deletions
diff --git a/engines/sci/sound/softseq/map-mt32-to-gm.h b/engines/sci/sound/softseq/map-mt32-to-gm.h
new file mode 100644
index 0000000000..d87ab777d7
--- /dev/null
+++ b/engines/sci/sound/softseq/map-mt32-to-gm.h
@@ -0,0 +1,552 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * 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 General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+namespace Sci {
+
+/* Patch not mapped */
+#define MIDI_UNMAPPED 0xff
+/* Patch mapped to rhythm key */
+#define MIDI_MAPPED_TO_RHYTHM 0xfe
+
+struct Mt32ToGmMap {
+ const char *name;
+ uint8 gmInstr;
+ uint8 gmRhythmKey;
+};
+
+static const char *GmInstrumentNames[] = {
+ /*000*/ "Acoustic Grand Piano",
+ /*001*/ "Bright Acoustic Piano",
+ /*002*/ "Electric Grand Piano",
+ /*003*/ "Honky-tonk Piano",
+ /*004*/ "Electric Piano 1",
+ /*005*/ "Electric Piano 2",
+ /*006*/ "Harpsichord",
+ /*007*/ "Clavinet",
+ /*008*/ "Celesta",
+ /*009*/ "Glockenspiel",
+ /*010*/ "Music Box",
+ /*011*/ "Vibraphone",
+ /*012*/ "Marimba",
+ /*013*/ "Xylophone",
+ /*014*/ "Tubular Bells",
+ /*015*/ "Dulcimer",
+ /*016*/ "Drawbar Organ",
+ /*017*/ "Percussive Organ",
+ /*018*/ "Rock Organ",
+ /*019*/ "Church Organ",
+ /*020*/ "Reed Organ",
+ /*021*/ "Accordion",
+ /*022*/ "Harmonica",
+ /*023*/ "Tango Accordion",
+ /*024*/ "Acoustic Guitar (nylon)",
+ /*025*/ "Acoustic Guitar (steel)",
+ /*026*/ "Electric Guitar (jazz)",
+ /*027*/ "Electric Guitar (clean)",
+ /*028*/ "Electric Guitar (muted)",
+ /*029*/ "Overdriven Guitar",
+ /*030*/ "Distortion Guitar",
+ /*031*/ "Guitar Harmonics",
+ /*032*/ "Acoustic Bass",
+ /*033*/ "Electric Bass (finger)",
+ /*034*/ "Electric Bass (pick)",
+ /*035*/ "Fretless Bass",
+ /*036*/ "Slap Bass 1",
+ /*037*/ "Slap Bass 2",
+ /*038*/ "Synth Bass 1",
+ /*039*/ "Synth Bass 2",
+ /*040*/ "Violin",
+ /*041*/ "Viola",
+ /*042*/ "Cello",
+ /*043*/ "Contrabass",
+ /*044*/ "Tremolo Strings",
+ /*045*/ "Pizzicato Strings",
+ /*046*/ "Orchestral Harp",
+ /*047*/ "Timpani",
+ /*048*/ "String Ensemble 1",
+ /*049*/ "String Ensemble 2",
+ /*050*/ "SynthStrings 1",
+ /*051*/ "SynthStrings 2",
+ /*052*/ "Choir Aahs",
+ /*053*/ "Voice Oohs",
+ /*054*/ "Synth Voice",
+ /*055*/ "Orchestra Hit",
+ /*056*/ "Trumpet",
+ /*057*/ "Trombone",
+ /*058*/ "Tuba",
+ /*059*/ "Muted Trumpet",
+ /*060*/ "French Horn",
+ /*061*/ "Brass Section",
+ /*062*/ "SynthBrass 1",
+ /*063*/ "SynthBrass 2",
+ /*064*/ "Soprano Sax",
+ /*065*/ "Alto Sax",
+ /*066*/ "Tenor Sax",
+ /*067*/ "Baritone Sax",
+ /*068*/ "Oboe",
+ /*069*/ "English Horn",
+ /*070*/ "Bassoon",
+ /*071*/ "Clarinet",
+ /*072*/ "Piccolo",
+ /*073*/ "Flute",
+ /*074*/ "Recorder",
+ /*075*/ "Pan Flute",
+ /*076*/ "Blown Bottle",
+ /*077*/ "Shakuhachi",
+ /*078*/ "Whistle",
+ /*079*/ "Ocarina",
+ /*080*/ "Lead 1 (square)",
+ /*081*/ "Lead 2 (sawtooth)",
+ /*082*/ "Lead 3 (calliope)",
+ /*083*/ "Lead 4 (chiff)",
+ /*084*/ "Lead 5 (charang)",
+ /*085*/ "Lead 6 (voice)",
+ /*086*/ "Lead 7 (fifths)",
+ /*087*/ "Lead 8 (bass+lead)",
+ /*088*/ "Pad 1 (new age)",
+ /*089*/ "Pad 2 (warm)",
+ /*090*/ "Pad 3 (polysynth)",
+ /*091*/ "Pad 4 (choir)",
+ /*092*/ "Pad 5 (bowed)",
+ /*093*/ "Pad 6 (metallic)",
+ /*094*/ "Pad 7 (halo)",
+ /*095*/ "Pad 8 (sweep)",
+ /*096*/ "FX 1 (rain)",
+ /*097*/ "FX 2 (soundtrack)",
+ /*098*/ "FX 3 (crystal)",
+ /*099*/ "FX 4 (atmosphere)",
+ /*100*/ "FX 5 (brightness)",
+ /*101*/ "FX 6 (goblins)",
+ /*102*/ "FX 7 (echoes)",
+ /*103*/ "FX 8 (sci-fi)",
+ /*104*/ "Sitar",
+ /*105*/ "Banjo",
+ /*106*/ "Shamisen",
+ /*107*/ "Koto",
+ /*108*/ "Kalimba",
+ /*109*/ "Bag pipe",
+ /*110*/ "Fiddle",
+ /*111*/ "Shannai",
+ /*112*/ "Tinkle Bell",
+ /*113*/ "Agogo",
+ /*114*/ "Steel Drums",
+ /*115*/ "Woodblock",
+ /*116*/ "Taiko Drum",
+ /*117*/ "Melodic Tom",
+ /*118*/ "Synth Drum",
+ /*119*/ "Reverse Cymbal",
+ /*120*/ "Guitar Fret Noise",
+ /*121*/ "Breath Noise",
+ /*122*/ "Seashore",
+ /*123*/ "Bird Tweet",
+ /*124*/ "Telephone Ring",
+ /*125*/ "Helicopter",
+ /*126*/ "Applause",
+ /*127*/ "Gunshot"
+};
+
+/* The GM Percussion map is downwards compatible to the MT32 map, which is used in SCI */
+static const char *GmPercussionNames[] = {
+ /*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /*20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /*30*/ 0, 0, 0, 0,
+ /* The preceeding percussions are not covered by the GM standard */
+ /*34*/ "Acoustic Bass Drum",
+ /*35*/ "Bass Drum 1",
+ /*36*/ "Side Stick",
+ /*37*/ "Acoustic Snare",
+ /*38*/ "Hand Clap",
+ /*39*/ "Electric Snare",
+ /*40*/ "Low Floor Tom",
+ /*41*/ "Closed Hi-Hat",
+ /*42*/ "High Floor Tom",
+ /*43*/ "Pedal Hi-Hat",
+ /*44*/ "Low Tom",
+ /*45*/ "Open Hi-Hat",
+ /*46*/ "Low-Mid Tom",
+ /*47*/ "Hi-Mid Tom",
+ /*48*/ "Crash Cymbal 1",
+ /*49*/ "High Tom",
+ /*50*/ "Ride Cymbal 1",
+ /*51*/ "Chinese Cymbal",
+ /*52*/ "Ride Bell",
+ /*53*/ "Tambourine",
+ /*54*/ "Splash Cymbal",
+ /*55*/ "Cowbell",
+ /*56*/ "Crash Cymbal 2",
+ /*57*/ "Vibraslap",
+ /*58*/ "Ride Cymbal 2",
+ /*59*/ "Hi Bongo",
+ /*60*/ "Low Bongo",
+ /*61*/ "Mute Hi Conga",
+ /*62*/ "Open Hi Conga",
+ /*63*/ "Low Conga",
+ /*64*/ "High Timbale",
+ /*65*/ "Low Timbale",
+ /*66*/ "High Agogo",
+ /*67*/ "Low Agogo",
+ /*68*/ "Cabasa",
+ /*69*/ "Maracas",
+ /*70*/ "Short Whistle",
+ /*71*/ "Long Whistle",
+ /*72*/ "Short Guiro",
+ /*73*/ "Long Guiro",
+ /*74*/ "Claves",
+ /*75*/ "Hi Wood Block",
+ /*76*/ "Low Wood Block",
+ /*77*/ "Mute Cuica",
+ /*78*/ "Open Cuica",
+ /*79*/ "Mute Triangle",
+ /*80*/ "Open Triangle"
+};
+
+/*******************************************
+ * Fancy instrument mappings begin here... *
+ *******************************************/
+
+
+static const Mt32ToGmMap Mt32PresetTimbreMaps[] = {
+ /*000*/ {"AcouPiano1", 0, MIDI_UNMAPPED},
+ /*001*/ {"AcouPiano2", 1, MIDI_UNMAPPED},
+ /*002*/ {"AcouPiano3", 0, MIDI_UNMAPPED},
+ /*003*/ {"ElecPiano1", 4, MIDI_UNMAPPED},
+ /*004*/ {"ElecPiano2", 5, MIDI_UNMAPPED},
+ /*005*/ {"ElecPiano3", 4, MIDI_UNMAPPED},
+ /*006*/ {"ElecPiano4", 5, MIDI_UNMAPPED},
+ /*007*/ {"Honkytonk ", 3, MIDI_UNMAPPED},
+ /*008*/ {"Elec Org 1", 16, MIDI_UNMAPPED},
+ /*009*/ {"Elec Org 2", 17, MIDI_UNMAPPED},
+ /*010*/ {"Elec Org 3", 18, MIDI_UNMAPPED},
+ /*011*/ {"Elec Org 4", 18, MIDI_UNMAPPED},
+ /*012*/ {"Pipe Org 1", 19, MIDI_UNMAPPED},
+ /*013*/ {"Pipe Org 2", 19, MIDI_UNMAPPED},
+ /*014*/ {"Pipe Org 3", 20, MIDI_UNMAPPED},
+ /*015*/ {"Accordion ", 21, MIDI_UNMAPPED},
+ /*016*/ {"Harpsi 1 ", 6, MIDI_UNMAPPED},
+ /*017*/ {"Harpsi 2 ", 6, MIDI_UNMAPPED},
+ /*018*/ {"Harpsi 3 ", 6, MIDI_UNMAPPED},
+ /*019*/ {"Clavi 1 ", 7, MIDI_UNMAPPED},
+ /*020*/ {"Clavi 2 ", 7, MIDI_UNMAPPED},
+ /*021*/ {"Clavi 3 ", 7, MIDI_UNMAPPED},
+ /*022*/ {"Celesta 1 ", 8, MIDI_UNMAPPED},
+ /*023*/ {"Celesta 2 ", 8, MIDI_UNMAPPED},
+ /*024*/ {"Syn Brass1", 62, MIDI_UNMAPPED},
+ /*025*/ {"Syn Brass2", 63, MIDI_UNMAPPED},
+ /*026*/ {"Syn Brass3", 62, MIDI_UNMAPPED},
+ /*027*/ {"Syn Brass4", 63, MIDI_UNMAPPED},
+ /*028*/ {"Syn Bass 1", 38, MIDI_UNMAPPED},
+ /*029*/ {"Syn Bass 2", 39, MIDI_UNMAPPED},
+ /*030*/ {"Syn Bass 3", 38, MIDI_UNMAPPED},
+ /*031*/ {"Syn Bass 4", 39, MIDI_UNMAPPED},
+ /*032*/ {"Fantasy ", 88, MIDI_UNMAPPED},
+ /*033*/ {"Harmo Pan ", 89, MIDI_UNMAPPED},
+ /*034*/ {"Chorale ", 52, MIDI_UNMAPPED},
+ /*035*/ {"Glasses ", 98, MIDI_UNMAPPED},
+ /*036*/ {"Soundtrack", 97, MIDI_UNMAPPED},
+ /*037*/ {"Atmosphere", 99, MIDI_UNMAPPED},
+ /*038*/ {"Warm Bell ", 89, MIDI_UNMAPPED},
+ /*039*/ {"Funny Vox ", 85, MIDI_UNMAPPED},
+ /*040*/ {"Echo Bell ", 39, MIDI_UNMAPPED},
+ /*041*/ {"Ice Rain ", 101, MIDI_UNMAPPED},
+ /*042*/ {"Oboe 2001 ", 68, MIDI_UNMAPPED},
+ /*043*/ {"Echo Pan ", 87, MIDI_UNMAPPED},
+ /*044*/ {"DoctorSolo", 86, MIDI_UNMAPPED},
+ /*045*/ {"Schooldaze", 103, MIDI_UNMAPPED},
+ /*046*/ {"BellSinger", 88, MIDI_UNMAPPED},
+ /*047*/ {"SquareWave", 80, MIDI_UNMAPPED},
+ /*048*/ {"Str Sect 1", 48, MIDI_UNMAPPED},
+ /*049*/ {"Str Sect 2", 48, MIDI_UNMAPPED},
+ /*050*/ {"Str Sect 3", 49, MIDI_UNMAPPED},
+ /*051*/ {"Pizzicato ", 45, MIDI_UNMAPPED},
+ /*052*/ {"Violin 1 ", 40, MIDI_UNMAPPED},
+ /*053*/ {"Violin 2 ", 40, MIDI_UNMAPPED},
+ /*054*/ {"Cello 1 ", 42, MIDI_UNMAPPED},
+ /*055*/ {"Cello 2 ", 42, MIDI_UNMAPPED},
+ /*056*/ {"Contrabass", 43, MIDI_UNMAPPED},
+ /*057*/ {"Harp 1 ", 46, MIDI_UNMAPPED},
+ /*058*/ {"Harp 2 ", 46, MIDI_UNMAPPED},
+ /*059*/ {"Guitar 1 ", 24, MIDI_UNMAPPED},
+ /*060*/ {"Guitar 2 ", 25, MIDI_UNMAPPED},
+ /*061*/ {"Elec Gtr 1", 26, MIDI_UNMAPPED},
+ /*062*/ {"Elec Gtr 2", 27, MIDI_UNMAPPED},
+ /*063*/ {"Sitar ", 104, MIDI_UNMAPPED},
+ /*064*/ {"Acou Bass1", 32, MIDI_UNMAPPED},
+ /*065*/ {"Acou Bass2", 33, MIDI_UNMAPPED},
+ /*066*/ {"Elec Bass1", 34, MIDI_UNMAPPED},
+ /*067*/ {"Elec Bass2", 39, MIDI_UNMAPPED},
+ /*068*/ {"Slap Bass1", 36, MIDI_UNMAPPED},
+ /*069*/ {"Slap Bass2", 37, MIDI_UNMAPPED},
+ /*070*/ {"Fretless 1", 35, MIDI_UNMAPPED},
+ /*071*/ {"Fretless 2", 35, MIDI_UNMAPPED},
+ /*072*/ {"Flute 1 ", 73, MIDI_UNMAPPED},
+ /*073*/ {"Flute 2 ", 73, MIDI_UNMAPPED},
+ /*074*/ {"Piccolo 1 ", 72, MIDI_UNMAPPED},
+ /*075*/ {"Piccolo 2 ", 72, MIDI_UNMAPPED},
+ /*076*/ {"Recorder ", 74, MIDI_UNMAPPED},
+ /*077*/ {"Panpipes ", 75, MIDI_UNMAPPED},
+ /*078*/ {"Sax 1 ", 64, MIDI_UNMAPPED},
+ /*079*/ {"Sax 2 ", 65, MIDI_UNMAPPED},
+ /*080*/ {"Sax 3 ", 66, MIDI_UNMAPPED},
+ /*081*/ {"Sax 4 ", 67, MIDI_UNMAPPED},
+ /*082*/ {"Clarinet 1", 71, MIDI_UNMAPPED},
+ /*083*/ {"Clarinet 2", 71, MIDI_UNMAPPED},
+ /*084*/ {"Oboe ", 68, MIDI_UNMAPPED},
+ /*085*/ {"Engl Horn ", 69, MIDI_UNMAPPED},
+ /*086*/ {"Bassoon ", 70, MIDI_UNMAPPED},
+ /*087*/ {"Harmonica ", 22, MIDI_UNMAPPED},
+ /*088*/ {"Trumpet 1 ", 56, MIDI_UNMAPPED},
+ /*089*/ {"Trumpet 2 ", 56, MIDI_UNMAPPED},
+ /*090*/ {"Trombone 1", 57, MIDI_UNMAPPED},
+ /*091*/ {"Trombone 2", 57, MIDI_UNMAPPED},
+ /*092*/ {"Fr Horn 1 ", 60, MIDI_UNMAPPED},
+ /*093*/ {"Fr Horn 2 ", 60, MIDI_UNMAPPED},
+ /*094*/ {"Tuba ", 58, MIDI_UNMAPPED},
+ /*095*/ {"Brs Sect 1", 61, MIDI_UNMAPPED},
+ /*096*/ {"Brs Sect 2", 61, MIDI_UNMAPPED},
+ /*097*/ {"Vibe 1 ", 11, MIDI_UNMAPPED},
+ /*098*/ {"Vibe 2 ", 11, MIDI_UNMAPPED},
+ /*099*/ {"Syn Mallet", 15, MIDI_UNMAPPED},
+ /*100*/ {"Wind Bell ", 88, MIDI_UNMAPPED},
+ /*101*/ {"Glock ", 9, MIDI_UNMAPPED},
+ /*102*/ {"Tube Bell ", 14, MIDI_UNMAPPED},
+ /*103*/ {"Xylophone ", 13, MIDI_UNMAPPED},
+ /*104*/ {"Marimba ", 12, MIDI_UNMAPPED},
+ /*105*/ {"Koto ", 107, MIDI_UNMAPPED},
+ /*106*/ {"Sho ", 111, MIDI_UNMAPPED},
+ /*107*/ {"Shakuhachi", 77, MIDI_UNMAPPED},
+ /*108*/ {"Whistle 1 ", 78, MIDI_UNMAPPED},
+ /*109*/ {"Whistle 2 ", 78, MIDI_UNMAPPED},
+ /*110*/ {"BottleBlow", 76, MIDI_UNMAPPED},
+ /*111*/ {"BreathPipe", 121, MIDI_UNMAPPED},
+ /*112*/ {"Timpani ", 47, MIDI_UNMAPPED},
+ /*113*/ {"MelodicTom", 117, MIDI_UNMAPPED},
+ /*114*/ {"Deep Snare", MIDI_MAPPED_TO_RHYTHM, 37},
+ /*115*/ {"Elec Perc1", 115, MIDI_UNMAPPED}, /* ? */
+ /*116*/ {"Elec Perc2", 118, MIDI_UNMAPPED}, /* ? */
+ /*117*/ {"Taiko ", 116, MIDI_UNMAPPED},
+ /*118*/ {"Taiko Rim ", 118, MIDI_UNMAPPED},
+ /*119*/ {"Cymbal ", MIDI_MAPPED_TO_RHYTHM, 50},
+ /*120*/ {"Castanets ", MIDI_UNMAPPED, MIDI_UNMAPPED},
+ /*121*/ {"Triangle ", 112, MIDI_UNMAPPED},
+ /*122*/ {"Orche Hit ", 55, MIDI_UNMAPPED},
+ /*123*/ {"Telephone ", 124, MIDI_UNMAPPED},
+ /*124*/ {"Bird Tweet", 123, MIDI_UNMAPPED},
+ /*125*/ {"OneNoteJam", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ? */
+ /*126*/ {"WaterBells", 98, MIDI_UNMAPPED},
+ /*127*/ {"JungleTune", MIDI_UNMAPPED, MIDI_UNMAPPED} /* ? */
+};
+
+static const Mt32ToGmMap Mt32RhythmTimbreMaps[] = {
+ /*00*/ {"Acou BD ", MIDI_MAPPED_TO_RHYTHM, 34},
+ /*01*/ {"Acou SD ", MIDI_MAPPED_TO_RHYTHM, 37},
+ /*02*/ {"Acou HiTom", 117, 49},
+ /*03*/ {"AcouMidTom", 117, 46},
+ /*04*/ {"AcouLowTom", 117, 40},
+ /*05*/ {"Elec SD ", MIDI_MAPPED_TO_RHYTHM, 39},
+ /*06*/ {"Clsd HiHat", MIDI_MAPPED_TO_RHYTHM, 41},
+ /*07*/ {"OpenHiHat1", MIDI_MAPPED_TO_RHYTHM, 45},
+ /*08*/ {"Crash Cym ", MIDI_MAPPED_TO_RHYTHM, 48},
+ /*09*/ {"Ride Cym ", MIDI_MAPPED_TO_RHYTHM, 50},
+ /*10*/ {"Rim Shot ", MIDI_MAPPED_TO_RHYTHM, 36},
+ /*11*/ {"Hand Clap ", MIDI_MAPPED_TO_RHYTHM, 38},
+ /*12*/ {"Cowbell ", MIDI_MAPPED_TO_RHYTHM, 55},
+ /*13*/ {"Mt HiConga", MIDI_MAPPED_TO_RHYTHM, 61},
+ /*14*/ {"High Conga", MIDI_MAPPED_TO_RHYTHM, 62},
+ /*15*/ {"Low Conga ", MIDI_MAPPED_TO_RHYTHM, 63},
+ /*16*/ {"Hi Timbale", MIDI_MAPPED_TO_RHYTHM, 64},
+ /*17*/ {"LowTimbale", MIDI_MAPPED_TO_RHYTHM, 65},
+ /*18*/ {"High Bongo", MIDI_MAPPED_TO_RHYTHM, 59},
+ /*19*/ {"Low Bongo ", MIDI_MAPPED_TO_RHYTHM, 60},
+ /*20*/ {"High Agogo", 113, 66},
+ /*21*/ {"Low Agogo ", 113, 67},
+ /*22*/ {"Tambourine", MIDI_MAPPED_TO_RHYTHM, 53},
+ /*23*/ {"Claves ", MIDI_MAPPED_TO_RHYTHM, 74},
+ /*24*/ {"Maracas ", MIDI_MAPPED_TO_RHYTHM, 69},
+ /*25*/ {"SmbaWhis L", 78, 71},
+ /*26*/ {"SmbaWhis S", 78, 70},
+ /*27*/ {"Cabasa ", MIDI_MAPPED_TO_RHYTHM, 68},
+ /*28*/ {"Quijada ", MIDI_MAPPED_TO_RHYTHM, 72},
+ /*29*/ {"OpenHiHat2", MIDI_MAPPED_TO_RHYTHM, 43}
+};
+
+static const uint8 Mt32PresetRhythmKeymap[] = {
+ MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED,
+ MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED,
+ MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED,
+ MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, 34, 34, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50, MIDI_UNMAPPED, MIDI_UNMAPPED, 53, MIDI_UNMAPPED, 55, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, 59,
+ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ 70, 71, 72, MIDI_UNMAPPED, 74, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED,
+ MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED,
+ MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED,
+ MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED,
+ MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED,
+ MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED, MIDI_UNMAPPED
+};
+
+/* +++ - Don't change unless you've got a good reason
+ ++ - Looks good, sounds ok
+ + - Not too bad, but is it right?
+ ? - Where do I map this one?
+ ?? - Any good ideas?
+ ??? - I'm clueless?
+ R - Rhythm... */
+static const Mt32ToGmMap Mt32MemoryTimbreMaps[] = {
+ {"AccPnoKA2 ", 1, MIDI_UNMAPPED}, /* ++ (KQ1) */
+ {"Acou BD ", MIDI_MAPPED_TO_RHYTHM, 34}, /* R (PQ2) */
+ {"Acou SD ", MIDI_MAPPED_TO_RHYTHM, 37}, /* R (PQ2) */
+ {"AcouPnoKA ", 0, MIDI_UNMAPPED}, /* ++ (KQ1) */
+ {"BASS ", 32, MIDI_UNMAPPED}, /* + (LSL3) */
+ {"BASSOONPCM", 70, MIDI_UNMAPPED}, /* + (CB) */
+ {"BEACH WAVE", 122, MIDI_UNMAPPED}, /* + (LSL3) */
+ {"BagPipes ", 109, MIDI_UNMAPPED},
+ {"BassPizzMS", 45, MIDI_UNMAPPED}, /* ++ (HQ) */
+ {"BassoonKA ", 70, MIDI_UNMAPPED}, /* ++ (KQ1) */
+ {"Bell MS", 112, MIDI_UNMAPPED}, /* ++ (iceMan) */
+ {"Bells MS", 112, MIDI_UNMAPPED}, /* + (HQ) */
+ {"Big Bell ", 14, MIDI_UNMAPPED}, /* + (CB) */
+ {"Bird Tweet", 123, MIDI_UNMAPPED},
+ {"BrsSect MS", 61, MIDI_UNMAPPED}, /* +++ (iceMan) */
+ {"CLAPPING ", 126, MIDI_UNMAPPED}, /* ++ (LSL3) */
+ {"Cabasa ", MIDI_MAPPED_TO_RHYTHM, 68}, /* R (HBoG) */
+ {"Calliope ", 82, MIDI_UNMAPPED}, /* +++ (HQ) */
+ {"CelticHarp", 46, MIDI_UNMAPPED}, /* ++ (CoC) */
+ {"Chicago MS", 1, MIDI_UNMAPPED}, /* ++ (iceMan) */
+ {"Chop ", 117, MIDI_UNMAPPED},
+ {"Chorale MS", 52, MIDI_UNMAPPED}, /* + (CoC) */
+ {"ClarinetMS", 71, MIDI_UNMAPPED},
+ {"Claves ", MIDI_MAPPED_TO_RHYTHM, 74}, /* R (PQ2) */
+ {"Claw MS", 118, MIDI_UNMAPPED}, /* + (HQ) */
+ {"ClockBell ", 14, MIDI_UNMAPPED}, /* + (CB) */
+ {"ConcertCym", MIDI_MAPPED_TO_RHYTHM, 54}, /* R ? (KQ1) */
+ {"Conga MS", MIDI_MAPPED_TO_RHYTHM, 63}, /* R (HQ) */
+ {"CoolPhone ", 124, MIDI_UNMAPPED}, /* ++ (LSL3) */
+ {"CracklesMS", 115, MIDI_UNMAPPED}, /* ? (CoC, HQ) */
+ {"CreakyD MS", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ??? (KQ1) */
+ {"Cricket ", 120, MIDI_UNMAPPED}, /* ? (CB) */
+ {"CrshCymbMS", MIDI_MAPPED_TO_RHYTHM, 56}, /* R +++ (iceMan) */
+ {"CstlGateMS", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ? (HQ) */
+ {"CymSwellMS", MIDI_MAPPED_TO_RHYTHM, 54}, /* R ? (CoC, HQ) */
+ {"CymbRollKA", MIDI_MAPPED_TO_RHYTHM, 56}, /* R ? (KQ1) */
+ {"Cymbal Lo ", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* R ? (LSL3) */
+ {"card ", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ? (HBoG) */
+ {"DirtGtr MS", 30, MIDI_UNMAPPED}, /* + (iceMan) */
+ {"DirtGtr2MS", 29, MIDI_UNMAPPED}, /* + (iceMan) */
+ {"E Bass MS", 33, MIDI_UNMAPPED}, /* + (SQ3) */
+ {"ElecBassMS", 33, MIDI_UNMAPPED},
+ {"ElecGtr MS", 27, MIDI_UNMAPPED}, /* ++ (iceMan) */
+ {"EnglHornMS", 69, MIDI_UNMAPPED},
+ {"FantasiaKA", 88, MIDI_UNMAPPED},
+ {"Fantasy ", 99, MIDI_UNMAPPED}, /* + (PQ2) */
+ {"Fantasy2MS", 99, MIDI_UNMAPPED}, /* ++ (CoC, HQ) */
+ {"Filter MS", 95, MIDI_UNMAPPED}, /* +++ (iceMan) */
+ {"Filter2 MS", 95, MIDI_UNMAPPED}, /* ++ (iceMan) */
+ {"Flame2 MS", 121, MIDI_UNMAPPED}, /* ? (HQ) */
+ {"Flames MS", 121, MIDI_UNMAPPED}, /* ? (HQ) */
+ {"Flute MS", 73, MIDI_UNMAPPED}, /* +++ (HQ) */
+ {"FogHorn MS", 58, MIDI_UNMAPPED},
+ {"FrHorn1 MS", 60, MIDI_UNMAPPED}, /* +++ (HQ) */
+ {"FunnyTrmp ", 56, MIDI_UNMAPPED}, /* ++ (CB) */
+ {"GameSnd MS", 80, MIDI_UNMAPPED},
+ {"Glock MS", 9, MIDI_UNMAPPED}, /* +++ (HQ) */
+ {"Gunshot ", 127, MIDI_UNMAPPED}, /* +++ (CB) */
+ {"Hammer MS", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ? (HQ) */
+ {"Harmonica2", 22, MIDI_UNMAPPED}, /* +++ (CB) */
+ {"Harpsi 1 ", 6, MIDI_UNMAPPED}, /* + (HBoG) */
+ {"Harpsi 2 ", 6, MIDI_UNMAPPED}, /* +++ (CB) */
+ {"Heart MS", 116, MIDI_UNMAPPED}, /* ? (iceMan) */
+ {"Horse1 MS", 115, MIDI_UNMAPPED}, /* ? (CoC, HQ) */
+ {"Horse2 MS", 115, MIDI_UNMAPPED}, /* ? (CoC, HQ) */
+ {"InHale MS", 121, MIDI_UNMAPPED}, /* ++ (iceMan) */
+ {"KNIFE ", 120, MIDI_UNMAPPED}, /* ? (LSL3) */
+ {"KenBanjo ", 105, MIDI_UNMAPPED}, /* +++ (CB) */
+ {"Kiss MS", 25, MIDI_UNMAPPED}, /* ++ (HQ) */
+ {"KongHit ", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ??? (KQ1) */
+ {"Koto ", 107, MIDI_UNMAPPED}, /* +++ (PQ2) */
+ {"Laser MS", 81, MIDI_UNMAPPED}, /* ?? (HQ) */
+ {"Meeps MS", 62, MIDI_UNMAPPED}, /* ? (HQ) */
+ {"MTrak MS", 62, MIDI_UNMAPPED}, /* ?? (iceMan) */
+ {"MachGun MS", 127, MIDI_UNMAPPED}, /* ? (iceMan) */
+ {"OCEANSOUND", 122, MIDI_UNMAPPED}, /* + (LSL3) */
+ {"Oboe 2001 ", 68, MIDI_UNMAPPED}, /* + (PQ2) */
+ {"Ocean MS", 122, MIDI_UNMAPPED}, /* + (iceMan) */
+ {"PPG 2.3 MS", 75, MIDI_UNMAPPED}, /* ? (iceMan) */
+ {"PianoCrank", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ? (CB) */
+ {"PicSnareMS", MIDI_MAPPED_TO_RHYTHM, 39}, /* R ? (iceMan) */
+ {"PiccoloKA ", 72, MIDI_UNMAPPED}, /* +++ (KQ1) */
+ {"PinkBassMS", 39, MIDI_UNMAPPED},
+ {"Pizz2 ", 45, MIDI_UNMAPPED}, /* ++ (CB) */
+ {"Portcullis", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ? (KQ1) */
+ {"Raspbry MS", 81, MIDI_UNMAPPED}, /* ? (HQ) */
+ {"RatSqueek ", 72, MIDI_UNMAPPED}, /* ? (CB, CoC) */
+ {"Record78 ", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* +++ (CB) */
+ {"RecorderMS", 74, MIDI_UNMAPPED}, /* +++ (CoC) */
+ {"Red Baron ", 125, MIDI_UNMAPPED}, /* ? (CB) */
+ {"ReedPipMS ", 20, MIDI_UNMAPPED}, /* +++ (Coc) */
+ {"RevCymb MS", 119, MIDI_UNMAPPED},
+ {"RifleShot ", 127, MIDI_UNMAPPED}, /* + (CB) */
+ {"RimShot MS", MIDI_MAPPED_TO_RHYTHM, 36}, /* R */
+ {"SHOWER ", 52, MIDI_UNMAPPED}, /* ? (LSL3) */
+ {"SQ Bass MS", 32, MIDI_UNMAPPED}, /* + (SQ3) */
+ {"ShakuVibMS", 79, MIDI_UNMAPPED}, /* + (iceMan) */
+ {"SlapBassMS", 36, MIDI_UNMAPPED}, /* +++ (iceMan) */
+ {"Snare MS", MIDI_MAPPED_TO_RHYTHM, 37}, /* R (HQ) */
+ {"Some Birds", 123, MIDI_UNMAPPED}, /* + (CB) */
+ {"Sonar MS", 78, MIDI_UNMAPPED}, /* ? (iceMan) */
+ {"Soundtrk2 ", 97, MIDI_UNMAPPED}, /* +++ (CB) */
+ {"Soundtrack", 97, MIDI_UNMAPPED}, /* ++ (CoC) */
+ {"SqurWaveMS", 80, MIDI_UNMAPPED},
+ {"StabBassMS", 34, MIDI_UNMAPPED}, /* + (iceMan) */
+ {"SteelDrmMS", 114, MIDI_UNMAPPED}, /* +++ (iceMan) */
+ {"StrSect1MS", 48, MIDI_UNMAPPED}, /* ++ (HQ) */
+ {"String MS", 45, MIDI_UNMAPPED}, /* + (CoC) */
+ {"Syn-Choir ", 91, MIDI_UNMAPPED},
+ {"Syn Brass4", 63, MIDI_UNMAPPED}, /* ++ (PQ2) */
+ {"SynBass MS", 38, MIDI_UNMAPPED},
+ {"SwmpBackgr", 120, MIDI_UNMAPPED}, /* ?? (CB,HQ) */
+ {"T-Bone2 MS", 57, MIDI_UNMAPPED}, /* +++ (HQ) */
+ {"Taiko ", 116, 34}, /* +++ (Coc) */
+ {"Taiko Rim ", 118, 36}, /* +++ (LSL3) */
+ {"Timpani1 ", 47, MIDI_UNMAPPED}, /* +++ (CB) */
+ {"Tom MS", 117, 47}, /* +++ (iceMan) */
+ {"Toms MS", 117, 47}, /* +++ (CoC, HQ) */
+ {"Tpt1prtl ", 56, MIDI_UNMAPPED}, /* +++ (KQ1) */
+ {"TriangleMS", 112, 80}, /* R (CoC) */
+ {"Trumpet 1 ", 56, MIDI_UNMAPPED}, /* +++ (CoC) */
+ {"Type MS", 114, MIDI_UNMAPPED}, /* ? (iceMan) */
+ {"WaterBells", 98, MIDI_UNMAPPED}, /* + (PQ2) */
+ {"WaterFallK", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ? (KQ1) */
+ {"Whiporill ", 123, MIDI_UNMAPPED}, /* + (CB) */
+ {"Wind ", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ? (CB) */
+ {"Wind MS", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ? (HQ, iceMan) */
+ {"Wind2 MS", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ? (CoC) */
+ {"Woodpecker", 115, MIDI_UNMAPPED}, /* ? (CB) */
+ {"WtrFall MS", MIDI_UNMAPPED, MIDI_UNMAPPED}, /* ? (CoC, HQ, iceMan) */
+ {0, 0, 0}
+};
+
+} // End of namespace Sci
diff --git a/engines/sci/sound/softseq/midi.cpp b/engines/sci/sound/softseq/midi.cpp
index 7951387762..d32d0c529b 100644
--- a/engines/sci/sound/softseq/midi.cpp
+++ b/engines/sci/sound/softseq/midi.cpp
@@ -31,6 +31,7 @@
#include "sci/resource.h"
#include "sci/sound/softseq/mididriver.h"
+#include "sci/sound/softseq/map-mt32-to-gm.h"
namespace Sci {
@@ -63,6 +64,11 @@ private:
void readMt32Patch(const byte *data, int size);
void readMt32DrvData();
+ void mapMt32ToGm(byte *data, size_t size);
+ uint8 lookupGmInstrument(const char *iname);
+ uint8 lookupGmRhythmKey(const char *iname);
+ uint8 getGmInstrument(const Mt32ToGmMap &Mt32Ins);
+
void sendMt32SysEx(const uint32 addr, Common::SeekableReadStream *str, int len, bool noDelay);
void sendMt32SysEx(const uint32 addr, const byte *buf, int len, bool noDelay);
void setMt32Volume(byte volume);
@@ -83,7 +89,7 @@ private:
uint8 hold;
uint8 volume;
- Channel() : mappedPatch(0xff), patch(0xff), velocityMapIdx(0), playing(false),
+ Channel() : mappedPatch(MIDI_UNMAPPED), patch(MIDI_UNMAPPED), velocityMapIdx(0), playing(false),
keyShift(0), volAdjust(0), pan(0x80), hold(0), volume(0x7f) { }
};
@@ -101,6 +107,11 @@ private:
uint8 _patchMap[128];
uint8 _velocityMapIdx[128];
uint8 _velocityMap[4][128];
+
+ // These are extensions used for our own MT-32 to GM mapping
+ uint8 _pitchBendRange[128];
+ uint8 _percussionVelocityScale[128];
+
byte _goodbyeMsg[20];
byte _sysExBuf[kMaxSysExSize];
};
@@ -123,14 +134,28 @@ MidiPlayer_Midi::~MidiPlayer_Midi() {
}
void MidiPlayer_Midi::noteOn(int channel, int note, int velocity) {
+ uint8 patch = _channels[channel].mappedPatch;
+
if (channel == MIDI_RHYTHM_CHANNEL) {
- note = _percussionMap[note];
- if (note == 0xff)
+ if (_percussionMap[note] == MIDI_UNMAPPED) {
+ debugC(kDebugLevelSound, "[Midi] Percussion instrument %i is unmapped", note);
return;
- } else {
- if (_channels[channel].mappedPatch == 0xff)
+ }
+
+ note = _percussionMap[note];
+ // Scale velocity;
+ velocity = velocity * _percussionVelocityScale[note] / 127;
+ } else if (patch >= 128) {
+ if (patch == MIDI_UNMAPPED)
return;
+ // Map to rhythm
+ channel = MIDI_RHYTHM_CHANNEL;
+ note = patch - 128;
+
+ // Scale velocity;
+ velocity = velocity * _percussionVelocityScale[note] / 127;
+ } else {
int8 keyshift = _keyShift[channel];
int shiftNote = note + keyshift;
@@ -210,12 +235,13 @@ void MidiPlayer_Midi::setPatch(int channel, int patch) {
_channels[channel].patch = patch;
_channels[channel].velocityMapIdx = _velocityMapIdx[patch];
- if (_channels[channel].mappedPatch == 0xff)
+ if (_channels[channel].mappedPatch == MIDI_UNMAPPED)
resetVol = true;
_channels[channel].mappedPatch = _patchMap[patch];
- if (_patchMap[patch] == 0xff) {
+ if (_patchMap[patch] == MIDI_UNMAPPED) {
+ debugC(kDebugLevelSound, "[Midi] Channel %i set to unmapped patch %i", channel, patch);
_driver->send(0xb0 | channel, 0x7b, 0);
_driver->send(0xb0 | channel, 0x40, 0);
return;
@@ -233,6 +259,10 @@ void MidiPlayer_Midi::setPatch(int channel, int patch) {
controlChange(channel, 0x07, _channels[channel].volume);
}
+ uint8 bendRange = _pitchBendRange[patch];
+ if (bendRange != MIDI_UNMAPPED)
+ _driver->setPitchBendRange(channel, bendRange);
+
_driver->send(0xc0 | channel, _patchMap[patch], 0);
}
@@ -539,6 +569,151 @@ void MidiPlayer_Midi::readMt32DrvData() {
}
}
+byte MidiPlayer_Midi::lookupGmInstrument(const char *iname) {
+ int i = 0;
+
+ while (Mt32MemoryTimbreMaps[i].name) {
+ if (scumm_strnicmp(iname, Mt32MemoryTimbreMaps[i].name, 10) == 0)
+ return getGmInstrument(Mt32MemoryTimbreMaps[i]);
+ i++;
+ }
+ return MIDI_UNMAPPED;
+}
+
+byte MidiPlayer_Midi::lookupGmRhythmKey(const char *iname) {
+ int i = 0;
+
+ while (Mt32MemoryTimbreMaps[i].name) {
+ if (scumm_strnicmp(iname, Mt32MemoryTimbreMaps[i].name, 10) == 0)
+ return Mt32MemoryTimbreMaps[i].gmRhythmKey;
+ i++;
+ }
+ return MIDI_UNMAPPED;
+}
+
+uint8 MidiPlayer_Midi::getGmInstrument(const Mt32ToGmMap &Mt32Ins) {
+ if (Mt32Ins.gmInstr == MIDI_MAPPED_TO_RHYTHM)
+ return Mt32Ins.gmRhythmKey + 0x80;
+ else
+ return Mt32Ins.gmInstr;
+}
+
+void MidiPlayer_Midi::mapMt32ToGm(byte *data, size_t size) {
+ // FIXME: Clean this up
+ int memtimbres, patches;
+ uint8 group, number, keyshift, finetune, bender_range;
+ uint8 *patchpointer;
+ uint32 pos;
+ int i;
+
+ for (i = 0; i < 128; i++) {
+ _patchMap[i] = getGmInstrument(Mt32PresetTimbreMaps[i]);
+ _pitchBendRange[i] = 12;
+ }
+
+ for (i = 0; i < 128; i++)
+ _percussionMap[i] = Mt32PresetRhythmKeymap[i];
+
+ memtimbres = *(data + 0x1eb);
+ pos = 0x1ec + memtimbres * 0xf6;
+
+ if (size > pos && ((0x100 * *(data + pos) + *(data + pos + 1)) == 0xabcd)) {
+ patches = 96;
+ pos += 2 + 8 * 48;
+ } else
+ patches = 48;
+
+ debugC(kDebugLevelSound, "[MT32-to-GM] %d MT-32 Patches detected", patches);
+ debugC(kDebugLevelSound, "[MT32-to-GM] %d MT-32 Memory Timbres", memtimbres);
+
+ debugC(kDebugLevelSound, "\n[MT32-to-GM] Mapping patches..");
+
+ for (i = 0; i < patches; i++) {
+ char name[11];
+
+ if (i < 48)
+ patchpointer = data + 0x6b + 8 * i;
+ else
+ patchpointer = data + 0x1ec + 8 * (i - 48) + memtimbres * 0xf6 + 2;
+
+ group = *patchpointer;
+ number = *(patchpointer + 1);
+ keyshift = *(patchpointer + 2);
+ finetune = *(patchpointer + 3);
+ bender_range = *(patchpointer + 4);
+
+ debugCN(kDebugLevelSound, " [%03d] ", i);
+
+ switch (group) {
+ case 1:
+ number += 64;
+ // Fall through
+ case 0:
+ _patchMap[i] = getGmInstrument(Mt32PresetTimbreMaps[number]);
+ debugCN(kDebugLevelSound, "%s -> ", Mt32PresetTimbreMaps[number].name);
+ break;
+ case 2:
+ strncpy(name, (const char *)data + 0x1ec + number * 0xf6, 10);
+ name[10] = 0;
+ _patchMap[i] = lookupGmInstrument(name);
+ debugCN(kDebugLevelSound, "%s -> ", name);
+ break;
+ case 3:
+ _patchMap[i] = getGmInstrument(Mt32RhythmTimbreMaps[number]);
+ debugCN(kDebugLevelSound, "%s -> ", Mt32RhythmTimbreMaps[number].name);
+ break;
+ default:
+ break;
+ }
+
+ if (_patchMap[i] == MIDI_UNMAPPED) {
+ debugC(kDebugLevelSound, "[Unmapped]");
+ } else {
+ if (_patchMap[i] >= 128) {
+ debugC(kDebugLevelSound, "%s [Rhythm]", GmPercussionNames[_patchMap[i] - 128]);
+ } else {
+ debugC(kDebugLevelSound, "%s", GmInstrumentNames[_patchMap[i]]);
+ }
+ }
+
+ _keyShift[i] = CLIP<uint8>(keyshift, 0, 48) - 24;
+ _pitchBendRange[i] = CLIP<uint8>(bender_range, 0, 24);
+ }
+
+ if (size > pos && ((0x100 * *(data + pos) + *(data + pos + 1)) == 0xdcba)) {
+ debugC(kDebugLevelSound, "\n[MT32-to-GM] Mapping percussion..");
+
+ for (i = 0; i < 64 ; i++) {
+ number = *(data + pos + 4 * i + 2);
+
+ debugCN(kDebugLevelSound, " [%03d] ", i + 23);
+
+ if (number < 64) {
+ char name[11];
+ strncpy(name, (const char *)data + 0x1ec + number * 0xf6, 10);
+ name[10] = 0;
+ debugCN(kDebugLevelSound, "%s -> ", name);
+ _percussionMap[i + 23] = lookupGmRhythmKey(name);
+ } else {
+ if (number < 94) {
+ debugCN(kDebugLevelSound, "%s -> ", Mt32RhythmTimbreMaps[number - 64].name);
+ _percussionMap[i + 23] = Mt32RhythmTimbreMaps[number - 64].gmRhythmKey;
+ } else {
+ debugCN(kDebugLevelSound, "[Key %03i] -> ", number);
+ _percussionMap[i + 23] = MIDI_UNMAPPED;
+ }
+ }
+
+ if (_percussionMap[i + 23] == MIDI_UNMAPPED)
+ debugC(kDebugLevelSound, "[Unmapped]");
+ else
+ debugC(kDebugLevelSound, "%s", GmPercussionNames[_percussionMap[i + 23]]);
+
+ _percussionVelocityScale[i + 23] = *(data + pos + 4 * i + 3) * 127 / 100;
+ }
+ }
+}
+
void MidiPlayer_Midi::setMt32Volume(byte volume) {
sendMt32SysEx(0x100016, &volume, 1);
}
@@ -567,6 +742,8 @@ int MidiPlayer_Midi::open(ResourceManager *resMan) {
_keyShift[i] = 0;
_volAdjust[i] = 0;
_velocityMapIdx[i] = 0;
+ _pitchBendRange[i] = MIDI_UNMAPPED;
+ _percussionVelocityScale[i] = 127;
}
Resource *res = NULL;
@@ -592,6 +769,7 @@ int MidiPlayer_Midi::open(ResourceManager *resMan) {
res = resMan->findResource(ResourceId(kResourceTypePatch, 4), 0);
if (res && isMt32GmPatch(res->data, res->size)) {
+ // There is a GM patch
readMt32GmPatch(res->data, res->size);
// Detect the format of patch 1, so that we know what play mask to use
@@ -601,7 +779,37 @@ int MidiPlayer_Midi::open(ResourceManager *resMan) {
else
_isOldPatchFormat = !isMt32GmPatch(res->data, res->size);
} else {
- warning("MT-32 to GM translation not yet supported");
+ // No GM patch found, map instruments using MT-32 patch
+
+ warning("Game has no native support for General MIDI, applying auto-mapping");
+
+ // Modify velocity map to make low velocity notes a little louder
+ for (uint i = 1; i < 0x40; i++)
+ _velocityMap[0][i] = 0x20 + (i - 1) / 2;
+
+ res = resMan->findResource(ResourceId(kResourceTypePatch, 1), 0);
+
+ if (res) {
+ if (!isMt32GmPatch(res->data, res->size))
+ mapMt32ToGm(res->data, res->size);
+ else
+ error("MT-32 patch has wrong type");
+ } else {
+ // No MT-32 patch present, try to read from MT32.DRV
+ Common::File f;
+
+ if (f.open("MT32.DRV")) {
+ int size = f.size();
+
+ assert(size >= 70);
+
+ f.seek(0x29);
+
+ // Read AdLib->MT-32 patch map
+ for (int i = 0; i < 48; i++)
+ _patchMap[i] = getGmInstrument(Mt32PresetTimbreMaps[f.readByte() & 0x7f]);
+ }
+ }
}
}