mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-20 08:48:13 +00:00
SCI: instead of queueing inside midiparser, we are queueing now globally in SciMusic, also some little cleanup
svn-id: r50130
This commit is contained in:
parent
6c854f30da
commit
1041067a0c
@ -61,14 +61,20 @@ MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) :
|
||||
_dataincToAdd = 0;
|
||||
_resetOnPause = false;
|
||||
_pSnd = 0;
|
||||
|
||||
_manualCommandCount = 0;
|
||||
}
|
||||
|
||||
MidiParser_SCI::~MidiParser_SCI() {
|
||||
unloadMusic();
|
||||
}
|
||||
|
||||
void MidiParser_SCI::mainThreadBegin() {
|
||||
_mainThreadCalled = true;
|
||||
}
|
||||
|
||||
void MidiParser_SCI::mainThreadEnd() {
|
||||
_mainThreadCalled = false;
|
||||
}
|
||||
|
||||
bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask, SciVersion soundVersion) {
|
||||
unloadMusic();
|
||||
_track = track;
|
||||
@ -107,7 +113,7 @@ void MidiParser_SCI::sendInitCommands() {
|
||||
byte voiceCount = 0;
|
||||
if (_channelUsed[i]) {
|
||||
voiceCount = _pSnd->soundRes->getInitialVoiceCount(i);
|
||||
sendToDriverQueue(0xB0 | i, 0x4B, voiceCount);
|
||||
sendToDriver(0xB0 | i, 0x4B, voiceCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -115,7 +121,8 @@ void MidiParser_SCI::sendInitCommands() {
|
||||
|
||||
// Send a velocity off signal to all channels
|
||||
for (int i = 0; i < 15; ++i) {
|
||||
sendToDriverQueue(0xB0 | i, 0x4E, 0); // Reset velocity
|
||||
if (_channelUsed[i])
|
||||
sendToDriver(0xB0 | i, 0x4E, 0); // Reset velocity
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,44 +152,27 @@ void MidiParser_SCI::unloadMusic() {
|
||||
}
|
||||
}
|
||||
|
||||
// this is used for scripts sending direct midi commands to us. we verify in that case that the channel is actually
|
||||
// used and actually store the command for getting really sent when being onTimer()
|
||||
void MidiParser_SCI::sendToDriverQueue(uint32 b) {
|
||||
byte midiChannel = b & 0xf;
|
||||
// this is used for scripts sending midi commands to us. we verify in that case that the channel is actually
|
||||
// used, so that channel remapping will work as well and then send them on
|
||||
void MidiParser_SCI::sendFromScriptToDriver(uint32 midi) {
|
||||
byte midiChannel = midi & 0xf;
|
||||
|
||||
if (!_channelUsed[midiChannel]) {
|
||||
// trying to send to an unused channel
|
||||
// this happens for cmdSendMidi at least in sq1vga right at the start, it's a script issue
|
||||
return;
|
||||
}
|
||||
|
||||
if (_manualCommandCount >= 200)
|
||||
error("driver queue is full");
|
||||
_manualCommands[_manualCommandCount] = b;
|
||||
_manualCommandCount++;
|
||||
sendToDriver(midi);
|
||||
}
|
||||
|
||||
// This sends the stored commands from queue to driver (is supposed to get called only during onTimer())
|
||||
// at least mt32 emulation doesn't like getting note-on commands from main thread (if we directly send, we would get
|
||||
// a crash during piano scene in lsl5)
|
||||
void MidiParser_SCI::sendQueueToDriver() {
|
||||
int curCommand = 0;
|
||||
void MidiParser_SCI::sendToDriver(uint32 midi) {
|
||||
byte midiChannel = midi & 0xf;
|
||||
|
||||
while (curCommand < _manualCommandCount) {
|
||||
sendToDriver(_manualCommands[curCommand]);
|
||||
curCommand++;
|
||||
}
|
||||
_manualCommandCount = 0;
|
||||
}
|
||||
|
||||
void MidiParser_SCI::sendToDriver(uint32 b) {
|
||||
byte midiChannel = b & 0xf;
|
||||
|
||||
if ((b & 0xFFF0) == 0x4EB0) {
|
||||
if ((midi & 0xFFF0) == 0x4EB0) {
|
||||
// this is channel mute only for sci1
|
||||
// it's velocity control for sci0
|
||||
if (_soundVersion >= SCI_VERSION_1_EARLY) {
|
||||
_channelMuted[midiChannel] = b & 0xFF0000 ? true : false;
|
||||
_channelMuted[midiChannel] = midi & 0xFF0000 ? true : false;
|
||||
return; // don't send this to driver at all
|
||||
}
|
||||
}
|
||||
@ -194,8 +184,11 @@ void MidiParser_SCI::sendToDriver(uint32 b) {
|
||||
int16 realChannel = _channelRemap[midiChannel];
|
||||
assert(realChannel != -1);
|
||||
|
||||
b = (b & 0xFFFFFFF0) | realChannel;
|
||||
_driver->send(b);
|
||||
midi = (midi & 0xFFFFFFF0) | realChannel;
|
||||
if (_mainThreadCalled)
|
||||
_music->putMidiCommandInQueue(midi);
|
||||
else
|
||||
_driver->send(midi);
|
||||
}
|
||||
|
||||
void MidiParser_SCI::parseNextEvent(EventInfo &info) {
|
||||
@ -681,7 +674,8 @@ void MidiParser_SCI::setVolume(byte volume) {
|
||||
case SCI_VERSION_1_LATE:
|
||||
// sending volume change to all used channels
|
||||
for (int i = 0; i < 15; i++)
|
||||
sendToDriverQueue(0xB0 + i, 7, _volume);
|
||||
if (_channelUsed[i])
|
||||
sendToDriver(0xB0 + i, 7, _volume);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -55,6 +55,10 @@ class MidiParser_SCI : public MidiParser {
|
||||
public:
|
||||
MidiParser_SCI(SciVersion soundVersion, SciMusic *music);
|
||||
~MidiParser_SCI();
|
||||
|
||||
void mainThreadBegin();
|
||||
void mainThreadEnd();
|
||||
|
||||
bool loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask, SciVersion soundVersion);
|
||||
bool loadMusic(byte *, uint32) {
|
||||
return false;
|
||||
@ -77,16 +81,11 @@ public:
|
||||
const byte *getMixedData() const { return _mixedData; }
|
||||
|
||||
void tryToOwnChannels();
|
||||
void sendToDriver(uint32 b);
|
||||
void sendFromScriptToDriver(uint32 midi);
|
||||
void sendToDriver(uint32 midi);
|
||||
void sendToDriver(byte status, byte firstOp, byte secondOp) {
|
||||
sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
|
||||
}
|
||||
void sendToDriverQueue(uint32 b);
|
||||
void sendToDriverQueue(byte status, byte firstOp, byte secondOp) {
|
||||
sendToDriverQueue(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
|
||||
}
|
||||
|
||||
void sendQueueToDriver();
|
||||
|
||||
protected:
|
||||
void parseNextEvent(EventInfo &info);
|
||||
@ -96,6 +95,9 @@ protected:
|
||||
|
||||
SciMusic *_music;
|
||||
|
||||
// this is set, when main thread calls us -> we send commands to queue instead to driver
|
||||
bool _mainThreadCalled;
|
||||
|
||||
SciVersion _soundVersion;
|
||||
byte *_mixedData;
|
||||
SoundResource::Track *_track;
|
||||
@ -112,9 +114,6 @@ protected:
|
||||
bool _channelUsed[16];
|
||||
int16 _channelRemap[16];
|
||||
bool _channelMuted[16];
|
||||
|
||||
int _manualCommandCount;
|
||||
uint32 _manualCommands[200];
|
||||
};
|
||||
|
||||
} // End of namespace Sci
|
||||
|
@ -46,6 +46,8 @@ SciMusic::SciMusic(SciVersion soundVersion)
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
_usedChannel[i] = 0;
|
||||
|
||||
_queuedCommandCount = 0;
|
||||
}
|
||||
|
||||
SciMusic::~SciMusic() {
|
||||
@ -102,6 +104,49 @@ void SciMusic::init() {
|
||||
_driverFirstChannel = _pMidiDrv->getFirstChannel();
|
||||
}
|
||||
|
||||
void SciMusic::miditimerCallback(void *p) {
|
||||
SciMusic *sciMusic = (SciMusic *)p;
|
||||
|
||||
Common::StackLock lock(sciMusic->_mutex);
|
||||
sciMusic->onTimer();
|
||||
}
|
||||
|
||||
void SciMusic::onTimer() {
|
||||
const MusicList::iterator end = _playList.end();
|
||||
// sending out queued commands that were "sent" via main thread
|
||||
sendMidiCommandsFromQueue();
|
||||
|
||||
for (MusicList::iterator i = _playList.begin(); i != end; ++i)
|
||||
(*i)->onTimer();
|
||||
|
||||
// for sending out fade commands immediately
|
||||
sendMidiCommandsFromQueue();
|
||||
}
|
||||
|
||||
void SciMusic::putMidiCommandInQueue(byte status, byte firstOp, byte secondOp) {
|
||||
putMidiCommandInQueue(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16));
|
||||
}
|
||||
|
||||
void SciMusic::putMidiCommandInQueue(uint32 midi) {
|
||||
if (_queuedCommandCount >= 1000)
|
||||
error("driver queue is full");
|
||||
_queuedCommands[_queuedCommandCount] = midi;
|
||||
_queuedCommandCount++;
|
||||
}
|
||||
|
||||
// This sends the stored commands from queue to driver (is supposed to get called only during onTimer())
|
||||
// at least mt32 emulation doesn't like getting note-on commands from main thread (if we directly send, we would get
|
||||
// a crash during piano scene in lsl5)
|
||||
void SciMusic::sendMidiCommandsFromQueue() {
|
||||
int curCommand = 0;
|
||||
|
||||
while (curCommand < _queuedCommandCount) {
|
||||
_pMidiDrv->send(_queuedCommands[curCommand]);
|
||||
curCommand++;
|
||||
}
|
||||
_queuedCommandCount = 0;
|
||||
}
|
||||
|
||||
void SciMusic::clearPlayList() {
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
@ -127,14 +172,6 @@ void SciMusic::stopAll() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SciMusic::miditimerCallback(void *p) {
|
||||
SciMusic *aud = (SciMusic *)p;
|
||||
|
||||
Common::StackLock lock(aud->_mutex);
|
||||
aud->onTimer();
|
||||
}
|
||||
|
||||
void SciMusic::soundSetSoundOn(bool soundOnFlag) {
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
@ -219,8 +256,10 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) {
|
||||
|
||||
// Find out what channels to filter for SCI0
|
||||
channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayId(), _pMidiDrv->hasRhythmChannel());
|
||||
pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion);
|
||||
|
||||
pSnd->pMidiParser->mainThreadBegin();
|
||||
pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion);
|
||||
pSnd->pMidiParser->mainThreadEnd();
|
||||
_mutex.unlock();
|
||||
}
|
||||
}
|
||||
@ -255,12 +294,6 @@ void SciMusic::freeChannels(MusicEntry *caller) {
|
||||
}
|
||||
}
|
||||
|
||||
void SciMusic::onTimer() {
|
||||
const MusicList::iterator end = _playList.end();
|
||||
for (MusicList::iterator i = _playList.begin(); i != end; ++i)
|
||||
(*i)->onTimer();
|
||||
}
|
||||
|
||||
void SciMusic::soundPlay(MusicEntry *pSnd) {
|
||||
_mutex.lock();
|
||||
|
||||
@ -316,18 +349,21 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
|
||||
DisposeAfterUse::NO);
|
||||
}
|
||||
} else {
|
||||
_mutex.lock();
|
||||
if (pSnd->pMidiParser) {
|
||||
_mutex.lock();
|
||||
pSnd->pMidiParser->mainThreadBegin();
|
||||
pSnd->pMidiParser->tryToOwnChannels();
|
||||
pSnd->pMidiParser->setVolume(pSnd->volume);
|
||||
if (pSnd->status == kSoundStopped) {
|
||||
pSnd->pMidiParser->sendInitCommands();
|
||||
pSnd->pMidiParser->jumpToTick(0);
|
||||
} else
|
||||
} else {
|
||||
// Fast forward to the last position and perform associated events when loading
|
||||
pSnd->pMidiParser->jumpToTick(pSnd->ticker, true);
|
||||
}
|
||||
pSnd->pMidiParser->mainThreadEnd();
|
||||
_mutex.unlock();
|
||||
}
|
||||
_mutex.unlock();
|
||||
}
|
||||
|
||||
pSnd->status = kSoundPlaying;
|
||||
@ -342,8 +378,10 @@ void SciMusic::soundStop(MusicEntry *pSnd) {
|
||||
|
||||
if (pSnd->pMidiParser) {
|
||||
_mutex.lock();
|
||||
pSnd->pMidiParser->mainThreadBegin();
|
||||
pSnd->pMidiParser->stop();
|
||||
freeChannels(pSnd);
|
||||
pSnd->pMidiParser->mainThreadEnd();
|
||||
_mutex.unlock();
|
||||
}
|
||||
}
|
||||
@ -354,7 +392,9 @@ void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) {
|
||||
_pMixer->setChannelVolume(pSnd->hCurrentAud, volume * 2); // Mixer is 0-255, SCI is 0-127
|
||||
} else if (pSnd->pMidiParser) {
|
||||
_mutex.lock();
|
||||
pSnd->pMidiParser->mainThreadBegin();
|
||||
pSnd->pMidiParser->setVolume(volume);
|
||||
pSnd->pMidiParser->mainThreadEnd();
|
||||
_mutex.unlock();
|
||||
}
|
||||
}
|
||||
@ -369,13 +409,15 @@ void SciMusic::soundSetPriority(MusicEntry *pSnd, byte prio) {
|
||||
void SciMusic::soundKill(MusicEntry *pSnd) {
|
||||
pSnd->status = kSoundStopped;
|
||||
|
||||
_mutex.lock();
|
||||
if (pSnd->pMidiParser) {
|
||||
_mutex.lock();
|
||||
pSnd->pMidiParser->mainThreadBegin();
|
||||
pSnd->pMidiParser->unloadMusic();
|
||||
pSnd->pMidiParser->mainThreadEnd();
|
||||
delete pSnd->pMidiParser;
|
||||
pSnd->pMidiParser = NULL;
|
||||
_mutex.unlock();
|
||||
}
|
||||
_mutex.unlock();
|
||||
|
||||
if (pSnd->pStreamAud) {
|
||||
_pMixer->stopHandle(pSnd->hCurrentAud);
|
||||
@ -409,8 +451,10 @@ void SciMusic::soundPause(MusicEntry *pSnd) {
|
||||
} else {
|
||||
if (pSnd->pMidiParser) {
|
||||
_mutex.lock();
|
||||
pSnd->pMidiParser->mainThreadBegin();
|
||||
pSnd->pMidiParser->pause();
|
||||
freeChannels(pSnd);
|
||||
pSnd->pMidiParser->mainThreadEnd();
|
||||
_mutex.unlock();
|
||||
}
|
||||
}
|
||||
@ -458,10 +502,12 @@ void SciMusic::sendMidiCommand(uint32 cmd) {
|
||||
|
||||
void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) {
|
||||
Common::StackLock lock(_mutex);
|
||||
if (pSnd->pMidiParser)
|
||||
pSnd->pMidiParser->sendToDriverQueue(cmd);
|
||||
else
|
||||
if (!pSnd->pMidiParser)
|
||||
error("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj));
|
||||
|
||||
pSnd->pMidiParser->mainThreadBegin();
|
||||
pSnd->pMidiParser->sendFromScriptToDriver(cmd);
|
||||
pSnd->pMidiParser->mainThreadEnd();
|
||||
}
|
||||
|
||||
void SciMusic::printPlayList(Console *con) {
|
||||
@ -567,8 +613,6 @@ void MusicEntry::onTimer() {
|
||||
|
||||
// Only process MIDI streams in this thread, not digital sound effects
|
||||
if (pMidiParser) {
|
||||
// Process manual commands first
|
||||
pMidiParser->sendQueueToDriver();
|
||||
pMidiParser->onTimer();
|
||||
ticker = (uint16)pMidiParser->getTick();
|
||||
}
|
||||
|
@ -132,7 +132,15 @@ public:
|
||||
~SciMusic();
|
||||
|
||||
void init();
|
||||
|
||||
void onTimer();
|
||||
void putMidiCommandInQueue(byte status, byte firstOp, byte secondOp);
|
||||
void putMidiCommandInQueue(uint32 midi);
|
||||
private:
|
||||
static void miditimerCallback(void *p);
|
||||
void sendMidiCommandsFromQueue();
|
||||
|
||||
public:
|
||||
void clearPlayList();
|
||||
void pauseAll(bool pause);
|
||||
void stopAll();
|
||||
@ -209,14 +217,16 @@ protected:
|
||||
// Mixed AdLib/MIDI mode: when enabled from the ScummVM sound options screen,
|
||||
// and a sound has a digital track, the sound from the AdLib track is played
|
||||
bool _bMultiMidi;
|
||||
private:
|
||||
static void miditimerCallback(void *p);
|
||||
|
||||
private:
|
||||
MusicList _playList;
|
||||
bool _soundOn;
|
||||
byte _masterVolume;
|
||||
MusicEntry *_usedChannel[16];
|
||||
|
||||
int _queuedCommandCount;
|
||||
uint32 _queuedCommands[1000];
|
||||
|
||||
int _driverFirstChannel;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user