Instrument definition revamp.
IMuseDriver abstract class removed. IMuseGM is now IMuseDriver. Miscellaneous cleanup. svn-id: r6017
This commit is contained in:
parent
3427e29e46
commit
65ee19610c
4 changed files with 616 additions and 326 deletions
|
@ -32,7 +32,7 @@ struct InstrumentExtra {
|
||||||
byte a, b, c, d, e, f, g, h;
|
byte a, b, c, d, e, f, g, h;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Instrument {
|
struct AdlibInstrument {
|
||||||
byte flags_1;
|
byte flags_1;
|
||||||
byte oplvl_1;
|
byte oplvl_1;
|
||||||
byte atdec_1;
|
byte atdec_1;
|
||||||
|
@ -66,7 +66,7 @@ private:
|
||||||
bool _pedal;
|
bool _pedal;
|
||||||
byte _program;
|
byte _program;
|
||||||
byte _pri_eff;
|
byte _pri_eff;
|
||||||
Instrument _part_instr;
|
AdlibInstrument _part_instr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MidiDriver_ADLIB *_owner;
|
MidiDriver_ADLIB *_owner;
|
||||||
|
@ -534,7 +534,7 @@ private:
|
||||||
|
|
||||||
void generate_samples(int16 *buf, int len);
|
void generate_samples(int16 *buf, int len);
|
||||||
void on_timer();
|
void on_timer();
|
||||||
void part_set_instrument (AdlibPart *part, Instrument * instr);
|
void part_set_instrument (AdlibPart *part, AdlibInstrument * instr);
|
||||||
void part_key_on (AdlibPart *part, byte note, byte velocity);
|
void part_key_on (AdlibPart *part, byte note, byte velocity);
|
||||||
void part_key_off (AdlibPart *part, byte note);
|
void part_key_off (AdlibPart *part, byte note);
|
||||||
|
|
||||||
|
@ -542,7 +542,7 @@ private:
|
||||||
void adlib_note_on(int chan, byte note, int mod);
|
void adlib_note_on(int chan, byte note, int mod);
|
||||||
void adlib_note_on_ex(int chan, byte note, int mod);
|
void adlib_note_on_ex(int chan, byte note, int mod);
|
||||||
int adlib_read_param(int chan, byte data);
|
int adlib_read_param(int chan, byte data);
|
||||||
void adlib_setup_channel(int chan, Instrument * instr, byte vol_1, byte vol_2);
|
void adlib_setup_channel(int chan, AdlibInstrument * instr, byte vol_1, byte vol_2);
|
||||||
byte adlib_read(byte port) {
|
byte adlib_read(byte port) {
|
||||||
return _adlib_reg_cache[port];
|
return _adlib_reg_cache[port];
|
||||||
}
|
}
|
||||||
|
@ -606,7 +606,7 @@ void AdlibPart::programChange (byte program)
|
||||||
if (!count)
|
if (!count)
|
||||||
warning ("No Adlib instrument defined for GM program %d", (int) program);
|
warning ("No Adlib instrument defined for GM program %d", (int) program);
|
||||||
_program = program;
|
_program = program;
|
||||||
_owner->part_set_instrument (this, (Instrument *) &map_gm_to_fm [program]);
|
_owner->part_set_instrument (this, (AdlibInstrument *) &map_gm_to_fm [program]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdlibPart::pitchBend (int16 bend)
|
void AdlibPart::pitchBend (int16 bend)
|
||||||
|
@ -841,8 +841,8 @@ void MidiDriver_ADLIB::sysEx_customInstrument (byte channel, uint32 type, byte *
|
||||||
void MidiDriver_ADLIB::sysEx_customInstrument (AdlibPart *part, uint32 type, byte *instr)
|
void MidiDriver_ADLIB::sysEx_customInstrument (AdlibPart *part, uint32 type, byte *instr)
|
||||||
{
|
{
|
||||||
if (type == 'ADL ') {
|
if (type == 'ADL ') {
|
||||||
Instrument *i = &part->_part_instr;
|
AdlibInstrument *i = &part->_part_instr;
|
||||||
memcpy(i, instr, sizeof(Instrument));
|
memcpy(i, instr, sizeof(AdlibInstrument));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1260,7 +1260,7 @@ void MidiDriver_ADLIB::mc_key_on (MidiChannelAdl * mc2, byte note, byte velocity
|
||||||
{
|
{
|
||||||
MidiChannelAdl *mc = (MidiChannelAdl *)mc2;
|
MidiChannelAdl *mc = (MidiChannelAdl *)mc2;
|
||||||
AdlibPart *part = mc->_part;
|
AdlibPart *part = mc->_part;
|
||||||
Instrument *instr = &part->_part_instr;
|
AdlibInstrument *instr = &part->_part_instr;
|
||||||
int c;
|
int c;
|
||||||
byte vol_1, vol_2;
|
byte vol_1, vol_2;
|
||||||
|
|
||||||
|
@ -1303,7 +1303,7 @@ void MidiDriver_ADLIB::mc_key_on (MidiChannelAdl * mc2, byte note, byte velocity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MidiDriver_ADLIB::adlib_setup_channel(int chan, Instrument * instr, byte vol_1, byte vol_2)
|
void MidiDriver_ADLIB::adlib_setup_channel(int chan, AdlibInstrument * instr, byte vol_1, byte vol_2)
|
||||||
{
|
{
|
||||||
byte port;
|
byte port;
|
||||||
|
|
||||||
|
@ -1445,8 +1445,8 @@ void MidiDriver_ADLIB::adlib_note_on(int chan, byte note, int mod)
|
||||||
adlib_playnote(chan, channel_table_2[chan] + code);
|
adlib_playnote(chan, channel_table_2[chan] + code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MidiDriver_ADLIB::part_set_instrument(AdlibPart *part, Instrument * instr)
|
void MidiDriver_ADLIB::part_set_instrument(AdlibPart *part, AdlibInstrument * instr)
|
||||||
{
|
{
|
||||||
Instrument *i = &part->_part_instr;
|
AdlibInstrument *i = &part->_part_instr;
|
||||||
memcpy(i, instr, sizeof(Instrument));
|
memcpy(i, instr, sizeof(AdlibInstrument));
|
||||||
}
|
}
|
||||||
|
|
425
scumm/imuse.cpp
425
scumm/imuse.cpp
|
@ -24,6 +24,7 @@
|
||||||
#include "sound/fmopl.h"
|
#include "sound/fmopl.h"
|
||||||
#include "sound/mididrv.h"
|
#include "sound/mididrv.h"
|
||||||
#include "scumm/imuse.h"
|
#include "scumm/imuse.h"
|
||||||
|
#include "scumm/instrument.h"
|
||||||
#include "scumm/saveload.h"
|
#include "scumm/saveload.h"
|
||||||
#include "scumm/sound.h"
|
#include "scumm/sound.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
@ -33,7 +34,6 @@
|
||||||
//
|
//
|
||||||
#define TICKS_PER_BEAT 480
|
#define TICKS_PER_BEAT 480
|
||||||
|
|
||||||
// #define FORCE_MT32_SOUNDS // Use only if you are driving an actual MT-32 or compatible
|
|
||||||
#define IMUSE_SYSEX_ID 0x7D
|
#define IMUSE_SYSEX_ID 0x7D
|
||||||
#define ROLAND_SYSEX_ID 0x41
|
#define ROLAND_SYSEX_ID 0x41
|
||||||
#define PERCUSSION_CHANNEL 9
|
#define PERCUSSION_CHANNEL 9
|
||||||
|
@ -44,20 +44,6 @@
|
||||||
#define MDPG_TAG "MDpg"
|
#define MDPG_TAG "MDpg"
|
||||||
#define MDHD_TAG "MDhd"
|
#define MDHD_TAG "MDhd"
|
||||||
|
|
||||||
#ifndef FORCE_MT32_SOUNDS
|
|
||||||
// Roland to General Midi patch table. Still needs some work.
|
|
||||||
static const byte mt32_to_gmidi[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
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// Put IMUSE specific classes here, instead of in a .h file
|
// Put IMUSE specific classes here, instead of in a .h file
|
||||||
|
@ -99,11 +85,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class IMuseDriver;
|
class IMuseDriver;
|
||||||
|
|
||||||
struct Part;
|
struct Part;
|
||||||
// struct MidiChannelAdl;
|
|
||||||
// struct MidiChannelGM;
|
|
||||||
struct Instrument;
|
|
||||||
|
|
||||||
|
|
||||||
struct HookDatas {
|
struct HookDatas {
|
||||||
|
@ -274,7 +256,10 @@ struct Part {
|
||||||
byte _percussion;
|
byte _percussion;
|
||||||
byte _bank;
|
byte _bank;
|
||||||
|
|
||||||
// Used to be in MidiDriverGM.
|
// New abstract instrument definition
|
||||||
|
Instrument _instrument;
|
||||||
|
|
||||||
|
// Used to be in MidiDriver
|
||||||
uint16 _actives[8];
|
uint16 _actives[8];
|
||||||
|
|
||||||
void key_on(byte note, byte velocity);
|
void key_on(byte note, byte velocity);
|
||||||
|
@ -286,7 +271,7 @@ struct Part {
|
||||||
void off();
|
void off();
|
||||||
void silence();
|
void silence();
|
||||||
void set_instrument(uint b);
|
void set_instrument(uint b);
|
||||||
void set_instrument(Instrument * data);
|
void set_instrument(byte * data);
|
||||||
|
|
||||||
void set_transpose(int8 transpose);
|
void set_transpose(int8 transpose);
|
||||||
void set_vol(uint8 volume);
|
void set_vol(uint8 volume);
|
||||||
|
@ -318,7 +303,10 @@ struct ImTrigger {
|
||||||
byte command [4];
|
byte command [4];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Abstract IMuseInternal driver class
|
|
||||||
|
|
||||||
|
// IMuseDriver class
|
||||||
|
|
||||||
class IMuseDriver {
|
class IMuseDriver {
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
|
@ -335,24 +323,63 @@ public:
|
||||||
pcAll = 1023,
|
pcAll = 1023,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void on_timer() = 0;
|
private:
|
||||||
virtual uint32 get_base_tempo() = 0;
|
IMuseInternal *_se;
|
||||||
virtual byte get_hardware_type() = 0;
|
OSystem *_system;
|
||||||
virtual void init(IMuseInternal *eng, OSystem *syst) = 0;
|
MidiDriver *_md;
|
||||||
virtual void uninit() = 0;
|
Instrument _glob_instr[32]; // Adlib custom instruments
|
||||||
virtual void update_pris() = 0;
|
|
||||||
virtual void set_instrument(uint slot, byte *instr) = 0;
|
byte _midi_program_last[16];
|
||||||
virtual void part_set_instrument(Part *part, Instrument * instr) = 0;
|
int16 _midi_pitchbend_last[16];
|
||||||
virtual void part_key_on(Part *part, byte note, byte velocity) = 0;
|
byte _midi_pitchbend_factor_last[16];
|
||||||
virtual void part_key_off(Part *part, byte note) = 0;
|
uint8 _midi_volume_last[16];
|
||||||
virtual void part_off(Part *part) = 0;
|
bool _midi_pedal_last[16];
|
||||||
virtual void part_changed(Part *part, uint16 what) = 0;
|
byte _midi_modwheel_last[16];
|
||||||
virtual void part_set_param(Part *part, byte param, int value) = 0;
|
byte _midi_effectlevel_last[16];
|
||||||
virtual int part_update_active(Part *part, uint16 *active) = 0;
|
byte _midi_chorus_last[16];
|
||||||
virtual byte get_channel_program (byte channel) = 0;
|
int8 _midi_pan_last[16];
|
||||||
|
|
||||||
|
|
||||||
|
void midiPitchBend(byte chan, int16 pitchbend);
|
||||||
|
void midiPitchBendFactor (byte chan, byte factor);
|
||||||
|
void midiVolume(byte chan, byte volume);
|
||||||
|
void midiPedal(byte chan, bool pedal);
|
||||||
|
void midiModWheel(byte chan, byte modwheel);
|
||||||
|
void midiEffectLevel(byte chan, byte level);
|
||||||
|
void midiChorus(byte chan, byte chorus);
|
||||||
|
void midiControl0(byte chan, byte value);
|
||||||
|
void midiPan(byte chan, int8 pan);
|
||||||
|
void midiNoteOn(byte chan, byte note, byte velocity);
|
||||||
|
void midiNoteOff(byte chan, byte note);
|
||||||
|
void midiSilence(byte chan);
|
||||||
|
void midiInit();
|
||||||
|
|
||||||
|
static void timer_callback (void *);
|
||||||
|
|
||||||
|
public:
|
||||||
|
IMuseDriver(MidiDriver *midi);
|
||||||
|
void uninit();
|
||||||
|
void init(IMuseInternal *eng, OSystem *os);
|
||||||
|
void update_pris();
|
||||||
|
void part_off(Part *part);
|
||||||
|
int part_update_active(Part *part, uint16 *active);
|
||||||
|
|
||||||
|
void on_timer() {}
|
||||||
|
void set_instrument(uint slot, byte *instr);
|
||||||
|
void part_set_param(Part *part, byte param, int value) {}
|
||||||
|
void part_key_on(Part *part, byte note, byte velocity);
|
||||||
|
void part_key_off(Part *part, byte note);
|
||||||
|
void part_changed(Part *part, uint16 what);
|
||||||
|
byte get_channel_program (byte channel) { return _midi_program_last [channel]; }
|
||||||
|
|
||||||
|
static int midi_driver_thread(void *param);
|
||||||
|
|
||||||
|
uint32 get_base_tempo() { return _md->getBaseTempo(); }
|
||||||
|
byte get_hardware_type() { return 5; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// WARNING: This is the internal variant of the IMUSE class.
|
// WARNING: This is the internal variant of the IMUSE class.
|
||||||
// imuse.h contains a public version of the same class.
|
// imuse.h contains a public version of the same class.
|
||||||
// the public version, only contains a set of methods.
|
// the public version, only contains a set of methods.
|
||||||
|
@ -486,92 +513,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct InstrumentExtra {
|
|
||||||
byte a, b, c, d, e, f, g, h;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Instrument {
|
|
||||||
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;
|
|
||||||
InstrumentExtra extra_a;
|
|
||||||
byte flags_b;
|
|
||||||
InstrumentExtra extra_b;
|
|
||||||
byte duration;
|
|
||||||
};
|
|
||||||
|
|
||||||
// IMuseGM classes
|
|
||||||
|
|
||||||
class IMuseGM : public IMuseDriver {
|
|
||||||
IMuseInternal *_se;
|
|
||||||
OSystem *_system;
|
|
||||||
MidiDriver *_md;
|
|
||||||
// MidiChannelGM _midi_channels[16];
|
|
||||||
|
|
||||||
Instrument _part_instr[32]; // Adlib custom instruments
|
|
||||||
Instrument _glob_instr[32]; // Adlib custom instruments
|
|
||||||
|
|
||||||
byte _midi_program_last[16];
|
|
||||||
int16 _midi_pitchbend_last[16];
|
|
||||||
byte _midi_pitchbend_factor_last[16];
|
|
||||||
uint8 _midi_volume_last[16];
|
|
||||||
bool _midi_pedal_last[16];
|
|
||||||
byte _midi_modwheel_last[16];
|
|
||||||
byte _midi_effectlevel_last[16];
|
|
||||||
byte _midi_chorus_last[16];
|
|
||||||
int8 _midi_pan_last[16];
|
|
||||||
|
|
||||||
|
|
||||||
void midiPitchBend(byte chan, int16 pitchbend);
|
|
||||||
void midiPitchBendFactor (byte chan, byte factor);
|
|
||||||
void midiVolume(byte chan, byte volume);
|
|
||||||
void midiPedal(byte chan, bool pedal);
|
|
||||||
void midiModWheel(byte chan, byte modwheel);
|
|
||||||
void midiEffectLevel(byte chan, byte level);
|
|
||||||
void midiChorus(byte chan, byte chorus);
|
|
||||||
void midiControl0(byte chan, byte value);
|
|
||||||
void midiProgram(MidiChannel *mc, byte program, bool mt32emulate);
|
|
||||||
void midiPan(byte chan, int8 pan);
|
|
||||||
void midiNoteOn(byte chan, byte note, byte velocity);
|
|
||||||
void midiNoteOff(byte chan, byte note);
|
|
||||||
void midiSilence(byte chan);
|
|
||||||
void midiInit();
|
|
||||||
|
|
||||||
static void timer_callback (void *);
|
|
||||||
|
|
||||||
public:
|
|
||||||
IMuseGM(MidiDriver *midi);
|
|
||||||
void uninit();
|
|
||||||
void init(IMuseInternal *eng, OSystem *os);
|
|
||||||
void update_pris();
|
|
||||||
void part_off(Part *part);
|
|
||||||
int part_update_active(Part *part, uint16 *active);
|
|
||||||
|
|
||||||
void on_timer() {}
|
|
||||||
void set_instrument(uint slot, byte *instr);
|
|
||||||
void part_set_instrument(Part *part, Instrument * instr);
|
|
||||||
void part_set_param(Part *part, byte param, int value) {}
|
|
||||||
void part_key_on(Part *part, byte note, byte velocity);
|
|
||||||
void part_key_off(Part *part, byte note);
|
|
||||||
void part_changed(Part *part, uint16 what);
|
|
||||||
byte get_channel_program (byte channel) { return _midi_program_last [channel]; }
|
|
||||||
|
|
||||||
static int midi_driver_thread(void *param);
|
|
||||||
|
|
||||||
uint32 get_base_tempo() { return _md->getBaseTempo(); } // 0x4A0000; }
|
|
||||||
byte get_hardware_type() { return 5; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
@ -708,17 +649,8 @@ byte *IMuseInternal::findTag(int sound, char *tag, int index)
|
||||||
byte *ptr = NULL;
|
byte *ptr = NULL;
|
||||||
int32 size, pos;
|
int32 size, pos;
|
||||||
|
|
||||||
if (_base_sounds) {
|
if (_base_sounds)
|
||||||
// The following hack was commented out because calling
|
|
||||||
// ensureResourceLoaded() is not safe from within this
|
|
||||||
// function. TODO: Make sure all Sam & Max music still works
|
|
||||||
// without this hack. It's very likely that changes to the
|
|
||||||
// resource expiration process solved whatever S&M problem
|
|
||||||
// this hack was originally intended to address.
|
|
||||||
// if (!_base_sounds[sound] && (sound > 1 || g_scumm->_gameId != GID_SAMNMAX))
|
|
||||||
// g_scumm->ensureResourceLoaded (rtSound, sound);
|
|
||||||
ptr = _base_sounds[sound];
|
ptr = _base_sounds[sound];
|
||||||
}
|
|
||||||
|
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
debug(1, "IMuseInternal::findTag completely failed finding sound %d", sound);
|
debug(1, "IMuseInternal::findTag completely failed finding sound %d", sound);
|
||||||
|
@ -1434,7 +1366,6 @@ int32 IMuseInternal::do_command(int a, int b, int c, int d, int e, int f, int g,
|
||||||
switch (d) {
|
switch (d) {
|
||||||
case 6:
|
case 6:
|
||||||
// Set player volume.
|
// Set player volume.
|
||||||
// Jamieson360: Good, this is consistent with IMuseDigital.
|
|
||||||
return player->set_vol (e);
|
return player->set_vol (e);
|
||||||
default:
|
default:
|
||||||
warning("IMuseInternal::do_command (6) unsupported sub-command %d", d);
|
warning("IMuseInternal::do_command (6) unsupported sub-command %d", d);
|
||||||
|
@ -1505,7 +1436,6 @@ int32 IMuseInternal::do_command(int a, int b, int c, int d, int e, int f, int g,
|
||||||
// The significance of parameter b is unknown.
|
// The significance of parameter b is unknown.
|
||||||
warning ("Incomplete support for iMuse::do_command(20)");
|
warning ("Incomplete support for iMuse::do_command(20)");
|
||||||
return do_command (c, d, e, f, g, h, 0, 0);
|
return do_command (c, d, e, f, g, h, 0, 0);
|
||||||
// return 0;
|
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1824,12 +1754,10 @@ int IMuseInternal::initialize(OSystem *syst, MidiDriver *midi, SoundMixer *mixer
|
||||||
|
|
||||||
IMuseDriver *driv;
|
IMuseDriver *driv;
|
||||||
|
|
||||||
if (midi == NULL) {
|
if (midi == NULL)
|
||||||
// driv = new IMuseAdlib(mixer);
|
|
||||||
driv = NULL;
|
driv = NULL;
|
||||||
} else {
|
else
|
||||||
driv = new IMuseGM(midi);
|
driv = new IMuseDriver (midi);
|
||||||
}
|
|
||||||
|
|
||||||
_driver = driv;
|
_driver = driv;
|
||||||
_hardware_type = driv->get_hardware_type();
|
_hardware_type = driv->get_hardware_type();
|
||||||
|
@ -2189,90 +2117,6 @@ byte *Player::parse_midi(byte *s)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 ", ??? }
|
|
||||||
};
|
|
||||||
|
|
||||||
void Player::parse_sysex(byte *p, uint len)
|
void Player::parse_sysex(byte *p, uint len)
|
||||||
{
|
{
|
||||||
byte code;
|
byte code;
|
||||||
|
@ -2290,29 +2134,9 @@ void Player::parse_sysex(byte *p, uint len)
|
||||||
// Roland custom instrument definition.
|
// Roland custom instrument definition.
|
||||||
part = get_part (p[0] & 0x0F);
|
part = get_part (p[0] & 0x0F);
|
||||||
if (part) {
|
if (part) {
|
||||||
#ifndef FORCE_MT32_SOUNDS
|
|
||||||
// Convert to a GM program change.
|
|
||||||
memcpy (buf, p + 6, 10);
|
|
||||||
buf[10] = '\0';
|
|
||||||
for (b = 0; b < ARRAYSIZE(roland_to_gm_map); ++b) {
|
|
||||||
if (!memcmp (roland_to_gm_map[b].name, buf, 10)) {
|
|
||||||
a = roland_to_gm_map[b].program;
|
|
||||||
for (b = 0; b < ARRAYSIZE(mt32_to_gmidi); ++b) {
|
|
||||||
if (mt32_to_gmidi [b] == a) {
|
|
||||||
part->set_program (b);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
warning ("Could not map MT-32 \"%s\" to GM %d", buf, (int) a);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
warning ("MT-32 instrument \"%s\" not supported yet", buf);
|
|
||||||
#else
|
|
||||||
// Send SysEx directly.
|
|
||||||
p[0] = part->_mc->getNumber();
|
p[0] = part->_mc->getNumber();
|
||||||
part->_mc->device()->sysEx (p - 1, len);
|
part->_instrument.roland (p - 1);
|
||||||
#endif
|
part->changed (IMuseDriver::pcProgram);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warning ("Unknown SysEx manufacturer 0x%02X", (int) a);
|
warning ("Unknown SysEx manufacturer 0x%02X", (int) a);
|
||||||
|
@ -2387,7 +2211,7 @@ void Player::parse_sysex(byte *p, uint len)
|
||||||
decode_sysex_bytes(p, buf, len - 3);
|
decode_sysex_bytes(p, buf, len - 3);
|
||||||
part = get_part(a);
|
part = get_part(a);
|
||||||
if (part)
|
if (part)
|
||||||
part->set_instrument((Instrument *) buf);
|
part->set_instrument((byte *) buf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 17: // Adlib instrument definition (Global)
|
case 17: // Adlib instrument definition (Global)
|
||||||
|
@ -3442,9 +3266,10 @@ void Part::set_onoff(bool on)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Part::set_instrument(Instrument * data)
|
void Part::set_instrument(byte * data)
|
||||||
{
|
{
|
||||||
_drv->part_set_instrument(this, data);
|
_instrument.adlib (data);
|
||||||
|
changed(IMuseDriver::pcProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Part::key_on(byte note, byte velocity)
|
void Part::key_on(byte note, byte velocity)
|
||||||
|
@ -3493,6 +3318,7 @@ void Part::setup(Player *player)
|
||||||
_pitchbend = 0;
|
_pitchbend = 0;
|
||||||
_effect_level = 64;
|
_effect_level = 64;
|
||||||
_program = player->_se->get_channel_program (_chan);
|
_program = player->_se->get_channel_program (_chan);
|
||||||
|
_instrument.program (_program, player->_mt32emulate);
|
||||||
_chorus = 0;
|
_chorus = 0;
|
||||||
_modwheel = 0;
|
_modwheel = 0;
|
||||||
_bank = 0;
|
_bank = 0;
|
||||||
|
@ -3551,6 +3377,7 @@ void Part::set_program(byte program)
|
||||||
if (_program != program || _bank != 0) {
|
if (_program != program || _bank != 0) {
|
||||||
_program = program;
|
_program = program;
|
||||||
_bank = 0;
|
_bank = 0;
|
||||||
|
_instrument.program (_program, _player->_mt32emulate);
|
||||||
changed(IMuseDriver::pcProgram);
|
changed(IMuseDriver::pcProgram);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3559,6 +3386,7 @@ void Part::set_instrument(uint b)
|
||||||
{
|
{
|
||||||
_bank = (byte)(b >> 8);
|
_bank = (byte)(b >> 8);
|
||||||
_program = (byte)b;
|
_program = (byte)b;
|
||||||
|
_instrument.program (_program, _player->_mt32emulate);
|
||||||
changed(IMuseDriver::pcProgram);
|
changed(IMuseDriver::pcProgram);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3569,7 +3397,7 @@ void Part::set_instrument(uint b)
|
||||||
//
|
//
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
|
|
||||||
IMuseGM::IMuseGM (MidiDriver *midi)
|
IMuseDriver::IMuseDriver (MidiDriver *midi)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -3591,7 +3419,7 @@ IMuseGM::IMuseGM (MidiDriver *midi)
|
||||||
_md = midi;
|
_md = midi;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::midiPitchBend(byte chan, int16 pitchbend)
|
void IMuseDriver::midiPitchBend(byte chan, int16 pitchbend)
|
||||||
{
|
{
|
||||||
uint16 tmp;
|
uint16 tmp;
|
||||||
|
|
||||||
|
@ -3602,21 +3430,21 @@ void IMuseGM::midiPitchBend(byte chan, int16 pitchbend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::midiPitchBendFactor (byte chan, byte factor) {
|
void IMuseDriver::midiPitchBendFactor (byte chan, byte factor) {
|
||||||
if (_midi_pitchbend_factor_last[chan] != factor) {
|
if (_midi_pitchbend_factor_last[chan] != factor) {
|
||||||
_midi_pitchbend_factor_last[chan] = factor;
|
_midi_pitchbend_factor_last[chan] = factor;
|
||||||
_md->setPitchBendRange (chan, factor);
|
_md->setPitchBendRange (chan, factor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::midiVolume(byte chan, byte volume)
|
void IMuseDriver::midiVolume(byte chan, byte volume)
|
||||||
{
|
{
|
||||||
if (_midi_volume_last[chan] != volume) {
|
if (_midi_volume_last[chan] != volume) {
|
||||||
_midi_volume_last[chan] = volume;
|
_midi_volume_last[chan] = volume;
|
||||||
_md->send(volume << 16 | 7 << 8 | 0xB0 | chan);
|
_md->send(volume << 16 | 7 << 8 | 0xB0 | chan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void IMuseGM::midiPedal(byte chan, bool pedal)
|
void IMuseDriver::midiPedal(byte chan, bool pedal)
|
||||||
{
|
{
|
||||||
if (_midi_pedal_last[chan] != pedal) {
|
if (_midi_pedal_last[chan] != pedal) {
|
||||||
_midi_pedal_last[chan] = pedal;
|
_midi_pedal_last[chan] = pedal;
|
||||||
|
@ -3624,7 +3452,7 @@ void IMuseGM::midiPedal(byte chan, bool pedal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::midiModWheel(byte chan, byte modwheel)
|
void IMuseDriver::midiModWheel(byte chan, byte modwheel)
|
||||||
{
|
{
|
||||||
if (_midi_modwheel_last[chan] != modwheel) {
|
if (_midi_modwheel_last[chan] != modwheel) {
|
||||||
_midi_modwheel_last[chan] = modwheel;
|
_midi_modwheel_last[chan] = modwheel;
|
||||||
|
@ -3632,7 +3460,7 @@ void IMuseGM::midiModWheel(byte chan, byte modwheel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::midiEffectLevel(byte chan, byte level)
|
void IMuseDriver::midiEffectLevel(byte chan, byte level)
|
||||||
{
|
{
|
||||||
if (_midi_effectlevel_last[chan] != level) {
|
if (_midi_effectlevel_last[chan] != level) {
|
||||||
_midi_effectlevel_last[chan] = level;
|
_midi_effectlevel_last[chan] = level;
|
||||||
|
@ -3640,7 +3468,7 @@ void IMuseGM::midiEffectLevel(byte chan, byte level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::midiChorus(byte chan, byte chorus)
|
void IMuseDriver::midiChorus(byte chan, byte chorus)
|
||||||
{
|
{
|
||||||
if (_midi_chorus_last[chan] != chorus) {
|
if (_midi_chorus_last[chan] != chorus) {
|
||||||
_midi_chorus_last[chan] = chorus;
|
_midi_chorus_last[chan] = chorus;
|
||||||
|
@ -3648,22 +3476,13 @@ void IMuseGM::midiChorus(byte chan, byte chorus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::midiControl0(byte chan, byte value)
|
void IMuseDriver::midiControl0(byte chan, byte value)
|
||||||
{
|
{
|
||||||
_md->send(value << 16 | 0 << 8 | 0xB0 | chan);
|
_md->send(value << 16 | 0 << 8 | 0xB0 | chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void IMuseGM::midiProgram(MidiChannel *mc, byte program, bool mt32emulate)
|
void IMuseDriver::midiPan(byte chan, int8 pan)
|
||||||
{
|
|
||||||
#ifndef FORCE_MT32_SOUNDS
|
|
||||||
if (mt32emulate)
|
|
||||||
program = mt32_to_gmidi[program];
|
|
||||||
#endif
|
|
||||||
mc->programChange (program);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IMuseGM::midiPan(byte chan, int8 pan)
|
|
||||||
{
|
{
|
||||||
if (_midi_pan_last[chan] != pan) {
|
if (_midi_pan_last[chan] != pan) {
|
||||||
_midi_pan_last[chan] = pan;
|
_midi_pan_last[chan] = pan;
|
||||||
|
@ -3671,24 +3490,24 @@ void IMuseGM::midiPan(byte chan, int8 pan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::midiNoteOn(byte chan, byte note, byte velocity)
|
void IMuseDriver::midiNoteOn(byte chan, byte note, byte velocity)
|
||||||
{
|
{
|
||||||
_md->send(velocity << 16 | note << 8 | 0x90 | chan);
|
_md->send(velocity << 16 | note << 8 | 0x90 | chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::midiNoteOff(byte chan, byte note)
|
void IMuseDriver::midiNoteOff(byte chan, byte note)
|
||||||
{
|
{
|
||||||
_md->send(note << 8 | 0x80 | chan);
|
_md->send(note << 8 | 0x80 | chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::midiSilence(byte chan)
|
void IMuseDriver::midiSilence(byte chan)
|
||||||
{
|
{
|
||||||
_md->send((64 << 8) | 0xB0 | chan);
|
_md->send((64 << 8) | 0xB0 | chan);
|
||||||
_md->send((123 << 8) | 0xB0 | chan);
|
_md->send((123 << 8) | 0xB0 | chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void IMuseGM::part_key_on(Part *part, byte note, byte velocity)
|
void IMuseDriver::part_key_on(Part *part, byte note, byte velocity)
|
||||||
{
|
{
|
||||||
MidiChannel *mc = part->_mc;
|
MidiChannel *mc = part->_mc;
|
||||||
|
|
||||||
|
@ -3700,12 +3519,12 @@ void IMuseGM::part_key_on(Part *part, byte note, byte velocity)
|
||||||
if (!mc)
|
if (!mc)
|
||||||
return;
|
return;
|
||||||
mc->volume (part->_vol_eff);
|
mc->volume (part->_vol_eff);
|
||||||
midiProgram (mc, part->_bank, part->_player->_mt32emulate);
|
mc->programChange (part->_bank);
|
||||||
mc->noteOn (note, velocity);
|
mc->noteOn (note, velocity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::part_key_off(Part *part, byte note)
|
void IMuseDriver::part_key_off(Part *part, byte note)
|
||||||
{
|
{
|
||||||
MidiChannel *mc = part->_mc;
|
MidiChannel *mc = part->_mc;
|
||||||
|
|
||||||
|
@ -3725,9 +3544,9 @@ void IMuseGM::part_key_off(Part *part, byte note)
|
||||||
#include <proto/dos.h>
|
#include <proto/dos.h>
|
||||||
#include "morphos.h"
|
#include "morphos.h"
|
||||||
#include "morphos_sound.h"
|
#include "morphos_sound.h"
|
||||||
int IMuseGM::midi_driver_thread(void *param)
|
int IMuseDriver::midi_driver_thread(void *param)
|
||||||
{
|
{
|
||||||
IMuseGM *mid = (IMuseGM *) param;
|
IMuseDriver *mid = (IMuseDriver *) param;
|
||||||
int old_time, cur_time;
|
int old_time, cur_time;
|
||||||
MsgPort *music_timer_port = NULL;
|
MsgPort *music_timer_port = NULL;
|
||||||
timerequest *music_timer_request = NULL;
|
timerequest *music_timer_request = NULL;
|
||||||
|
@ -3764,7 +3583,7 @@ int IMuseGM::midi_driver_thread(void *param)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void IMuseGM::init(IMuseInternal *eng, OSystem *syst)
|
void IMuseDriver::init(IMuseInternal *eng, OSystem *syst)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -3773,28 +3592,28 @@ void IMuseGM::init(IMuseInternal *eng, OSystem *syst)
|
||||||
// Open MIDI driver
|
// Open MIDI driver
|
||||||
int result = _md->open();
|
int result = _md->open();
|
||||||
if (result)
|
if (result)
|
||||||
error("IMuseGM::error = %s", MidiDriver::getErrorName(result));
|
error("IMuseDriver::error = %s", MidiDriver::getErrorName(result));
|
||||||
|
|
||||||
// Connect to the driver's timer
|
// Connect to the driver's timer
|
||||||
_se = eng;
|
_se = eng;
|
||||||
_md->setTimerCallback (NULL, &IMuseGM::timer_callback);
|
_md->setTimerCallback (NULL, &IMuseDriver::timer_callback);
|
||||||
|
|
||||||
for (i = 0; i != ARRAYSIZE(_midi_program_last); i++) {
|
for (i = 0; i != ARRAYSIZE(_midi_program_last); i++) {
|
||||||
_midi_program_last [i] = 255;
|
_midi_program_last [i] = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::timer_callback (void *) {
|
void IMuseDriver::timer_callback (void *) {
|
||||||
if (g_scumm->_imuse)
|
if (g_scumm->_imuse)
|
||||||
g_scumm->_imuse->on_timer();
|
g_scumm->_imuse->on_timer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::uninit()
|
void IMuseDriver::uninit()
|
||||||
{
|
{
|
||||||
_md->close();
|
_md->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::update_pris()
|
void IMuseDriver::update_pris()
|
||||||
{
|
{
|
||||||
Part *part, *hipart;
|
Part *part, *hipart;
|
||||||
int i;
|
int i;
|
||||||
|
@ -3838,7 +3657,7 @@ void IMuseGM::update_pris()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int IMuseGM::part_update_active(Part *part, uint16 *active)
|
int IMuseDriver::part_update_active(Part *part, uint16 *active)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
uint16 *act, mask, bits;
|
uint16 *act, mask, bits;
|
||||||
|
@ -3864,20 +3683,15 @@ int IMuseGM::part_update_active(Part *part, uint16 *active)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::part_set_instrument (Part *part, Instrument *instr)
|
void IMuseDriver::set_instrument(uint slot, byte *data)
|
||||||
{
|
{
|
||||||
Instrument *i = &_part_instr[part->_slot];
|
if (slot < 32) {
|
||||||
memcpy(i, instr, sizeof(Instrument));
|
// memcpy(&_glob_instr[slot], data, sizeof(Instrument));
|
||||||
part->changed (pcProgram);
|
_glob_instr[slot].adlib (data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMuseGM::set_instrument(uint slot, byte *data)
|
void IMuseDriver::part_changed(Part *part, uint16 what)
|
||||||
{
|
|
||||||
if (slot < 32)
|
|
||||||
memcpy(&_glob_instr[slot], data, sizeof(Instrument));
|
|
||||||
}
|
|
||||||
|
|
||||||
void IMuseGM::part_changed(Part *part, uint16 what)
|
|
||||||
{
|
{
|
||||||
MidiChannel *mc;
|
MidiChannel *mc;
|
||||||
|
|
||||||
|
@ -3919,25 +3733,8 @@ void IMuseGM::part_changed(Part *part, uint16 what)
|
||||||
if (what & pcEffectLevel)
|
if (what & pcEffectLevel)
|
||||||
mc->effectLevel (part->_effect_level);
|
mc->effectLevel (part->_effect_level);
|
||||||
|
|
||||||
if (what & pcProgram) {
|
if (what & pcProgram)
|
||||||
if (part->_player->_isGM) {
|
part->_instrument.send (mc);
|
||||||
if (part->_program < 128) {
|
|
||||||
_midi_program_last [part->_chan] = part->_program;
|
|
||||||
if (part->_bank) {
|
|
||||||
mc->controlChange (0, part->_bank);
|
|
||||||
midiProgram (mc, part->_program, part->_player->_mt32emulate);
|
|
||||||
mc->controlChange (0, 0);
|
|
||||||
} else {
|
|
||||||
midiProgram (mc, part->_program, part->_player->_mt32emulate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (part->_program < 32) {
|
|
||||||
memcpy (&_part_instr [part->_slot], &_glob_instr[part->_program], sizeof (Instrument));
|
|
||||||
}
|
|
||||||
mc->sysEx_customInstrument ('ADL ', (byte *) (&_part_instr [part->_slot]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (what & pcChorus)
|
if (what & pcChorus)
|
||||||
mc->chorusLevel (part->_effect_level);
|
mc->chorusLevel (part->_effect_level);
|
||||||
|
@ -3947,7 +3744,7 @@ void IMuseGM::part_changed(Part *part, uint16 what)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void IMuseGM::part_off(Part *part)
|
void IMuseDriver::part_off(Part *part)
|
||||||
{
|
{
|
||||||
MidiChannel *mc = part->_mc;
|
MidiChannel *mc = part->_mc;
|
||||||
if (mc) {
|
if (mc) {
|
||||||
|
|
431
scumm/instrument.cpp
Normal file
431
scumm/instrument.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
62
scumm/instrument.h
Normal file
62
scumm/instrument.h
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/* 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$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INSTRUMENT_H
|
||||||
|
#define INSTRUMENT_H
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "common/scummsys.h"
|
||||||
|
|
||||||
|
class Serializer;
|
||||||
|
class MidiChannel;
|
||||||
|
|
||||||
|
class InstrumentInternal {
|
||||||
|
public:
|
||||||
|
virtual void saveOrLoad (Serializer *s) = 0;
|
||||||
|
virtual void send (MidiChannel *mc) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Instrument {
|
||||||
|
private:
|
||||||
|
byte _type;
|
||||||
|
InstrumentInternal *_instrument;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
itNone = 0,
|
||||||
|
itProgram = 1,
|
||||||
|
itAdlib = 2,
|
||||||
|
itRoland = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
Instrument() : _type (0), _instrument (0) { }
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
void program (byte program, bool mt32);
|
||||||
|
void adlib (byte *instrument);
|
||||||
|
void roland (byte *instrument);
|
||||||
|
|
||||||
|
byte getType() { return _type; }
|
||||||
|
void saveOrLoad (Serializer *s);
|
||||||
|
void send (MidiChannel *mc) { if (_instrument) _instrument->send (mc); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Add table
Add a link
Reference in a new issue