mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-14 16:07:39 +00:00
KYRA: (EOB II/PC98) - sound improvements
This commit is contained in:
parent
e8d21cf93a
commit
4077a9d82d
@ -592,7 +592,7 @@ void CharacterGenerator::drawButton(int index, int buttonState) {
|
||||
|
||||
_screen->copyRegion(160, 0, c->destX << 3, c->destY, p->w << 3, p->h, 2, 0, Screen::CR_NO_P_CHECK);
|
||||
_screen->updateScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterGenerator::processButtonClick(int index) {
|
||||
drawButton(index, 1);
|
||||
|
@ -346,7 +346,7 @@ void DarkMoonEngine::seq_playIntro() {
|
||||
|
||||
sq.printText(3, textColor1); // The message was urgent.
|
||||
|
||||
if (_flags.platform == Common::kPlatformPC98)
|
||||
if (!skipFlag() && !shouldQuit() && _flags.platform == Common::kPlatformPC98)
|
||||
snd_playSong(55);
|
||||
|
||||
sq.loadScene(1, 2);
|
||||
@ -447,7 +447,7 @@ void DarkMoonEngine::seq_playIntro() {
|
||||
|
||||
sq.animCommand(16);
|
||||
|
||||
if (_flags.platform == Common::kPlatformPC98)
|
||||
if (!skipFlag() && !shouldQuit() && _flags.platform == Common::kPlatformPC98)
|
||||
snd_playSong(56);
|
||||
|
||||
sq.printText(7, textColor2); // Thank you for coming so quickly
|
||||
@ -594,7 +594,7 @@ void DarkMoonEngine::seq_playIntro() {
|
||||
sq.animCommand(20);
|
||||
sq.animCommand(18);
|
||||
|
||||
if (_flags.platform == Common::kPlatformPC98)
|
||||
if (!skipFlag() && !shouldQuit() && _flags.platform == Common::kPlatformPC98)
|
||||
snd_playSong(57);
|
||||
|
||||
sq.fadeText();
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
kSavedState = 1 << 10
|
||||
};
|
||||
|
||||
CapcomPC98Player(bool playerPrio, uint16 playerFlag, uint16 reservedChanFlags);
|
||||
CapcomPC98Player(bool playerPrio, uint16 playFlags, uint16 chanReserveFlags, uint16 chanDisableFlags);
|
||||
virtual ~CapcomPC98Player() {}
|
||||
|
||||
virtual bool init() = 0;
|
||||
@ -51,16 +51,21 @@ public:
|
||||
void startSound(const uint8 *data, uint8 volume, bool loop);
|
||||
void stopSound();
|
||||
uint8 getMarker(uint8 id) const { return _soundMarkers[id & 0x0F]; }
|
||||
static uint16 getPlayerStatus() { return _flags; }
|
||||
|
||||
static uint16 getStatus() { return _flags; }
|
||||
|
||||
void fadeOut(uint16 speed);
|
||||
void allNotesOff(uint16 chanFlags = 0xFFFF);
|
||||
virtual void setMasterVolume (int vol) = 0;
|
||||
|
||||
void nextTick();
|
||||
virtual void processSounds() {}
|
||||
virtual void processSounds() = 0;
|
||||
|
||||
protected:
|
||||
uint16 _soundMarkers[16];
|
||||
const uint16 _reservedChanFlags;
|
||||
uint8 _fadeState;
|
||||
const uint16 _chanReserveFlags;
|
||||
const uint16 _chanDisableFlags;
|
||||
|
||||
private:
|
||||
virtual void send(uint32 evt) = 0;
|
||||
@ -68,9 +73,9 @@ private:
|
||||
void storeEvent(uint32 evt);
|
||||
void restorePlayer();
|
||||
virtual void restoreStateIntern() {}
|
||||
uint16 playFlag() const { return _playerFlag & (kStdPlay | kPrioPlay); }
|
||||
uint16 extraFlag() const { return _playerFlag & kPrioClaim; }
|
||||
uint16 stopFlag() const { return (_playerFlag & (kStdPlay | kPrioPlay)) << 8; }
|
||||
uint16 playFlag() const { return _playFlags & (kStdPlay | kPrioPlay); }
|
||||
uint16 extraFlag() const { return _playFlags & kPrioClaim; }
|
||||
uint16 stopFlag() const { return (_playFlags & (kStdPlay | kPrioPlay)) << 8; }
|
||||
|
||||
const uint8 *_data;
|
||||
const uint8 *_curPos;
|
||||
@ -82,10 +87,13 @@ private:
|
||||
static uint16 _flags;
|
||||
bool _loop;
|
||||
|
||||
uint16 _fadeSpeed;
|
||||
uint16 _fadeTicker;
|
||||
|
||||
Common::Array<uint32> _storedEvents;
|
||||
|
||||
const bool _playerPrio;
|
||||
const uint16 _playerFlag;
|
||||
const uint16 _playFlags;
|
||||
};
|
||||
|
||||
class CapcomPC98_MIDI final : public CapcomPC98Player {
|
||||
@ -96,11 +104,13 @@ public:
|
||||
~CapcomPC98_MIDI();
|
||||
|
||||
bool init() override;
|
||||
void deinit() override;
|
||||
void deinit() override {}
|
||||
void reset() override;
|
||||
|
||||
void setMasterVolume (int vol) override;
|
||||
|
||||
void processSounds() override;
|
||||
|
||||
private:
|
||||
void send(uint32 evt) override;
|
||||
PC98AudioCore::MutexLock lockMutex() override;
|
||||
@ -109,6 +119,8 @@ private:
|
||||
const bool _isMT32;
|
||||
const uint8 *_programMapping;
|
||||
|
||||
uint8 _chanVolume[16];
|
||||
|
||||
static const uint8 _programMapping_mt32ToGM[128];
|
||||
|
||||
MutexProc &_mproc;
|
||||
@ -116,7 +128,7 @@ private:
|
||||
|
||||
class CapcomPC98_FM_Channel {
|
||||
public:
|
||||
CapcomPC98_FM_Channel(uint8 id, PC98AudioCore *&ac, const Common::Array<const uint8*>&instruments);
|
||||
CapcomPC98_FM_Channel(uint8 id, PC98AudioCore *&ac, const Common::Array<const uint8*>&instruments, const uint8 &fadeState);
|
||||
~CapcomPC98_FM_Channel();
|
||||
|
||||
void reset();
|
||||
@ -203,10 +215,12 @@ private:
|
||||
PC98AudioCore *&_ac;
|
||||
const Common::Array<const uint8*>&_instruments;
|
||||
|
||||
const uint8 &_fadeState;
|
||||
|
||||
static const uint16 _freqMSBTable[12];
|
||||
static const uint8 _freqLSBTables[12][64];
|
||||
static const uint8 _volTablesInst[4][128];
|
||||
static const uint8 _volTableOut[128];
|
||||
static const uint8 _volTableCarrier[128];
|
||||
static const uint8 _volTablePara[128];
|
||||
};
|
||||
|
||||
@ -214,7 +228,7 @@ class CapcomPC98_FM final : public CapcomPC98Player, PC98AudioPluginDriver {
|
||||
public:
|
||||
typedef Common::Functor0Mem<void, CapcomPC98AudioDriverInternal> CBProc;
|
||||
|
||||
CapcomPC98_FM(Audio::Mixer *mixer, CBProc &cbproc, bool playerPrio, uint16 playerFlag, uint8 reservedChanFlags, bool needsTimer);
|
||||
CapcomPC98_FM(Audio::Mixer *mixer, CBProc &cbproc, bool playerPrio, uint16 playFlags, uint8 chanReserveFlags, uint8 chanDisableFlags, bool needsTimer);
|
||||
~CapcomPC98_FM() override;
|
||||
|
||||
bool init() override;
|
||||
@ -228,7 +242,7 @@ public:
|
||||
|
||||
private:
|
||||
void send(uint32 evt) override;
|
||||
void timerCallbackB() override;
|
||||
void timerCallbackA() override;
|
||||
void processSounds() override;
|
||||
|
||||
void controlChange(uint8 ch, uint8 control, uint8 val);
|
||||
@ -262,10 +276,14 @@ public:
|
||||
void stopSong();
|
||||
void startSoundEffect(const uint8 *data, uint8 volume);
|
||||
void stopSoundEffect();
|
||||
|
||||
int checkSoundMarker() const;
|
||||
bool songIsPlaying() const;
|
||||
bool soundEffectIsPlaying() const;
|
||||
|
||||
void fadeOut();
|
||||
void allNotesOff();
|
||||
|
||||
void setMusicVolume(int volume);
|
||||
void setSoundEffectVolume(int volume);
|
||||
|
||||
@ -292,7 +310,8 @@ private:
|
||||
|
||||
uint16 CapcomPC98Player::_flags = 0;
|
||||
|
||||
CapcomPC98Player::CapcomPC98Player(bool playerPrio, uint16 playerFlag, uint16 reservedChanFlags) : _playerPrio(playerPrio), _playerFlag(playerFlag), _reservedChanFlags(reservedChanFlags), _data(nullptr), _curPos(nullptr), _numEventsTotal(0), _numEventsLeft(0), _volume(0), _midiTicker(0), _loop(false) {
|
||||
CapcomPC98Player::CapcomPC98Player(bool playerPrio, uint16 playFlags, uint16 chanReserveFlags, uint16 chanDisableFlags) : _playerPrio(playerPrio), _playFlags(playFlags), _chanReserveFlags(chanReserveFlags), _chanDisableFlags(chanDisableFlags),
|
||||
_data(nullptr), _curPos(nullptr), _numEventsTotal(0), _numEventsLeft(0), _volume(0), _midiTicker(0), _loop(false), _fadeState(0), _fadeSpeed(1), _fadeTicker(0) {
|
||||
memset(_soundMarkers, 0, sizeof(_soundMarkers));
|
||||
_flags = 0;
|
||||
}
|
||||
@ -303,15 +322,13 @@ void CapcomPC98Player::startSound(const uint8 *data, uint8 volume, bool loop) {
|
||||
PC98AudioCore::MutexLock lock = lockMutex();
|
||||
_numEventsTotal = _numEventsLeft = READ_LE_UINT16(data);
|
||||
_data = _curPos = data + 2;
|
||||
_volume = volume & 0x7f;
|
||||
_volume = volume & 0x7F;
|
||||
_loop = loop;
|
||||
_midiTicker = 0;
|
||||
|
||||
if (_volume != 0x7f) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if ((1 << i) & _reservedChanFlags)
|
||||
send(0x0007B0 | i | (_volume << 16));
|
||||
}
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if ((1 << i) & _chanReserveFlags)
|
||||
send(0x0007B0 | i | (_volume << 16));
|
||||
}
|
||||
|
||||
_flags &= ~(stopFlag() | kFadeOut);
|
||||
@ -320,22 +337,50 @@ void CapcomPC98Player::startSound(const uint8 *data, uint8 volume, bool loop) {
|
||||
|
||||
void CapcomPC98Player::stopSound() {
|
||||
while (_flags & playFlag()) {
|
||||
g_system->delayMillis(5);
|
||||
g_system->delayMillis(4);
|
||||
PC98AudioCore::MutexLock lock = lockMutex();
|
||||
_flags |= stopFlag();
|
||||
}
|
||||
g_system->delayMillis(8);
|
||||
}
|
||||
|
||||
void CapcomPC98Player::fadeOut(uint16 speed) {
|
||||
if (speed) {
|
||||
_fadeTicker =_fadeSpeed = speed;
|
||||
_fadeState = 0;
|
||||
_flags |= kFadeOut;
|
||||
} else {
|
||||
stopSound();
|
||||
}
|
||||
}
|
||||
|
||||
void CapcomPC98Player::allNotesOff(uint16 chanFlags) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if ((1 << i) & chanFlags)
|
||||
send(0x007BB0 | i);
|
||||
}
|
||||
}
|
||||
|
||||
void CapcomPC98Player::nextTick() {
|
||||
if (_flags & playFlag()) {
|
||||
if (_flags & kFadeOut) {
|
||||
if (_fadeTicker) {
|
||||
--_fadeTicker;
|
||||
} else {
|
||||
_fadeTicker = _fadeSpeed;
|
||||
if (++_fadeState == 100)
|
||||
_flags |= stopFlag();
|
||||
}
|
||||
} else {
|
||||
_fadeState = 0;
|
||||
_fadeTicker = _fadeSpeed;
|
||||
}
|
||||
|
||||
if (!_playerPrio) {
|
||||
if (_flags & kPrioClaim) {
|
||||
_flags &= ~kPrioClaim;
|
||||
_flags |= kSavedState;
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if ((1 << i) & ~_reservedChanFlags)
|
||||
send(0x007BB0 | i);
|
||||
}
|
||||
allNotesOff(~_chanReserveFlags);
|
||||
} else if (((_flags & kPrioStop) || !(_flags & kPrioPlay)) && (_flags & kSavedState)) {
|
||||
_flags &= ~kSavedState;
|
||||
restorePlayer();
|
||||
@ -343,11 +388,10 @@ void CapcomPC98Player::nextTick() {
|
||||
}
|
||||
|
||||
if (_flags & stopFlag()) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if ((1 << i) & _reservedChanFlags)
|
||||
send(0x007BB0 | i);
|
||||
}
|
||||
allNotesOff((_playerPrio || (_flags & kPrioPlay)) ? _chanReserveFlags : 0xFFFF);
|
||||
_flags &= ~playFlag();
|
||||
if (!(_flags & (kStdPlay | kPrioPlay)))
|
||||
_flags &= ~kFadeOut;
|
||||
|
||||
} else if (_numEventsLeft) {
|
||||
bool eot = false;
|
||||
@ -360,12 +404,17 @@ void CapcomPC98Player::nextTick() {
|
||||
break;
|
||||
|
||||
_midiTicker -= (in & 0xFF);
|
||||
if (_playerPrio || !(_flags & kPrioPlay) || ((_flags & kPrioPlay) && ((1 << ((in >> 8) & 0x0f)) & _reservedChanFlags))) {
|
||||
if (_volume == 0x7f || ((in >> 12) & 0xfff) != 0x70B)
|
||||
send(in >> 8);
|
||||
} else {
|
||||
storeEvent(in >> 8);
|
||||
uint8 chanFlag = 1 << ((in >> 8) & 0x0F);
|
||||
|
||||
if (!(chanFlag & _chanDisableFlags)) {
|
||||
if (_playerPrio || !(_flags & kPrioPlay) || ((_flags & kPrioPlay) && (chanFlag & _chanReserveFlags))) {
|
||||
if (_volume == 0x7F || ((in >> 12) & 0xFFF) != 0x07B)
|
||||
send(in >> 8);
|
||||
} else {
|
||||
storeEvent(in >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
_curPos += 4;
|
||||
eot = (--_numEventsLeft == 0);
|
||||
}
|
||||
@ -374,12 +423,8 @@ void CapcomPC98Player::nextTick() {
|
||||
if (_loop) {
|
||||
_numEventsLeft = _numEventsTotal;
|
||||
_curPos = _data;
|
||||
} else if (_playerPrio || !(_flags & kPrioPlay)) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if ((1 << i) & _reservedChanFlags)
|
||||
send(0x007BB0 | i);
|
||||
}
|
||||
|
||||
} else {
|
||||
allNotesOff((_playerPrio || (_flags & kPrioPlay)) ? _chanReserveFlags : 0xFFFF);
|
||||
_flags &= ~playFlag();
|
||||
}
|
||||
}
|
||||
@ -392,13 +437,13 @@ void CapcomPC98Player::nextTick() {
|
||||
}
|
||||
|
||||
void CapcomPC98Player::storeEvent(uint32 evt) {
|
||||
if ((1 << (evt & 0x0f)) & _reservedChanFlags)
|
||||
if ((1 << (evt & 0x0F)) & _chanReserveFlags)
|
||||
return;
|
||||
|
||||
uint8 st = evt & 0xff;
|
||||
uint8 st = evt & 0xFF;
|
||||
|
||||
for (Common::Array<uint32>::iterator i = _storedEvents.begin(); i != _storedEvents.end(); ++i) {
|
||||
if ((*i & 0xff) == st) {
|
||||
if ((*i & 0xFF) == st) {
|
||||
*i = evt;
|
||||
return;
|
||||
}
|
||||
@ -406,7 +451,7 @@ void CapcomPC98Player::storeEvent(uint32 evt) {
|
||||
|
||||
st >>= 4;
|
||||
|
||||
if (st == 0x0b || st == 0x0c || st == 0x0e)
|
||||
if (st == 0x0B || st == 0x0C || st == 0x0E)
|
||||
_storedEvents.push_back(evt);
|
||||
}
|
||||
|
||||
@ -417,7 +462,7 @@ void CapcomPC98Player::restorePlayer() {
|
||||
_storedEvents.clear();
|
||||
}
|
||||
|
||||
CapcomPC98_MIDI::CapcomPC98_MIDI(MidiDriver::DeviceHandle dev, bool isMT32, MutexProc &mutexProc) : CapcomPC98Player(true, kStdPlay, 0xffff), _isMT32(isMT32), _mproc(mutexProc), _midi(nullptr), _programMapping(nullptr) {
|
||||
CapcomPC98_MIDI::CapcomPC98_MIDI(MidiDriver::DeviceHandle dev, bool isMT32, MutexProc &mutexProc) : CapcomPC98Player(true, kStdPlay, 0xFFFF, 0), _isMT32(isMT32), _mproc(mutexProc), _midi(nullptr), _programMapping(nullptr) {
|
||||
_midi = MidiDriver::createMidi(dev);
|
||||
uint8 *map = new uint8[128];
|
||||
assert(map);
|
||||
@ -430,6 +475,7 @@ CapcomPC98_MIDI::CapcomPC98_MIDI(MidiDriver::DeviceHandle dev, bool isMT32, Mute
|
||||
}
|
||||
|
||||
_programMapping = map;
|
||||
memset(_chanVolume, 0, sizeof(_chanVolume));
|
||||
}
|
||||
|
||||
CapcomPC98_MIDI::~CapcomPC98_MIDI() {
|
||||
@ -458,20 +504,25 @@ bool CapcomPC98_MIDI::init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void CapcomPC98_MIDI::deinit() {
|
||||
|
||||
}
|
||||
|
||||
void CapcomPC98_MIDI::reset() {
|
||||
|
||||
memset(_chanVolume, 0x7F, sizeof(_chanVolume));
|
||||
}
|
||||
|
||||
void CapcomPC98_MIDI::send(uint32 evt) {
|
||||
if ((evt & 0xF0) == 0xC0) {
|
||||
evt = (evt & 0xFF) | (_programMapping[(evt >> 8) & 0xFF] << 8);
|
||||
} else if ((evt & 0xF0) == 0xB0 && ((evt >> 8) & 0xFF) == 3) {
|
||||
_soundMarkers[evt & 0x0F] = (evt >> 16) & 0xFF;
|
||||
return;
|
||||
uint8 cmd = evt & 0xF0;
|
||||
uint8 ch = evt & 0x0F;
|
||||
uint8 p1 = (evt >> 8) & 0xFF;
|
||||
uint8 p2 = (evt >> 16) & 0xFF;
|
||||
|
||||
if (cmd == 0xC0) {
|
||||
evt = (evt & 0xFF) | (_programMapping[p1] << 8);
|
||||
} else if (cmd == 0xB0) {
|
||||
if (p1 == 3) {
|
||||
_soundMarkers[ch] = p2;
|
||||
return;
|
||||
} else if (((evt >> 8) & 0xFF) == 7) {
|
||||
_chanVolume[ch] = p2;
|
||||
}
|
||||
}
|
||||
_midi->send(evt);
|
||||
}
|
||||
@ -480,6 +531,13 @@ void CapcomPC98_MIDI::setMasterVolume (int vol) {
|
||||
|
||||
}
|
||||
|
||||
void CapcomPC98_MIDI::processSounds() {
|
||||
if (_fadeState) {
|
||||
for (int i = 0; i < 16; ++i)
|
||||
_midi->send(0x0007B0 | i | (CLIP<int>(_chanVolume[i] - _fadeState, 0, 127) << 16));
|
||||
}
|
||||
}
|
||||
|
||||
PC98AudioCore::MutexLock CapcomPC98_MIDI::lockMutex() {
|
||||
if (!_mproc.isValid())
|
||||
error("CapcomPC98_MIDI::lockMutex(): Invalid call");
|
||||
@ -498,10 +556,10 @@ const uint8 CapcomPC98_MIDI::_programMapping_mt32ToGM[128] = {
|
||||
0x70, 0x71, 0x72, 0x76, 0x75, 0x74, 0x73, 0x77, 0x78, 0x79, 0x7a, 0x7c, 0x7b, 0x7d, 0x7e, 0x7f
|
||||
};
|
||||
|
||||
CapcomPC98_FM_Channel::CapcomPC98_FM_Channel(uint8 id, PC98AudioCore *&ac, const Common::Array<const uint8*>&instruments) : _regOffset(id), _ac(ac), _instruments(instruments),
|
||||
CapcomPC98_FM_Channel::CapcomPC98_FM_Channel(uint8 id, PC98AudioCore *&ac, const Common::Array<const uint8*>&instruments, const uint8 &fadeState) : _regOffset(id), _ac(ac), _instruments(instruments),
|
||||
_isPlaying(false), _note(0), _carrier(0), _volume(0), _velocity(0), _noteEffCur(0), _program(0), _noteEffPrev(0), _breathControl(0), _frequency(0), _modWheel(0), _pitchBendSensitivity(0),
|
||||
_pitchBendPara(0), _pitchBendEff(0), _vbrState(0), _vbrStep(0), _vbrCycleTicker(0), _vbrDelayTicker(0), _vbrHandler(nullptr), _prtEnable(false),
|
||||
_prtTime(0), _prtState(0), _prtStep(0), _prtCycleLength(0) {
|
||||
_prtTime(0), _prtState(0), _prtStep(0), _prtCycleLength(0), _fadeState(fadeState) {
|
||||
typedef void (CapcomPC98_FM_Channel::*Proc)();
|
||||
static const Proc procs[] = {
|
||||
&CapcomPC98_FM_Channel::vbrHandler0,
|
||||
@ -533,7 +591,7 @@ CapcomPC98_FM_Channel::~CapcomPC98_FM_Channel() {
|
||||
|
||||
void CapcomPC98_FM_Channel::reset() {
|
||||
_vbrHandler = _vbrHandlers[4];
|
||||
_frequency = 0xffff;
|
||||
_frequency = 0xFFFF;
|
||||
_vbrState = 0;
|
||||
_prtState = 0;
|
||||
_prtCycleLength = 0;
|
||||
@ -542,8 +600,8 @@ void CapcomPC98_FM_Channel::reset() {
|
||||
_pitchBendEff = 0;
|
||||
_pitchBendPara = 0;
|
||||
_isPlaying = false;
|
||||
_note = 0xff;
|
||||
_volume = 0x7f;
|
||||
_note = 0xFF;
|
||||
_volume = 0x7F;
|
||||
_velocity = _breathControl = 0x40;
|
||||
_noteEffCur = 60;
|
||||
_modWheel = 0;
|
||||
@ -580,7 +638,7 @@ void CapcomPC98_FM_Channel::noteOn(uint8 note, uint8 velo) {
|
||||
|
||||
if (!_isPlaying) {
|
||||
updateVolume();
|
||||
_ac->writeReg(0, 0x28, _regOffset | 0xf0);
|
||||
_ac->writeReg(0, 0x28, _regOffset | 0xF0);
|
||||
}
|
||||
|
||||
_isPlaying = true;
|
||||
@ -591,10 +649,9 @@ void CapcomPC98_FM_Channel::programChange(uint8 prg) {
|
||||
return;
|
||||
|
||||
_program = prg;
|
||||
|
||||
loadInstrument(_instruments[prg]);
|
||||
|
||||
_ac->writeReg(0, 0xb0 + _regOffset, _instrument.fbl_alg);
|
||||
_ac->writeReg(0, 0xB0 + _regOffset, _instrument.fbl_alg);
|
||||
|
||||
static const uint8 carriers[] = { 0x08, 0x08, 0x08, 0x08, 0x0C, 0x0E, 0x0E, 0x0F };
|
||||
_carrier = carriers[_instrument.fbl_alg & 7];
|
||||
@ -620,6 +677,7 @@ void CapcomPC98_FM_Channel::pitchBend(uint16 pb) {
|
||||
|
||||
void CapcomPC98_FM_Channel::restore() {
|
||||
programChange(_program);
|
||||
_frequency = 0xFFFF;
|
||||
}
|
||||
|
||||
void CapcomPC98_FM_Channel::modWheel(uint8 mw) {
|
||||
@ -642,7 +700,8 @@ void CapcomPC98_FM_Channel::portamentoTime(uint8 pt) {
|
||||
|
||||
void CapcomPC98_FM_Channel::volume(uint8 vol) {
|
||||
_volume = vol;
|
||||
updateVolume();
|
||||
if (_isPlaying)
|
||||
updateVolume();
|
||||
}
|
||||
|
||||
void CapcomPC98_FM_Channel::togglePortamento(uint8 enable) {
|
||||
@ -652,8 +711,8 @@ void CapcomPC98_FM_Channel::togglePortamento(uint8 enable) {
|
||||
void CapcomPC98_FM_Channel::allNotesOff() {
|
||||
_isPlaying = false;
|
||||
for (int i = _regOffset; i < 16 + _regOffset; i += 4) {
|
||||
_ac->writeReg(0, 0x40 + i, 0x7f);
|
||||
_ac->writeReg(0, 0x80 + i, 0xff);
|
||||
_ac->writeReg(0, 0x40 + i, 0x7F);
|
||||
_ac->writeReg(0, 0x80 + i, 0xFF);
|
||||
}
|
||||
_ac->writeReg(0, 0x28, _regOffset);
|
||||
}
|
||||
@ -666,6 +725,9 @@ void CapcomPC98_FM_Channel::processSounds() {
|
||||
(*_vbrHandler)();
|
||||
updatePortamento();
|
||||
updateFrequency();
|
||||
|
||||
if (_fadeState)
|
||||
updateVolume();
|
||||
}
|
||||
|
||||
void CapcomPC98_FM_Channel::loadInstrument(const uint8 *in) {
|
||||
@ -694,44 +756,50 @@ void CapcomPC98_FM_Channel::updatePitchBend() {
|
||||
|
||||
void CapcomPC98_FM_Channel::updateVolume() {
|
||||
uint8 cr = _carrier;
|
||||
|
||||
uint8 dbg[4];
|
||||
const uint8 *s = _instrument.regData;
|
||||
for (int i = _regOffset; i < 16 + _regOffset; i += 4) {
|
||||
uint16 vol = 0;
|
||||
if (cr & 1) {
|
||||
vol += _volTableOut[_volume];
|
||||
//vol += _fadeState;
|
||||
vol += _volTableCarrier[_volume];
|
||||
vol += _fadeState;
|
||||
}
|
||||
|
||||
uint8 a = _breathControl;
|
||||
uint8 b = s[10];
|
||||
if (b & 0x80) {
|
||||
a = ~a & 0x7f;
|
||||
b &= 0x7f;
|
||||
a = ~a & 0x7F;
|
||||
b &= 0x7F;
|
||||
}
|
||||
vol += (((_volTablePara[a] * b) & 0x7fff) >> 7);
|
||||
vol += (((_volTablePara[a] * b) & 0x7FFF) >> 7);
|
||||
|
||||
a = _velocity;
|
||||
b = s[7];
|
||||
if (b & 0x80) {
|
||||
a = ~a & 0x7f;
|
||||
b &= 0x7f;
|
||||
a = ~a & 0x7F;
|
||||
b &= 0x7F;
|
||||
}
|
||||
vol += (((_volTablePara[a] * b) & 0x7fff) >> 7);
|
||||
vol += (((_volTablePara[a] * b) & 0x7FFF) >> 7);
|
||||
|
||||
a = _volTablesInst[s[8] & 3][_noteEffCur];
|
||||
b = s[9];
|
||||
if (b & 0x80) {
|
||||
a = ~a & 0x7f;
|
||||
b &= 0x7f;
|
||||
a = ~a & 0x7F;
|
||||
b &= 0x7F;
|
||||
}
|
||||
vol += (((a * b) & 0x7fff) >> 7);
|
||||
vol += (((a * b) & 0x7FFF) >> 7);
|
||||
vol += s[1];
|
||||
vol = MIN<uint16>(vol, 0x7f);
|
||||
|
||||
_ac->writeReg(0, 0x40 + i, vol & 0xff);
|
||||
if (vol > 0x7f)
|
||||
vol=vol;
|
||||
|
||||
vol = MIN<uint16>(vol, 0x7F);
|
||||
|
||||
_ac->writeReg(0, 0x40 + i, vol & 0xFF);
|
||||
s += 13;
|
||||
cr >>= 1;
|
||||
|
||||
dbg[i >> 2] = vol & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
@ -746,21 +814,21 @@ void CapcomPC98_FM_Channel::updatePortamento() {
|
||||
|
||||
void CapcomPC98_FM_Channel::updateFrequency() {
|
||||
int16 tone = (MIN<int16>(_modWheel + _instrument.vbrSensitivity, 255) * (_vbrState >> 16)) >> 8;
|
||||
tone = CLIP<int16>(tone + (_noteEffCur << 8), 0, 0x5fff);
|
||||
tone = CLIP<int16>(tone + _pitchBendEff, 0, 0x5fff);
|
||||
tone = CLIP<int16>(tone + (_prtState >> 16), 0, 0x5fff);
|
||||
tone = CLIP<int16>(tone + (_noteEffCur << 8), 0, 0x5FFF);
|
||||
tone = CLIP<int16>(tone + _pitchBendEff, 0, 0x5FFF);
|
||||
tone = CLIP<int16>(tone + (_prtState >> 16), 0, 0x5FFF);
|
||||
|
||||
uint8 block = ((tone >> 8) / 12) & 7;
|
||||
uint8 msb = (tone >> 8) % 12;
|
||||
uint8 lsb = (tone & 0xff) >> 2;
|
||||
uint8 lsb = (tone & 0xFF) >> 2;
|
||||
|
||||
uint16 freq = (block << 11) + _freqMSBTable[msb] + _freqLSBTables[msb][lsb];
|
||||
if (_frequency == freq)
|
||||
return;
|
||||
|
||||
_frequency = freq;
|
||||
_ac->writeReg(0, 0xa4 + _regOffset, freq >> 8);
|
||||
_ac->writeReg(0, 0xa0 + _regOffset, freq & 0xff);
|
||||
_ac->writeReg(0, 0xA4 + _regOffset, freq >> 8);
|
||||
_ac->writeReg(0, 0xA0 + _regOffset, freq & 0xFF);
|
||||
}
|
||||
|
||||
void CapcomPC98_FM_Channel::setupPortamento() {
|
||||
@ -770,7 +838,7 @@ void CapcomPC98_FM_Channel::setupPortamento() {
|
||||
return;
|
||||
}
|
||||
|
||||
int16 diff = (_noteEffCur << 8) - CLIP<int16>((_prtState >> 16) | (_noteEffPrev << 8), 0, 0x5fff);
|
||||
int16 diff = (_noteEffCur << 8) - CLIP<int16>((_prtState >> 16) | (_noteEffPrev << 8), 0, 0x5FFF);
|
||||
_prtCycleLength = _prtTime;
|
||||
_prtStep = (diff << 16) / _prtTime;
|
||||
_prtState = (-diff << 16);
|
||||
@ -991,7 +1059,7 @@ const uint8 CapcomPC98_FM_Channel::_volTablesInst[4][128] = {
|
||||
}
|
||||
};
|
||||
|
||||
const uint8 CapcomPC98_FM_Channel::_volTableOut[] = {
|
||||
const uint8 CapcomPC98_FM_Channel::_volTableCarrier[] = {
|
||||
0x2a, 0x2a, 0x29, 0x29, 0x29, 0x28, 0x28, 0x28, 0x27, 0x27, 0x27, 0x26, 0x26, 0x26, 0x25, 0x25,
|
||||
0x25, 0x24, 0x24, 0x24, 0x23, 0x23, 0x23, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x20, 0x20, 0x20,
|
||||
0x1f, 0x1f, 0x1f, 0x1e, 0x1e, 0x1e, 0x1d, 0x1d, 0x1d, 0x1c, 0x1c, 0x1c, 0x1b, 0x1b, 0x1b, 0x1a,
|
||||
@ -1013,13 +1081,13 @@ const uint8 CapcomPC98_FM_Channel::_volTablePara[] = {
|
||||
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
|
||||
};
|
||||
|
||||
CapcomPC98_FM::CapcomPC98_FM(Audio::Mixer *mixer, CBProc &proc, bool playerPrio, uint16 playerFlag, uint8 reservedChanFlags, bool needsTimer) : CapcomPC98Player(playerPrio, playerFlag, reservedChanFlags), PC98AudioPluginDriver(), _cbProc(proc), _ac(nullptr), _chan(nullptr), _ready(false) {
|
||||
CapcomPC98_FM::CapcomPC98_FM(Audio::Mixer *mixer, CBProc &proc, bool playerPrio, uint16 playFlags, uint8 chanReserveFlags, uint8 chanDisableFlags, bool needsTimer) : CapcomPC98Player(playerPrio, playFlags, chanReserveFlags, chanDisableFlags), PC98AudioPluginDriver(), _cbProc(proc), _ac(nullptr), _chan(nullptr), _ready(false) {
|
||||
_ac = new PC98AudioCore(mixer, needsTimer ? this : nullptr, kType26);
|
||||
assert(_ac);
|
||||
_chan = new CapcomPC98_FM_Channel*[3];
|
||||
assert(_chan);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
_chan[i] = new CapcomPC98_FM_Channel(i, _ac, _instruments);
|
||||
_chan[i] = new CapcomPC98_FM_Channel(i, _ac, _instruments, _fadeState);
|
||||
}
|
||||
|
||||
CapcomPC98_FM::~CapcomPC98_FM() {
|
||||
@ -1052,8 +1120,9 @@ bool CapcomPC98_FM::init() {
|
||||
for (int i = 0; i < 3; ++i)
|
||||
_ac->writeReg(0, 0xB0 + i, 0xC0);
|
||||
|
||||
_ac->writeReg(0, 0x26, 230);
|
||||
_ac->writeReg(0, 0x27, 0x2a);
|
||||
_ac->writeReg(0, 0x24, 0x91);
|
||||
_ac->writeReg(0, 0x25, 0x00);
|
||||
_ac->writeReg(0, 0x27, 0x15);
|
||||
|
||||
loadInstruments(_initData, 1);
|
||||
|
||||
@ -1099,14 +1168,14 @@ PC98AudioCore::MutexLock CapcomPC98_FM::lockMutex() {
|
||||
}
|
||||
|
||||
void CapcomPC98_FM::send(uint32 evt) {
|
||||
uint8 ch = evt & 0x0f;
|
||||
uint8 p1 = (evt >> 8) & 0xff;
|
||||
uint8 p2 = (evt >> 16) & 0xff;
|
||||
uint8 ch = evt & 0x0F;
|
||||
uint8 p1 = (evt >> 8) & 0xFF;
|
||||
uint8 p2 = (evt >> 16) & 0xFF;
|
||||
|
||||
if (ch > 2)
|
||||
return;
|
||||
|
||||
switch (evt & 0xf0) {
|
||||
switch (evt & 0xF0) {
|
||||
case 0x80:
|
||||
_chan[ch]->noteOff(p1);
|
||||
break;
|
||||
@ -1116,14 +1185,14 @@ void CapcomPC98_FM::send(uint32 evt) {
|
||||
else
|
||||
_chan[ch]->noteOff(p1);
|
||||
break;
|
||||
case 0xb0:
|
||||
case 0xB0:
|
||||
controlChange(ch, p1, p2);
|
||||
break;
|
||||
case 0xc0:
|
||||
case 0xC0:
|
||||
_chan[ch]->programChange(p1);
|
||||
break;
|
||||
case 0xe0:
|
||||
_chan[ch]->pitchBend(((p2 & 0x7f) << 7) | (p1 & 0x7f));
|
||||
case 0xE0:
|
||||
_chan[ch]->pitchBend(((p2 & 0x7F) << 7) | (p1 & 0x7F));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -1131,7 +1200,7 @@ void CapcomPC98_FM::send(uint32 evt) {
|
||||
}
|
||||
|
||||
|
||||
void CapcomPC98_FM::timerCallbackB() {
|
||||
void CapcomPC98_FM::timerCallbackA() {
|
||||
if (_ready && _cbProc.isValid()) {
|
||||
PC98AudioCore::MutexLock lock = _ac->stackLockMutex();
|
||||
_cbProc();
|
||||
@ -1179,7 +1248,7 @@ void CapcomPC98_FM::controlChange(uint8 ch, uint8 control, uint8 val) {
|
||||
|
||||
void CapcomPC98_FM::restoreStateIntern() {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if ((1 << i) & _reservedChanFlags)
|
||||
if ((1 << i) & _chanReserveFlags)
|
||||
continue;
|
||||
_chan[i]->restore();
|
||||
}
|
||||
@ -1204,11 +1273,11 @@ CapcomPC98AudioDriverInternal::CapcomPC98AudioDriverInternal(Audio::Mixer *mixer
|
||||
|
||||
if (type == MT_MT32 || type == MT_GM) {
|
||||
_players[0] = new CapcomPC98_MIDI(dev, type == MT_MT32, *_mutexProc);
|
||||
_players[1] = _fmDevice = new CapcomPC98_FM(mixer, *_timerProc, true, CapcomPC98Player::kPrioPlay, 7, true);
|
||||
_players[1] = _fmDevice = new CapcomPC98_FM(mixer, *_timerProc, true, CapcomPC98Player::kPrioPlay, 4, (uint8)~4, true);
|
||||
_marker = 1;
|
||||
} else {
|
||||
_players[0] = new CapcomPC98_FM(mixer, *_timerProc, false, CapcomPC98Player::kStdPlay, 3, false);
|
||||
_players[1] = _fmDevice = new CapcomPC98_FM(mixer, *_timerProc, true, CapcomPC98Player::kPrioPlay | CapcomPC98Player::kPrioClaim, 4, true);
|
||||
_players[0] = new CapcomPC98_FM(mixer, *_timerProc, false, CapcomPC98Player::kStdPlay, 3, 0, false);
|
||||
_players[1] = _fmDevice = new CapcomPC98_FM(mixer, *_timerProc, true, CapcomPC98Player::kPrioPlay | CapcomPC98Player::kPrioClaim, 4, (uint8)~4, true);
|
||||
}
|
||||
|
||||
bool ready = true;
|
||||
@ -1293,11 +1362,25 @@ int CapcomPC98AudioDriverInternal::checkSoundMarker() const {
|
||||
}
|
||||
|
||||
bool CapcomPC98AudioDriverInternal::songIsPlaying() const {
|
||||
return CapcomPC98Player::getPlayerStatus() & CapcomPC98Player::kStdPlay;
|
||||
return CapcomPC98Player::getStatus() & CapcomPC98Player::kStdPlay;
|
||||
}
|
||||
|
||||
bool CapcomPC98AudioDriverInternal::soundEffectIsPlaying() const {
|
||||
return CapcomPC98Player::getPlayerStatus() & CapcomPC98Player::kPrioPlay;
|
||||
return CapcomPC98Player::getStatus() & CapcomPC98Player::kPrioPlay;
|
||||
}
|
||||
|
||||
void CapcomPC98AudioDriverInternal::fadeOut() {
|
||||
if (!_ready)
|
||||
return;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
_players[i]->fadeOut(1);
|
||||
}
|
||||
|
||||
void CapcomPC98AudioDriverInternal::allNotesOff() {
|
||||
if (!_ready)
|
||||
return;
|
||||
for (int i = 0; i < 2; ++i)
|
||||
_players[i]->allNotesOff();
|
||||
}
|
||||
|
||||
void CapcomPC98AudioDriverInternal::setMusicVolume(int volume) {
|
||||
@ -1384,6 +1467,16 @@ bool CapcomPC98AudioDriver::soundEffectIsPlaying() const {
|
||||
return _drv ? _drv->soundEffectIsPlaying() : false;
|
||||
}
|
||||
|
||||
void CapcomPC98AudioDriver::fadeOut() {
|
||||
if (_drv)
|
||||
_drv->fadeOut();
|
||||
}
|
||||
|
||||
void CapcomPC98AudioDriver::allNotesOff() {
|
||||
if (_drv)
|
||||
_drv->allNotesOff();
|
||||
}
|
||||
|
||||
void CapcomPC98AudioDriver::setMusicVolume(int volume) {
|
||||
if (_drv)
|
||||
_drv->setMusicVolume(volume);
|
||||
|
@ -49,10 +49,14 @@ public:
|
||||
void stopSong();
|
||||
void startSoundEffect(const uint8 *data, uint8 volume);
|
||||
void stopSoundEffect();
|
||||
|
||||
int checkSoundMarker() const;
|
||||
bool songIsPlaying() const;
|
||||
bool soundEffectIsPlaying() const;
|
||||
|
||||
void fadeOut();
|
||||
void allNotesOff();
|
||||
|
||||
void setMusicVolume(int volume);
|
||||
void setSoundEffectVolume(int volume);
|
||||
|
||||
|
@ -559,11 +559,12 @@ public:
|
||||
|
||||
void beginFadeOut() override;
|
||||
|
||||
void pause(bool paused) override;
|
||||
|
||||
void updateVolumeSettings() override;
|
||||
|
||||
int checkTrigger() override;
|
||||
|
||||
void resetTrigger() override;
|
||||
void resetTrigger() override {} // This sound class is for EOB II only, this method is not needed there.
|
||||
|
||||
private:
|
||||
void restartBackgroundMusic();
|
||||
|
@ -182,18 +182,18 @@ void SoundPC98_Darkmoon::stopAllSoundEffects() {
|
||||
}
|
||||
|
||||
void SoundPC98_Darkmoon::beginFadeOut() {
|
||||
haltTrack();
|
||||
stopAllSoundEffects();
|
||||
_driver->fadeOut();
|
||||
}
|
||||
|
||||
void SoundPC98_Darkmoon::pause(bool paused) {
|
||||
if (_ready && paused)
|
||||
_driver->allNotesOff();
|
||||
}
|
||||
|
||||
int SoundPC98_Darkmoon::checkTrigger() {
|
||||
return _driver ? _driver->checkSoundMarker() : 99;
|
||||
}
|
||||
|
||||
void SoundPC98_Darkmoon::resetTrigger() {
|
||||
|
||||
}
|
||||
|
||||
void SoundPC98_Darkmoon::restartBackgroundMusic() {
|
||||
if (_lastTrack == -1) {
|
||||
haltTrack();
|
||||
|
Loading…
x
Reference in New Issue
Block a user