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

dreammaster dreammaster at scummvm.org
Thu Sep 15 04:17:44 CEST 2016


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:
a06d1b7efe XEEN: Implemented frequency shifting in music driver


Commit: a06d1b7efe0066d17fdc7d30e9c8983fcd3f8094
    https://github.com/scummvm/scummvm/commit/a06d1b7efe0066d17fdc7d30e9c8983fcd3f8094
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2016-09-14T22:17:38-04:00

Commit Message:
XEEN: Implemented frequency shifting in music driver

Changed paths:
    engines/xeen/music.cpp
    engines/xeen/music.h



diff --git a/engines/xeen/music.cpp b/engines/xeen/music.cpp
index 932cca1..415b413 100644
--- a/engines/xeen/music.cpp
+++ b/engines/xeen/music.cpp
@@ -34,10 +34,7 @@ namespace Xeen {
 MusicDriver::MusicDriver() : _fieldF(false), _field1E(false), _lowMusicIgnored(false),
 		_musCountdownTimer(0), _fxCountdownTimer(0), _musDataPtr(nullptr),
 		_fxDataPtr(nullptr), _fxStartPtr(nullptr), _musStartPtr(nullptr) {
-	Common::fill(&_flags[0], &_flags[CHANNEL_COUNT], false);
-	Common::fill(&_field15C[0], &_field15C[CHANNEL_COUNT], 0);
-	Common::fill(&_field165[0], &_field165[CHANNEL_COUNT], 0);
-	Common::fill(&_field177[0], &_field177[CHANNEL_COUNT], 0);
+	_channels.resize(CHANNEL_COUNT);
 }
 
 void MusicDriver::execute() {
@@ -57,7 +54,8 @@ void MusicDriver::execute() {
 	}
 
 	if (flag) {
-		postProcess();
+		// Do paused handling and exit immediately
+		pausePostProcess();
 		return;
 	}
 
@@ -92,8 +90,8 @@ bool MusicDriver::musSetCountdown(const byte *&srcP, byte param) {
 	_musCountdownTimer = param;
 	_musDataPtr = srcP;
 
-	// Do post-processing and stop processing
-	postProcess();
+	// Do paused handling and break out of processing loop
+	pausePostProcess();
 	return true;
 }
 
@@ -107,17 +105,17 @@ bool MusicDriver::musSkipWord(const byte *&srcP, byte param) {
 }
 
 
-bool MusicDriver::cmdClearFlag(const byte *&srcP, byte param) {
-	_flags[param] = false;
+bool MusicDriver::cmdFreezeFrequency(const byte *&srcP, byte param) {
+	_channels[param]._changeFrequency = false;
 	return false;
 }
 
-bool MusicDriver::cmdWibbly(const byte *&srcP, byte param) {
+bool MusicDriver::cmdChangeFrequency(const byte *&srcP, byte param) {
 	if (param != 7 || !_fieldF) {
-		_field15C[param] = *srcP++;
-		_field177[param] = 0xFF;
-		_flags[param] = true;
-		_field165[param] = READ_BE_UINT16(srcP);
+		_channels[param]._freqCtrChange = (int8)*srcP++;
+		_channels[param]._freqCtr = 0xFF;
+		_channels[param]._changeFrequency = true;
+		_channels[param]._freqChange = (int16)READ_BE_UINT16(srcP);
 		srcP += 2;
 	} else {
 		srcP += 3;
@@ -154,8 +152,8 @@ bool MusicDriver::fxSetCountdown(const byte *&srcP, byte param) {
 	_fxCountdownTimer = param;
 	_musDataPtr = srcP;
 
-	// Do post-processing and stop processing
-	postProcess();
+	// Do paused handling and break out of processing loop
+	pausePostProcess();
 	return true;
 }
 
@@ -174,7 +172,7 @@ void MusicDriver::playFX(uint effectId, const byte *data) {
 		_musStartPtr = nullptr;
 		_fxDataPtr = _fxStartPtr = data;
 		_fxCountdownTimer = 0;
-		_flags[7] = _flags[8] = 0;
+		_channels[7]._changeFrequency = _channels[8]._changeFrequency = false;
 		resetFX();
 		_lowMusicIgnored = true;
 	}
@@ -188,8 +186,8 @@ const CommandFn MusicDriver::MUSIC_COMMANDS[16] = {
 	&MusicDriver::musSetPanning,		&MusicDriver::cmdNoOperation,
 	&MusicDriver::musFade,				&MusicDriver::musStartNote,
 	&MusicDriver::musSetVolume,			&MusicDriver::musInjectMidi,
-	&MusicDriver::musPlayInstrument,	&MusicDriver::cmdClearFlag,
-	&MusicDriver::cmdWibbly,			&MusicDriver::musEndSubroutine
+	&MusicDriver::musPlayInstrument,	&MusicDriver::cmdFreezeFrequency,
+	&MusicDriver::cmdChangeFrequency,			&MusicDriver::musEndSubroutine
 };
 
 const CommandFn MusicDriver::FX_COMMANDS[16] = {
@@ -199,18 +197,16 @@ const CommandFn MusicDriver::FX_COMMANDS[16] = {
 	&MusicDriver::fxSetPanning,		&MusicDriver::fxChannelOff,
 	&MusicDriver::fxFade,			&MusicDriver::fxStartNote,
 	&MusicDriver::cmdNoOperation,	&MusicDriver::fxInjectMidi,
-	&MusicDriver::fxPlayInstrument,	&MusicDriver::cmdClearFlag,
-	&MusicDriver::cmdWibbly,		&MusicDriver::fxEndSubroutine
+	&MusicDriver::fxPlayInstrument,	&MusicDriver::cmdFreezeFrequency,
+	&MusicDriver::cmdChangeFrequency,		&MusicDriver::fxEndSubroutine
 };
 
 /*------------------------------------------------------------------------*/
 
-AdlibMusicDriver::AdlibMusicDriver() : _field180(0), _field182(0), _volume(127) {
+AdlibMusicDriver::AdlibMusicDriver() : _field180(0), _field181(0), _field182(0),
+		_volume(127) {
 	Common::fill(&_musInstrumentPtrs[0], &_musInstrumentPtrs[16], (const byte *)nullptr);
 	Common::fill(&_fxInstrumentPtrs[0], &_fxInstrumentPtrs[16], (const byte *)nullptr);
-	Common::fill(&_frequencies[0], &_frequencies[7], 0);
-	Common::fill(&_volumes[0], &_volumes[CHANNEL_COUNT], 0);
-	Common::fill(&_scalingValues[0], &_scalingValues[CHANNEL_COUNT], 0);
 
 	_opl = OPL::Config::create();
 	_opl->init();
@@ -238,6 +234,11 @@ void AdlibMusicDriver::initialize() {
 	AdlibMusicDriver::resetFX();
 }
 
+void AdlibMusicDriver::playFX(uint effectId, const byte *data) {
+	Common::StackLock slock(_driverMutex);
+	MusicDriver::playFX(effectId, data);
+}
+
 void AdlibMusicDriver::write(int reg, int val) {
 	_queue.push(RegisterValue(reg, val));
 }
@@ -251,23 +252,74 @@ void AdlibMusicDriver::flush() {
 	}
 }
 
+void AdlibMusicDriver::pausePostProcess() {
+	if (_field180 && ((_field181 += _field180) < 0)) {
+		if (--_field182 < 0) {
+			_field1E = false;
+			_field180 = 0;
+			resetFrequencies();
+		} else {
+			for (int channelNum = 6; channelNum >= 0; --channelNum) {
+				if (_channels[channelNum]._volume < 63)
+					setOutputLevel(channelNum, ++_channels[channelNum]._volume);
+			}
+		}
+	}
+
+	for (int channelNum = 8; channelNum != 6 || (channelNum == 7 && _fieldF); --channelNum) {
+		Channel &chan = _channels[channelNum];
+		if (!chan._changeFrequency || (chan._freqCtr += chan._freqCtrChange) >= 0)
+			continue;
+
+		uint freq = chan._frequency & 0x3FF;
+		uint val = chan._frequency >> 8;
+		byte val1 = val & 0x20;
+		byte val2 = val & 0x1C;
+
+		freq += chan._freqChange;
+		if (chan._freqChange < 0) {
+			if (freq <= 388) {
+				freq <<= 1;
+				if (!(freq & 0x3FF))
+					--freq;
+			}
+
+			val2 = (val2 - 4) & 0x1C;
+		} else {
+			if (freq >= 734) {
+				freq >>= 1;
+				if (!(freq & 0x3FF))
+					++freq;
+			}
+
+			val2 = (val2 + 4) & 0x1C;
+		}
+
+		freq &= 0x3FF;
+		freq |= (val2 << 8);
+		freq |= val1;
+		chan._frequency = freq;
+		setFrequency(channelNum, freq);
+	}
+}
+
 void AdlibMusicDriver::resetFX() {
 	if (!_fieldF) {
-		_frequencies[7] = 0;
+		_channels[7]._frequency = 0;
 		setFrequency(7, 0);
-		_volumes[7] = 63;
+		_channels[7]._volume = 63;
 		setOutputLevel(7, 63);
 	}
 
-	_frequencies[8] = 0;
+	_channels[8]._frequency = 0;
 	setFrequency(8, 0);
-	_volumes[8] = 63;
+	_channels[8]._volume = 63;
 	setOutputLevel(8, 63);
 }
 
 void AdlibMusicDriver::resetFrequencies() {
 	for (int opNum = 6; opNum >= 0; --opNum) {
-		_frequencies[opNum] = 0;
+		_channels[opNum]._frequency = 0;
 		setFrequency(opNum, 0);
 	}
 }
@@ -283,7 +335,7 @@ uint AdlibMusicDriver::calcFrequency(byte note) {
 
 void AdlibMusicDriver::setOutputLevel(byte channelNum, uint level) {
 	write(0x40 + OPERATOR2_INDEXES[channelNum], level |
-		(_scalingValues[channelNum] & 0xC0));
+		(_channels[channelNum]._scalingValue & 0xC0));
 }
 
 void AdlibMusicDriver::playInstrument(byte channelNum, const byte *data) {
@@ -298,7 +350,7 @@ void AdlibMusicDriver::playInstrument(byte channelNum, const byte *data) {
 	write(0x20 + op2, *data++);
 
 	int scalingVal = *data++;
-	_scalingValues[channelNum] = scalingVal;
+	_channels[channelNum]._scalingValue = scalingVal;
 	scalingVal += (127 - _volume) / 2;
 
 	if (scalingVal > 63) {
@@ -336,7 +388,7 @@ bool AdlibMusicDriver::musSetPanning(const byte *&srcP, byte param) {
 bool AdlibMusicDriver::musFade(const byte *&srcP, byte param) {
 	++srcP;
 	if (param < 7)
-		setFrequency(param, _frequencies[param]);
+		setFrequency(param, _channels[param]._frequency);
 
 	return false;
 }
@@ -347,7 +399,7 @@ bool AdlibMusicDriver::musStartNote(const byte *&srcP, byte param) {
 		++srcP;		// Second byte is fade, which is unused by Adlib
 		uint freq = calcFrequency(note);
 		setFrequency(param, freq);
-		_frequencies[param] = freq | 0x2000;
+		_channels[param]._frequency = freq | 0x2000;
 		setFrequency(param, freq);
 	} else {
 		srcP += 2;
@@ -358,7 +410,7 @@ bool AdlibMusicDriver::musStartNote(const byte *&srcP, byte param) {
 
 bool AdlibMusicDriver::musSetVolume(const byte *&srcP, byte param) {
 	if (*srcP++ == 2 && !_field180) {
-		_volumes[param] = *srcP;
+		_channels[param]._volume = *srcP;
 		setOutputLevel(param, *srcP);
 	}
 
@@ -391,7 +443,7 @@ bool AdlibMusicDriver::fxSetInstrument(const byte *&srcP, byte param) {
 
 bool AdlibMusicDriver::fxSetVolume(const byte *&srcP, byte param) {
 	if (!_field180 && (!_fieldF || param != 7)) {
-		_volumes[param] = *srcP;
+		_channels[param]._volume = *srcP;
 		setOutputLevel(param, *srcP);
 	}
 
@@ -412,22 +464,22 @@ bool AdlibMusicDriver::fxSetPanning(const byte *&srcP, byte param) {
 	if (!_fieldF || param != 7) {
 		uint freq = calcFrequency(note);
 		setFrequency(param, freq);
-		_frequencies[param] = freq;
+		_channels[param]._frequency = freq;
 	}
 
 	return false;
 }
 
 bool AdlibMusicDriver::fxChannelOff(const byte *&srcP, byte param) {
-	_frequencies[param] &= ~0x2000;
-	write(0xB0 + param, _frequencies[param]);
+	_channels[param]._frequency &= ~0x2000;
+	write(0xB0 + param, _channels[param]._frequency);
 	return false;
 }
 
 bool AdlibMusicDriver::fxFade(const byte *&srcP, byte param) {
 	uint freq = calcFrequency(*srcP++);
 	if (!_fieldF || param != 7) {
-		_frequencies[param] = freq;
+		_channels[param]._frequency = freq;
 		setFrequency(param, freq);
 	}
 
@@ -439,7 +491,7 @@ bool AdlibMusicDriver::fxStartNote(const byte *&srcP, byte param) {
 		byte note = *srcP++;
 		uint freq = calcFrequency(note);
 		setFrequency(param, freq);
-		_frequencies[param] = freq | 0x2000;
+		_channels[param]._frequency = freq | 0x2000;
 		setFrequency(param, freq);
 	} else {
 		++srcP;
@@ -462,6 +514,7 @@ bool AdlibMusicDriver::fxPlayInstrument(const byte *&srcP, byte param) {
 	return false;
 }
 
+
 const byte AdlibMusicDriver::OPERATOR1_INDEXES[CHANNEL_COUNT] = {
 	0, 1, 2, 8, 9, 0xA, 0x10, 0x11, 0x12
 };
@@ -480,10 +533,12 @@ const uint AdlibMusicDriver::WAVEFORMS[24] = {
 
 Music::Music(Audio::Mixer *mixer) : _mixer(mixer), _musicDriver(nullptr) {
 	_mixer = mixer;
+	_musicDriver = new AdlibMusicDriver();
 	loadEffectsData();
 }
 
 Music::~Music() {
+	delete _musicDriver;
 	delete[] _effectsData;
 }
 
diff --git a/engines/xeen/music.h b/engines/xeen/music.h
index 0d5188e..e6cfbba 100644
--- a/engines/xeen/music.h
+++ b/engines/xeen/music.h
@@ -46,6 +46,7 @@ typedef bool (MusicDriver::*CommandFn)(const byte *&srcP, byte param);
  * Base class for music drivers
  */
 class MusicDriver {
+protected:
 	struct Subroutine {
 		const byte *_returnP;
 		const byte *_jumpP;
@@ -53,22 +54,28 @@ class MusicDriver {
 		Subroutine(const byte *returnP, const byte *endP) :
 			_returnP(returnP), _jumpP(endP) {}
 	};
+	struct Channel {
+		bool _changeFrequency;
+		int _freqCtrChange;
+		int _freqChange;
+		int _freqCtr;
+		byte _volume;
+		byte _scalingValue;
+		uint _frequency;
+		Channel() : _changeFrequency(false), _freqCtr(0), _freqCtrChange(0),
+			_freqChange(0), _volume(0), _scalingValue(0), _frequency(0) {}
+	};
 private:
 	static const CommandFn FX_COMMANDS[16];
 	static const CommandFn MUSIC_COMMANDS[16];
 private:
 	Common::Stack<Subroutine> _musSubroutines, _fxSubroutines;
-	bool _field1E;
 	int _musCountdownTimer;
 	int _fxCountdownTimer;
 	bool _lowMusicIgnored;
 	const byte *_fxDataPtr, *_musDataPtr;
 	const byte *_fxStartPtr;
 	const byte *_musStartPtr;
-	bool _flags[CHANNEL_COUNT];
-	byte _field15C[CHANNEL_COUNT];
-	byte _field165[CHANNEL_COUNT];
-	byte _field177[CHANNEL_COUNT];
 private:
 	/**
 	 * Executes the next command
@@ -77,7 +84,9 @@ private:
 	 */
 	bool command(const byte *&srcP);
 protected:
+	Common::Array<Channel> _channels;
 	bool _fieldF;
+	bool _field1E;
 protected:
 	/**
 	 * Executes a series of commands until instructed to stop
@@ -97,8 +106,8 @@ protected:
 	virtual bool musSetVolume(const byte *&srcP, byte param) = 0;
 	virtual bool musInjectMidi(const byte *&srcP, byte param) = 0;
 	virtual bool musPlayInstrument(const byte *&srcP, byte param) = 0;
-	virtual bool cmdClearFlag(const byte *&srcP, byte param);
-	virtual bool cmdWibbly(const byte *&srcP, byte param);
+	virtual bool cmdFreezeFrequency(const byte *&srcP, byte param);
+	virtual bool cmdChangeFrequency(const byte *&srcP, byte param);
 	virtual bool musEndSubroutine(const byte *&srcP, byte param);
 
 	// FX commands
@@ -116,7 +125,10 @@ protected:
 	virtual bool fxPlayInstrument(const byte *&srcP, byte param) = 0;
 	virtual bool fxEndSubroutine(const byte *&srcP, byte param);
 
-	virtual void postProcess() = 0;
+	/**
+	 * Post-processing done when a pause countdown starts or is in progress
+	 */
+	virtual void pausePostProcess() = 0;
 
 	/**
 	 * Does a reset of any sound effect
@@ -136,7 +148,7 @@ public:
 	/**
 	 * Starts an special effect playing
 	 */
-	void playFX(uint effectId, const byte *data);
+	virtual void playFX(uint effectId, const byte *data);
 };
 
 class AdlibMusicDriver : public MusicDriver {
@@ -156,12 +168,10 @@ private:
 	OPL::OPL *_opl;
 	Common::Queue<RegisterValue> _queue;
 	Common::Mutex _driverMutex;
-	byte _volumes[CHANNEL_COUNT];
-	byte _scalingValues[CHANNEL_COUNT];
 	const byte *_musInstrumentPtrs[16];
 	const byte *_fxInstrumentPtrs[16];
-	uint _frequencies[7];
 	int _field180;
+	int _field181;
 	int _field182;
 	int _volume;
 private:
@@ -232,6 +242,11 @@ protected:
 	virtual bool fxPlayInstrument(const byte *&srcP, byte param);
 
 	/**
+	 * Post-processing done when a pause countdown starts or is in progress
+	 */
+	virtual void pausePostProcess();
+
+	/**
 	 * Does a reset of any sound effect
 	 */
 	virtual void resetFX();
@@ -245,6 +260,11 @@ public:
 	 * Destructor
 	 */
 	virtual ~AdlibMusicDriver();
+
+	/**
+	 * Starts an special effect playing
+	 */
+	virtual void playFX(uint effectId, const byte *data);
 };
 
 





More information about the Scummvm-git-logs mailing list