FM-TOWNS AUDIO: Unlock internal mutex before calling imuse timer proc.

This commit is contained in:
athrxx 2011-05-23 16:37:58 +02:00 committed by unknown
parent 3d42141e9d
commit c60807cbb9
6 changed files with 39 additions and 51 deletions

View File

@ -103,12 +103,12 @@ private:
class TownsAudioInterfaceInternal : public TownsPC98_FmSynth {
public:
TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver);
TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false);
~TownsAudioInterfaceInternal();
static TownsAudioInterfaceInternal *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver);
static TownsAudioInterfaceInternal *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false);
static void releaseRef();
bool checkPluginDriver(TownsAudioInterfacePluginDriver *driver);
bool checkPluginDriver(TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false);
bool init();
@ -252,7 +252,8 @@ private:
static const uint16 _pcmPhase2[];
};
TownsAudioInterfaceInternal::TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns),
TownsAudioInterfaceInternal::TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) :
TownsPC98_FmSynth(mixer, kTypeTowns, externalMutexHandling),
_fmInstruments(0), _pcmInstruments(0), _pcmChan(0), _waveTables(0), _waveTablesTotalDataSize(0),
_baserate(55125.0f / (float)mixer->getOutputRate()), _tickLength(0), _timer(0), _drv(driver),
_pcmSfxChanMask(0), _musicVolume(Audio::Mixer::kMaxMixerVolume), _sfxVolume(Audio::Mixer::kMaxMixerVolume),
@ -395,13 +396,13 @@ TownsAudioInterfaceInternal::~TownsAudioInterfaceInternal() {
delete[] _pcmChan;
}
TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) {
TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) {
_refCount++;
if (_refCount == 1 && _refInstance == 0)
_refInstance = new TownsAudioInterfaceInternal(mixer, driver);
_refInstance = new TownsAudioInterfaceInternal(mixer, driver, externalMutexHandling);
else if (_refCount < 2 || _refInstance == 0)
error("TownsAudioInterfaceInternal::addNewRef(): Internal reference management failure");
else if (!_refInstance->checkPluginDriver(driver))
else if (!_refInstance->checkPluginDriver(driver, externalMutexHandling))
error("TownsAudioInterfaceInternal::addNewRef(): Plugin driver conflict");
return _refInstance;
@ -419,7 +420,7 @@ void TownsAudioInterfaceInternal::releaseRef() {
}
}
bool TownsAudioInterfaceInternal::checkPluginDriver(TownsAudioInterfacePluginDriver *driver) {
bool TownsAudioInterfaceInternal::checkPluginDriver(TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) {
if (_refCount <= 1)
return true;
@ -428,6 +429,7 @@ bool TownsAudioInterfaceInternal::checkPluginDriver(TownsAudioInterfacePluginDri
return false;
} else {
_drv = driver;
_externalMutex = externalMutexHandling;
}
return true;
@ -1669,7 +1671,6 @@ void TownsAudioInterfaceInternal::updateOutputVolumeInternal() {
int volume = (int)(((float)(maxVol * 255) / 63.0f));
int balance = maxVol ? (int)( ( ((int)_outputLevel[13] * (_outputMute[13] ^ 1) - _outputLevel[12] * (_outputMute[12] ^ 1)) * 127) / (float)maxVol) : 0;
Common::StackLock lock(_mutex);
g_system->getAudioCDManager()->setVolume(volume);
g_system->getAudioCDManager()->setBalance(balance);
@ -1854,8 +1855,8 @@ void TownsAudio_WaveTable::clear() {
data = 0;
}
TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) {
_intf = TownsAudioInterfaceInternal::addNewRef(mixer, driver);
TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling) {
_intf = TownsAudioInterfaceInternal::addNewRef(mixer, driver, externalMutexHandling);
}
TownsAudioInterface::~TownsAudioInterface() {
@ -1887,12 +1888,4 @@ void TownsAudioInterface::setSoundEffectVolume(int volume) {
void TownsAudioInterface::setSoundEffectChanMask(int mask) {
_intf->setSoundEffectChanMask(mask);
}
void TownsAudioInterface::lockInternal() {
_intf->mutexLock();
}
void TownsAudioInterface::unlockInternal() {
_intf->mutexUnlock();
}
}

View File

@ -35,7 +35,7 @@ public:
class TownsAudioInterface {
public:
TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver);
TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver, bool externalMutexHandling = false);
~TownsAudioInterface();
bool init();
@ -48,13 +48,6 @@ public:
// The first 6 bits are the 6 fm channels. The next 8 bits are pcm channels.
void setSoundEffectChanMask(int mask);
// These methods should not be needed in standard situations, since the mutex
// is handled internally. However, they may be required to avoid lockup situations
// if the code using this class has a mutex of its own (example for a lockup
// situation: imuse.cpp, line 78).
void lockInternal();
void unlockInternal();
private:
TownsAudioInterfaceInternal *_intf;
};

View File

@ -834,7 +834,9 @@ const uint8 TownsMidiInputChannel::_programAdjustLevel[] = {
MidiDriver_TOWNS::MidiDriver_TOWNS(Audio::Mixer *mixer) : _timerProc(0), _timerProcPara(0), _channels(0), _out(0),
_chanState(0), _operatorLevelTable(0), _tickCounter1(0), _tickCounter2(0), _rand(1), _allocCurPos(0), _isOpen(false) {
_intf = new TownsAudioInterface(mixer, this);
// We set exteral mutex handling to true, since this driver is only suitable for use with the SCUMM engine
// which has its own mutex. This causes lockups which cannot always be avoided.
_intf = new TownsAudioInterface(mixer, this, true);
_channels = new TownsMidiInputChannel*[32];
for (int i = 0; i < 32; i++)

View File

@ -851,7 +851,7 @@ void TownsPC98_FmSynthPercussionSource::advanceInput(RhtChannel *ins) {
}
#endif // DISABLE_PC98_RHYTHM_CHANNEL
TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type) :
TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type, bool externalMutexHandling) :
_mixer(mixer),
_chanInternal(0), _ssg(0),
#ifndef DISABLE_PC98_RHYTHM_CHANNEL
@ -861,7 +861,8 @@ TownsPC98_FmSynth::TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type) :
_hasPercussion(type == kType86 ? true : false),
_oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0),
_rtt(type == kTypeTowns ? 0x514767 : 0x5B8D80), _baserate(55125.0f / (float)mixer->getOutputRate()),
_volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _ready(false) {
_volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255),
_regProtectionFlag(false), _externalMutex(externalMutexHandling), _ready(false) {
memset(&_timers[0], 0, sizeof(ChipTimer));
memset(&_timers[1], 0, sizeof(ChipTimer));
@ -1147,7 +1148,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
bool locked = false;
if (_ready) {
mutexLock();
_mutex.lock();
locked = true;
}
@ -1157,7 +1158,19 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
for (int i = 0; i < 2; i++) {
if (_timers[i].enabled && _timers[i].cb) {
if (!_timers[i].smpTillCb) {
if (locked && _externalMutex) {
_mutex.unlock();
locked = false;
}
(this->*_timers[i].cb)();
if (_ready && !locked && _externalMutex) {
_mutex.lock();
locked = true;
}
_timers[i].smpTillCb = _timers[i].smpPerCb;
_timers[i].smpTillCbRem += _timers[i].smpPerCbRem;
@ -1201,7 +1214,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
}
if (locked)
mutexUnlock();
_mutex.unlock();
delete[] tmpStart;
@ -1220,14 +1233,6 @@ int TownsPC98_FmSynth::getRate() const {
return _mixer->getOutputRate();
}
void TownsPC98_FmSynth::mutexLock() {
_mutex.lock();
}
void TownsPC98_FmSynth::mutexUnlock() {
_mutex.unlock();
}
void TownsPC98_FmSynth::deinit() {
_ready = false;
_mixer->stopHandle(_soundHandle);

View File

@ -59,7 +59,7 @@ public:
kType86
};
TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type);
TownsPC98_FmSynth(Audio::Mixer *mixer, EmuType type, bool externalMutexHandling = false);
virtual ~TownsPC98_FmSynth();
virtual bool init();
@ -73,9 +73,6 @@ public:
bool endOfData() const;
int getRate() const;
void mutexLock();
void mutexUnlock();
protected:
void deinit();
@ -104,6 +101,7 @@ protected:
const bool _hasPercussion;
Common::Mutex _mutex;
bool _externalMutex;
private:
void generateTables();

View File

@ -581,15 +581,12 @@ Player_Towns_v2::Player_Towns_v2(ScummEngine *vm, Audio::Mixer *mixer, IMuse *im
}
Player_Towns_v2::~Player_Towns_v2() {
// Avoid lockup in imuse.cpp, line 78
_intf->lockInternal();
if (_imuseDispose)
delete _imuse;
_intf->unlockInternal();
delete _intf;
_intf = 0;
if (_imuseDispose)
delete _imuse;
delete[] _sblData;
delete[] _soundOverride;
}