[Scummvm-git-logs] scummvm master -> a4b5e9fe21c5b7c8bd38c265d71745cff2dfc253

athrxx noreply at scummvm.org
Wed Jun 14 18:52:50 UTC 2023


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
a4b5e9fe21 KYRA: (EOB II/PC98) - support GMM volume control


Commit: a4b5e9fe21c5b7c8bd38c265d71745cff2dfc253
    https://github.com/scummvm/scummvm/commit/a4b5e9fe21c5b7c8bd38c265d71745cff2dfc253
Author: athrxx (athrxx at scummvm.org)
Date: 2023-06-14T20:52:29+02:00

Commit Message:
KYRA: (EOB II/PC98) - support GMM volume control

Changed paths:
    engines/kyra/sound/drivers/capcom98.cpp


diff --git a/engines/kyra/sound/drivers/capcom98.cpp b/engines/kyra/sound/drivers/capcom98.cpp
index 08424da1eb4..edbb0be0eda 100644
--- a/engines/kyra/sound/drivers/capcom98.cpp
+++ b/engines/kyra/sound/drivers/capcom98.cpp
@@ -22,6 +22,7 @@
 #ifdef ENABLE_EOB
 
 #include "kyra/sound/drivers/capcom98.h"
+#include "audio/mixer.h"
 #include "audio/softsynth/fmtowns_pc98/pc98_audio.h"
 #include "common/func.h"
 #include "common/system.h"
@@ -56,7 +57,9 @@ public:
 
 	void fadeOut(uint16 speed);
 	void allNotesOff(uint16 chanFlags = 0xFFFF);
-	virtual void setMasterVolume (int vol) = 0;
+
+	void setMusicVolume (int vol);
+	void setSoundEffectVolume (int vol);
 
 	void nextTick();
 	virtual void processSounds() = 0;
@@ -64,14 +67,18 @@ public:
 protected:
 	uint16 _soundMarkers[16];
 	uint8 _fadeState;
+	uint16 _musicVolume;
+	uint16 _sfxVolume;
 	const uint16 _chanReserveFlags;
 	const uint16 _chanDisableFlags;
 
 private:
 	virtual void send(uint32 evt) = 0;
 	virtual PC98AudioCore::MutexLock lockMutex() = 0;
+	virtual void updateMasterVolume() = 0;
 	void storeEvent(uint32 evt);
 	void restorePlayer();
+	virtual void setVolControlMask() {}
 	virtual void restoreStateIntern() {}
 	uint16 playFlag() const { return _playFlags & (kStdPlay | kPrioPlay); }
 	uint16 extraFlag() const { return _playFlags & kPrioClaim; }
@@ -107,13 +114,12 @@ public:
 	void deinit() override {}
 	void reset() override;
 
-	void setMasterVolume (int vol) override;
-
 	void processSounds() override;
 
 private:
 	void send(uint32 evt) override;
 	PC98AudioCore::MutexLock lockMutex() override;
+	void updateMasterVolume() override;
 
 	MidiDriver *_midi;
 	const bool _isMT32;
@@ -228,7 +234,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 playFlags, uint8 chanReserveFlags, uint8 chanDisableFlags, bool needsTimer);
+	CapcomPC98_FM(Audio::Mixer *mixer, CBProc &cbproc, bool playerPrio, uint16 playFlags, uint8 chanReserveFlags, uint8 chanDisableFlags, uint16 volControlMask, bool needsTimer);
 	~CapcomPC98_FM() override;
 
 	bool init() override;
@@ -236,17 +242,17 @@ public:
 	void reset() override;
 	void loadInstruments(const uint8 *data, uint16 number) override;
 
-	void setMasterVolume (int vol) override;
-
 	PC98AudioCore::MutexLock lockMutex() override;
 
 private:
 	void send(uint32 evt) override;
+	void updateMasterVolume() override;
 	void timerCallbackA() override;
 	void processSounds() override;
 
 	void controlChange(uint8 ch, uint8 control, uint8 val);
 
+	void setVolControlMask() override;
 	void restoreStateIntern() override;
 
 	PC98AudioCore *_ac;
@@ -256,6 +262,7 @@ private:
 	CBProc &_cbProc;
 
 	bool _ready;
+	const uint16 _volControlMask;
 
 	static const uint8 _initData[72];
 };
@@ -311,7 +318,7 @@ private:
 uint16 CapcomPC98Player::_flags = 0;
 
 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) {
+	_data(nullptr), _curPos(nullptr), _numEventsTotal(0), _numEventsLeft(0), _volume(0), _midiTicker(0), _loop(false), _fadeState(0), _fadeSpeed(1), _fadeTicker(0), _musicVolume(0), _sfxVolume(0) {
 	memset(_soundMarkers, 0, sizeof(_soundMarkers));
 	_flags = 0;
 }
@@ -361,6 +368,16 @@ void CapcomPC98Player::allNotesOff(uint16 chanFlags) {
 	}
 }
 
+void CapcomPC98Player::setMusicVolume (int vol) {
+	_musicVolume = vol;
+	updateMasterVolume();
+}
+
+void CapcomPC98Player::setSoundEffectVolume (int vol) {
+	_sfxVolume = vol;
+	updateMasterVolume();
+}
+
 void CapcomPC98Player::nextTick() {
 	if (_flags & playFlag()) {
 		if (_flags & kFadeOut) {
@@ -376,14 +393,17 @@ void CapcomPC98Player::nextTick() {
 			_fadeTicker = _fadeSpeed;
 		}
 
-		if (!_playerPrio) {
+		if (_playerPrio && (_flags & kPrioClaim)) {
+			_flags &= ~kPrioClaim;
+			setVolControlMask();
+		} else if (!_playerPrio) {
 			if (_flags & kPrioClaim) {
-				_flags &= ~kPrioClaim;
 				_flags |= kSavedState;
 				allNotesOff(~_chanReserveFlags);
 			} else if (((_flags & kPrioStop) || !(_flags & kPrioPlay)) && (_flags & kSavedState)) {
 				_flags &= ~kSavedState;
 				restorePlayer();
+				setVolControlMask();
 			}
 		}
 
@@ -494,9 +514,12 @@ bool CapcomPC98_MIDI::init() {
 	if (_isMT32) {
 		_midi->sendMT32Reset();
 	} else {
+		// Don't send the reset from the common code here, since that also forces a GS reset
+		// which we don't want. A GS reset will change the sound output in a quite obvious way
+		// and make it sound different from the original output.
 		static const byte gmResetSysEx[] = { 0x7E, 0x7F, 0x09, 0x01 };
 		_midi->sysEx(gmResetSysEx, sizeof(gmResetSysEx));
-		g_system->delayMillis(100);
+		g_system->delayMillis(50);
 	}
 
 	reset();
@@ -527,10 +550,6 @@ void CapcomPC98_MIDI::send(uint32 evt) {
 	_midi->send(evt);
 }
 
-void CapcomPC98_MIDI::setMasterVolume (int vol) {
-
-}
-
 void CapcomPC98_MIDI::processSounds() {
 	if (_fadeState) {
 		for (int i = 0; i < 16; ++i)
@@ -544,6 +563,26 @@ PC98AudioCore::MutexLock CapcomPC98_MIDI::lockMutex() {
 	return _mproc();
 }
 
+void CapcomPC98_MIDI::updateMasterVolume()  {
+	// This driver is not used for sound effects. So I don't add support for sound effects volume control.
+	if (_isMT32) {
+		byte vol = _musicVolume * 100 / Audio::Mixer::kMaxMixerVolume;
+		byte mt32VolSysEx[9] = { 0x41, 0x10, 0x16, 0x12, 0x10, 0x00, 0x16, vol, 0x00 };
+		byte chk = 0;
+		for (int i = 4; i < 8; ++i)
+			chk += mt32VolSysEx[i];
+		mt32VolSysEx[8] = 0x80 - (chk & 0x7f);
+		_midi->sysEx(mt32VolSysEx, sizeof(mt32VolSysEx));	
+	} else {
+		uint16 vol = _musicVolume * 0x3FFF / Audio::Mixer::kMaxMixerVolume;
+		byte vl = vol & 0x7F;
+		byte vh = (vol >> 7) & 0x7F;
+		byte gmVolSysEx[6] = { 0x7F, 0x7F, 0x04, 0x01, vl, vh };
+		_midi->sysEx(gmVolSysEx, sizeof(gmVolSysEx));
+	}
+	g_system->delayMillis(40);
+}
+
 // This is not identical to the one we have in our common code (not even similar).
 const uint8 CapcomPC98_MIDI::_programMapping_mt32ToGM[128] = {
 	0x00, 0x02, 0x01, 0x03, 0x04, 0x05, 0x10, 0x13, 0x16, 0x65, 0x0a, 0x00, 0x68, 0x67, 0x2e, 0x25,
@@ -1078,7 +1117,7 @@ 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 playFlags, uint8 chanReserveFlags, uint8 chanDisableFlags, bool needsTimer) : CapcomPC98Player(playerPrio, playFlags, chanReserveFlags, chanDisableFlags), 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, uint16 volControlMask, bool needsTimer) : CapcomPC98Player(playerPrio, playFlags, chanReserveFlags, chanDisableFlags), PC98AudioPluginDriver(), _cbProc(proc), _volControlMask(volControlMask), _ac(nullptr), _chan(nullptr), _ready(false) {
 	_ac = new PC98AudioCore(mixer, needsTimer ? this : nullptr, kType26);
 	assert(_ac);
 	_chan = new CapcomPC98_FM_Channel*[3];
@@ -1100,6 +1139,9 @@ bool CapcomPC98_FM::init() {
 	if (!(_chan && _ac && _ac->init()))
 		return false;
 
+	if (_volControlMask == 0xFFFF) 
+		setVolControlMask();
+
 	_ac->writeReg(0, 7, 0xBF);
 	for (int i = 0; i < 14; ++i) {
 		if (i != 7)
@@ -1154,10 +1196,6 @@ void CapcomPC98_FM::loadInstruments(const uint8 *data, uint16 number) {
 	}
 }
 
-void CapcomPC98_FM::setMasterVolume (int vol) {
-
-}
-
 PC98AudioCore::MutexLock CapcomPC98_FM::lockMutex() {
 	if (!_ready)
 		error("CapcomPC98_FM::lockMutex(): Invalid call");
@@ -1196,7 +1234,6 @@ void CapcomPC98_FM::send(uint32 evt) {
 	}
 }
 
-
 void CapcomPC98_FM::timerCallbackA() {
 	if (_ready && _cbProc.isValid()) {
 		PC98AudioCore::MutexLock lock = _ac->stackLockMutex();
@@ -1209,6 +1246,11 @@ void CapcomPC98_FM::processSounds() {
 		_chan[i]->processSounds();
 }
 
+void CapcomPC98_FM::updateMasterVolume()  {
+	_ac->setMusicVolume(_musicVolume);
+	_ac->setSoundEffectVolume(_sfxVolume);
+}
+
 void CapcomPC98_FM::controlChange(uint8 ch, uint8 control, uint8 val) {
 	if (ch > 2)
 		return;
@@ -1251,6 +1293,10 @@ void CapcomPC98_FM::restoreStateIntern() {
 	}
 }
 
+void CapcomPC98_FM::setVolControlMask() {
+	_ac->setSoundEffectChanMask(_volControlMask);
+}
+
 const uint8 CapcomPC98_FM::_initData[72] = {
 	0x49, 0x4e, 0x49, 0x54, 0x5f, 0x56, 0x4f, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	0x00, 0x00,
 	0x00, 0x00, 0x01, 0x7f, 0x1f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x1f,
@@ -1270,11 +1316,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, 4, (uint8)~4, true);
+		_players[1] = _fmDevice = new CapcomPC98_FM(mixer, *_timerProc, true, CapcomPC98Player::kPrioPlay, 4, (uint8)~4, 0xFFFF, true);
 		_marker = 1;
 	} else {
-		_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);
+		_players[0] = new CapcomPC98_FM(mixer, *_timerProc, false, CapcomPC98Player::kStdPlay, 3, 0, 0, false);
+		_players[1] = _fmDevice = new CapcomPC98_FM(mixer, *_timerProc, true, CapcomPC98Player::kPrioPlay | CapcomPC98Player::kPrioClaim, 4, (uint8)~4, 4, true);
 	}
 
 	bool ready = true;
@@ -1405,8 +1451,11 @@ PC98AudioCore::MutexLock CapcomPC98AudioDriverInternal::lockMutex() {
 void CapcomPC98AudioDriverInternal::updateMasterVolume() {
 	if (!_ready)
 		return;
-	_players[0]->setMasterVolume(_musicVolume);
-	_players[1]->setMasterVolume(_sfxVolume);
+
+	for (int i = 0; i < 2; ++i) {
+		_players[i]->setMusicVolume(_musicVolume);
+		_players[i]->setSoundEffectVolume(_sfxVolume);
+	}
 }
 
 CapcomPC98AudioDriver::CapcomPC98AudioDriver(Audio::Mixer *mixer, MidiDriver::DeviceHandle dev) {




More information about the Scummvm-git-logs mailing list