mirror of
https://github.com/libretro/scummvm.git
synced 2025-05-16 02:56:00 +00:00
Revamped Adlib functionality.
IMuseAdlib is defunct. New MidiDriver_ADLIB device. Simon 1/2 now supports Adlib. svn-id: r5677
This commit is contained in:
parent
d7e443cd7c
commit
c9ed09e7df
1366
backends/midi/adlib.cpp
Normal file
1366
backends/midi/adlib.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -408,7 +408,7 @@ bool GameDetector::parseMusicDriver(const char *s) {
|
|||||||
{"etude",MD_ETUDE},
|
{"etude",MD_ETUDE},
|
||||||
{"midiemu",MD_MIDIEMU},
|
{"midiemu",MD_MIDIEMU},
|
||||||
{"alsa", MD_ALSA},
|
{"alsa", MD_ALSA},
|
||||||
{"adlib",-1},
|
{"adlib", MD_ADLIB},
|
||||||
};
|
};
|
||||||
|
|
||||||
const MusicDrivers *md = music_drivers;
|
const MusicDrivers *md = music_drivers;
|
||||||
@ -418,7 +418,7 @@ bool GameDetector::parseMusicDriver(const char *s) {
|
|||||||
|
|
||||||
for(i=0; i!=ARRAYSIZE(music_drivers); i++,md++) {
|
for(i=0; i!=ARRAYSIZE(music_drivers); i++,md++) {
|
||||||
if (!scumm_stricmp(md->name, s)) {
|
if (!scumm_stricmp(md->name, s)) {
|
||||||
if (md->id == -1) {
|
if (md->id == MD_ADLIB) {
|
||||||
_use_adlib = true;
|
_use_adlib = true;
|
||||||
}
|
}
|
||||||
_midi_driver = md->id;
|
_midi_driver = md->id;
|
||||||
@ -574,6 +574,7 @@ int GameDetector::detectMain()
|
|||||||
* and the game is one of those that want adlib as
|
* and the game is one of those that want adlib as
|
||||||
* default */
|
* default */
|
||||||
if (_midi_driver == MD_AUTO && _features & GF_ADLIB_DEFAULT) {
|
if (_midi_driver == MD_AUTO && _features & GF_ADLIB_DEFAULT) {
|
||||||
|
_midi_driver = MD_ADLIB;
|
||||||
_use_adlib = true;
|
_use_adlib = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -649,15 +650,19 @@ MidiDriver *GameDetector::createMidi() {
|
|||||||
/* FIXME: We should, for the Unix targets, attempt to detect */
|
/* FIXME: We should, for the Unix targets, attempt to detect */
|
||||||
/* whether a sequencer is available, and use it in */
|
/* whether a sequencer is available, and use it in */
|
||||||
/* preference */
|
/* preference */
|
||||||
|
/*
|
||||||
if (drv == MD_AUTO) {
|
if (drv == MD_AUTO) {
|
||||||
_use_adlib = true;
|
_use_adlib = true;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
if (drv == MD_AUTO) drv = MD_ADLIB;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch(drv) {
|
switch(drv) {
|
||||||
case MD_AUTO:
|
case MD_AUTO:
|
||||||
case MD_NULL: return MidiDriver_NULL_create();
|
case MD_NULL: return MidiDriver_NULL_create();
|
||||||
|
case MD_ADLIB: _use_adlib = true; return MidiDriver_ADLIB_create();
|
||||||
#if defined(WIN32) && !defined(_WIN32_WCE)
|
#if defined(WIN32) && !defined(_WIN32_WCE)
|
||||||
case MD_WINDOWS: return MidiDriver_WIN_create();
|
case MD_WINDOWS: return MidiDriver_WIN_create();
|
||||||
#endif
|
#endif
|
||||||
|
@ -355,7 +355,8 @@ public:
|
|||||||
pcProgram = 64,
|
pcProgram = 64,
|
||||||
pcChorus = 128,
|
pcChorus = 128,
|
||||||
pcPitchBendFactor = 256,
|
pcPitchBendFactor = 256,
|
||||||
pcAll = 511,
|
pcPriority = 512,
|
||||||
|
pcAll = 1023,
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual void on_timer() = 0;
|
virtual void on_timer() = 0;
|
||||||
@ -665,6 +666,8 @@ class IMuseGM : public IMuseDriver {
|
|||||||
MidiDriver *_md;
|
MidiDriver *_md;
|
||||||
MidiChannelGM _midi_channels[16];
|
MidiChannelGM _midi_channels[16];
|
||||||
|
|
||||||
|
Instrument _glob_instr[32]; // Adlib custom instruments
|
||||||
|
|
||||||
byte _midi_program_last[16];
|
byte _midi_program_last[16];
|
||||||
int16 _midi_pitchbend_last[16];
|
int16 _midi_pitchbend_last[16];
|
||||||
byte _midi_pitchbend_factor_last[16];
|
byte _midi_pitchbend_factor_last[16];
|
||||||
@ -691,6 +694,8 @@ class IMuseGM : public IMuseDriver {
|
|||||||
void midiSilence(byte chan);
|
void midiSilence(byte chan);
|
||||||
void midiInit();
|
void midiInit();
|
||||||
|
|
||||||
|
static void timer_callback (void *);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IMuseGM(MidiDriver *midi);
|
IMuseGM(MidiDriver *midi);
|
||||||
void uninit();
|
void uninit();
|
||||||
@ -700,8 +705,8 @@ public:
|
|||||||
int part_update_active(Part *part, uint16 *active);
|
int part_update_active(Part *part, uint16 *active);
|
||||||
|
|
||||||
void on_timer() {}
|
void on_timer() {}
|
||||||
void set_instrument(uint slot, byte *instr) {}
|
void set_instrument(uint slot, byte *instr);
|
||||||
void part_set_instrument(Part *part, Instrument * instr) {}
|
void part_set_instrument(Part *part, Instrument * instr);
|
||||||
void part_set_param(Part *part, byte param, int value) {}
|
void part_set_param(Part *part, byte param, int value) {}
|
||||||
void part_key_on(Part *part, byte note, byte velocity);
|
void part_key_on(Part *part, byte note, byte velocity);
|
||||||
void part_key_off(Part *part, byte note);
|
void part_key_off(Part *part, byte note);
|
||||||
@ -710,7 +715,7 @@ public:
|
|||||||
|
|
||||||
static int midi_driver_thread(void *param);
|
static int midi_driver_thread(void *param);
|
||||||
|
|
||||||
uint32 get_base_tempo() { return 0x4A0000; }
|
uint32 get_base_tempo() { return _md->getBaseTempo(); } // 0x4A0000; }
|
||||||
byte get_hardware_type() { return 5; }
|
byte get_hardware_type() { return 5; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2199,7 +2204,6 @@ byte *Player::parse_midi(byte *s)
|
|||||||
|
|
||||||
case 0xC: /* program change */
|
case 0xC: /* program change */
|
||||||
value = *s++;
|
value = *s++;
|
||||||
debug (2, "Player::parse_midi - Setting channel %2d to program %d", chan, value); // Jamieson630: Helps to build the GM-to-FM mapping
|
|
||||||
part = get_part(chan);
|
part = get_part(chan);
|
||||||
if (part)
|
if (part)
|
||||||
part->set_program(value);
|
part->set_program(value);
|
||||||
@ -2212,7 +2216,6 @@ byte *Player::parse_midi(byte *s)
|
|||||||
case 0xE: /* pitch bend */
|
case 0xE: /* pitch bend */
|
||||||
part = get_part(chan);
|
part = get_part(chan);
|
||||||
if (part)
|
if (part)
|
||||||
// part->set_pitchbend(((s[1] - 0x40) << 7) | s[0]);
|
|
||||||
part->set_pitchbend(((s[1] << 7) | s[0]) - 0x2000);
|
part->set_pitchbend(((s[1] << 7) | s[0]) - 0x2000);
|
||||||
s += 2;
|
s += 2;
|
||||||
break;
|
break;
|
||||||
@ -2392,7 +2395,7 @@ void Player::parse_sysex(byte *p, uint len)
|
|||||||
if (part) {
|
if (part) {
|
||||||
part->set_onoff (p[2] & 0x01);
|
part->set_onoff (p[2] & 0x01);
|
||||||
part->set_vol ((p[5] & 0x0F) << 4 | (p[6] & 0x0F));
|
part->set_vol ((p[5] & 0x0F) << 4 | (p[6] & 0x0F));
|
||||||
part->_percussion = ((p[9] & 0x08) > 0);
|
part->_percussion = _isGM ? ((p[9] & 0x08) > 0) : false;
|
||||||
if (part->_percussion) {
|
if (part->_percussion) {
|
||||||
if (part->_mc)
|
if (part->_mc)
|
||||||
part->off();
|
part->off();
|
||||||
@ -2431,7 +2434,7 @@ void Player::parse_sysex(byte *p, uint len)
|
|||||||
|
|
||||||
case 16: /* set instrument in part */
|
case 16: /* set instrument in part */
|
||||||
a = *p++ & 0x0F;
|
a = *p++ & 0x0F;
|
||||||
if (_se->_hardware_type != *p++)
|
if (_se->_hardware_type != *p++ && false)
|
||||||
break;
|
break;
|
||||||
decode_sysex_bytes(p, buf, len - 3);
|
decode_sysex_bytes(p, buf, len - 3);
|
||||||
part = get_part(a);
|
part = get_part(a);
|
||||||
@ -2441,7 +2444,7 @@ void Player::parse_sysex(byte *p, uint len)
|
|||||||
|
|
||||||
case 17: /* set global instrument */
|
case 17: /* set global instrument */
|
||||||
p++;
|
p++;
|
||||||
if (_se->_hardware_type != *p++)
|
if (_se->_hardware_type != *p++ && false)
|
||||||
break;
|
break;
|
||||||
a = *p++;
|
a = *p++;
|
||||||
decode_sysex_bytes(p, buf, len - 4);
|
decode_sysex_bytes(p, buf, len - 4);
|
||||||
@ -3422,6 +3425,7 @@ void Part::set_vol(uint8 vol)
|
|||||||
void Part::set_pri(int8 pri)
|
void Part::set_pri(int8 pri)
|
||||||
{
|
{
|
||||||
_pri_eff = clamp((_pri = pri) + _player->_priority, 0, 255);
|
_pri_eff = clamp((_pri = pri) + _player->_priority, 0, 255);
|
||||||
|
changed(IMuseDriver::pcPriority);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Part::set_pan(int8 pan)
|
void Part::set_pan(int8 pan)
|
||||||
@ -4947,7 +4951,8 @@ void IMuseGM::init(IMuseInternal *eng, OSystem *syst)
|
|||||||
|
|
||||||
/* Install the on_timer thread */
|
/* Install the on_timer thread */
|
||||||
_se = eng;
|
_se = eng;
|
||||||
syst->create_thread(midi_driver_thread, this);
|
// syst->create_thread(midi_driver_thread, this);
|
||||||
|
_md->setTimerCallback (NULL, &IMuseGM::timer_callback);
|
||||||
|
|
||||||
for (i = 0, mc = _midi_channels; i != ARRAYSIZE(_midi_channels); i++, mc++) {
|
for (i = 0, mc = _midi_channels; i != ARRAYSIZE(_midi_channels); i++, mc++) {
|
||||||
mc->_chan = i;
|
mc->_chan = i;
|
||||||
@ -4955,6 +4960,10 @@ void IMuseGM::init(IMuseInternal *eng, OSystem *syst)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IMuseGM::timer_callback (void *) {
|
||||||
|
g_scumm->_imuse->on_timer();
|
||||||
|
}
|
||||||
|
|
||||||
void IMuseGM::uninit()
|
void IMuseGM::uninit()
|
||||||
{
|
{
|
||||||
_md->close();
|
_md->close();
|
||||||
@ -5034,6 +5043,21 @@ int IMuseGM::part_update_active(Part *part, uint16 *active)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IMuseGM::part_set_instrument (Part *part, Instrument *instr)
|
||||||
|
{
|
||||||
|
if (!part->_mc)
|
||||||
|
update_pris();
|
||||||
|
if (!part->_mc)
|
||||||
|
return;
|
||||||
|
_md->sysEx_customInstrument (part->_mc->gm()->_chan, 'ADL ', (byte *)instr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IMuseGM::set_instrument(uint slot, byte *data)
|
||||||
|
{
|
||||||
|
if (slot < 32)
|
||||||
|
memcpy(&_glob_instr[slot], data, sizeof(Instrument));
|
||||||
|
}
|
||||||
|
|
||||||
void IMuseGM::part_changed(Part *part, uint16 what)
|
void IMuseGM::part_changed(Part *part, uint16 what)
|
||||||
{
|
{
|
||||||
MidiChannelGM *mc;
|
MidiChannelGM *mc;
|
||||||
@ -5078,6 +5102,7 @@ void IMuseGM::part_changed(Part *part, uint16 what)
|
|||||||
midiEffectLevel(mc->_chan, part->_effect_level);
|
midiEffectLevel(mc->_chan, part->_effect_level);
|
||||||
|
|
||||||
if (what & pcProgram && part->_program < 128) {
|
if (what & pcProgram && part->_program < 128) {
|
||||||
|
if (part->_player->_isGM) {
|
||||||
_midi_program_last [part->_chan] = part->_program;
|
_midi_program_last [part->_chan] = part->_program;
|
||||||
if (part->_bank) {
|
if (part->_bank) {
|
||||||
midiControl0(mc->_chan, part->_bank);
|
midiControl0(mc->_chan, part->_bank);
|
||||||
@ -5086,10 +5111,16 @@ void IMuseGM::part_changed(Part *part, uint16 what)
|
|||||||
} else {
|
} else {
|
||||||
midiProgram(mc->_chan, part->_program, part->_player->_mt32emulate);
|
midiProgram(mc->_chan, part->_program, part->_player->_mt32emulate);
|
||||||
}
|
}
|
||||||
|
} else if (part->_program < 32) {
|
||||||
|
part_set_instrument(part, &_glob_instr[part->_program]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (what & pcChorus)
|
if (what & pcChorus)
|
||||||
midiChorus(mc->_chan, part->_effect_level);
|
midiChorus(mc->_chan, part->_effect_level);
|
||||||
|
|
||||||
|
if (what & pcPriority)
|
||||||
|
_md->send ((part->_pri_eff << 16) | (18 << 8) | 0xB0 | mc->_chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -608,20 +608,21 @@ int Scumm::readSoundResource(int type, int idx)
|
|||||||
pri = 15;
|
pri = 15;
|
||||||
break;
|
break;
|
||||||
case MKID('ADL '):
|
case MKID('ADL '):
|
||||||
|
pri = 1;
|
||||||
if (_use_adlib)
|
if (_use_adlib)
|
||||||
pri = 10;
|
pri = 10;
|
||||||
break;
|
break;
|
||||||
case MKID('ROL '):
|
case MKID('ROL '):
|
||||||
if (!_use_adlib)
|
|
||||||
pri = 2;
|
|
||||||
break;
|
|
||||||
case MKID('GMD '):
|
|
||||||
// if (!_use_adlib)
|
// if (!_use_adlib)
|
||||||
pri = 3;
|
pri = 3;
|
||||||
break;
|
break;
|
||||||
|
case MKID('GMD '):
|
||||||
|
// if (!_use_adlib)
|
||||||
|
pri = 4;
|
||||||
|
break;
|
||||||
case MKID('MAC '):
|
case MKID('MAC '):
|
||||||
// if (!_use_adlib)
|
// if (!_use_adlib)
|
||||||
pri = 1;
|
pri = 2;
|
||||||
break;
|
break;
|
||||||
case MKID('SPK '):
|
case MKID('SPK '):
|
||||||
if (!_use_adlib)
|
if (!_use_adlib)
|
||||||
|
@ -165,11 +165,11 @@ Scumm::Scumm (GameDetector *detector, OSystem *syst)
|
|||||||
_imuseDigital = new IMuseDigital(this);
|
_imuseDigital = new IMuseDigital(this);
|
||||||
_imuse = NULL;
|
_imuse = NULL;
|
||||||
} else {
|
} else {
|
||||||
if (detector->_use_adlib) {
|
if (detector->_use_adlib && false) {
|
||||||
_imuse = IMuse::create_adlib(syst, _mixer);
|
_imuse = IMuse::create_adlib(syst, _mixer);
|
||||||
} else {
|
} else {
|
||||||
void *midiTemp = detector->createMidi();
|
void *midiTemp = detector->createMidi();
|
||||||
if (!midiTemp) { // Fallback to adlib/midiemu
|
if (!midiTemp) { // Fallback to Adlib
|
||||||
_imuse = IMuse::create_adlib(syst, _mixer);
|
_imuse = IMuse::create_adlib(syst, _mixer);
|
||||||
} else {
|
} else {
|
||||||
_imuse = IMuse::create_midi(syst, detector->createMidi());
|
_imuse = IMuse::create_midi(syst, detector->createMidi());
|
||||||
|
@ -35,6 +35,67 @@
|
|||||||
#include "common/engine.h" // for warning/error/debug
|
#include "common/engine.h" // for warning/error/debug
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Common MPU401 implementation methods
|
||||||
|
//
|
||||||
|
////////////////////////////////////////
|
||||||
|
|
||||||
|
typedef void TimerCallback (void *);
|
||||||
|
|
||||||
|
class MidiDriver_MPU401 : public MidiDriver {
|
||||||
|
private:
|
||||||
|
bool _started_thread;
|
||||||
|
TimerCallback *_timer_proc;
|
||||||
|
void *_timer_param;
|
||||||
|
|
||||||
|
static int midi_driver_thread (void *param);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void setTimerCallback (void *timer_param, void (*timer_proc) (void *));
|
||||||
|
virtual uint32 getBaseTempo (void) { return 0x4A0000; }
|
||||||
|
};
|
||||||
|
|
||||||
|
void MidiDriver_MPU401::setTimerCallback (void *timer_param, void (*timer_proc) (void *))
|
||||||
|
{
|
||||||
|
if (!_timer_proc || !timer_proc) {
|
||||||
|
_timer_proc = (TimerCallback *) timer_proc;
|
||||||
|
_timer_param = timer_param;
|
||||||
|
if (!_started_thread && timer_proc)
|
||||||
|
g_system->create_thread (midi_driver_thread, this);
|
||||||
|
_started_thread = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MidiDriver_MPU401::midi_driver_thread(void *param)
|
||||||
|
{
|
||||||
|
MidiDriver_MPU401 *mid = (MidiDriver_MPU401 *)param;
|
||||||
|
int old_time, cur_time;
|
||||||
|
|
||||||
|
old_time = g_system->get_msecs();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
g_system->delay_msecs(10);
|
||||||
|
|
||||||
|
cur_time = g_system->get_msecs();
|
||||||
|
while (old_time < cur_time) {
|
||||||
|
old_time += 10;
|
||||||
|
// Don't use mid->_se_on_timer()
|
||||||
|
// We must come in through IMuseMonitor to protect
|
||||||
|
// against conflicts with script access to IMuse.
|
||||||
|
if (mid->_timer_proc)
|
||||||
|
(*(mid->_timer_proc)) (mid->_timer_param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME - the following disables reverb support in the QuickTime / CoreAudio
|
// FIXME - the following disables reverb support in the QuickTime / CoreAudio
|
||||||
// midi backends. For some reasons, reverb will suck away a *lot* of CPU time.
|
// midi backends. For some reasons, reverb will suck away a *lot* of CPU time.
|
||||||
// Until we know for sure what is causing this and if there is a better way to
|
// Until we know for sure what is causing this and if there is a better way to
|
||||||
@ -44,7 +105,7 @@
|
|||||||
#if defined(WIN32) && !defined(_WIN32_WCE)
|
#if defined(WIN32) && !defined(_WIN32_WCE)
|
||||||
|
|
||||||
/* Windows MIDI driver */
|
/* Windows MIDI driver */
|
||||||
class MidiDriver_WIN : public MidiDriver {
|
class MidiDriver_WIN : public MidiDriver_MPU401 {
|
||||||
public:
|
public:
|
||||||
int open(int mode);
|
int open(int mode);
|
||||||
void close();
|
void close();
|
||||||
@ -304,7 +365,7 @@ MidiDriver *MidiDriver_WIN_create()
|
|||||||
#include "morphos_sound.h"
|
#include "morphos_sound.h"
|
||||||
|
|
||||||
/* MorphOS MIDI driver */
|
/* MorphOS MIDI driver */
|
||||||
class MidiDriver_ETUDE:public MidiDriver {
|
class MidiDriver_ETUDE:public MidiDriver_MPU401 {
|
||||||
public:
|
public:
|
||||||
int open(int mode);
|
int open(int mode);
|
||||||
void close();
|
void close();
|
||||||
@ -515,7 +576,7 @@ MidiDriver *MidiDriver_ETUDE_create()
|
|||||||
#define SEQ_MIDIPUTC 5
|
#define SEQ_MIDIPUTC 5
|
||||||
#define SPECIAL_CHANNEL 9
|
#define SPECIAL_CHANNEL 9
|
||||||
|
|
||||||
class MidiDriver_SEQ:public MidiDriver {
|
class MidiDriver_SEQ:public MidiDriver_MPU401 {
|
||||||
public:
|
public:
|
||||||
MidiDriver_SEQ();
|
MidiDriver_SEQ();
|
||||||
int open(int mode);
|
int open(int mode);
|
||||||
@ -655,7 +716,7 @@ MidiDriver *MidiDriver_SEQ_create()
|
|||||||
|
|
||||||
|
|
||||||
/* QuickTime MIDI driver */
|
/* QuickTime MIDI driver */
|
||||||
class MidiDriver_QT:public MidiDriver {
|
class MidiDriver_QT:public MidiDriver_MPU401 {
|
||||||
public:
|
public:
|
||||||
int open(int mode);
|
int open(int mode);
|
||||||
void close();
|
void close();
|
||||||
@ -872,7 +933,7 @@ MidiDriver *MidiDriver_QT_create()
|
|||||||
|
|
||||||
/* CoreAudio MIDI driver */
|
/* CoreAudio MIDI driver */
|
||||||
/* Based on code by Benjamin W. Zale */
|
/* Based on code by Benjamin W. Zale */
|
||||||
class MidiDriver_CORE:public MidiDriver {
|
class MidiDriver_CORE:public MidiDriver_MPU401 {
|
||||||
public:
|
public:
|
||||||
MidiDriver_CORE():au_MusicDevice(NULL), au_output(NULL) {
|
MidiDriver_CORE():au_MusicDevice(NULL), au_output(NULL) {
|
||||||
} int open(int mode);
|
} int open(int mode);
|
||||||
@ -979,7 +1040,7 @@ MidiDriver *MidiDriver_CORE_create()
|
|||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
|
||||||
/* NULL driver */
|
/* NULL driver */
|
||||||
class MidiDriver_NULL:public MidiDriver {
|
class MidiDriver_NULL:public MidiDriver_MPU401 {
|
||||||
public:
|
public:
|
||||||
int open(int mode);
|
int open(int mode);
|
||||||
void close() { }
|
void close() { }
|
||||||
@ -1051,7 +1112,7 @@ const char *MidiDriver::get_error_name(int error_code)
|
|||||||
|
|
||||||
#define ADDR_DELIM ".:"
|
#define ADDR_DELIM ".:"
|
||||||
|
|
||||||
class MidiDriver_ALSA:public MidiDriver {
|
class MidiDriver_ALSA:public MidiDriver_MPU401 {
|
||||||
public:
|
public:
|
||||||
MidiDriver_ALSA();
|
MidiDriver_ALSA();
|
||||||
int open(int mode);
|
int open(int mode);
|
||||||
|
@ -106,6 +106,12 @@ public:
|
|||||||
send((range << 16) | ( 6 << 8) | (0xB0 | channel));
|
send((range << 16) | ( 6 << 8) | (0xB0 | channel));
|
||||||
send(( 0 << 16) | ( 38 << 8) | (0xB0 | channel));
|
send(( 0 << 16) | ( 38 << 8) | (0xB0 | channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void sysEx_customInstrument (byte channel, uint32 type, byte *instr) { }
|
||||||
|
|
||||||
|
// Timing functions - MidiDriver now operates timers
|
||||||
|
virtual void setTimerCallback (void *timer_param, void (*timer_proc) (void *)) = 0;
|
||||||
|
virtual uint32 getBaseTempo (void) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -122,12 +128,14 @@ enum {
|
|||||||
MD_COREAUDIO = 7,
|
MD_COREAUDIO = 7,
|
||||||
MD_MIDIEMU = 8,
|
MD_MIDIEMU = 8,
|
||||||
MD_ALSA = 9,
|
MD_ALSA = 9,
|
||||||
|
MD_ADLIB = 10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Factory functions => no need to include the specific classes
|
/* Factory functions => no need to include the specific classes
|
||||||
* in this header => faster compile */
|
* in this header => faster compile */
|
||||||
extern MidiDriver *MidiDriver_NULL_create();
|
extern MidiDriver *MidiDriver_NULL_create();
|
||||||
|
extern MidiDriver *MidiDriver_ADLIB_create();
|
||||||
extern MidiDriver *MidiDriver_WIN_create();
|
extern MidiDriver *MidiDriver_WIN_create();
|
||||||
extern MidiDriver *MidiDriver_TIMIDITY_create();
|
extern MidiDriver *MidiDriver_TIMIDITY_create();
|
||||||
extern MidiDriver *MidiDriver_SEQ_create();
|
extern MidiDriver *MidiDriver_SEQ_create();
|
||||||
|
@ -37,6 +37,7 @@ private:
|
|||||||
int _event_count;
|
int _event_count;
|
||||||
int _event_index;
|
int _event_index;
|
||||||
|
|
||||||
|
long _driver_tempo;
|
||||||
long _tempo;
|
long _tempo;
|
||||||
uint16 _ticks_per_beat;
|
uint16 _ticks_per_beat;
|
||||||
long _delay;
|
long _delay;
|
||||||
@ -44,8 +45,8 @@ private:
|
|||||||
volatile bool _active;
|
volatile bool _active;
|
||||||
|
|
||||||
uint32 property(int prop, uint32 param);
|
uint32 property(int prop, uint32 param);
|
||||||
static int timer_thread (void *param);
|
static void timer_thread (void *param);
|
||||||
void on_timer (void);
|
void on_timer();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MidiStreamer (MidiDriver *target);
|
MidiStreamer (MidiDriver *target);
|
||||||
@ -56,6 +57,9 @@ public:
|
|||||||
void pause(bool p) { _paused = p; }
|
void pause(bool p) { _paused = p; }
|
||||||
void set_stream_callback(void *param, StreamCallback *sc);
|
void set_stream_callback(void *param, StreamCallback *sc);
|
||||||
void setPitchBendRange (byte channel, uint range) { _target->setPitchBendRange (channel, range); }
|
void setPitchBendRange (byte channel, uint range) { _target->setPitchBendRange (channel, range); }
|
||||||
|
|
||||||
|
void setTimerCallback (void *timer_param, void (*timer_proc) (void *)) { }
|
||||||
|
uint32 getBaseTempo (void) { return _target->getBaseTempo(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
MidiStreamer::MidiStreamer (MidiDriver *target) :
|
MidiStreamer::MidiStreamer (MidiDriver *target) :
|
||||||
@ -82,7 +86,7 @@ void MidiStreamer::set_stream_callback (void *param, StreamCallback *sc)
|
|||||||
_event_index = 0;
|
_event_index = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
int MidiStreamer::timer_thread (void *param) {
|
int MidiStreamer::timer_thread (void *param) {
|
||||||
MidiStreamer *mid = (MidiStreamer *) param;
|
MidiStreamer *mid = (MidiStreamer *) param;
|
||||||
int old_time, cur_time;
|
int old_time, cur_time;
|
||||||
@ -109,10 +113,14 @@ int MidiStreamer::timer_thread (void *param) {
|
|||||||
mid->_active = false;
|
mid->_active = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
void MidiStreamer::timer_thread (void *param) {
|
||||||
|
((MidiStreamer *) param)->on_timer();
|
||||||
|
}
|
||||||
|
|
||||||
void MidiStreamer::on_timer()
|
void MidiStreamer::on_timer()
|
||||||
{
|
{
|
||||||
_delay += 10000;
|
_delay += _driver_tempo; // 10000;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (_event_index >= _event_count) {
|
if (_event_index >= _event_count) {
|
||||||
_event_count = _stream_proc (_stream_param, _events, ARRAYSIZE (_events));
|
_event_count = _stream_proc (_stream_param, _events, ARRAYSIZE (_events));
|
||||||
@ -145,18 +153,17 @@ int MidiStreamer::open (int mode)
|
|||||||
if (res && res != MERR_ALREADY_OPEN)
|
if (res && res != MERR_ALREADY_OPEN)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
// Wait for existing timer thread to shut down.
|
|
||||||
while (_active);
|
|
||||||
|
|
||||||
_event_index = _event_count = _delay = 0;
|
_event_index = _event_count = _delay = 0;
|
||||||
_mode = mode;
|
_mode = mode;
|
||||||
_paused = false;
|
_paused = false;
|
||||||
_active = true;
|
|
||||||
|
|
||||||
if (mode == MO_SIMPLE)
|
if (mode == MO_SIMPLE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
g_system->create_thread (timer_thread, this);
|
// g_system->create_thread (timer_thread, this);
|
||||||
|
_driver_tempo = _target->getBaseTempo() / 500;
|
||||||
|
|
||||||
|
_target->setTimerCallback (this, &timer_thread);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,6 +171,15 @@ void MidiStreamer::close()
|
|||||||
{
|
{
|
||||||
if (!_mode)
|
if (!_mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
_target->setTimerCallback (NULL, NULL);
|
||||||
|
|
||||||
|
// Turn off all notes on all channels,
|
||||||
|
// just to catch anything still playing.
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 16; ++i)
|
||||||
|
_target->send ((0x7B << 8) | 0xB0 | i);
|
||||||
|
|
||||||
_mode = 0;
|
_mode = 0;
|
||||||
_paused = true;
|
_paused = true;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user