MIDI: Send a reset MIDI device signal on startup.

This is currently done in the engine code. I adapted AGI, AGOS, DRACI,
GROOVIE, LURE, MADE, QUEEN, SAGA, SKY, TINSEL and TOUCHE to send a reset
device on startup. The sound output still works fine (started up a game
from every engine), so this should hopefully not introduce any regressions.

As far as I can tell it seems that SCUMM does send a proper device reset, so
I did not touch it. KYRA only sends a proper reset for MT-32 currently. I am
not sure about SCI though.

This fixes bug #3066826 "SIMON: MIDI notes off when using RTL after SCI".

svn-id: r52736
This commit is contained in:
Johannes Schickel 2010-09-15 22:00:20 +00:00
parent bb5db4aa3b
commit 6588398ce6
19 changed files with 97 additions and 20 deletions

View File

@ -74,8 +74,12 @@ SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, p
DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB);
_driver = MidiDriver::createMidi(dev);
if (ConfMan.getBool("native_mt32"))
if (ConfMan.getBool("native_mt32") || MidiDriver::getMusicType(dev) == MT_MT32) {
_nativeMT32 = true;
_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
} else {
_nativeMT32 = false;
}
memset(_channel, 0, sizeof(_channel));
memset(_channelVolume, 255, sizeof(_channelVolume));
@ -125,10 +129,10 @@ int SoundGenMIDI::open() {
_driver->setTimerCallback(this, &onTimer);
// General MIDI System On message
// Resets all GM devices to default settings
_driver->sysEx((const byte *)"\x7E\x7F\x09\x01", 4);
g_system->delayMillis(20);
if (_nativeMT32)
_driver->sendMT32Reset();
else
_driver->sendGMReset();
return 0;
}

View File

@ -562,11 +562,11 @@ Common::Error AGOSEngine::init() {
_driver = MidiDriver::createMidi(dev);
if (_nativeMT32) {
if (_nativeMT32)
_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
}
_midi.mapMT32toGM (getGameType() != GType_SIMON2 && !_nativeMT32);
_midi.setNativeMT32(_nativeMT32);
_midi.mapMT32toGM(getGameType() != GType_SIMON2 && !_nativeMT32);
_midi.setDriver(_driver);

View File

@ -77,10 +77,10 @@ int MidiPlayer::open() {
return ret;
_driver->setTimerCallback(this, &onTimer);
// General MIDI System On message
// Resets all GM devices to default settings
_driver->sysEx((const byte *)"\x7E\x7F\x09\x01", 4);
g_system->delayMillis(20);
if (_nativeMT32)
_driver->sendMT32Reset();
else
_driver->sendGMReset();
return 0;
}

View File

@ -61,6 +61,7 @@ protected:
MidiDriver *_driver;
bool _map_mt32_to_gm;
bool _passThrough;
bool _nativeMT32;
MusicInfo _music;
MusicInfo _sfx;
@ -97,6 +98,7 @@ public:
void loadS1D(Common::File *in, bool sfx = false);
void mapMT32toGM(bool map);
void setNativeMT32(bool nativeMT32) { _nativeMT32 = nativeMT32; }
void setLoop(bool loop);
void startTrack(int track);
void queueTrack(int track, bool loop);

View File

@ -170,6 +170,7 @@ int DraciEngine::init() {
_music = new MusicPlayer(_midiDriver, musicPathMask);
_music->setNativeMT32(native_mt32);
_music->open();
//_music->setAdLib(adlib);
// Load the game's fonts

View File

@ -40,13 +40,8 @@ MusicPlayer::MusicPlayer(MidiDriver *driver, const char *pathMask) : _parser(0),
memset(_channel, 0, sizeof(_channel));
memset(_channelVolume, 255, sizeof(_channelVolume));
_masterVolume = 0;
this->open();
_smfParser = MidiParser::createParser_SMF();
_midiMusicData = NULL;
// TODO: Load cmf.ins with the instrument table. It seems that an
// interface for such an operation is supported for AdLib. Maybe for
// this card, setting instruments is necessary.
}
MusicPlayer::~MusicPlayer() {
@ -89,6 +84,15 @@ int MusicPlayer::open() {
if (ret)
return ret;
if (_nativeMT32)
_driver->sendMT32Reset();
else
_driver->sendGMReset();
// TODO: Load cmf.ins with the instrument table. It seems that an
// interface for such an operation is supported for AdLib. Maybe for
// this card, setting instruments is necessary.
_driver->setTimerCallback(this, &onTimer);
return 0;
}

View File

@ -427,10 +427,14 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String &gtlName)
setTimbreAD(9, _timbres[i]);
}
} else if ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")) {
_driver->sendMT32Reset();
// MT-32
_musicType = MT_MT32;
loadTimbres(gtlName + ".mt");
} else {
_driver->sendGMReset();
// GM
_musicType = 0;
}

View File

@ -63,8 +63,12 @@ SoundManager::SoundManager() {
_driver = NULL;
} else {
if (_nativeMT32)
if (_nativeMT32) {
_driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
_driver->sendMT32Reset();
} else {
_driver->sendGMReset();
}
for (index = 0; index < NUM_CHANNELS; ++index) {
_channelsInner[index].midiChannel = _driver->allocateChannel();

View File

@ -107,6 +107,7 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng
_music = new MusicPlayer(driver);
_music->setNativeMT32(native_mt32);
_music->open();
//_music->setAdLib(adlib);
// Set default sound frequency

View File

@ -40,7 +40,6 @@ namespace Made {
MusicPlayer::MusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) {
memset(_channel, 0, sizeof(_channel));
_masterVolume = 0;
this->open();
_xmidiParser = MidiParser::createParser_XMIDI();
_smfParser = MidiParser::createParser_SMF();
}
@ -81,6 +80,11 @@ int MusicPlayer::open() {
if (ret)
return ret;
if (_nativeMT32)
_driver->sendMT32Reset();
else
_driver->sendGMReset();
_driver->setTimerCallback(this, &onTimer);
return 0;
}

View File

@ -82,6 +82,11 @@ MidiMusic::MidiMusic(QueenEngine *vm)
_driver->open();
_driver->setTimerCallback(this, &timerCallback);
if (_nativeMT32)
_driver->sendMT32Reset();
else
_driver->sendGMReset();
_parser = MidiParser::createParser_SMF();
_parser->setMidiDriver(this);
_parser->setTimerRate(_driver->getBaseTempo());

View File

@ -60,6 +60,19 @@ MusicDriver::~MusicDriver() {
delete _driver;
}
int MusicDriver::open() {
int retValue = _driver->open();
if (retValue)
return retValue;
if (_nativeMT32)
_driver->sendMT32Reset();
else
_driver->sendGMReset();
return 0;
}
void MusicDriver::setVolume(int volume) {
volume = CLIP(volume, 0, 255);

View File

@ -57,7 +57,7 @@ public:
void setGM(bool isGM) { _isGM = isGM; }
//MidiDriver interface implementation
int open() { return _driver->open(); }
int open();
void close() { _driver->close(); }
void send(uint32 b);

View File

@ -44,6 +44,7 @@ GmMusic::GmMusic(MidiDriver *pMidiDrv, Disk *pDisk) : MusicBase(pDisk) {
error("Can't open midi device. Errorcode: %d", midiRes);
_timerCount = 0;
_midiDrv->setTimerCallback(this, passTimerFunc);
_midiDrv->sendGMReset();
}
GmMusic::~GmMusic() {

View File

@ -44,6 +44,7 @@ MT32Music::MT32Music(MidiDriver *pMidiDrv, Disk *pDisk) : MusicBase(pDisk) {
error("Can't open midi device. Errorcode: %d",midiRes);
_timerCount = 0;
_midiDrv->setTimerCallback(this, passTimerFunc);
_midiDrv->sendMT32Reset();
}
MT32Music::~MT32Music() {

View File

@ -867,6 +867,11 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc)
//_midiMusic->setNativeMT32(native_mt32);
//_midiMusic->setAdLib(adlib);
if (native_mt32)
_driver->sendMT32Reset();
else
_driver->sendGMReset();
_musicVolume = ConfMan.getInt("music_volume");
_sound = new SoundManager(this);

View File

@ -101,6 +101,11 @@ int MidiPlayer::open() {
_parser->setMidiDriver(this);
_parser->setTimerRate(_driver->getBaseTempo());
_driver->setTimerCallback(this, &timerCallback);
if (_nativeMT32)
_driver->sendMT32Reset();
else
_driver->sendGMReset();
}
return ret;
}

View File

@ -306,3 +306,16 @@ MidiDriver::DeviceHandle MidiDriver::getDeviceHandle(const Common::String &ident
return 0;
}
void MidiDriver::sendMT32Reset() {
static const byte resetSysEx[] = { 0x41, 0x10, 0x16, 0x12, 0x7F, 0x00, 0x00, 0x01, 0x00 };
sysEx(resetSysEx, sizeof(resetSysEx));
g_system->delayMillis(100);
}
void MidiDriver::sendGMReset() {
static const byte resetSysEx[] = { 0x7E, 0x7F, 0x09, 0x01 };
sysEx(resetSysEx, sizeof(resetSysEx));
g_system->delayMillis(100);
}

View File

@ -215,6 +215,16 @@ public:
send(0xB0 | channel, 100, 127);
}
/**
* Send a Roland MT-32 reset sysEx to the midi device.
*/
void sendMT32Reset();
/**
* Send a General MIDI reset sysEx to the midi device.
*/
void sendGMReset();
/**
* Transmit a sysEx to the midi device.
*