mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
Added rudimentary Adlib percussion support.
Semantic fixes -- Adlib "MIDI Channels" are now "Voices" Miscellaneous cleanup/streamlining. svn-id: r7520
This commit is contained in:
parent
f3a5fc79c1
commit
979b465415
@ -26,7 +26,7 @@
|
||||
#include "common/util.h"
|
||||
|
||||
class MidiDriver_ADLIB;
|
||||
struct MidiChannelAdl;
|
||||
struct AdlibVoice;
|
||||
|
||||
struct InstrumentExtra {
|
||||
byte a, b, c, d, e, f, g, h;
|
||||
@ -54,9 +54,9 @@ struct AdlibInstrument {
|
||||
class AdlibPart : public MidiChannel {
|
||||
friend class MidiDriver_ADLIB;
|
||||
|
||||
private:
|
||||
protected:
|
||||
// AdlibPart *_prev, *_next;
|
||||
MidiChannelAdl *_mc;
|
||||
AdlibVoice *_voice;
|
||||
int16 _pitchbend;
|
||||
byte _pitchbend_factor;
|
||||
int8 _transpose_eff;
|
||||
@ -68,7 +68,7 @@ private:
|
||||
byte _pri_eff;
|
||||
AdlibInstrument _part_instr;
|
||||
|
||||
private:
|
||||
protected:
|
||||
MidiDriver_ADLIB *_owner;
|
||||
bool _allocated;
|
||||
byte _channel;
|
||||
@ -104,6 +104,35 @@ public:
|
||||
void sysEx_customInstrument (uint32 type, byte *instr);
|
||||
};
|
||||
|
||||
// FYI (Jamieson630)
|
||||
// It is assumed that any invocation to AdlibPercussionChannel
|
||||
// will be done through the MidiChannel base class as opposed to the
|
||||
// AdlibPart base class. If this were NOT the case, all the functions
|
||||
// listed below would need to be virtual in AdlibPart as well as MidiChannel.
|
||||
class AdlibPercussionChannel : public AdlibPart {
|
||||
friend class MidiDriver_ADLIB;
|
||||
|
||||
protected:
|
||||
void init (MidiDriver_ADLIB *owner, byte channel);
|
||||
|
||||
public:
|
||||
void noteOff (byte note);
|
||||
void noteOn (byte note, byte velocity);
|
||||
void programChange (byte program) { }
|
||||
void pitchBend (int16 bend) { }
|
||||
|
||||
// Control Change messages
|
||||
void controlChange (byte control, byte value) { }
|
||||
void modulationWheel (byte value) { }
|
||||
void pitchBendFactor (byte value) { }
|
||||
void detune (byte value) { }
|
||||
void priority (byte value) { }
|
||||
void sustain (bool value) { }
|
||||
|
||||
// SysEx messages
|
||||
void sysEx_customInstrument (uint32 type, byte *instr) { }
|
||||
};
|
||||
|
||||
struct Struct10 {
|
||||
byte active;
|
||||
int16 cur_val;
|
||||
@ -130,9 +159,9 @@ struct Struct11 {
|
||||
Struct10 *s10;
|
||||
};
|
||||
|
||||
struct MidiChannelAdl {
|
||||
struct AdlibVoice {
|
||||
AdlibPart *_part;
|
||||
MidiChannelAdl *_next, *_prev;
|
||||
AdlibVoice *_next, *_prev;
|
||||
byte _waitforpedal;
|
||||
byte _note;
|
||||
byte _channel;
|
||||
@ -145,7 +174,7 @@ struct MidiChannelAdl {
|
||||
Struct10 _s10b;
|
||||
Struct11 _s11b;
|
||||
|
||||
MidiChannelAdl() : _part (0), _next(0), _prev(0) {}
|
||||
AdlibVoice() : _part (0), _next(0), _prev(0) {}
|
||||
};
|
||||
|
||||
struct AdlibSetParams {
|
||||
@ -411,6 +440,63 @@ static byte map_gm_to_fm [128][30] = {
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } // Unknown
|
||||
};
|
||||
|
||||
struct PercussionMapEntry {
|
||||
byte _key; // 0 means no map data
|
||||
char *_name;
|
||||
byte _instrument [30];
|
||||
};
|
||||
|
||||
static PercussionMapEntry gm_percussion_to_fm [47] = {
|
||||
// The first entry is actual for key 34 (0-based)
|
||||
{ 0, "Acoustic Bass Drum", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Bass Drum 1", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 72, "Side Stick", { 0x0F, 0x21, 0x07, 0xE3, 0x01, 0x09, 0x30, 0x0B, 0xF6, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 59, "Acoustic Snare", { 0x00, 0x3F, 0x09, 0x00, 0x02, 0x06, 0x00, 0x57, 0x00, 0x7C, 0x0E, 0x80, 0x02, 0x08, 0x03, 0x1B, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 65, "Hand Clap", { 0x00, 0x3F, 0x09, 0x00, 0x02, 0x06, 0x00, 0x57, 0x00, 0x7C, 0x0E, 0x80, 0x02, 0x08, 0x03, 0x1B, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 71, "Electric Snare", { 0x00, 0x3F, 0x09, 0x00, 0x02, 0x06, 0x00, 0x57, 0x00, 0x7C, 0x0E, 0x80, 0x02, 0x08, 0x03, 0x1B, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 50, "Low Floor Tom", { 0x0F, 0x10, 0x10, 0x09, 0x49, 0x02, 0x12, 0x07, 0x9A, 0x7C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 80, "Closed Hi-Hat", { 0x00, 0x3F, 0x09, 0x00, 0x02, 0x06, 0x00, 0x57, 0x00, 0x7C, 0x0E, 0x80, 0x02, 0x08, 0x03, 0x1B, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 55, "High Floor Tom", { 0x0F, 0x10, 0x10, 0x09, 0x49, 0x02, 0x12, 0x07, 0x9A, 0x7C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 74, "Pedal Hi-Hat", { 0x00, 0x3F, 0x09, 0x00, 0x02, 0x06, 0x00, 0x57, 0x00, 0x7C, 0x0E, 0x80, 0x02, 0x08, 0x03, 0x1B, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 62, "Low Tom", { 0x0F, 0x10, 0x10, 0x09, 0x49, 0x02, 0x12, 0x07, 0x9A, 0x7C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 72, "Open Hi-Hat", { 0xCF, 0x3B, 0x2A, 0xFE, 0x7E, 0xC0, 0xC0, 0x0C, 0xEB, 0x63, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 } },
|
||||
{ 70, "Low-Mid Tom", { 0x0F, 0x10, 0x10, 0x09, 0x49, 0x02, 0x12, 0x07, 0x9A, 0x7C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 78, "High-Mid Tom", { 0x0F, 0x10, 0x10, 0x09, 0x49, 0x02, 0x12, 0x07, 0x9A, 0x7C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 60, "Crash Cymbal 1", { 0xCF, 0x3B, 0x2A, 0xFE, 0x7E, 0xC0, 0xC0, 0x0C, 0xEB, 0x63, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 } },
|
||||
{ 86, "High Tom", { 0x0F, 0x10, 0x10, 0x09, 0x49, 0x02, 0x12, 0x07, 0x9A, 0x7C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Ride Cymbal 1", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Chinese Cymbal", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Ride Bell", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 61, "Tambourine", { 0xE0, 0x3F, 0xAF, 0xF5, 0x7F, 0xEC, 0x2E, 0x0E, 0xC4, 0x7A, 0x08, 0x01, 0x00, 0x03, 0x1E, 0x01, 0x1E, 0x00, 0x00, 0x1E, 0xA8, 0x00, 0x01, 0x20, 0x06, 0x23, 0x04, 0x03, 0x20, 0x00 } },
|
||||
{ 75, "Splash Cymbal", { 0xCF, 0x3B, 0x2A, 0xFE, 0x7E, 0xC0, 0xC0, 0x0C, 0xEB, 0x63, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 } },
|
||||
{ 60, "Cowbell", { 0xEC, 0x34, 0x07, 0x00, 0x01, 0xE7, 0x3F, 0x05, 0x00, 0x4F, 0x09, 0xA1, 0x00, 0x01, 0x1E, 0x02, 0x1D, 0x01, 0x01, 0x22, 0xA8, 0x00, 0x01, 0x24, 0x06, 0x20, 0x04, 0x03, 0x24, 0x00 } },
|
||||
{ 69, "Crash Cymbal 2", { 0xCF, 0x3B, 0x2A, 0xFE, 0x7E, 0xC0, 0xC0, 0x0C, 0xEB, 0x63, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 } },
|
||||
{ 0, "Vibraslap", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Ride Cymbal 2", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "High Bongo", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Low Bongo", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Mute High Conga", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 66, "Open High Conga", { 0x21, 0x3F, 0x05, 0x95, 0x00, 0x21, 0x30, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 60, "Low Conga", { 0x21, 0x3F, 0x05, 0x95, 0x00, 0x21, 0x30, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "High Timbale", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Low Timbale", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "High Agogo", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Low Agogo", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Cabasa", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Maracas", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Short Whistle", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Long Whistle", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Short Guiro", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Long Guiro", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Claves", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 72, "High Wood Block", { 0x0F, 0x21, 0x07, 0xE3, 0x01, 0x09, 0x30, 0x0B, 0xF6, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 66, "Low Wood Block", { 0x0F, 0x21, 0x07, 0xE3, 0x01, 0x09, 0x30, 0x0B, 0xF6, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Mute Cuica", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 62, "Open Cuica", { 0x00, 0x23, 0x96, 0x00, 0x00, 0x00, 0x3F, 0x69, 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x21, 0x08, 0x1F, 0x00, 0x00, 0x1F, 0x0E, 0x00, 0x0B, 0x3E, 0x12, 0x1F, 0x00, 0x00, 0x1F, 0x00 } },
|
||||
{ 0, "Mute Triangle", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
||||
{ 0, "Open Triangle", { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
|
||||
};
|
||||
|
||||
static byte lookup_table[64][32];
|
||||
const byte volume_table[] = {
|
||||
0, 4, 7, 11,
|
||||
@ -482,6 +568,7 @@ typedef void TimerCallback (void *);
|
||||
|
||||
class MidiDriver_ADLIB : public MidiDriver {
|
||||
friend class AdlibPart;
|
||||
friend class AdlibPercussionChannel;
|
||||
|
||||
public:
|
||||
MidiDriver_ADLIB();
|
||||
@ -504,7 +591,7 @@ public:
|
||||
}
|
||||
|
||||
MidiChannel *allocateChannel();
|
||||
MidiChannel *getPercussionChannel() { return NULL; } // Percussion currently not supported
|
||||
MidiChannel *getPercussionChannel() { return &_percussion; } // Percussion partially supported
|
||||
|
||||
private:
|
||||
bool _isOpen;
|
||||
@ -519,18 +606,16 @@ private:
|
||||
int _adlib_timer_counter;
|
||||
|
||||
uint16 channel_table_2[9];
|
||||
int _midichan_index;
|
||||
int _voice_index;
|
||||
int _next_tick;
|
||||
uint16 curnote_table[9];
|
||||
MidiChannelAdl _midi_channels[9];
|
||||
AdlibVoice _voices[9];
|
||||
AdlibPart _parts[32];
|
||||
|
||||
void sysEx_customInstrument (AdlibPart *part, uint32 type, byte *instr);
|
||||
AdlibPercussionChannel _percussion;
|
||||
|
||||
void generate_samples(int16 *buf, int len);
|
||||
void on_timer();
|
||||
void part_set_instrument (AdlibPart *part, AdlibInstrument * instr);
|
||||
void part_key_on (AdlibPart *part, byte note, byte velocity);
|
||||
void part_key_on (AdlibPart *part, AdlibInstrument *instr, byte note, byte velocity);
|
||||
void part_key_off (AdlibPart *part, byte note);
|
||||
|
||||
void adlib_key_off(int chan);
|
||||
@ -546,21 +631,21 @@ private:
|
||||
void adlib_write(byte port, byte value);
|
||||
void adlib_playnote(int channel, int note);
|
||||
|
||||
MidiChannelAdl *allocate_midichan(byte pri);
|
||||
AdlibVoice *allocate_voice(byte pri);
|
||||
|
||||
void reset_tick();
|
||||
void mc_off(MidiChannelAdl * mc);
|
||||
void mc_off(AdlibVoice * voice);
|
||||
|
||||
static void link_mc (AdlibPart *part, MidiChannelAdl *mc);
|
||||
void mc_inc_stuff(MidiChannelAdl *mc, Struct10 * s10, Struct11 * s11);
|
||||
void mc_init_stuff(MidiChannelAdl *mc, Struct10 * s10, Struct11 * s11, byte flags,
|
||||
static void link_mc (AdlibPart *part, AdlibVoice *voice);
|
||||
void mc_inc_stuff(AdlibVoice *voice, Struct10 * s10, Struct11 * s11);
|
||||
void mc_init_stuff(AdlibVoice *voice, Struct10 * s10, Struct11 * s11, byte flags,
|
||||
InstrumentExtra * ie);
|
||||
|
||||
static void struct10_init(Struct10 * s10, InstrumentExtra * ie);
|
||||
static byte struct10_ontimer(Struct10 * s10, Struct11 * s11);
|
||||
static void struct10_setup(Struct10 * s10);
|
||||
static int random_nr(int a);
|
||||
void mc_key_on (MidiChannelAdl * mc, byte note, byte velocity);
|
||||
void mc_key_on (AdlibVoice *voice, AdlibInstrument *instr, byte note, byte velocity);
|
||||
|
||||
static void premix_proc(void *param, int16 *buf, uint len);
|
||||
};
|
||||
@ -581,7 +666,7 @@ void AdlibPart::noteOff (byte note) {
|
||||
}
|
||||
|
||||
void AdlibPart::noteOn (byte note, byte velocity) {
|
||||
_owner->part_key_on (this, note, velocity);
|
||||
_owner->part_key_on (this, &_part_instr, note, velocity);
|
||||
}
|
||||
|
||||
void AdlibPart::programChange (byte program) {
|
||||
@ -595,15 +680,15 @@ void AdlibPart::programChange (byte program) {
|
||||
if (!count)
|
||||
warning ("No Adlib instrument defined for GM program %d", (int) program);
|
||||
_program = program;
|
||||
_owner->part_set_instrument (this, (AdlibInstrument *) &map_gm_to_fm [program]);
|
||||
memcpy(&_part_instr, &map_gm_to_fm [program], sizeof(AdlibInstrument));
|
||||
}
|
||||
|
||||
void AdlibPart::pitchBend (int16 bend) {
|
||||
MidiChannelAdl *mc;
|
||||
AdlibVoice *voice;
|
||||
|
||||
_pitchbend = bend;
|
||||
for (mc = _mc; mc; mc = mc->_next) {
|
||||
_owner->adlib_note_on(mc->_channel, mc->_note + _transpose_eff,
|
||||
for (voice = _voice; voice; voice = voice->_next) {
|
||||
_owner->adlib_note_on(voice->_channel, voice->_note + _transpose_eff,
|
||||
(_pitchbend * _pitchbend_factor >> 6) + _detune_eff);
|
||||
}
|
||||
}
|
||||
@ -628,45 +713,45 @@ void AdlibPart::controlChange (byte control, byte value) {
|
||||
}
|
||||
|
||||
void AdlibPart::modulationWheel (byte value) {
|
||||
MidiChannelAdl *mc;
|
||||
AdlibVoice *voice;
|
||||
|
||||
_modwheel = value;
|
||||
for (mc = _mc; mc; mc = mc->_next) {
|
||||
if (mc->_s10a.active && mc->_s11a.flag0x40)
|
||||
mc->_s10a.modwheel = _modwheel >> 2;
|
||||
if (mc->_s10b.active && mc->_s11b.flag0x40)
|
||||
mc->_s10b.modwheel = _modwheel >> 2;
|
||||
for (voice = _voice; voice; voice = voice->_next) {
|
||||
if (voice->_s10a.active && voice->_s11a.flag0x40)
|
||||
voice->_s10a.modwheel = _modwheel >> 2;
|
||||
if (voice->_s10b.active && voice->_s11b.flag0x40)
|
||||
voice->_s10b.modwheel = _modwheel >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
void AdlibPart::volume (byte value) {
|
||||
MidiChannelAdl *mc;
|
||||
AdlibVoice *voice;
|
||||
|
||||
_vol_eff = value;
|
||||
for (mc = _mc; mc; mc = mc->_next) {
|
||||
_owner->adlib_set_param(mc->_channel, 0, volume_table[lookup_table[mc->_vol_2][_vol_eff >> 2]]);
|
||||
if (mc->_twochan) {
|
||||
_owner->adlib_set_param(mc->_channel, 13, volume_table[lookup_table[mc->_vol_1][_vol_eff >> 2]]);
|
||||
for (voice = _voice; voice; voice = voice->_next) {
|
||||
_owner->adlib_set_param(voice->_channel, 0, volume_table[lookup_table[voice->_vol_2][_vol_eff >> 2]]);
|
||||
if (voice->_twochan) {
|
||||
_owner->adlib_set_param(voice->_channel, 13, volume_table[lookup_table[voice->_vol_1][_vol_eff >> 2]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdlibPart::pitchBendFactor (byte value) {
|
||||
MidiChannelAdl *mc;
|
||||
AdlibVoice *voice;
|
||||
|
||||
_pitchbend_factor = value;
|
||||
for (mc = _mc; mc; mc = mc->_next) {
|
||||
_owner->adlib_note_on(mc->_channel, mc->_note + _transpose_eff,
|
||||
for (voice = _voice; voice; voice = voice->_next) {
|
||||
_owner->adlib_note_on(voice->_channel, voice->_note + _transpose_eff,
|
||||
(_pitchbend * _pitchbend_factor >> 6) + _detune_eff);
|
||||
}
|
||||
}
|
||||
|
||||
void AdlibPart::detune (byte value) {
|
||||
MidiChannelAdl *mc;
|
||||
AdlibVoice *voice;
|
||||
|
||||
_detune_eff = value;
|
||||
for (mc = _mc; mc; mc = mc->_next) {
|
||||
_owner->adlib_note_on(mc->_channel, mc->_note + _transpose_eff,
|
||||
for (voice = _voice; voice; voice = voice->_next) {
|
||||
_owner->adlib_note_on(voice->_channel, voice->_note + _transpose_eff,
|
||||
(_pitchbend * _pitchbend_factor >> 6) + _detune_eff);
|
||||
}
|
||||
}
|
||||
@ -676,24 +761,66 @@ void AdlibPart::priority (byte value) {
|
||||
}
|
||||
|
||||
void AdlibPart::sustain (bool value) {
|
||||
MidiChannelAdl *mc;
|
||||
AdlibVoice *voice;
|
||||
|
||||
_pedal = value;
|
||||
if (!value) {
|
||||
for (mc = _mc; mc; mc = mc->_next) {
|
||||
if (mc->_waitforpedal)
|
||||
_owner->mc_off(mc);
|
||||
for (voice = _voice; voice; voice = voice->_next) {
|
||||
if (voice->_waitforpedal)
|
||||
_owner->mc_off(voice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AdlibPart::allNotesOff() {
|
||||
while (_mc)
|
||||
_owner->mc_off (_mc);
|
||||
while (_voice)
|
||||
_owner->mc_off (_voice);
|
||||
}
|
||||
|
||||
void AdlibPart::sysEx_customInstrument (uint32 type, byte *instr) {
|
||||
_owner->sysEx_customInstrument (this, type, instr);
|
||||
if (type == 'ADL ') {
|
||||
AdlibInstrument *i = &_part_instr;
|
||||
memcpy(i, instr, sizeof(AdlibInstrument));
|
||||
}
|
||||
}
|
||||
|
||||
// MidiChannel method implementations for percussion
|
||||
|
||||
void AdlibPercussionChannel::init (MidiDriver_ADLIB *owner, byte channel) {
|
||||
AdlibPart::init (owner, channel);
|
||||
_pri_eff = 0;
|
||||
_vol_eff = 127;
|
||||
}
|
||||
|
||||
void AdlibPercussionChannel::noteOff (byte note) {
|
||||
// Jamieson630: Unless I run into a specific instrument that
|
||||
// may require a key off, I'm going to ignore this message.
|
||||
// The rationale is that a percussion instrument should
|
||||
// fade out of its own accord, and the Adlib instrument
|
||||
// definitions used should follow this rule. Since
|
||||
// percussion voices are allocated at the lowest priority
|
||||
// anyway, we know that "hanging" percussion sounds will
|
||||
// not prevent later musical instruments (or even other
|
||||
// percussion sounds) from playing.
|
||||
/*
|
||||
if (note < 34 || note > 81)
|
||||
return; // Out of GM range
|
||||
byte key = gm_percussion_to_fm [note-34]._key;
|
||||
if (key == 0)
|
||||
return;
|
||||
_owner->part_key_off (this, key);
|
||||
*/
|
||||
}
|
||||
|
||||
void AdlibPercussionChannel::noteOn (byte note, byte velocity) {
|
||||
if (note < 34 || note > 81)
|
||||
return; // Out of GM range
|
||||
byte key = gm_percussion_to_fm [note-34]._key;
|
||||
if (key == 0) {
|
||||
debug (2, "No FM map for GM percussion key %d (%s)", (int) note, gm_percussion_to_fm [note-34]._name);
|
||||
return;
|
||||
}
|
||||
_owner->part_key_on (this, (AdlibInstrument *) &gm_percussion_to_fm [note-34]._instrument, key, velocity);
|
||||
}
|
||||
|
||||
// MidiDriver method implementations
|
||||
@ -703,6 +830,7 @@ MidiDriver_ADLIB::MidiDriver_ADLIB() {
|
||||
for (i = 0; i < ARRAYSIZE(_parts); ++i) {
|
||||
_parts[i].init (this, i);
|
||||
}
|
||||
_percussion.init (this, 0);
|
||||
_game_SmallHeader = false;
|
||||
_isOpen = false;
|
||||
}
|
||||
@ -713,12 +841,12 @@ int MidiDriver_ADLIB::open() {
|
||||
_isOpen = true;
|
||||
|
||||
int i;
|
||||
MidiChannelAdl *mc;
|
||||
AdlibVoice *voice;
|
||||
|
||||
for (i = 0, mc = _midi_channels; i != ARRAYSIZE(_midi_channels); i++, mc++) {
|
||||
mc->_channel = i;
|
||||
mc->_s11a.s10 = &mc->_s10b;
|
||||
mc->_s11b.s10 = &mc->_s10a;
|
||||
for (i = 0, voice = _voices; i != ARRAYSIZE(_voices); i++, voice++) {
|
||||
voice->_channel = i;
|
||||
voice->_s11a.s10 = &voice->_s10b;
|
||||
voice->_s11b.s10 = &voice->_s10a;
|
||||
}
|
||||
|
||||
_adlib_reg_cache = (byte *)calloc(256, 1);
|
||||
@ -740,9 +868,9 @@ int MidiDriver_ADLIB::open() {
|
||||
|
||||
void MidiDriver_ADLIB::close() {
|
||||
uint i;
|
||||
for (i = 0; i < ARRAYSIZE(_midi_channels); ++i) {
|
||||
if (_midi_channels [i]._part)
|
||||
mc_off (&_midi_channels [i]);
|
||||
for (i = 0; i < ARRAYSIZE(_voices); ++i) {
|
||||
if (_voices [i]._part)
|
||||
mc_off (&_voices [i]);
|
||||
}
|
||||
|
||||
// Detach the premix callback handler
|
||||
@ -760,14 +888,19 @@ void MidiDriver_ADLIB::send (uint32 b) {
|
||||
byte param1 = (byte) ((b >> 8) & 0xFF);
|
||||
byte cmd = (byte) (b & 0xF0);
|
||||
byte chan = (byte) (b & 0x0F);
|
||||
AdlibPart *part = &_parts [chan];
|
||||
|
||||
AdlibPart *part;
|
||||
if (chan == 9)
|
||||
part = &_percussion;
|
||||
else
|
||||
part = &_parts [chan];
|
||||
|
||||
switch (cmd) {
|
||||
case 0x80:// Note Off
|
||||
part_key_off (part, param1);
|
||||
part->noteOff (param1);
|
||||
break;
|
||||
case 0x90: // Note On
|
||||
part_key_on (part, param1, param2);
|
||||
part->noteOn (param1, param2);
|
||||
break;
|
||||
case 0xA0: // Aftertouch
|
||||
break; // Not supported.
|
||||
@ -775,8 +908,7 @@ void MidiDriver_ADLIB::send (uint32 b) {
|
||||
part->controlChange (param1, param2);
|
||||
break;
|
||||
case 0xC0: // Program Change
|
||||
if (chan != 9)
|
||||
part->programChange (param1);
|
||||
part->programChange (param1);
|
||||
break;
|
||||
case 0xD0: // Channel Pressure
|
||||
break; // Not supported.
|
||||
@ -805,25 +937,18 @@ uint32 MidiDriver_ADLIB::property (int prop, uint32 param) {
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::setPitchBendRange (byte channel, uint range) {
|
||||
MidiChannelAdl *mc;
|
||||
AdlibVoice *voice;
|
||||
AdlibPart *part = &_parts [channel];
|
||||
|
||||
part->_pitchbend_factor = range;
|
||||
for (mc = part->_mc; mc; mc = mc->_next) {
|
||||
adlib_note_on(mc->_channel, mc->_note + part->_transpose_eff,
|
||||
for (voice = part->_voice; voice; voice = voice->_next) {
|
||||
adlib_note_on(voice->_channel, voice->_note + part->_transpose_eff,
|
||||
(part->_pitchbend * part->_pitchbend_factor >> 6) + part->_detune_eff);
|
||||
}
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::sysEx_customInstrument (byte channel, uint32 type, byte *instr) {
|
||||
sysEx_customInstrument (&_parts [channel], type, instr);
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::sysEx_customInstrument (AdlibPart *part, uint32 type, byte *instr) {
|
||||
if (type == 'ADL ') {
|
||||
AdlibInstrument *i = &part->_part_instr;
|
||||
memcpy(i, instr, sizeof(AdlibInstrument));
|
||||
}
|
||||
_parts[channel].sysEx_customInstrument (type, instr);
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::setTimerCallback (void *timer_param, void (*timer_proc) (void *)) {
|
||||
@ -888,68 +1013,68 @@ void MidiDriver_ADLIB::reset_tick() {
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::on_timer() {
|
||||
MidiChannelAdl *mc;
|
||||
AdlibVoice *voice;
|
||||
int i;
|
||||
|
||||
_adlib_timer_counter += 0xD69;
|
||||
while (_adlib_timer_counter >= 0x411B) {
|
||||
_adlib_timer_counter -= 0x411B;
|
||||
mc = _midi_channels;
|
||||
for (i = 0; i != ARRAYSIZE(_midi_channels); i++, mc++) {
|
||||
if (!mc->_part)
|
||||
voice = _voices;
|
||||
for (i = 0; i != ARRAYSIZE(_voices); i++, voice++) {
|
||||
if (!voice->_part)
|
||||
continue;
|
||||
if (mc->_duration && (mc->_duration -= 0x11) <= 0) {
|
||||
mc_off(mc);
|
||||
if (voice->_duration && (voice->_duration -= 0x11) <= 0) {
|
||||
mc_off(voice);
|
||||
return;
|
||||
}
|
||||
if (mc->_s10a.active) {
|
||||
mc_inc_stuff(mc, &mc->_s10a, &mc->_s11a);
|
||||
if (voice->_s10a.active) {
|
||||
mc_inc_stuff(voice, &voice->_s10a, &voice->_s11a);
|
||||
}
|
||||
if (mc->_s10b.active) {
|
||||
mc_inc_stuff(mc, &mc->_s10b, &mc->_s11b);
|
||||
if (voice->_s10b.active) {
|
||||
mc_inc_stuff(voice, &voice->_s10b, &voice->_s11b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::mc_off(MidiChannelAdl * mc2) {
|
||||
MidiChannelAdl *mc = (MidiChannelAdl *)mc2, *tmp;
|
||||
void MidiDriver_ADLIB::mc_off(AdlibVoice *voice) {
|
||||
AdlibVoice *tmp;
|
||||
|
||||
adlib_key_off(mc->_channel);
|
||||
adlib_key_off(voice->_channel);
|
||||
|
||||
tmp = mc->_prev;
|
||||
tmp = voice->_prev;
|
||||
|
||||
if (mc->_next)
|
||||
mc->_next->_prev = tmp;
|
||||
if (voice->_next)
|
||||
voice->_next->_prev = tmp;
|
||||
if (tmp)
|
||||
tmp->_next = mc->_next;
|
||||
tmp->_next = voice->_next;
|
||||
else
|
||||
mc->_part->_mc = mc->_next;
|
||||
mc->_part = NULL;
|
||||
voice->_part->_voice = voice->_next;
|
||||
voice->_part = NULL;
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::mc_inc_stuff(MidiChannelAdl *mc, Struct10 *s10, Struct11 *s11) {
|
||||
void MidiDriver_ADLIB::mc_inc_stuff(AdlibVoice *voice, Struct10 *s10, Struct11 *s11) {
|
||||
byte code;
|
||||
AdlibPart *part = mc->_part;
|
||||
AdlibPart *part = voice->_part;
|
||||
|
||||
code = struct10_ontimer(s10, s11);
|
||||
|
||||
if (code & 1) {
|
||||
switch (s11->param) {
|
||||
case 0:
|
||||
mc->_vol_2 = s10->start_value + s11->modify_val;
|
||||
adlib_set_param(mc->_channel, 0,
|
||||
volume_table[lookup_table[mc->_vol_2]
|
||||
voice->_vol_2 = s10->start_value + s11->modify_val;
|
||||
adlib_set_param(voice->_channel, 0,
|
||||
volume_table[lookup_table[voice->_vol_2]
|
||||
[part->_vol_eff >> 2]]);
|
||||
break;
|
||||
case 13:
|
||||
mc->_vol_1 = s10->start_value + s11->modify_val;
|
||||
if (mc->_twochan) {
|
||||
adlib_set_param(mc->_channel, 13,
|
||||
volume_table[lookup_table[mc->_vol_1]
|
||||
voice->_vol_1 = s10->start_value + s11->modify_val;
|
||||
if (voice->_twochan) {
|
||||
adlib_set_param(voice->_channel, 13,
|
||||
volume_table[lookup_table[voice->_vol_1]
|
||||
[part->_vol_eff >> 2]]);
|
||||
} else {
|
||||
adlib_set_param(mc->_channel, 13, mc->_vol_1);
|
||||
adlib_set_param(voice->_channel, 13, voice->_vol_1);
|
||||
}
|
||||
break;
|
||||
case 30:
|
||||
@ -959,14 +1084,14 @@ void MidiDriver_ADLIB::mc_inc_stuff(MidiChannelAdl *mc, Struct10 *s10, Struct11
|
||||
s11->s10->unk3 = (char)s11->modify_val;
|
||||
break;
|
||||
default:
|
||||
adlib_set_param(mc->_channel, s11->param,
|
||||
adlib_set_param(voice->_channel, s11->param,
|
||||
s10->start_value + s11->modify_val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (code & 2 && s11->flag0x10)
|
||||
adlib_key_onoff(mc->_channel);
|
||||
adlib_key_onoff(voice->_channel);
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::adlib_key_off(int chan){
|
||||
@ -1153,37 +1278,37 @@ int MidiDriver_ADLIB::random_nr(int a) {
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::part_key_off (AdlibPart *part, byte note) {
|
||||
MidiChannelAdl *mc;
|
||||
AdlibVoice *voice;
|
||||
|
||||
for (mc = part->_mc; mc; mc = mc->_next) {
|
||||
if (mc->_note == note) {
|
||||
for (voice = part->_voice; voice; voice = voice->_next) {
|
||||
if (voice->_note == note) {
|
||||
if (part->_pedal)
|
||||
mc->_waitforpedal = true;
|
||||
voice->_waitforpedal = true;
|
||||
else
|
||||
mc_off(mc);
|
||||
mc_off(voice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::part_key_on (AdlibPart *part, byte note, byte velocity) {
|
||||
MidiChannelAdl *mc;
|
||||
void MidiDriver_ADLIB::part_key_on (AdlibPart *part, AdlibInstrument *instr, byte note, byte velocity) {
|
||||
AdlibVoice *voice;
|
||||
|
||||
mc = allocate_midichan(part->_pri_eff);
|
||||
if (!mc)
|
||||
voice = allocate_voice(part->_pri_eff);
|
||||
if (!voice)
|
||||
return;
|
||||
|
||||
link_mc(part, mc);
|
||||
mc_key_on(mc, note, velocity);
|
||||
link_mc(part, voice);
|
||||
mc_key_on(voice, instr, note, velocity);
|
||||
}
|
||||
|
||||
MidiChannelAdl *MidiDriver_ADLIB::allocate_midichan(byte pri) {
|
||||
MidiChannelAdl *ac, *best = NULL;
|
||||
AdlibVoice *MidiDriver_ADLIB::allocate_voice(byte pri) {
|
||||
AdlibVoice *ac, *best = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
if (++_midichan_index >= 9)
|
||||
_midichan_index = 0;
|
||||
ac = &_midi_channels[_midichan_index];
|
||||
if (++_voice_index >= 9)
|
||||
_voice_index = 0;
|
||||
ac = &_voices[_voice_index];
|
||||
if (!ac->_part)
|
||||
return ac;
|
||||
if (!ac->_next) {
|
||||
@ -1199,59 +1324,57 @@ MidiChannelAdl *MidiDriver_ADLIB::allocate_midichan(byte pri) {
|
||||
return best;
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::link_mc (AdlibPart *part, MidiChannelAdl *mc) {
|
||||
mc->_part = part;
|
||||
mc->_next = (MidiChannelAdl *)part->_mc;
|
||||
part->_mc = mc;
|
||||
mc->_prev = NULL;
|
||||
void MidiDriver_ADLIB::link_mc (AdlibPart *part, AdlibVoice *voice) {
|
||||
voice->_part = part;
|
||||
voice->_next = (AdlibVoice *)part->_voice;
|
||||
part->_voice = voice;
|
||||
voice->_prev = NULL;
|
||||
|
||||
if (mc->_next)
|
||||
mc->_next->_prev = mc;
|
||||
if (voice->_next)
|
||||
voice->_next->_prev = voice;
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::mc_key_on (MidiChannelAdl *mc2, byte note, byte velocity) {
|
||||
MidiChannelAdl *mc = (MidiChannelAdl *)mc2;
|
||||
AdlibPart *part = mc->_part;
|
||||
AdlibInstrument *instr = &part->_part_instr;
|
||||
void MidiDriver_ADLIB::mc_key_on (AdlibVoice *voice, AdlibInstrument *instr, byte note, byte velocity) {
|
||||
AdlibPart *part = voice->_part;
|
||||
int c;
|
||||
byte vol_1, vol_2;
|
||||
|
||||
mc->_twochan = instr->feedback & 1;
|
||||
mc->_note = note;
|
||||
mc->_waitforpedal = false;
|
||||
mc->_duration = instr->duration;
|
||||
if (mc->_duration != 0)
|
||||
mc->_duration *= 63;
|
||||
voice->_twochan = instr->feedback & 1;
|
||||
voice->_note = note;
|
||||
voice->_waitforpedal = false;
|
||||
voice->_duration = instr->duration;
|
||||
if (voice->_duration != 0)
|
||||
voice->_duration *= 63;
|
||||
|
||||
vol_1 = (instr->oplvl_1 & 0x3F) + lookup_table[velocity >> 1][instr->waveform_1 >> 2];
|
||||
if (vol_1 > 0x3F)
|
||||
vol_1 = 0x3F;
|
||||
mc->_vol_1 = vol_1;
|
||||
voice->_vol_1 = vol_1;
|
||||
|
||||
vol_2 = (instr->oplvl_2 & 0x3F) + lookup_table[velocity >> 1][instr->waveform_2 >> 2];
|
||||
if (vol_2 > 0x3F)
|
||||
vol_2 = 0x3F;
|
||||
mc->_vol_2 = vol_2;
|
||||
voice->_vol_2 = vol_2;
|
||||
|
||||
c = part->_vol_eff >> 2;
|
||||
|
||||
vol_2 = volume_table[lookup_table[vol_2][c]];
|
||||
if (mc->_twochan)
|
||||
if (voice->_twochan)
|
||||
vol_1 = volume_table[lookup_table[vol_1][c]];
|
||||
|
||||
adlib_setup_channel(mc->_channel, instr, vol_1, vol_2);
|
||||
adlib_note_on_ex(mc->_channel, part->_transpose_eff + note, part->_detune_eff + (part->_pitchbend * part->_pitchbend_factor >> 6));
|
||||
adlib_setup_channel(voice->_channel, instr, vol_1, vol_2);
|
||||
adlib_note_on_ex(voice->_channel, part->_transpose_eff + note, part->_detune_eff + (part->_pitchbend * part->_pitchbend_factor >> 6));
|
||||
|
||||
if (instr->flags_a & 0x80) {
|
||||
mc_init_stuff(mc, &mc->_s10a, &mc->_s11a, instr->flags_a, &instr->extra_a);
|
||||
mc_init_stuff(voice, &voice->_s10a, &voice->_s11a, instr->flags_a, &instr->extra_a);
|
||||
} else {
|
||||
mc->_s10a.active = 0;
|
||||
voice->_s10a.active = 0;
|
||||
}
|
||||
|
||||
if (instr->flags_b & 0x80) {
|
||||
mc_init_stuff(mc, &mc->_s10b, &mc->_s11b, instr->flags_b, &instr->extra_b);
|
||||
mc_init_stuff(voice, &voice->_s10b, &voice->_s11b, instr->flags_b, &instr->extra_b);
|
||||
} else {
|
||||
mc->_s10b.active = 0;
|
||||
voice->_s10b.active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1292,9 +1415,9 @@ void MidiDriver_ADLIB::adlib_note_on_ex(int chan, byte note, int mod)
|
||||
adlib_playnote(chan, code);
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::mc_init_stuff (MidiChannelAdl *mc, Struct10 * s10,
|
||||
void MidiDriver_ADLIB::mc_init_stuff (AdlibVoice *voice, Struct10 * s10,
|
||||
Struct11 * s11, byte flags, InstrumentExtra * ie) {
|
||||
AdlibPart *part = mc->_part;
|
||||
AdlibPart *part = voice->_part;
|
||||
s11->modify_val = 0;
|
||||
s11->flag0x40 = flags & 0x40;
|
||||
s10->loop = flags & 0x20;
|
||||
@ -1310,10 +1433,10 @@ void MidiDriver_ADLIB::mc_init_stuff (MidiChannelAdl *mc, Struct10 * s10,
|
||||
|
||||
switch (s11->param) {
|
||||
case 0:
|
||||
s10->start_value = mc->_vol_2;
|
||||
s10->start_value = voice->_vol_2;
|
||||
break;
|
||||
case 13:
|
||||
s10->start_value = mc->_vol_1;
|
||||
s10->start_value = voice->_vol_1;
|
||||
break;
|
||||
case 30:
|
||||
s10->start_value = 31;
|
||||
@ -1324,7 +1447,7 @@ void MidiDriver_ADLIB::mc_init_stuff (MidiChannelAdl *mc, Struct10 * s10,
|
||||
s11->s10->unk3 = 0;
|
||||
break;
|
||||
default:
|
||||
s10->start_value = adlib_read_param(mc->_channel, s11->param);
|
||||
s10->start_value = adlib_read_param(voice->_channel, s11->param);
|
||||
}
|
||||
|
||||
struct10_init(s10, ie);
|
||||
@ -1390,8 +1513,3 @@ void MidiDriver_ADLIB::adlib_note_on(int chan, byte note, int mod) {
|
||||
curnote_table[chan] = code;
|
||||
adlib_playnote(chan, channel_table_2[chan] + code);
|
||||
}
|
||||
|
||||
void MidiDriver_ADLIB::part_set_instrument(AdlibPart *part, AdlibInstrument *instr) {
|
||||
AdlibInstrument *i = &part->_part_instr;
|
||||
memcpy(i, instr, sizeof(AdlibInstrument));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user