aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_audio.cpp13
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_midi.cpp32
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp10
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp30
-rw-r--r--audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h8
5 files changed, 59 insertions, 34 deletions
diff --git a/audio/softsynth/fmtowns_pc98/towns_audio.cpp b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
index 33606128bf..51c2000514 100644
--- a/audio/softsynth/fmtowns_pc98/towns_audio.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_audio.cpp
@@ -411,13 +411,13 @@ bool TownsAudioInterfaceIntern::checkPluginDriver(TownsAudioInterfacePluginDrive
if (_refCount <= 1)
return true;
- Common::StackLock lock(_mutex);
-
if (_drv) {
if (driver && driver != _drv)
return false;
} else {
+ lock();
_drv = driver;
+ unlock();
}
return true;
@@ -467,8 +467,11 @@ int TownsAudioInterfaceIntern::processCommand(int command, va_list &args) {
if (command < 0 || command > 81)
return 4;
- Common::StackLock lock(_mutex);
- return (this->*_intfOpcodes[command])(args);
+ lock();
+ int res = (this->*_intfOpcodes[command])(args);
+ unlock();
+
+ return res;
}
void TownsAudioInterfaceIntern::setMusicVolume(int volume) {
@@ -539,13 +542,11 @@ void TownsAudioInterfaceIntern::nextTickEx(int32 *buffer, uint32 bufferSize) {
}
void TownsAudioInterfaceIntern::timerCallbackA() {
- Common::StackLock lock(_mutex);
if (_drv && _ready)
_drv->timerCallback(0);
}
void TownsAudioInterfaceIntern::timerCallbackB() {
- Common::StackLock lock(_mutex);
if (_ready) {
if (_drv)
_drv->timerCallback(1);
diff --git a/audio/softsynth/fmtowns_pc98/towns_midi.cpp b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
index 7072149d2d..ff14bb158a 100644
--- a/audio/softsynth/fmtowns_pc98/towns_midi.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_midi.cpp
@@ -52,7 +52,7 @@ public:
private:
struct StateA {
uint8 numLoop;
- int32 fld_1;
+ uint32 fld_1;
int32 duration;
int32 fld_9;
int16 effectState;
@@ -60,10 +60,10 @@ private:
uint8 ar1[4];
uint8 ar2[4];
int8 modWheelSensitivity;
- uint8 modWheelState;
+ int8 modWheelState;
uint8 fld_1c;
uint32 fld_1d;
- int32 fld_21;
+ uint32 fld_21;
uint32 fld_25;
int8 dir;
uint32 fld_2a;
@@ -71,14 +71,14 @@ private:
} *_stateA;
struct StateB {
- int8 inc;
+ int16 inc;
uint8 type;
uint8 useModWheel;
uint8 fld_6;
StateA *a;
} *_stateB;
- uint16 getEffectState(uint8 type);
+ int16 getEffectState(uint8 type);
void initEffect(StateA *a, const uint8 *effectData);
void updateEffectOuter3(StateA *a, StateB *b);
int updateEffectOuter(StateA *a, StateB *b);
@@ -159,7 +159,7 @@ private:
int8 _transpose;
uint8 _fld_1f;
int8 _detune;
- uint8 _modWheel;
+ int8 _modWheel;
uint8 _sustain;
uint8 _pitchBendFactor;
int16 _pitchBend;
@@ -392,7 +392,7 @@ int TownsMidiOutputChannel::checkPriority(int pri) {
return kHighPriority;
}
-uint16 TownsMidiOutputChannel::getEffectState(uint8 type) {
+int16 TownsMidiOutputChannel::getEffectState(uint8 type) {
uint8 chan = (type < 13) ? _chanMap2[_chan] : ((type < 26) ? _chanMap[_chan] : _chan);
if (type == 28)
@@ -404,7 +404,7 @@ uint16 TownsMidiOutputChannel::getEffectState(uint8 type) {
else if (type > 12)
type -= 13;
- uint32 res = 0;
+ int32 res = 0;
uint8 cs = (_driver->_chanState[chan].get(_effectDefs[type * 4] >> 5) & _effectDefs[type * 4 + 2]) >> _effectDefs[type * 4 + 1];
if (_effectDefs[type * 4 + 3])
res = _effectDefs[type * 4 + 3] - cs;
@@ -422,7 +422,7 @@ void TownsMidiOutputChannel::initEffect(StateA *a, const uint8 *effectData) {
a->ar1[2] = effectData[5];
a->ar1[3] = effectData[6];
a->ar2[0] = effectData[2];
- a->ar2[1] = effectData[3];
+ a->ar2[1] = effectData[4];
a->ar2[2] = 0;
a->ar2[3] = effectData[7];
updateEffect(a);
@@ -434,10 +434,10 @@ void TownsMidiOutputChannel::updateEffectOuter3(StateA *a, StateB *b) {
if (f & 1) {
switch (b->type) {
case 0:
- _carrierTl = (a->effectState & 0xff) + b->inc; /*???*/
+ _carrierTl = a->effectState + b->inc; /*???*/
break;
case 13:
- _modulatorTl = (a->effectState & 0xff) + b->inc; /*???*/
+ _modulatorTl = a->effectState + b->inc; /*???*/
break;
case 30:
b->a->modWheelState = b->inc;
@@ -504,7 +504,7 @@ int TownsMidiOutputChannel::updateEffectOuter(StateA *a, StateB *b) {
void TownsMidiOutputChannel::updateEffect(StateA *a) {
uint8 c = a->numLoop - 1;
uint16 v = a->ar1[c];
- int e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]];
+ int32 e = _effectData[_driver->_chanOutputLevel[((v & 0x7f) << 5) + a->modWheelSensitivity]];
if (v & 0x80)
e = _driver->randomValue(e);
@@ -545,7 +545,7 @@ int TownsMidiOutputChannel::lookupVolume(int a, int b) {
if (b == 31)
return a;
- if (a > 63)
+ if (a > 63 || a < -63)
return ((a + 1) * b) >> 5;
if (b < 0) {
@@ -760,6 +760,10 @@ void TownsMidiInputChannel::controlChange(byte control, byte value) {
case 64:
controlSustain(value);
break;
+ case 123:
+ while (_outChan)
+ _outChan->disconnect();
+ break;
default:
break;
}
@@ -793,7 +797,7 @@ void TownsMidiInputChannel::controlVolume(byte value) {
uint16 v2 = value;
if (_chanIndex != 16) {
_ctrlVolume = value;
- v2 = value;
+ v2 = _player->getEffectiveVolume();
}
_tl = (v1 * v2) >> 7;*/
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_driver.cpp
index 289cc95863..e35da91cbb 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();
- Common::StackLock lock(_mutex);
+ lock();
uint8 *src_a = _trackPtr = _musicBuffer = data;
for (uint8 i = 0; i < 3; i++) {
@@ -1176,6 +1176,7 @@ 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) {
@@ -1194,16 +1195,17 @@ void TownsPC98_AudioDriver::loadSoundEffectData(uint8 *data, uint8 trackNum) {
return;
}
- Common::StackLock lock(_mutex);
+ lock();
_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() {
- Common::StackLock lock(_mutex);
+ lock();
_musicPlaying = false;
_sfxPlaying = false;
@@ -1230,13 +1232,13 @@ void TownsPC98_AudioDriver::reset() {
if (_rhythmChannel)
_rhythmChannel->reset();
#endif
+ unlock();
}
void TownsPC98_AudioDriver::fadeStep() {
if (!_musicPlaying)
return;
- Common::StackLock lock(_mutex);
for (int j = 0; j < _numChan; j++) {
if (_updateChannelsFlag & _channels[j]->_idFlag)
_channels[j]->fadeStep();
diff --git a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
index 57ab8d9e1f..9412538685 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
@@ -837,8 +837,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), _ready(false) {
+ _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _externLock(0), _ready(false) {
memset(&_timers[0], 0, sizeof(ChipTimer));
memset(&_timers[1], 0, sizeof(ChipTimer));
@@ -931,9 +930,9 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {
if (_regProtectionFlag || !_ready)
return;
- static const uint8 oprOrdr[] = { 0, 2, 1, 3 };
+ lock();
- Common::StackLock lock(_mutex);
+ static const uint8 oprOrdr[] = { 0, 2, 1, 3 };
uint8 h = regAddress & 0xf0;
uint8 l = (regAddress & 0x0f);
@@ -1081,6 +1080,7 @@ void TownsPC98_FmSynth::writeReg(uint8 part, uint8 regAddress, uint8 value) {
if (l == 0) {
c->frqTemp = (c->frqTemp & 0xff00) | value;
c->updateEnvelopeParameters = true;
+ c->fmIndex = (c->frqTemp >> 4 & 0x7f);
for (int i = 0; i < 4; i++)
co[i]->frequency(c->frqTemp);
} else if (l == 4) {
@@ -1112,18 +1112,17 @@ 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) {
- Common::StackLock lock(_mutex);
-
memset(buffer, 0, sizeof(int16) * numSamples);
int32 *tmp = new int32[numSamples];
int32 *tmpStart = tmp;
memset(tmp, 0, sizeof(int32) * numSamples);
int32 samplesLeft = numSamples >> 1;
- while (_ready && samplesLeft) {
+ while (_ready && !_externLock && samplesLeft) {
int32 render = samplesLeft;
for (int i = 0; i < 2; i++) {
@@ -1173,6 +1172,7 @@ int TownsPC98_FmSynth::readBuffer(int16 *buffer, const int numSamples) {
}
delete[] tmpStart;
+
return numSamples;
}
@@ -1187,7 +1187,7 @@ uint8 TownsPC98_FmSynth::readSSGStatus() {
}
void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) {
- Common::StackLock lock(_mutex);
+ lock();
_volumeA = CLIP<uint16>(volA, 0, Audio::Mixer::kMaxMixerVolume);
_volumeB = CLIP<uint16>(volB, 0, Audio::Mixer::kMaxMixerVolume);
if (_ssg)
@@ -1196,10 +1196,11 @@ void TownsPC98_FmSynth::setVolumeIntern(int volA, int volB) {
if (_prc)
_prc->setVolumeIntern(_volumeA, _volumeB);
#endif
+ unlock();
}
void TownsPC98_FmSynth::setVolumeChannelMasks(int channelMaskA, int channelMaskB) {
- Common::StackLock lock(_mutex);
+ lock();
_volMaskA = channelMaskA;
_volMaskB = channelMaskB;
if (_ssg)
@@ -1208,6 +1209,17 @@ 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();
+ _externLock++;
+}
+
+void TownsPC98_FmSynth::unlock() {
+ _mutex.unlock();
+ _externLock--;
}
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 5edd1a3ab8..f1494b6ba7 100644
--- a/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
+++ b/audio/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
@@ -102,11 +102,13 @@ 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);
@@ -124,6 +126,7 @@ private:
}
uint16 frqTemp;
+ uint8 fmIndex;
bool enableLeft;
bool enableRight;
bool updateEnvelopeParameters;
@@ -179,6 +182,9 @@ private:
Audio::Mixer *_mixer;
Audio::SoundHandle _soundHandle;
+ int _externLock;
+ Common::Mutex _mutex;
+
#ifndef DISABLE_PC98_RHYTHM_CHANNEL
static const uint8 _percussionData[];
#endif