[Scummvm-cvs-logs] SF.net SVN: scummvm:[50561] scummvm/trunk/engines/kyra

athrxx at users.sourceforge.net athrxx at users.sourceforge.net
Thu Jul 1 19:47:47 CEST 2010


Revision: 50561
          http://scummvm.svn.sourceforge.net/scummvm/?rev=50561&view=rev
Author:   athrxx
Date:     2010-07-01 17:47:46 +0000 (Thu, 01 Jul 2010)

Log Message:
-----------
KYRA/PC98: implement proper volume control (which distinguishes between music and sfx)

Modified Paths:
--------------
    scummvm/trunk/engines/kyra/sound_intern.h
    scummvm/trunk/engines/kyra/sound_towns.cpp

Modified: scummvm/trunk/engines/kyra/sound_intern.h
===================================================================
--- scummvm/trunk/engines/kyra/sound_intern.h	2010-07-01 17:42:39 UTC (rev 50560)
+++ scummvm/trunk/engines/kyra/sound_intern.h	2010-07-01 17:47:46 UTC (rev 50561)
@@ -180,6 +180,8 @@
 	int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx) { return -1; }
 	void playSoundEffect(uint8);
 
+	void updateVolumeSettings();
+
 protected:
 	int _lastTrack;
 	uint8 *_musicTrackData;
@@ -207,6 +209,8 @@
 	int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx);
 	void playSoundEffect(uint8 track);
 
+	void updateVolumeSettings();
+
 protected:
 	Audio::AudioStream *_currentSFX;
 	int _lastTrack;

Modified: scummvm/trunk/engines/kyra/sound_towns.cpp
===================================================================
--- scummvm/trunk/engines/kyra/sound_towns.cpp	2010-07-01 17:42:39 UTC (rev 50560)
+++ scummvm/trunk/engines/kyra/sound_towns.cpp	2010-07-01 17:47:46 UTC (rev 50561)
@@ -23,7 +23,9 @@
  *
  */
 
+#include "common/config-manager.h"
 #include "common/system.h"
+
 #include "kyra/resource.h"
 #include "kyra/sound_intern.h"
 #include "kyra/screen.h"
@@ -1491,6 +1493,9 @@
 
 	void nextTick(int32 *buffer, uint32 bufferSize);
 
+	void setVolumeIntern(int volA, int volB) { _volumeA = volA; _volumeB = volB; }
+	void setVolumeChannelMasks(int channelMaskA, int channelMaskB) { _volMaskA = channelMaskA; _volMaskB = channelMaskB; }
+
 	uint8 chanEnable() const { return _chanEnable; }
 private:
 	void updatesRegs();
@@ -1530,6 +1535,11 @@
 
 	uint8 **_reg;
 
+	uint16 _volumeA;
+	uint16 _volumeB;
+	int _volMaskA;
+	int _volMaskB;
+
 	bool _ready;
 };
 
@@ -1544,6 +1554,9 @@
 
 	void nextTick(int32 *buffer, uint32 bufferSize);
 
+	void setVolumeIntern(int volA, int volB) { _volumeA = volA; _volumeB = volB; }
+	void setVolumeChannelMasks(int channelMaskA, int channelMaskB) { _volMaskA = channelMaskA; _volMaskB = channelMaskB; }
+
 private:
 	struct RhtChannel {
 		const uint8 *data;
@@ -1579,6 +1592,11 @@
 
 	uint8 **_reg;
 
+	uint16 _volumeA;
+	uint16 _volumeB;
+	int _volMaskA;
+	int _volMaskB;
+
 	bool _ready;
 };
 
@@ -1605,20 +1623,27 @@
 	int getRate() const { return _mixer->getOutputRate(); }
 
 protected:
-	void generateTables();
-
 	void toggleRegProtection(bool prot) { _regProtectionFlag = prot; }
 	uint8 readSSGStatus() { return _ssg->chanEnable(); }
 
 	virtual void timerCallbackA() = 0;
 	virtual void timerCallbackB() = 0;
 
+	// The audio driver can store and apply two different audio settings
+	// (usually for music and sound effects). The channel mask will determine
+	// which channels get effected by the setting. The first bits will be
+	// the normal opn channels, the next bits the ssg channels and the final
+	// bit the rhythm channel.
+	void setVolumeIntern(int volA, int volB);
+	void setVolumeChannelMasks(int channelMaskA, int channelMaskB);
+
 	const int _numChan;
 	const int _numSSG;
 	const bool _hasPercussion;
 
 	Common::Mutex _mutex;
 private:
+	void generateTables();
 	void nextTick(int32 *buffer, uint32 bufferSize);
 	void generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed);
 
@@ -1671,6 +1696,9 @@
 
 	OpnTimer _timers[2];
 
+	int _volMaskA, _volMaskB;
+	uint16 _volumeA, _volumeB;
+
 	const float _baserate;
 	uint32 _timerbase;
 
@@ -1710,6 +1738,9 @@
 	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();
 
@@ -1752,6 +1783,9 @@
 	uint8 *_sfxData;
 	uint16 _sfxOffsets[2];
 
+	uint16 _musicVolume;
+	uint16 _sfxVolume;
+
 	static const uint8 _drvTables[];
 
 	bool _ready;
@@ -2558,7 +2592,8 @@
 TownsPC98_OpnSquareSineSource::TownsPC98_OpnSquareSineSource(const uint32 timerbase) : _tlTable(0),
 	_tleTable(0), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0), _reg(0), _rand(1), _outN(1),
 	_nTick(0), _evpUpdateCnt(0), _evpTimer(0x1f), _pReslt(0x1f), _attack(0), _cont(false), _evpUpdate(true),
-	_timer(0), _noiseGenerator(0), _chanEnable(0) {
+	_timer(0), _noiseGenerator(0), _chanEnable(0),
+	_volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) {
 
 	memset(_channels, 0, sizeof(_channels));
 	memset(_updateRequestBuf, 0, sizeof(_updateRequestBuf));
@@ -2718,6 +2753,13 @@
 		}
 
 		finOut /= 3;
+
+		if ((1 << i) & _volMaskA)
+			finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume;
+
+		if ((1 << i) & _volMaskB)
+			finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume;
+
 		buffer[i << 1] += finOut;
 		buffer[(i << 1) + 1] += finOut;
 	}
@@ -2733,7 +2775,7 @@
 }
 
 TownsPC98_OpnPercussionSource::TownsPC98_OpnPercussionSource(const uint32 timerbase) :
-	_tickLength(timerbase * 2), _timer(0), _ready(false) {
+	_tickLength(timerbase * 2), _timer(0), _ready(false), _volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) {
 
 	memset(_rhChan, 0, sizeof(RhtChannel) * 6);
 	_reg = new uint8 *[40];
@@ -2892,6 +2934,12 @@
 
 		finOut <<= 1;
 
+		if (1 & _volMaskA)
+			finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume;
+
+		if (1 & _volMaskB)
+			finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume;
+
 		buffer[i << 1] += finOut;
 		buffer[(i << 1) + 1] += finOut;
 	}
@@ -2928,6 +2976,7 @@
 	_numChan(type == OD_TYPE26 ? 3 : 6), _numSSG(type == OD_TOWNS ? 0 : 3), _hasPercussion(type == OD_TYPE86 ? true : false),
 	_oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0),
 	_baserate(55125.0f / (float)mixer->getOutputRate()),
+	_volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255),
 	_regProtectionFlag(false), _ready(false) {
 
 	memset(&_timers[0], 0, sizeof(OpnTimer));
@@ -2978,7 +3027,7 @@
 		_prc->init(_percussionData);
 	}
 
-	_mixer->playStream(Audio::Mixer::kMusicSoundType,
+	_mixer->playStream(Audio::Mixer::kPlainSoundType,
 		&_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
 
 	_ready = true;
@@ -3229,6 +3278,26 @@
 	return numSamples;
 }
 
+void TownsPC98_OpnCore::setVolumeIntern(int volA, int volB) {
+	Common::StackLock lock(_mutex);
+	_volumeA = volA;
+	_volumeB = volB;
+	if (_ssg)
+		_ssg->setVolumeIntern(volA, volB);
+	if (_prc)
+		_prc->setVolumeIntern(volA, volB);
+}
+
+void TownsPC98_OpnCore::setVolumeChannelMasks(int channelMaskA, int channelMaskB) {
+	Common::StackLock lock(_mutex);
+	_volMaskA = channelMaskA;
+	_volMaskB = channelMaskB;
+	if (_ssg)
+		_ssg->setVolumeChannelMasks(_volMaskA >> _numChan, _volMaskB >> _numChan);
+	if (_prc)
+		_prc->setVolumeChannelMasks(_volMaskA >> (_numChan + _numSSG), _volMaskB >> (_numChan + _numSSG));	
+}
+
 void TownsPC98_OpnCore::generateTables() {
 	delete[] _oprRates;
 	_oprRates = new uint8[128];
@@ -3389,6 +3458,12 @@
 
 			int32 finOut = (output << 2) / ((_numChan + _numSSG - 3) / 3);
 
+			if ((1 << i) & _volMaskA)
+				finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume;
+
+			if ((1 << i) & _volMaskB)
+				finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume;
+
 			if (_chanInternal[i].enableLeft)
 				*leftSample += finOut;
 
@@ -3409,11 +3484,14 @@
 	_updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), _finishedChannelsFlag(0),
 	_updateSSGFlag(type == OD_TOWNS ? 0x00 : 0x07), _finishedSSGFlag(0),
 	_updateRhythmFlag(type == OD_TYPE86 ? 0x01 : 0x00), _finishedRhythmFlag(0),
-	_updateSfxFlag(type == OD_TOWNS ? 0x00 : 0x06), _finishedSfxFlag(0),
+	_updateSfxFlag(0), _finishedSfxFlag(0),
 
 	_musicTickCounter(0),
 
+	_musicVolume(255), _sfxVolume(255),
+
 	_musicPlaying(false), _sfxPlaying(false), _fading(false), _looping(0), _ready(false) {
+
 	_sfxOffsets[0] = _sfxOffsets[1] = 0;
 }
 
@@ -3451,6 +3529,8 @@
 
 	TownsPC98_OpnCore::init();
 
+	setVolumeChannelMasks(-1, 0);
+
 	_channels = new TownsPC98_OpnChannel *[_numChan];
 	for (int i = 0; i < _numChan; i++) {
 		int ii = i * 6;
@@ -3665,8 +3745,11 @@
 		_trackPtr = _musicBuffer;
 	}
 
-	if (_finishedSfxFlag == _updateSfxFlag)
+	if (_updateSfxFlag && _finishedSfxFlag == _updateSfxFlag) {
 		_sfxPlaying = false;
+		_updateSfxFlag = 0;
+		setVolumeChannelMasks(-1, 0);
+	}
 }
 
 void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) {
@@ -3681,14 +3764,21 @@
 }
 
 void TownsPC98_OpnDriver::startSoundEffect() {
-	for (int i = 0; i < 2; i++) {
+	int i = 0;
+	for (; i < 2; i++) {
 		if (_sfxOffsets[i]) {
 			_ssgChannels[i + 1]->protect();
 			_sfxChannels[i]->reset();
 			_sfxChannels[i]->loadData(_sfxData + _sfxOffsets[i]);
+			_updateSfxFlag |= _sfxChannels[i]->_idFlag;
 		}
 	}
 
+	int volFlags = 0;
+	for (i = 0; i < (_numChan + _numSSG - 2); i++)
+		volFlags |= (1 << i);
+	setVolumeChannelMasks(volFlags, ~volFlags);
+
 	_sfxData = 0;
 }
 
@@ -4049,7 +4139,9 @@
 
 bool SoundPC98::init() {
 	_driver = new TownsPC98_OpnDriver(_mixer, TownsPC98_OpnDriver::OD_TYPE26);
-	return _driver->init();
+	bool reslt = _driver->init();
+	updateVolumeSettings();
+	return reslt;
 }
 
 void SoundPC98::loadSoundFile(uint file) {
@@ -4122,7 +4214,14 @@
 	_driver->loadSoundEffectData(_sfxTrackData, track);
 }
 
+void SoundPC98::updateVolumeSettings() {
+	if (!_driver)
+		return;
 
+	_driver->setMusicVolume(ConfMan.getInt("music_volume"));
+	_driver->setSoundEffectVolume(ConfMan.getInt("sfx_volume"));
+}
+
 //	KYRA 2
 
 SoundTownsPC98_v2::SoundTownsPC98_v2(KyraEngine_v1 *vm, Audio::Mixer *mixer) :
@@ -4160,7 +4259,9 @@
 		_useFmSfx = true;
 	}
 
-	return _driver->init();
+	bool reslt = _driver->init();
+	updateVolumeSettings();
+	return reslt;
 }
 
 void SoundTownsPC98_v2::loadSoundFile(Common::String file) {
@@ -4315,6 +4416,14 @@
 	_driver->loadSoundEffectData(_sfxTrackData, track);
 }
 
+void SoundTownsPC98_v2::updateVolumeSettings() {
+	if (!_driver)
+		return;
+
+	_driver->setMusicVolume(ConfMan.getInt("music_volume"));
+	_driver->setSoundEffectVolume(ConfMan.getInt("sfx_volume"));
+}
+
 // static resources
 
 const uint32 TownsPC98_OpnCore::_adtStat[] = {


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list