mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-18 07:53:12 +00:00
FM-TOWNS AUDIO: Unlock internal mutex before calling imuse timer proc.
This commit is contained in:
parent
3d42141e9d
commit
c60807cbb9
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
};
|
||||
|
@ -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++)
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user