aboutsummaryrefslogtreecommitdiff
path: root/audio/softsynth/fmtowns_pc98
diff options
context:
space:
mode:
authorathrxx2011-05-20 16:06:14 +0200
committerathrxx2011-05-20 20:28:15 +0200
commit2d1fa6c3f8bdc635d49978ad48f72619707d6893 (patch)
treec2d0e1a6fde7dd9fa4f13389887747dea2cf45aa /audio/softsynth/fmtowns_pc98
parentffc2a93daa8d0dd4fed97427ae7f00e4194b26c4 (diff)
downloadscummvm-rg350-2d1fa6c3f8bdc635d49978ad48f72619707d6893.tar.gz
scummvm-rg350-2d1fa6c3f8bdc635d49978ad48f72619707d6893.tar.bz2
scummvm-rg350-2d1fa6c3f8bdc635d49978ad48f72619707d6893.zip
FM-TOWNS AUDIO: fix thread lockups and cleanup
- fixed lockup situation in imuse destructor (only concerning the fm-towns driver) - fixed lockup situation when AudioCDManager functions get called (in both cases both the main thread and the mixer thread would get locked in different mutex belonging to the other thread)
Diffstat (limited to 'audio/softsynth/fmtowns_pc98')
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_audio.cpp228
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_audio.h11
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_midi.cpp68
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp104
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_driver.h34
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp60
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h23
7 files changed, 284 insertions, 244 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