aboutsummaryrefslogtreecommitdiff
path: root/scumm/instrument.cpp
diff options
context:
space:
mode:
authorJamieson Christian2002-12-18 13:22:40 +0000
committerJamieson Christian2002-12-18 13:22:40 +0000
commit65ee19610c5e050ac00078739ac4ffae3e443b7c (patch)
tree6bee2eddb32c67c76acd076c7b8ee0b64c5835fc /scumm/instrument.cpp
parent3427e29e4671fe9aaa499148633406811e96594a (diff)
downloadscummvm-rg350-65ee19610c5e050ac00078739ac4ffae3e443b7c.tar.gz
scummvm-rg350-65ee19610c5e050ac00078739ac4ffae3e443b7c.tar.bz2
scummvm-rg350-65ee19610c5e050ac00078739ac4ffae3e443b7c.zip
Instrument definition revamp.
IMuseDriver abstract class removed. IMuseGM is now IMuseDriver. Miscellaneous cleanup. svn-id: r6017
Diffstat (limited to 'scumm/instrument.cpp')
-rw-r--r--scumm/instrument.cpp431
1 files changed, 431 insertions, 0 deletions
diff --git a/scumm/instrument.cpp b/scumm/instrument.cpp
new file mode 100644
index 0000000000..4d0270a0a7
--- /dev/null
+++ b/scumm/instrument.cpp
@@ -0,0 +1,431 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ */
+
+#include "stdafx.h"
+#include "scumm/scumm.h"
+#include "scumm/saveload.h"
+#include "scumm/instrument.h"
+#include "sound/mididrv.h"
+
+#define NATIVE_MT32 false
+
+static const byte mt32_to_gm[128] = {
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 0, 2, 4, 4, 5, 3, 16, 17, 18, 16, 16, 19, 20, 21, // 0x
+ 6, 6, 6, 7, 7, 7, 8, 112, 62, 62, 63, 63, 38, 38, 39, 39, // 1x
+ 88, 95, 52, 98, 97, 99, 14, 54, 102, 96, 53, 102, 81, 100, 14, 80, // 2x
+ 48, 48, 49, 45, 41, 40, 42, 42, 43, 46, 45, 24, 25, 28, 27, 104, // 3x
+ 32, 32, 34, 33, 36, 37, 35, 35, 79, 73, 72, 72, 74, 75, 64, 65, // 4x
+ 66, 67, 71, 71, 68, 69, 70, 22, 56, 59, 57, 57, 60, 60, 58, 61, // 5x
+ 61, 11, 11, 98, 14, 9, 14, 13, 12, 107, 107, 77, 78, 78, 76, 76, // 6x
+ 47, 117, 127, 118, 118, 116, 115, 119, 115, 112, 55, 124, 123, 0, 14, 117 // 7x
+};
+
+static struct {
+ char *name;
+ byte program;
+}
+roland_to_gm_map [] = {
+ // Monkey Island 2 instruments
+ // TODO: Complete
+// { "badspit ", ??? },
+ { "Big Drum ", 116 },
+// { "burp ", ??? },
+// { "dinkfall ", ??? },
+// { "Fire Pit ", ??? },
+// { "foghorn ", ??? },
+ { "glop ", 39 },
+// { "jacob's la", ??? },
+ { "LeshBass ", 33 },
+// { "lowsnort ", ??? },
+// { "ML explosn", ??? },
+ { "ReggaeBass", 32 },
+// { "rope fall ", ??? },
+// { "rumble ", ??? },
+// { "SdTrk Bend", ??? },
+// { "snort ", ??? },
+// { "spitting ", ??? },
+ { "Swell 1 ", 95 },
+ { "Swell 2 ", 95 }
+// { "thnderclap", ??? },
+
+ // Fate of Atlantis instruments
+ // TODO: Build
+// { "*aah! ", ??? },
+// { "*ooh! ", ??? },
+// { "*ShotFar4 ", ??? },
+// { "*splash3 ", ??? },
+// { "*torpedo5 ", ??? },
+// { "*whip3 ", ??? },
+// { "*woodknock", ??? },
+// { "35 lavabub", ??? },
+// { "49 bzzt! ", ??? },
+// { "applause ", ??? },
+// { "Arabongo ", ??? },
+// { "Big Drum ", ??? }, // DUPLICATE (todo: confirm)
+// { "bodythud1 ", ??? },
+// { "boneKLOK2 ", ??? },
+// { "boom10 ", ??? },
+// { "boom11 ", ??? },
+// { "boom15 ", ??? },
+// { "boxclik1a ", ??? },
+// { "brassbonk3", ??? },
+// { "carstart ", ??? },
+// { "cb tpt 2 ", ??? },
+// { "cell door ", ??? },
+// { "chains ", ??? },
+// { "crash ", ??? },
+// { "crsrt/idl3", ??? },
+// { "Fire Pit ", ??? }, // DUPLICATE (todo: confirm)
+// { "Fzooom ", ??? },
+// { "Fzooom 2 ", ??? },
+// { "ghostwhosh", ??? },
+// { "glasssmash", ??? },
+// { "gloop2 ", ??? },
+// { "gunShotNea", ??? },
+// { "idoorclse ", ??? },
+// { "knife ", ??? },
+// { "lavacmbl4 ", ??? },
+// { "Mellow Str", ??? },
+// { "mtlheater1", ??? },
+// { "pachinko5 ", ??? },
+// { "Ping1 ", ??? },
+// { "rockcrunch", ??? },
+// { "rumble ", ??? }, // DUPLICATE (todo: confirm)
+// { "runngwatr ", ??? },
+// { "scrape2 ", ??? },
+// { "snakeHiss ", ??? },
+// { "snort ", ??? }, // DUPLICATE (todo: confirm)
+// { "spindle4 ", ??? },
+// { "splash2 ", ??? },
+// { "squirel ", ??? },
+// { "steam3 ", ??? },
+// { "stonwheel6", ??? },
+// { "street ", ??? },
+// { "trickle4 ", ??? }
+};
+
+
+
+class Instrument_Program : public InstrumentInternal {
+private:
+ byte _program;
+ bool _mt32;
+
+public:
+ Instrument_Program (byte program, bool mt32);
+ Instrument_Program (Serializer *s);
+ void saveOrLoad (Serializer *s);
+ void send (MidiChannel *mc);
+};
+
+class Instrument_Adlib : public InstrumentInternal {
+private:
+ struct {
+ byte flags_1;
+ byte oplvl_1;
+ byte atdec_1;
+ byte sustrel_1;
+ byte waveform_1;
+ byte flags_2;
+ byte oplvl_2;
+ byte atdec_2;
+ byte sustrel_2;
+ byte waveform_2;
+ byte feedback;
+ byte flags_a;
+ struct { byte a,b,c,d,e,f,g,h; } extra_a;
+ byte flags_b;
+ struct { byte a,b,c,d,e,f,g,h; } extra_b;
+ byte duration;
+ } _instrument;
+
+public:
+ Instrument_Adlib (byte *data);
+ Instrument_Adlib (Serializer *s);
+ void saveOrLoad (Serializer *s);
+ void send (MidiChannel *mc);
+};
+
+class Instrument_Roland : public InstrumentInternal {
+private:
+ struct {
+ byte roland_id;
+ byte device_id;
+ byte model_id;
+ byte command;
+ byte address[3];
+ struct {
+ byte name[10];
+ byte partial_struct12;
+ byte partial_struct34;
+ byte partial_mute;
+ byte env_mode;
+ } common;
+ struct {
+ byte wg_pitch_coarse;
+ byte wg_pitch_fine;
+ byte wg_pitch_keyfollow;
+ byte wg_pitch_bender_sw;
+ byte wg_waveform_pcm_bank;
+ byte wg_pcm_wave_num;
+ byte wg_pulse_width;
+ byte wg_pw_velo_sens;
+ byte p_env_depth;
+ byte p_evn_velo_sens;
+ byte p_env_time_keyf;
+ byte p_env_time[4];
+ byte p_env_level[3];
+ byte p_env_sustain_level;
+ byte end_level;
+ byte p_lfo_rate;
+ byte p_lfo_depth;
+ byte p_lfo_mod_sens;
+ byte tvf_cutoff_freq;
+ byte tvf_resonance;
+ byte tvf_keyfollow;
+ byte tvf_bias_point_dir;
+ byte tvf_bias_level;
+ byte tvf_env_depth;
+ byte tvf_env_velo_sens;
+ byte tvf_env_depth_keyf;
+ byte tvf_env_time_keyf;
+ byte tvf_env_time[5];
+ byte tvf_env_level[3];
+ byte tvf_env_sustain_level;
+ byte tva_level;
+ byte tva_velo_sens;
+ byte tva_bias_point_1;
+ byte tva_bias_level_1;
+ byte tva_bias_point_2;
+ byte tva_bias_level_2;
+ byte tva_env_time_keyf;
+ byte tva_env_time_v_follow;
+ byte tva_env_time[5];
+ byte tva_env_level[3];
+ byte tva_env_sustain_level;
+ } partial[4];
+ } _instrument;
+
+ char _instrument_name [11];
+
+public:
+ Instrument_Roland (byte *data);
+ Instrument_Roland (Serializer *s);
+ void saveOrLoad (Serializer *s);
+ void send (MidiChannel *mc);
+};
+
+
+
+////////////////////////////////////////
+//
+// Instrument class members
+//
+////////////////////////////////////////
+
+void Instrument::clear()
+{
+ if (_instrument)
+ delete _instrument;
+ _instrument = NULL;
+ _type = itNone;
+}
+
+void Instrument::program (byte program, bool mt32)
+{
+ clear();
+ if (program > 127)
+ return;
+ _type = itProgram;
+ _instrument = new Instrument_Program (program, mt32);
+}
+
+void Instrument::adlib (byte *instrument)
+{
+ clear();
+ if (!instrument)
+ return;
+ _type = itAdlib;
+ _instrument = new Instrument_Adlib (instrument);
+}
+
+void Instrument::roland (byte *instrument)
+{
+ clear();
+ if (!instrument)
+ return;
+ _type = itRoland;
+ _instrument = new Instrument_Roland (instrument);
+}
+
+void Instrument::saveOrLoad (Serializer *s)
+{
+ if (s->isSaving()) {
+ s->saveByte (_type);
+ if (_instrument)
+ _instrument->saveOrLoad (s);
+ } else {
+ clear();
+ byte type = s->loadByte();
+ switch (type) {
+ case itNone:
+ break;
+ case itProgram:
+ _instrument = new Instrument_Program (s);
+ break;
+ case itAdlib:
+ _instrument = new Instrument_Adlib (s);
+ break;
+ case itRoland:
+ _instrument = new Instrument_Roland (s);
+ break;
+ default:
+ warning ("No known instrument classification #%d", (int) type);
+ }
+ }
+}
+
+
+
+////////////////////////////////////////
+//
+// Instrument_Program class members
+//
+////////////////////////////////////////
+
+Instrument_Program::Instrument_Program (byte program, bool mt32) :
+_program (program),
+_mt32 (mt32)
+{
+ if (program > 127)
+ _program = 255;
+}
+
+Instrument_Program::Instrument_Program (Serializer *s)
+{
+ _program = 255;
+ if (!s->isSaving())
+ saveOrLoad (s);
+}
+
+void Instrument_Program::saveOrLoad (Serializer *s)
+{
+ _program = s->loadByte();
+ _mt32 = (s->loadByte() > 0);
+}
+
+void Instrument_Program::send (MidiChannel *mc)
+{
+ if (_program > 127)
+ return;
+
+ if (NATIVE_MT32) // if (mc->device()->mt32device())
+ mc->programChange (_mt32 ? _program : _program /*gm_to_mt32 [_program]*/);
+ else
+ mc->programChange (_mt32 ? mt32_to_gm [_program] : _program);
+}
+
+
+
+////////////////////////////////////////
+//
+// Instrument_Adlib class members
+//
+////////////////////////////////////////
+
+Instrument_Adlib::Instrument_Adlib (byte *data)
+{
+ memcpy (&_instrument, data, sizeof (_instrument));
+}
+
+Instrument_Adlib::Instrument_Adlib (Serializer *s)
+{
+ if (!s->isSaving())
+ saveOrLoad (s);
+ else
+ memset (&_instrument, 0, sizeof (_instrument));
+}
+
+void Instrument_Adlib::saveOrLoad (Serializer *s)
+{
+ if (s->isSaving())
+ s->saveBytes (&_instrument, sizeof (_instrument));
+ else
+ s->loadBytes (&_instrument, sizeof (_instrument));
+}
+
+void Instrument_Adlib::send (MidiChannel *mc)
+{
+ mc->sysEx_customInstrument ('ADL ', (byte *) &_instrument);
+}
+
+
+
+////////////////////////////////////////
+//
+// Instrument_Roland class members
+//
+////////////////////////////////////////
+
+Instrument_Roland::Instrument_Roland (byte *data)
+{
+ memcpy (&_instrument, data, sizeof (_instrument));
+ memcpy (&_instrument_name, &_instrument.common.name, sizeof (_instrument.common.name));
+ _instrument_name[10] = '\0';
+}
+
+Instrument_Roland::Instrument_Roland (Serializer *s)
+{
+ _instrument_name[0] = '\0';
+ if (!s->isSaving())
+ saveOrLoad (s);
+ else
+ memset (&_instrument, 0, sizeof (_instrument));
+}
+
+void Instrument_Roland::saveOrLoad (Serializer *s)
+{
+ if (s->isSaving())
+ s->saveBytes (&_instrument, sizeof (_instrument));
+ else
+ s->loadBytes (&_instrument, sizeof (_instrument));
+ memcpy (&_instrument_name, &_instrument.common.name, sizeof (_instrument.common.name));
+ _instrument_name[10] = '\0';
+}
+
+void Instrument_Roland::send (MidiChannel *mc)
+{
+ if (NATIVE_MT32) { // if (mc->device()->mt32device()) {
+ mc->device()->sysEx ((byte *) &_instrument, sizeof (_instrument));
+ } else {
+ // Convert to a GM program change.
+ byte i;
+ for (i = 0; i != ARRAYSIZE(roland_to_gm_map); ++i) {
+ if (!memcmp (roland_to_gm_map[i].name, _instrument.common.name, 10)) {
+ mc->programChange (roland_to_gm_map[i].program);
+ return;
+ }
+ }
+ warning ("MT-32 instrument \"%s\" not supported yet", _instrument_name);
+ mc->programChange (0);
+ }
+}