diff options
| -rw-r--r-- | audio/softsynth/fmtowns_pc98/towns_audio.cpp | 228 | ||||
| -rw-r--r-- | audio/softsynth/fmtowns_pc98/towns_audio.h | 11 | ||||
| -rw-r--r-- | audio/softsynth/fmtowns_pc98/towns_midi.cpp | 68 | ||||
| -rw-r--r-- | audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp | 104 | ||||
| -rw-r--r-- | audio/softsynth/fmtowns_pc98/towns_pc98_driver.h | 34 | ||||
| -rw-r--r-- | audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp | 60 | ||||
| -rw-r--r-- | audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h | 23 | ||||
| -rw-r--r-- | engines/scumm/player_towns.cpp | 9 | 
8 files changed, 290 insertions, 247 deletions
diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp index 719bc981ee..635f9354cc 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp @@ -30,7 +30,7 @@  class TownsAudio_PcmChannel { -friend class TownsAudioInterfaceIntern; +friend class TownsAudioInterfaceInternal;  public:  	TownsAudio_PcmChannel();  	~TownsAudio_PcmChannel(); @@ -80,7 +80,7 @@ private:  };  class TownsAudio_WaveTable { -friend class TownsAudioInterfaceIntern; +friend class TownsAudioInterfaceInternal;  public:  	TownsAudio_WaveTable();  	~TownsAudio_WaveTable(); @@ -101,12 +101,12 @@ private:  	int8 *data;  }; -class TownsAudioInterfaceIntern : public TownsPC98_FmSynth { +class TownsAudioInterfaceInternal : public TownsPC98_FmSynth {  public: -	TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); -	~TownsAudioInterfaceIntern(); +	TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); +	~TownsAudioInterfaceInternal(); -	static TownsAudioInterfaceIntern *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver); +	static TownsAudioInterfaceInternal *addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver);  	static void releaseRef();  	bool checkPluginDriver(TownsAudioInterfacePluginDriver *driver); @@ -127,7 +127,7 @@ private:  	void timerCallbackA();  	void timerCallbackB(); -	typedef int (TownsAudioInterfaceIntern::*TownsAudioIntfCallback)(va_list &); +	typedef int (TownsAudioInterfaceInternal::*TownsAudioIntfCallback)(va_list &);  	const TownsAudioIntfCallback *_intfOpcodes;  	int intf_reset(va_list &args); @@ -223,9 +223,11 @@ private:  	void pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w);  	void updateOutputVolume(); +	void updateOutputVolumeInternal();  	uint8 _outputVolumeFlags;  	uint8 _outputLevel[16];  	uint8 _outputMute[16]; +	bool _updateOutputVol;  	const float _baserate;  	uint32 _timerBase; @@ -239,7 +241,7 @@ private:  	TownsAudioInterfacePluginDriver *_drv;  	bool _ready; -	static TownsAudioInterfaceIntern *_refInstance; +	static TownsAudioInterfaceInternal *_refInstance;  	static int _refCount;  	static const uint8 _chanFlags[]; @@ -250,15 +252,15 @@ private:  	static const uint16 _pcmPhase2[];  }; -TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns), +TownsAudioInterfaceInternal::TownsAudioInterfaceInternal(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) : TownsPC98_FmSynth(mixer, kTypeTowns),  	_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),  	_outputVolumeFlags(0), _pcmChanOut(0), _pcmChanReserved(0), _pcmChanKeyPressed(0),  	_pcmChanEffectPlaying(0), _pcmChanKeyPlaying(0), _fmChanPlaying(0),  -	_numReservedChannels(0), _numWaveTables(0), _ready(false) { +	_numReservedChannels(0), _numWaveTables(0), _updateOutputVol(false), _ready(false) { -#define INTCB(x) &TownsAudioInterfaceIntern::intf_##x +#define INTCB(x) &TownsAudioInterfaceInternal::intf_##x  	static const TownsAudioIntfCallback intfCb[] = {  		// 0  		INTCB(reset), @@ -381,7 +383,7 @@ TownsAudioInterfaceIntern::TownsAudioInterfaceIntern(Audio::Mixer *mixer, TownsA  	_tickLength = 2 * _timerBase;  } -TownsAudioInterfaceIntern::~TownsAudioInterfaceIntern() { +TownsAudioInterfaceInternal::~TownsAudioInterfaceInternal() {  	_ready = false;  	deinit(); @@ -393,19 +395,19 @@ TownsAudioInterfaceIntern::~TownsAudioInterfaceIntern() {  	delete[] _pcmChan;  } -TownsAudioInterfaceIntern *TownsAudioInterfaceIntern::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) { +TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::addNewRef(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) {  	_refCount++;  	if (_refCount == 1 && _refInstance == 0) -		_refInstance = new TownsAudioInterfaceIntern(mixer, driver); +		_refInstance = new TownsAudioInterfaceInternal(mixer, driver);  	else if (_refCount < 2 || _refInstance == 0) -		error("TownsAudioInterfaceIntern::addNewRef(): Internal reference management failure"); +		error("TownsAudioInterfaceInternal::addNewRef(): Internal reference management failure");  	else if (!_refInstance->checkPluginDriver(driver)) -		error("TownsAudioInterfaceIntern::addNewRef(): Plugin driver conflict"); +		error("TownsAudioInterfaceInternal::addNewRef(): Plugin driver conflict");  	return _refInstance;  } -void TownsAudioInterfaceIntern::releaseRef() { +void TownsAudioInterfaceInternal::releaseRef() {  	if (!_refCount)  		return; @@ -417,7 +419,7 @@ void TownsAudioInterfaceIntern::releaseRef() {  	}  } -bool TownsAudioInterfaceIntern::checkPluginDriver(TownsAudioInterfacePluginDriver *driver) { +bool TownsAudioInterfaceInternal::checkPluginDriver(TownsAudioInterfacePluginDriver *driver) {  	if (_refCount <= 1)  		return true; @@ -425,15 +427,13 @@ bool TownsAudioInterfaceIntern::checkPluginDriver(TownsAudioInterfacePluginDrive  		if (driver && driver != _drv)  			return false;  	} else { -		lock();  		_drv = driver; -		unlock();  	}  	return true;  } -bool TownsAudioInterfaceIntern::init() { +bool TownsAudioInterfaceInternal::init() {  	if (_ready)  		return true; @@ -457,7 +457,7 @@ bool TownsAudioInterfaceIntern::init() {  	return true;  } -int TownsAudioInterfaceIntern::callback(int command, ...) { +int TownsAudioInterfaceInternal::callback(int command, ...) {  	if (!_ready)  		return 1; @@ -470,40 +470,42 @@ int TownsAudioInterfaceIntern::callback(int command, ...) {  	return res;  } -int TownsAudioInterfaceIntern::processCommand(int command, va_list &args) { +int TownsAudioInterfaceInternal::processCommand(int command, va_list &args) {  	if (!_ready)  		return 1;  	if (command < 0 || command > 81)  		return 4; -	lock(); +	Common::StackLock lock(_mutex);  	int res = (this->*_intfOpcodes[command])(args); -	unlock();  	return res;  } -void TownsAudioInterfaceIntern::setMusicVolume(int volume) { +void TownsAudioInterfaceInternal::setMusicVolume(int volume) {  	_musicVolume = CLIP<uint16>(volume, 0, Audio::Mixer::kMaxMixerVolume);  	setVolumeIntern(_musicVolume, _sfxVolume);  } -void TownsAudioInterfaceIntern::setSoundEffectVolume(int volume) { +void TownsAudioInterfaceInternal::setSoundEffectVolume(int volume) {  	_sfxVolume = CLIP<uint16>(volume, 0, Audio::Mixer::kMaxMixerVolume);  	setVolumeIntern(_musicVolume, _sfxVolume);  } -void TownsAudioInterfaceIntern::setSoundEffectChanMask(int mask) { +void TownsAudioInterfaceInternal::setSoundEffectChanMask(int mask) {  	_pcmSfxChanMask = mask >> 6;  	mask &= 0x3f;  	setVolumeChannelMasks(~mask, mask);  } -void TownsAudioInterfaceIntern::nextTickEx(int32 *buffer, uint32 bufferSize) { +void TownsAudioInterfaceInternal::nextTickEx(int32 *buffer, uint32 bufferSize) {  	if (!_ready)  		return; +	if (_updateOutputVol) +		updateOutputVolumeInternal(); +  	for (uint32 i = 0; i < bufferSize; i++) {  		_timer += _tickLength;  		while (_timer > 0x514767) { @@ -551,12 +553,12 @@ void TownsAudioInterfaceIntern::nextTickEx(int32 *buffer, uint32 bufferSize) {  	}  } -void TownsAudioInterfaceIntern::timerCallbackA() { +void TownsAudioInterfaceInternal::timerCallbackA() {  	if (_drv && _ready)  		_drv->timerCallback(0);  } -void TownsAudioInterfaceIntern::timerCallbackB() { +void TownsAudioInterfaceInternal::timerCallbackB() {  	if (_ready) {  		if (_drv)  			_drv->timerCallback(1); @@ -564,62 +566,62 @@ void TownsAudioInterfaceIntern::timerCallbackB() {  	}  } -int TownsAudioInterfaceIntern::intf_reset(va_list &args) { +int TownsAudioInterfaceInternal::intf_reset(va_list &args) {  	fmReset();  	pcmReset();  	callback(68);  	return 0;  } -int TownsAudioInterfaceIntern::intf_keyOn(va_list &args) { +int TownsAudioInterfaceInternal::intf_keyOn(va_list &args) {  	int chan = va_arg(args, int);  	int note = va_arg(args, int);  	int velo = va_arg(args, int);  	return (chan & 0x40) ? pcmKeyOn(chan, note, velo) : fmKeyOn(chan, note, velo);  } -int TownsAudioInterfaceIntern::intf_keyOff(va_list &args) { +int TownsAudioInterfaceInternal::intf_keyOff(va_list &args) {  	int chan = va_arg(args, int);  	return (chan & 0x40) ? pcmKeyOff(chan) : fmKeyOff(chan);  } -int TownsAudioInterfaceIntern::intf_setPanPos(va_list &args) { +int TownsAudioInterfaceInternal::intf_setPanPos(va_list &args) {  	int chan = va_arg(args, int);  	int mode = va_arg(args, int);  	return (chan & 0x40) ? pcmSetPanPos(chan, mode) : fmSetPanPos(chan, mode);  } -int TownsAudioInterfaceIntern::intf_setInstrument(va_list &args) { +int TownsAudioInterfaceInternal::intf_setInstrument(va_list &args) {  	int chan = va_arg(args, int);  	int instrId = va_arg(args, int);  	return (chan & 0x40) ? pcmSetInstrument(chan, instrId) : fmSetInstrument(chan, instrId);  } -int TownsAudioInterfaceIntern::intf_loadInstrument(va_list &args) { +int TownsAudioInterfaceInternal::intf_loadInstrument(va_list &args) {  	int chanType = va_arg(args, int);  	int instrId = va_arg(args, int);  	uint8 *instrData = va_arg(args, uint8 *);  	return (chanType & 0x40) ? pcmLoadInstrument(instrId, instrData) : fmLoadInstrument(instrId, instrData);  } -int TownsAudioInterfaceIntern::intf_setPitch(va_list &args) { +int TownsAudioInterfaceInternal::intf_setPitch(va_list &args) {  	int chan = va_arg(args, int);  	int16 pitch = (int16)(va_arg(args, int) & 0xffff);  	return (chan & 0x40) ? pcmSetPitch(chan, pitch) : fmSetPitch(chan, pitch);  } -int TownsAudioInterfaceIntern::intf_setLevel(va_list &args) { +int TownsAudioInterfaceInternal::intf_setLevel(va_list &args) {  	int chan = va_arg(args, int);  	int lvl = va_arg(args, int);  	return (chan & 0x40) ? pcmSetLevel(chan, lvl) : fmSetLevel(chan, lvl);  } -int TownsAudioInterfaceIntern::intf_chanOff(va_list &args) { +int TownsAudioInterfaceInternal::intf_chanOff(va_list &args) {  	int chan = va_arg(args, int);  	return (chan & 0x40) ? pcmChanOff(chan) : fmChanOff(chan);  } -int TownsAudioInterfaceIntern::intf_writeReg(va_list &args) { +int TownsAudioInterfaceInternal::intf_writeReg(va_list &args) {  	int part = va_arg(args, int) ? 1 : 0;  	int reg = va_arg(args, int);  	int val = va_arg(args, int); @@ -630,7 +632,7 @@ int TownsAudioInterfaceIntern::intf_writeReg(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_writeRegBuffer(va_list &args) { +int TownsAudioInterfaceInternal::intf_writeRegBuffer(va_list &args) {  	int part = va_arg(args, int) ? 1 : 0;  	int reg = va_arg(args, int);  	int val = va_arg(args, int); @@ -642,7 +644,7 @@ int TownsAudioInterfaceIntern::intf_writeRegBuffer(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_readRegBuffer(va_list &args) { +int TownsAudioInterfaceInternal::intf_readRegBuffer(va_list &args) {  	int part = va_arg(args, int) ? 1 : 0;  	int reg = va_arg(args, int);  	uint8 *dst = va_arg(args, uint8 *); @@ -655,7 +657,7 @@ int TownsAudioInterfaceIntern::intf_readRegBuffer(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_setTimerA(va_list &args) { +int TownsAudioInterfaceInternal::intf_setTimerA(va_list &args) {  	int enable = va_arg(args, int);  	int tempo = va_arg(args, int); @@ -670,7 +672,7 @@ int TownsAudioInterfaceIntern::intf_setTimerA(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_setTimerB(va_list &args) { +int TownsAudioInterfaceInternal::intf_setTimerB(va_list &args) {  	int enable = va_arg(args, int);  	int tempo = va_arg(args, int); @@ -684,17 +686,17 @@ int TownsAudioInterfaceIntern::intf_setTimerB(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_enableTimerA(va_list &args) { +int TownsAudioInterfaceInternal::intf_enableTimerA(va_list &args) {  	bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x15);  	return 0;  } -int TownsAudioInterfaceIntern::intf_enableTimerB(va_list &args) { +int TownsAudioInterfaceInternal::intf_enableTimerB(va_list &args) {  	bufferedWriteReg(0, 0x27, _fmSaveReg[0][0x27] | 0x2a);  	return 0;  } -int TownsAudioInterfaceIntern::intf_loadSamples(va_list &args) { +int TownsAudioInterfaceInternal::intf_loadSamples(va_list &args) {  	uint32 dest = va_arg(args, uint32);  	int size = va_arg(args, int);  	uint8 *src = va_arg(args, uint8*); @@ -717,7 +719,7 @@ int TownsAudioInterfaceIntern::intf_loadSamples(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_reserveEffectChannels(va_list &args) { +int TownsAudioInterfaceInternal::intf_reserveEffectChannels(va_list &args) {  	int numChan = va_arg(args, int);  	if (numChan > 8)  		return 3; @@ -749,7 +751,7 @@ int TownsAudioInterfaceIntern::intf_reserveEffectChannels(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_loadWaveTable(va_list &args) { +int TownsAudioInterfaceInternal::intf_loadWaveTable(va_list &args) {  	uint8 *data = va_arg(args, uint8 *);  	if (_numWaveTables > 127)  		return 3; @@ -776,7 +778,7 @@ int TownsAudioInterfaceIntern::intf_loadWaveTable(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_unloadWaveTable(va_list &args) { +int TownsAudioInterfaceInternal::intf_unloadWaveTable(va_list &args) {  	int id = va_arg(args, int);  	if (id == -1) { @@ -803,7 +805,7 @@ int TownsAudioInterfaceIntern::intf_unloadWaveTable(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_pcmPlayEffect(va_list &args) { +int TownsAudioInterfaceInternal::intf_pcmPlayEffect(va_list &args) {  	int chan = va_arg(args, int);  	int note = va_arg(args, int);  	int velo = va_arg(args, int); @@ -853,13 +855,13 @@ int TownsAudioInterfaceIntern::intf_pcmPlayEffect(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_pcmChanOff(va_list &args) { +int TownsAudioInterfaceInternal::intf_pcmChanOff(va_list &args) {  	int chan = va_arg(args, int);  	pcmChanOff(chan);  	return 0;  } -int TownsAudioInterfaceIntern::intf_pcmEffectPlaying(va_list &args) { +int TownsAudioInterfaceInternal::intf_pcmEffectPlaying(va_list &args) {  	int chan = va_arg(args, int);  	if (chan < 0x40 || chan > 0x47)  		return 1; @@ -867,54 +869,54 @@ int TownsAudioInterfaceIntern::intf_pcmEffectPlaying(va_list &args) {  	return (_pcmChanEffectPlaying & _chanFlags[chan]) ? 1 : 0;  } -int TownsAudioInterfaceIntern::intf_fmKeyOn(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmKeyOn(va_list &args) {  	int chan = va_arg(args, int);  	int note = va_arg(args, int);  	int velo = va_arg(args, int);  	return fmKeyOn(chan, note, velo);  } -int TownsAudioInterfaceIntern::intf_fmKeyOff(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmKeyOff(va_list &args) {  	int chan = va_arg(args, int);  	return fmKeyOff(chan);  } -int TownsAudioInterfaceIntern::intf_fmSetPanPos(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmSetPanPos(va_list &args) {  	int chan = va_arg(args, int);  	int mode = va_arg(args, int);  	return fmSetPanPos(chan, mode);  } -int TownsAudioInterfaceIntern::intf_fmSetInstrument(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmSetInstrument(va_list &args) {  	int chan = va_arg(args, int);  	int instrId = va_arg(args, int);  	return fmSetInstrument(chan, instrId);  } -int TownsAudioInterfaceIntern::intf_fmLoadInstrument(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmLoadInstrument(va_list &args) {  	int instrId = va_arg(args, int);  	uint8 *instrData = va_arg(args, uint8 *);  	return fmLoadInstrument(instrId, instrData);  } -int TownsAudioInterfaceIntern::intf_fmSetPitch(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmSetPitch(va_list &args) {  	int chan = va_arg(args, int);  	uint16 freq = va_arg(args, int) & 0xffff;  	return fmSetPitch(chan, freq);  } -int TownsAudioInterfaceIntern::intf_fmSetLevel(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmSetLevel(va_list &args) {  	int chan = va_arg(args, int);  	int lvl = va_arg(args, int);  	return fmSetLevel(chan, lvl);  } -int TownsAudioInterfaceIntern::intf_fmReset(va_list &args) { +int TownsAudioInterfaceInternal::intf_fmReset(va_list &args) {  	fmReset();  	return 0;  } -int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) { +int TownsAudioInterfaceInternal::intf_setOutputVolume(va_list &args) {  	int chanType = va_arg(args, int);  	int left = va_arg(args, int);  	int right = va_arg(args, int); @@ -951,14 +953,14 @@ int TownsAudioInterfaceIntern::intf_setOutputVolume(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_resetOutputVolume(va_list &args) { +int TownsAudioInterfaceInternal::intf_resetOutputVolume(va_list &args) {  	memset(_outputLevel, 0, sizeof(_outputLevel));  	_outputVolumeFlags = 0;  	updateOutputVolume();  	return 0;  } -int TownsAudioInterfaceIntern::intf_getOutputVolume(va_list &args) { +int TownsAudioInterfaceInternal::intf_getOutputVolume(va_list &args) {  	int chanType = va_arg(args, int);  	int *left = va_arg(args, int*);  	int *right = va_arg(args, int*); @@ -978,7 +980,7 @@ int TownsAudioInterfaceIntern::intf_getOutputVolume(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_setOutputMute(va_list &args) { +int TownsAudioInterfaceInternal::intf_setOutputMute(va_list &args) {  	int flags = va_arg(args, int);  	_outputVolumeFlags = flags;  	uint8 mute = flags & 3; @@ -1007,31 +1009,31 @@ int TownsAudioInterfaceIntern::intf_setOutputMute(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_cdaToggle(va_list &args) { +int TownsAudioInterfaceInternal::intf_cdaToggle(va_list &args) {  	//int mode = va_arg(args, int);  	//_unkMask = mode ? 0x7f : 0x3f;  	return 0;  } -int TownsAudioInterfaceIntern::intf_getOutputVolume2(va_list &args) { +int TownsAudioInterfaceInternal::intf_getOutputVolume2(va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_getOutputMute (va_list &args) { +int TownsAudioInterfaceInternal::intf_getOutputMute (va_list &args) {  	return 0;  } -int TownsAudioInterfaceIntern::intf_pcmUpdateEnvelopeGenerator(va_list &args) { +int TownsAudioInterfaceInternal::intf_pcmUpdateEnvelopeGenerator(va_list &args) {  	for (int i = 0; i < 8; i++)  		pcmUpdateEnvelopeGenerator(i);  	return 0;  } -int TownsAudioInterfaceIntern::intf_notImpl(va_list &args) { +int TownsAudioInterfaceInternal::intf_notImpl(va_list &args) {  	return 4;  } -void TownsAudioInterfaceIntern::fmReset() { +void TownsAudioInterfaceInternal::fmReset() {  	TownsPC98_FmSynth::reset();  	_fmChanPlaying = 0; @@ -1059,7 +1061,7 @@ void TownsAudioInterfaceIntern::fmReset() {  	}  } -int TownsAudioInterfaceIntern::fmKeyOn(int chan, int note, int velo) { +int TownsAudioInterfaceInternal::fmKeyOn(int chan, int note, int velo) {  	if (chan > 5)  		return 1;  	if (note < 12 || note > 107 || (velo & 0x80)) @@ -1139,7 +1141,7 @@ int TownsAudioInterfaceIntern::fmKeyOn(int chan, int note, int velo) {  	return 0;  } -int TownsAudioInterfaceIntern::fmKeyOff(int chan) { +int TownsAudioInterfaceInternal::fmKeyOff(int chan) {  	if (chan > 5)  		return 1;  	_fmChanPlaying &= ~_chanFlags[chan]; @@ -1149,7 +1151,7 @@ int TownsAudioInterfaceIntern::fmKeyOff(int chan) {  	return 0;  } -int TownsAudioInterfaceIntern::fmChanOff(int chan) { +int TownsAudioInterfaceInternal::fmChanOff(int chan) {  	if (chan > 5)  		return 1;  	_fmChanPlaying &= ~_chanFlags[chan]; @@ -1167,7 +1169,7 @@ int TownsAudioInterfaceIntern::fmChanOff(int chan) {  	return 0;  } -int TownsAudioInterfaceIntern::fmSetPanPos(int chan, int value) { +int TownsAudioInterfaceInternal::fmSetPanPos(int chan, int value) {  	if (chan > 5)  		return 1; @@ -1186,7 +1188,7 @@ int TownsAudioInterfaceIntern::fmSetPanPos(int chan, int value) {  	return 0;  } -int TownsAudioInterfaceIntern::fmSetInstrument(int chan, int instrId) { +int TownsAudioInterfaceInternal::fmSetInstrument(int chan, int instrId) {  	if (chan > 5)  		return 1;  	if (instrId > 127) @@ -1230,7 +1232,7 @@ int TownsAudioInterfaceIntern::fmSetInstrument(int chan, int instrId) {  	return 0;  } -int TownsAudioInterfaceIntern::fmLoadInstrument(int instrId, const uint8 *data) { +int TownsAudioInterfaceInternal::fmLoadInstrument(int instrId, const uint8 *data) {  	if (instrId > 127)  		return 3;  	assert(data); @@ -1238,7 +1240,7 @@ int TownsAudioInterfaceIntern::fmLoadInstrument(int instrId, const uint8 *data)  	return 0;  } -int TownsAudioInterfaceIntern::fmSetPitch(int chan, int pitch) { +int TownsAudioInterfaceInternal::fmSetPitch(int chan, int pitch) {  	if (chan > 5)  		return 1; @@ -1325,7 +1327,7 @@ int TownsAudioInterfaceIntern::fmSetPitch(int chan, int pitch) {  	return 0;  } -int TownsAudioInterfaceIntern::fmSetLevel(int chan, int lvl) { +int TownsAudioInterfaceInternal::fmSetLevel(int chan, int lvl) {  	if (chan > 5)  		return 1;  	if (lvl > 127) @@ -1348,12 +1350,12 @@ int TownsAudioInterfaceIntern::fmSetLevel(int chan, int lvl) {  	return 0;  } -void TownsAudioInterfaceIntern::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) { +void TownsAudioInterfaceInternal::bufferedWriteReg(uint8 part, uint8 regAddress, uint8 value) {  	_fmSaveReg[part][regAddress] = value;  	writeReg(part, regAddress, value);  } -void TownsAudioInterfaceIntern::pcmReset() { +void TownsAudioInterfaceInternal::pcmReset() {  	_pcmChanOut = 0;  	_pcmChanReserved = _pcmChanKeyPressed = _pcmChanEffectPlaying = _pcmChanKeyPlaying = 0;  	_numReservedChannels = 0; @@ -1381,7 +1383,7 @@ void TownsAudioInterfaceIntern::pcmReset() {  	}  } -int TownsAudioInterfaceIntern::pcmKeyOn(int chan, int note, int velo) { +int TownsAudioInterfaceInternal::pcmKeyOn(int chan, int note, int velo) {  	if (chan < 0x40 || chan > 0x47)  		return 1; @@ -1452,7 +1454,7 @@ int TownsAudioInterfaceIntern::pcmKeyOn(int chan, int note, int velo) {  	return 0;  } -int TownsAudioInterfaceIntern::pcmKeyOff(int chan) { +int TownsAudioInterfaceInternal::pcmKeyOff(int chan) {  	if (chan < 0x40 || chan > 0x47)  		return 1; @@ -1462,7 +1464,7 @@ int TownsAudioInterfaceIntern::pcmKeyOff(int chan) {  	return 0;  } -int TownsAudioInterfaceIntern::pcmChanOff(int chan) { +int TownsAudioInterfaceInternal::pcmChanOff(int chan) {  	if (chan < 0x40 || chan > 0x47)  		return 1; @@ -1476,7 +1478,7 @@ int TownsAudioInterfaceIntern::pcmChanOff(int chan) {  	return 0;  } -int TownsAudioInterfaceIntern::pcmSetPanPos(int chan, int mode) { +int TownsAudioInterfaceInternal::pcmSetPanPos(int chan, int mode) {  	if (chan > 0x47)  		return 1;  	if (mode & 0x80) @@ -1499,7 +1501,7 @@ int TownsAudioInterfaceIntern::pcmSetPanPos(int chan, int mode) {  	return 0;  } -int TownsAudioInterfaceIntern::pcmSetInstrument(int chan, int instrId) { +int TownsAudioInterfaceInternal::pcmSetInstrument(int chan, int instrId) {  	if (chan > 0x47)  		return 1;  	if (instrId > 31) @@ -1509,7 +1511,7 @@ int TownsAudioInterfaceIntern::pcmSetInstrument(int chan, int instrId) {  	return 0;  } -int TownsAudioInterfaceIntern::pcmLoadInstrument(int instrId, const uint8 *data) { +int TownsAudioInterfaceInternal::pcmLoadInstrument(int instrId, const uint8 *data) {  	if (instrId > 31)  		return 3;  	assert(data); @@ -1517,7 +1519,7 @@ int TownsAudioInterfaceIntern::pcmLoadInstrument(int instrId, const uint8 *data)  	return 0;  } -int TownsAudioInterfaceIntern::pcmSetPitch(int chan, int pitch) { +int TownsAudioInterfaceInternal::pcmSetPitch(int chan, int pitch) {  	if (chan > 0x47)  		return 1; @@ -1547,7 +1549,7 @@ int TownsAudioInterfaceIntern::pcmSetPitch(int chan, int pitch) {  	return 0;  } -int TownsAudioInterfaceIntern::pcmSetLevel(int chan, int lvl) { +int TownsAudioInterfaceInternal::pcmSetLevel(int chan, int lvl) {  	if (chan > 0x47)  		return 1; @@ -1576,7 +1578,7 @@ int TownsAudioInterfaceIntern::pcmSetLevel(int chan, int lvl) {  	return 0;  } -void TownsAudioInterfaceIntern::pcmUpdateEnvelopeGenerator(int chan) { +void TownsAudioInterfaceInternal::pcmUpdateEnvelopeGenerator(int chan) {  	TownsAudio_PcmChannel *p = &_pcmChan[chan];  	if (!p->envCurrentLevel) {  		_pcmChanKeyPlaying &= ~_chanFlags[chan]; @@ -1618,7 +1620,7 @@ void TownsAudioInterfaceIntern::pcmUpdateEnvelopeGenerator(int chan) {  	p->velo = (p->envCurrentLevel >> 8) << 1;  } -void TownsAudioInterfaceIntern::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w) { +void TownsAudioInterfaceInternal::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, TownsAudio_WaveTable *w) {  	int8 diff = p->note - w->baseNote;  	uint16 r = w->rate + w->rateOffs;  	uint16 bl = 0; @@ -1647,7 +1649,16 @@ void TownsAudioInterfaceIntern::pcmCalcPhaseStep(TownsAudio_PcmChannel *p, Towns  	p->step = (s * p->stepPitch) >> 14;  } -void TownsAudioInterfaceIntern::updateOutputVolume() { +void TownsAudioInterfaceInternal::updateOutputVolume() { +	// Avoid calls to g_system->getAudioCDManager() functions from the main thread +	// since this can cause mutex lockups. +	_updateOutputVol = true; +} + +void TownsAudioInterfaceInternal::updateOutputVolumeInternal() { +	if (!_ready) +		return; +  	// FM Towns seems to support volumes of 0 - 63 for each channel.  	// We recalculate sane values for our 0 to 255 volume range and  	// balance values for our -128 to 127 volume range @@ -1658,38 +1669,41 @@ void TownsAudioInterfaceIntern::updateOutputVolume() {  	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); + +	_updateOutputVol = false;  } -TownsAudioInterfaceIntern *TownsAudioInterfaceIntern::_refInstance = 0; +TownsAudioInterfaceInternal *TownsAudioInterfaceInternal::_refInstance = 0; -int TownsAudioInterfaceIntern::_refCount = 0; +int TownsAudioInterfaceInternal::_refCount = 0; -const uint8 TownsAudioInterfaceIntern::_chanFlags[] = { +const uint8 TownsAudioInterfaceInternal::_chanFlags[] = {  	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80  }; -const uint16 TownsAudioInterfaceIntern::_frequency[] = { +const uint16 TownsAudioInterfaceInternal::_frequency[] = {  	0x028C, 0x02B4, 0x02DC, 0x030A, 0x0338, 0x0368, 0x039C, 0x03D4, 0x040E, 0x044A, 0x048C, 0x04D0  }; -const uint8 TownsAudioInterfaceIntern::_carrier[] = { +const uint8 TownsAudioInterfaceInternal::_carrier[] = {  	0x10, 0x10, 0x10, 0x10, 0x30, 0x70, 0x70, 0xF0  }; -const uint8 TownsAudioInterfaceIntern::_fmDefaultInstrument[] = { +const uint8 TownsAudioInterfaceInternal::_fmDefaultInstrument[] = {  	0x45, 0x4C, 0x45, 0x50, 0x49, 0x41, 0x4E, 0x4F, 0x01, 0x0A, 0x02, 0x01,  	0x1E, 0x32, 0x05, 0x00, 0x9C, 0xDC, 0x9C, 0xDC, 0x07, 0x03, 0x14, 0x08,  	0x00, 0x03, 0x05, 0x05, 0x55, 0x45, 0x27, 0xA7, 0x04, 0xC0, 0x00, 0x00,  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  }; -const uint16 TownsAudioInterfaceIntern::_pcmPhase1[] =  { +const uint16 TownsAudioInterfaceInternal::_pcmPhase1[] =  {  	0x879B, 0x0F37, 0x1F58, 0x306E, 0x4288, 0x55B6, 0x6A08, 0x7F8F, 0x965E, 0xAE88, 0xC882, 0xE341  }; -const uint16 TownsAudioInterfaceIntern::_pcmPhase2[] =  { +const uint16 TownsAudioInterfaceInternal::_pcmPhase2[] =  {  	0xFEFE, 0xF1A0, 0xE411, 0xD744, 0xCB2F, 0xBFC7, 0xB504, 0xAAE2, 0xA144, 0x9827, 0x8FAC  }; @@ -1841,11 +1855,11 @@ void TownsAudio_WaveTable::clear() {  }  TownsAudioInterface::TownsAudioInterface(Audio::Mixer *mixer, TownsAudioInterfacePluginDriver *driver) { -	_intf = TownsAudioInterfaceIntern::addNewRef(mixer, driver); +	_intf = TownsAudioInterfaceInternal::addNewRef(mixer, driver);  }  TownsAudioInterface::~TownsAudioInterface() { -	TownsAudioInterfaceIntern::releaseRef(); +	TownsAudioInterfaceInternal::releaseRef();  	_intf = 0;  } @@ -1874,3 +1888,11 @@ void TownsAudioInterface::setSoundEffectVolume(int volume) {  void TownsAudioInterface::setSoundEffectChanMask(int mask) {  	_intf->setSoundEffectChanMask(mask);  } + +void TownsAudioInterface::lockInternal() { +	_intf->lock(); +} + +void TownsAudioInterface::unlockInternal() { +	_intf->unlock(); +} diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.h b/audio/softsynth/fmtowns_pc98/towns_audio.h index 2c58d46d06..b00243f610 100644 --- a/audio/softsynth/fmtowns_pc98/towns_audio.h +++ b/audio/softsynth/fmtowns_pc98/towns_audio.h @@ -25,7 +25,7 @@  #include "audio/mixer.h" -class TownsAudioInterfaceIntern; +class TownsAudioInterfaceInternal;  class TownsAudioInterfacePluginDriver {  public: @@ -48,8 +48,15 @@ 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: -	TownsAudioInterfaceIntern *_intf; +	TownsAudioInterfaceInternal *_intf;  };  #endif diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp index 3c7ce7d0e4..00f0d43b98 100644 --- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp @@ -835,19 +835,6 @@ 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); -} - -MidiDriver_TOWNS::~MidiDriver_TOWNS() { -	close(); -	delete _intf; -} - -int MidiDriver_TOWNS::open() { -	if (_isOpen) -		return MERR_ALREADY_OPEN; - -	if (!_intf->init()) -		return MERR_CANNOT_CONNECT;  	_channels = new TownsMidiInputChannel*[32];  	for (int i = 0; i < 32; i++) @@ -866,6 +853,38 @@ int MidiDriver_TOWNS::open() {  	}  	for (int i = 0; i < 64; i++)  		_operatorLevelTable[i << 5] = 0; +} + +MidiDriver_TOWNS::~MidiDriver_TOWNS() { +	close(); +	delete _intf; + +	if (_channels) { +		for (int i = 0; i < 32; i++) +			delete _channels[i]; +		delete[] _channels; +	} +	_channels = 0; + +	if (_out) { +		for (int i = 0; i < 6; i++) +			delete _out[i]; +		delete[] _out; +	} +	_out = 0; + +	delete[] _chanState; +	_chanState = 0; +	delete[] _operatorLevelTable; +	_operatorLevelTable = 0; +} + +int MidiDriver_TOWNS::open() { +	if (_isOpen) +		return MERR_ALREADY_OPEN; + +	if (!_intf->init()) +		return MERR_CANNOT_CONNECT;  	_intf->callback(0); @@ -876,9 +895,7 @@ int MidiDriver_TOWNS::open() {  	_intf->callback(33, 8);  	_intf->setSoundEffectChanMask(~0x3f); -	 _tickCounter1 = _tickCounter2 = 0; -	 _allocCurPos = 0; -	 _rand = 1; +	_allocCurPos = 0;  	_isOpen = true; @@ -893,25 +910,6 @@ void MidiDriver_TOWNS::close() {  	setTimerCallback(0, 0);  	g_system->delayMillis(20); -	 -	if (_channels) { -		for (int i = 0; i < 32; i++) -			delete _channels[i]; -		delete[] _channels; -	} -	_channels = 0; - -	if (_out) { -		for (int i = 0; i < 6; i++) -			delete _out[i]; -		delete[] _out; -	} -	_out = 0; - -	delete[] _chanState; -	_chanState = 0; -	delete[] _operatorLevelTable; -	_operatorLevelTable = 0;  }  void MidiDriver_TOWNS::send(uint32 b) { diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp index e35da91cbb..ee20068e74 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp @@ -1145,7 +1145,7 @@ void TownsPC98_AudioDriver::loadMusicData(uint8 *data, bool loadPaused) {  	reset(); -	lock(); +	Common::StackLock lock(_mutex);  	uint8 *src_a = _trackPtr = _musicBuffer = data;  	for (uint8 i = 0; i < 3; i++) { @@ -1176,7 +1176,6 @@ void TownsPC98_AudioDriver::loadMusicData(uint8 *data, bool loadPaused) {  	_finishedChannelsFlag = _finishedSSGFlag = _finishedRhythmFlag = 0;  	_musicPlaying = (loadPaused ? false : true); -	unlock();  }  void TownsPC98_AudioDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) { @@ -1195,17 +1194,16 @@ void TownsPC98_AudioDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) {  		return;  	} -	lock(); +	Common::StackLock lock(_mutex);  	_sfxData = _sfxBuffer = data;  	_sfxOffsets[0] = READ_LE_UINT16(&_sfxData[(trackNum << 2)]);  	_sfxOffsets[1] = READ_LE_UINT16(&_sfxData[(trackNum << 2) + 2]);  	_sfxPlaying = true;  	_finishedSfxFlag = 0; -	unlock();  }  void TownsPC98_AudioDriver::reset() { -	lock(); +	Common::StackLock lock(_mutex);  	_musicPlaying = false;  	_sfxPlaying = false; @@ -1232,7 +1230,6 @@ void TownsPC98_AudioDriver::reset() {  	if (_rhythmChannel)  		_rhythmChannel->reset();  #endif -	unlock();  }  void TownsPC98_AudioDriver::fadeStep() { @@ -1263,37 +1260,30 @@ void TownsPC98_AudioDriver::fadeStep() {  	}  } -void TownsPC98_AudioDriver::timerCallbackB() { -	_sfxOffs = 0; - -	if (_musicPlaying) { -		_musicTickCounter++; - -		for (int i = 0; i < _numChan; i++) { -			if (_updateChannelsFlag & _channels[i]->_idFlag) { -				_channels[i]->processEvents(); -				_channels[i]->processFrequency(); -			} -		} +void TownsPC98_AudioDriver::pause() { +	_musicPlaying = false; +} +	 +void TownsPC98_AudioDriver::cont() { +	_musicPlaying = true; +} -		for (int i = 0; i < _numSSG; i++) { -			if (_updateSSGFlag & _ssgChannels[i]->_idFlag) { -				_ssgChannels[i]->processEvents(); -				_ssgChannels[i]->processFrequency(); -			} -		} +bool TownsPC98_AudioDriver::looping() { +	return _looping == _updateChannelsFlag ? true : false; +} -#ifndef DISABLE_PC98_RHYTHM_CHANNEL -		if (_hasPercussion) -			if (_updateRhythmFlag & _rhythmChannel->_idFlag) -				_rhythmChannel->processEvents(); -#endif -	} +bool TownsPC98_AudioDriver::musicPlaying() { +	return _musicPlaying; +} -	toggleRegProtection(false); +void TownsPC98_AudioDriver::setMusicVolume(int volume) { +	_musicVolume = volume; +	setVolumeIntern(_musicVolume, _sfxVolume); +} -	if (_finishedChannelsFlag == _updateChannelsFlag && _finishedSSGFlag == _updateSSGFlag && _finishedRhythmFlag == _updateRhythmFlag) -		_musicPlaying = false; +void TownsPC98_AudioDriver::setSoundEffectVolume(int volume) { +	_sfxVolume = volume; +	setVolumeIntern(_musicVolume, _sfxVolume);  }  void TownsPC98_AudioDriver::timerCallbackA() { @@ -1321,15 +1311,37 @@ void TownsPC98_AudioDriver::timerCallbackA() {  	}  } -void TownsPC98_AudioDriver::setMusicTempo(uint8 tempo) { -	writeReg(0, 0x26, tempo); -	writeReg(0, 0x27, 0x33); -} +void TownsPC98_AudioDriver::timerCallbackB() { +	_sfxOffs = 0; -void TownsPC98_AudioDriver::setSfxTempo(uint16 tempo) { -	writeReg(0, 0x24, tempo & 0xff); -	writeReg(0, 0x25, tempo >> 8); -	writeReg(0, 0x27, 0x33); +	if (_musicPlaying) { +		_musicTickCounter++; + +		for (int i = 0; i < _numChan; i++) { +			if (_updateChannelsFlag & _channels[i]->_idFlag) { +				_channels[i]->processEvents(); +				_channels[i]->processFrequency(); +			} +		} + +		for (int i = 0; i < _numSSG; i++) { +			if (_updateSSGFlag & _ssgChannels[i]->_idFlag) { +				_ssgChannels[i]->processEvents(); +				_ssgChannels[i]->processFrequency(); +			} +		} + +#ifndef DISABLE_PC98_RHYTHM_CHANNEL +		if (_hasPercussion) +			if (_updateRhythmFlag & _rhythmChannel->_idFlag) +				_rhythmChannel->processEvents(); +#endif +	} + +	toggleRegProtection(false); + +	if (_finishedChannelsFlag == _updateChannelsFlag && _finishedSSGFlag == _updateSSGFlag && _finishedRhythmFlag == _updateRhythmFlag) +		_musicPlaying = false;  }  void TownsPC98_AudioDriver::startSoundEffect() { @@ -1352,6 +1364,16 @@ void TownsPC98_AudioDriver::startSoundEffect() {  	_sfxData = 0;  } +void TownsPC98_AudioDriver::setMusicTempo(uint8 tempo) { +	writeReg(0, 0x26, tempo); +	writeReg(0, 0x27, 0x33); +} + +void TownsPC98_AudioDriver::setSfxTempo(uint16 tempo) { +	writeReg(0, 0x24, tempo & 0xff); +	writeReg(0, 0x25, tempo >> 8); +	writeReg(0, 0x27, 0x33); +}  const uint8 TownsPC98_AudioDriver::_drvTables[] = {  	//  channel presets  	0x00, 0x80, 0x00, 0x00, 0x00, 0x01, diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.h b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.h index 46ee23895b..ff58482227 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.h @@ -50,33 +50,19 @@ public:  	void fadeStep(); -	void pause() { -		_musicPlaying = false; -	} -	void cont() { -		_musicPlaying = true; -	} +	void pause(); +	void cont(); -	void timerCallbackB(); +	bool looping(); +	bool musicPlaying(); + +	void setMusicVolume(int volume); +	void setSoundEffectVolume(int volume); + +private:  	void timerCallbackA(); +	void timerCallbackB(); -	bool looping() { -		return _looping == _updateChannelsFlag ? true : false; -	} -	bool musicPlaying() { -		return _musicPlaying; -	} - -	void setMusicVolume(int volume) { -		_musicVolume = volume; -		setVolumeIntern(_musicVolume, _sfxVolume); -	} -	void setSoundEffectVolume(int volume) { -		_sfxVolume = volume; -		setVolumeIntern(_musicVolume, _sfxVolume); -	} - -protected:  	void startSoundEffect();  	void setMusicTempo(uint8 tempo); diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp index bc5aa32823..b09a9f65d1 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp @@ -861,7 +861,7 @@ 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), _lock(0), _ready(false) { +	_volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _ready(false) {  	memset(&_timers[0], 0, sizeof(ChipTimer));  	memset(&_timers[1], 0, sizeof(ChipTimer)); @@ -928,7 +928,7 @@ bool TownsPC98_FmSynth::init() {  }  void TownsPC98_FmSynth::reset() { -	lock(); +	Common::StackLock lock(_mutex);  	for (int i = 0; i < _numChan; i++) {  		for (int ii = 0; ii < 4; ii++)  			_chanInternal[i].opr[ii]->reset(); @@ -948,14 +948,13 @@ void TownsPC98_FmSynth::reset() {  	if (_prc)  		_prc->reset();  #endif -	unlock();  }  void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {  	if (_regProtectionFlag || !_ready)  		return; -	lock(); +	Common::StackLock lock(_mutex);  	static const uint8 oprOrdr[] = { 0, 2, 1, 3 }; @@ -1137,7 +1136,6 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {  	default:  		warning("TownsPC98_FmSynth: UNKNOWN ADDRESS %d", regAddress);  	} -	unlock();  }  int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) { @@ -1146,9 +1144,14 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {  	int32 *tmpStart = tmp;  	memset(tmp, 0, sizeof(int32) * numSamples);  	int32 samplesLeft = numSamples >> 1; -	_lock |= 0x10000; -	while (_ready && !(_lock & 0xffff) && samplesLeft) { +	bool locked = false; +	if (_ready) { +		lock(); +		locked = true; +	} + +	while (_ready && samplesLeft) {  		int32 render = samplesLeft;  		for (int i = 0; i < 2; i++) { @@ -1197,17 +1200,38 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {  		tmp += (render << 1);  	} -	_lock &= ~0x10000; +	if (locked) +		unlock(); +  	delete[] tmpStart;  	return numSamples;  } +bool TownsPC98_FmSynth::isStereo() const { +	return true; +} + +bool TownsPC98_FmSynth::endOfData() const { +	return false; +} + +int TownsPC98_FmSynth::getRate() const { +	return _mixer->getOutputRate(); +} + +void TownsPC98_FmSynth::lock() { +	_mutex.lock(); +} + +void TownsPC98_FmSynth::unlock() { +	_mutex.unlock(); +} +  void TownsPC98_FmSynth::deinit() {  	_ready = false; -	while (_lock) -		g_system->delayMillis(20);  	_mixer->stopHandle(_soundHandle); +	Common::StackLock lock(_mutex);  	_timers[0].cb = _timers[1].cb = &TownsPC98_FmSynth::idleTimerCallback;  } @@ -1216,7 +1240,7 @@ uint8 TownsPC98_FmSynth::readSSGStatus() {  }  void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) { -	lock(); +	Common::StackLock lock(_mutex);  	_volumeA = CLIP<uint16>(volA, 0, Audio::Mixer::kMaxMixerVolume);  	_volumeB = CLIP<uint16>(volB, 0, Audio::Mixer::kMaxMixerVolume);  	if (_ssg) @@ -1225,11 +1249,10 @@ void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) {  	if (_prc)  		_prc->setVolumeIntern(_volumeA, _volumeB);  #endif -	unlock();  }  void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB) { -	lock(); +	Common::StackLock lock(_mutex);  	_volMaskA = channelMaskA;  	_volMaskB = channelMaskB;  	if (_ssg) @@ -1238,17 +1261,6 @@ void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB  	if (_prc)  		_prc->setVolumeChannelMasks(_volMaskA >> (_numChan + _numSSG), _volMaskB >> (_numChan + _numSSG));  #endif -	unlock(); -} - -void TownsPC98_FmSynth::lock() { -	_mutex.lock(); -	_lock++; -} - -void  TownsPC98_FmSynth::unlock() { -	_mutex.unlock(); -	_lock--;  }  void TownsPC98_FmSynth::generateTables() { diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h index f7bcc90585..a1b09abd3a 100644 --- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h +++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h @@ -69,15 +69,12 @@ public:  	// AudioStream interface  	int readBuffer(int16 *buffer, const int numSamples); -	bool isStereo() const { -		return true; -	} -	bool endOfData() const { -		return false; -	} -	int getRate() const { -		return _mixer->getOutputRate(); -	} +	bool isStereo() const; +	bool endOfData() const; +	int getRate() const; + +	void lock(); +	void unlock();  protected:  	void deinit(); @@ -102,13 +99,12 @@ protected:  	void setVolumeIntern(int volA, int volB);  	void setVolumeChannelMasks(int channelMaskA, int channelMaskB); -	void lock(); -	void unlock(); -  	const int _numChan;  	const int _numSSG;  	const bool _hasPercussion; +	Common::Mutex _mutex; +  private:  	void generateTables();  	void nextTick(int32 *buffer, uint32 bufferSize); @@ -182,9 +178,6 @@ private:  	Audio::Mixer *_mixer;  	Audio::SoundHandle _soundHandle; -	int _lock; -	Common::Mutex _mutex; -  #ifndef DISABLE_PC98_RHYTHM_CHANNEL  	static const uint8 _percussionData[];  #endif diff --git a/engines/scumm/player_towns.cpp b/engines/scumm/player_towns.cpp index 5d49478cb0..15b2f65797 100644 --- a/engines/scumm/player_towns.cpp +++ b/engines/scumm/player_towns.cpp @@ -581,11 +581,14 @@ Player_Towns_v2::Player_Towns_v2(ScummEngine *vm, Audio::Mixer *mixer, IMuse *im  }  Player_Towns_v2::~Player_Towns_v2() { -	delete _intf; -	_intf = 0; - +	// Avoid lockup in imuse.cpp, line 78 +	_intf->lockInternal();  	if (_imuseDispose)  		delete _imuse; +	_intf->unlockInternal(); + +	delete _intf; +	_intf = 0;  	delete[] _sblData;  	delete[] _soundOverride;  | 
