[Scummvm-cvs-logs] CVS: scummvm/sword1 control.cpp,1.17,1.18 music.cpp,1.10,1.11 music.h,1.3,1.4 sword1.cpp,1.25,1.26

Torbj?rn Andersson eriktorbjorn at users.sourceforge.net
Thu Jan 1 07:23:05 CET 2004


Update of /cvsroot/scummvm/scummvm/sword1
In directory sc8-pr-cvs1:/tmp/cvs-serv14909

Modified Files:
	control.cpp music.cpp music.h sword1.cpp 
Log Message:
Rewrote the music code. It now follows the same basic idea as the one in
BS2, which has worked pretty well so far. I haven't implemented pausing and
volume since the code I replaced didn't have it either, as far as I could
tell.


Index: control.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/control.cpp,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- control.cpp	1 Jan 2004 08:55:26 -0000	1.17
+++ control.cpp	1 Jan 2004 15:22:15 -0000	1.18
@@ -231,7 +231,6 @@
 	_music->startMusic(61, 1);
 
 	do {
-		_music->stream();
 		if (newMode) {
 			mode = newMode;
 			fullRefresh = true;

Index: music.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/music.cpp,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- music.cpp	30 Dec 2003 22:57:52 -0000	1.10
+++ music.cpp	1 Jan 2004 15:22:15 -0000	1.11
@@ -19,192 +19,149 @@
  *
  */
 
-// todo: add fadeout, crossfading.
-// this code always loops. make it depend on _loopFlag
-
 #include "stdafx.h"
 #include "music.h"
 #include "sound/mixer.h"
 #include "common/util.h"
 #include "common/file.h"
 
+// This means fading takes about half a second. This may need some tuning...
+#define FADE_SAMPLES 5512
+
+// These functions are only called from SwordMusic, so I'm just going to
+// assume that if locking is needed it has already been taken care of.
+
+void SwordMusicHandle::fadeDown() {
+	if (_fading < 0)
+		_fading = -_fading;
+	else if (_fading == 0)
+		_fading = FADE_SAMPLES;
+}
+
+void SwordMusicHandle::fadeUp() {
+	if (_fading > 0)
+		_fading = -_fading;
+	else if (_fading == 0)
+		_fading = -FADE_SAMPLES;
+}
+
+bool SwordMusicHandle::endOfData() const {
+	return !streaming();
+}
+
+int SwordMusicHandle::readBuffer(int16 *buffer, const int numSamples) {
+	int samples;
+	for (samples = 0; samples < numSamples && !endOfData(); samples++)
+		*buffer++ = read();
+	return samples;
+}
+
+int16 SwordMusicHandle::read() {
+	if (!streaming())
+		return 0;
+	int16 sample = _file.readUint16LE();
+	if (_file.ioFailed()) {
+		if (!_looping) {
+			stop();
+			return 0;
+		}
+		_file.clearIOFailed();
+		_file.seek(WAVEHEADERSIZE);
+		sample = _file.readUint16LE();
+	}
+	if (_fading > 0) {
+		if (--_fading == 0) {
+			_looping = false;
+			_file.close();
+		}
+		sample = (sample * _fading) / FADE_SAMPLES;
+	} else if (_fading < 0) {
+		_fading++;
+		sample = (sample * (FADE_SAMPLES + _fading)) / FADE_SAMPLES;
+	}
+	return sample;
+}
+
+bool SwordMusicHandle::play(const char *filename, bool loop) {
+	uint8 wavHeader[WAVEHEADERSIZE];
+	stop();
+	_file.open(filename);
+	if (!_file.isOpen())
+		return false;
+	_file.read(wavHeader, WAVEHEADERSIZE);
+	_stereo = (READ_LE_UINT16(wavHeader + 0x16) == 2);
+	_rate = READ_LE_UINT16(wavHeader + 0x18);
+	_looping = loop;
+	fadeUp();
+	return true;
+}
+
+void SwordMusicHandle::stop() {
+	if (_file.isOpen())
+		_file.close();
+	_fading = 0;
+	_looping = false;
+}
+
 SwordMusic::SwordMusic(OSystem *system, SoundMixer *pMixer) {
 	_system = system;
 	_mixer = pMixer;
 	_mixer->setupPremix(passMixerFunc, this);
-	_fading = false;
-	_playing = false;
-	_loop = false;
 	_mutex = _system->create_mutex();
-	_fadeSmpInBuf = _fadeBufPos = _waveSize = _wavePos = _bufPos = _smpInBuf = 0;
-	assert(_mixer->getOutputRate() == 22050);
-	_fadeBuf = NULL;
-	_musicBuf = NULL;
+	_converter[0] = NULL;
+	_converter[1] = NULL;
 }
 
 SwordMusic::~SwordMusic() {
 	_mixer->setupPremix(0, 0);
+	delete _converter[0];
+	delete _converter[1];
 }
 
 void SwordMusic::passMixerFunc(void *param, int16 *buf, uint len) {
 	((SwordMusic*)param)->mixer(buf, len);
 }
 
-void SwordMusic::mixTo(int16 *src, int16 *dst, uint32 len) {
-	if (!_playing)
-		memset(dst, 0, len * 8);
-	if (!_fading) { // no fading, simply copy it over
-		for (uint32 cnt = 0; cnt < len; cnt++)
-			dst[(cnt << 2) | 0] = dst[(cnt << 2) | 1] =
-			dst[(cnt << 2) | 2] = dst[(cnt << 2) | 3] = (int16)READ_LE_UINT16(src + cnt);
-	} else {
-		if (_fadeBuf) { // do a cross fade
-			for (uint32 cnt = 0; cnt < len; cnt++) {
-				int16 resVal = ((int16)READ_LE_UINT16(_fadeBuf + _fadeBufPos) * _fadeVal) >> 15;
-				resVal += ((int16)READ_LE_UINT16(src + cnt) * (32768 - _fadeVal)) >> 15;
-				dst[(cnt << 2) | 0] = dst[(cnt << 2) | 1] =
-				dst[(cnt << 2) | 2] = dst[(cnt << 2) | 3] = resVal;
-				_fadeVal--;
-				_fadeBufPos++;
-				_fadeSmpInBuf--;
-			}
-			if ((!_fadeVal) || (!_fadeSmpInBuf)) {
-				free(_fadeBuf);
-				_fadeBuf = NULL;
-				_fading = false;
-			}
-			if (_fadeBufPos == BUFSIZE)
-				_fadeBufPos = 0;
-		} else { // simple fadeout
-			for (uint32 cnt = 0; cnt < len; cnt++) {
-				dst[(cnt << 2) | 0] = dst[(cnt << 2) | 1] =
-				dst[(cnt << 2) | 2] = dst[(cnt << 2) | 3] = 
-				((int16)READ_LE_UINT16(src + cnt) * _fadeVal) >> 15;
-				_fadeVal--;
-			}
-			if ((!_fadeVal) || (!_smpInBuf)) {
-				_fading = _playing = false;
-				free(_musicBuf);
-				_musicBuf = NULL;
-			}
-		}
-	}
-}
-
 void SwordMusic::mixer(int16 *buf, uint32 len) {
-	if (!_playing) {
-		memset(buf, 0, 2 * len * sizeof(int16));
-		return;
-	}
-	uint32 remain = 0;	
-	if (_smpInBuf < (len >> 1)) {
-		if (_loop)
-			return;
-		remain = (len >> 1) - _smpInBuf;
-		len = _smpInBuf << 1;
-	}
-	_system->lock_mutex(_mutex);
-	len >>= 1;
-	while (len) {
-		uint32 length = len;
-		length = MIN(length, BUFSIZE - _bufPos);
-		if (_fading && _fadeBuf) {
-			length = MIN(length, (uint32)_fadeVal);
-			length = MIN(length, _fadeSmpInBuf);
-			length = MIN(length, BUFSIZE - _fadeBufPos);
-		}
-		mixTo(_musicBuf + _bufPos, buf, length);
-		len -= length;
-		buf += 4 * length;
-		_bufPos += length;
-		_smpInBuf -= length;
-		if (_bufPos == BUFSIZE)
-			_bufPos = 0;
-	}
-	if (remain) {
-		memset(buf, 0, remain * 8);
-		_playing = false;
-	}
-	_system->unlock_mutex(_mutex);
-}
-
-void SwordMusic::stream(void) {
-	// make sure we've got enough samples in buffer.
-	if ((_smpInBuf < 4 * SAMPLERATE) && _playing && _musicFile.isOpen()) {
-		_system->lock_mutex(_mutex);
-		uint32 loadTotal = BUFSIZE - _smpInBuf;
-		while (uint32 doLoad = loadTotal) {
-			if (BUFSIZE - ((_bufPos + _smpInBuf) % BUFSIZE) < loadTotal)
-				doLoad = BUFSIZE - (_bufPos + _smpInBuf) % BUFSIZE;
-			doLoad = MIN(doLoad, _waveSize - _wavePos);
-			
-			int16 *dest = _musicBuf + ((_bufPos + _smpInBuf) % BUFSIZE);
-			_musicFile.read(dest, doLoad * 2);
-			_wavePos += doLoad;
-			if (_wavePos == _waveSize) {
-				if (_loop) {
-					_wavePos = 0;
-					_musicFile.seek(WAVEHEADERSIZE);
-				} else
-					loadTotal = doLoad;
-			}
-			loadTotal -= doLoad;
-			_smpInBuf += doLoad;
+	Common::StackLock lock(_mutex);
+	for (int i = 0; i < ARRAYSIZE(_handles); i++) {
+		if (_handles[i].streaming() && _converter[i]) {
+			st_volume_t vol = 255;
+			_converter[i]->flow(_handles[i], buf, len, vol, vol);
 		}
-		_system->unlock_mutex(_mutex);
 	}
 }
 
 void SwordMusic::startMusic(int32 tuneId, int32 loopFlag) {
-	_system->lock_mutex(_mutex);
-	_loop = (loopFlag > 0);
-	if (tuneId) {		
-		if (_musicFile.isOpen())
-			_musicFile.close();
+	Common::StackLock lock(_mutex);
+	if (strlen(_tuneList[tuneId]) > 0) {
+		int newStream = 0;
+		if (_handles[0].streaming() && _handles[1].streaming()) {
+			// If both handles are playing, stop the one that's
+			// fading down.
+			if (_handles[0].fading() > 0)
+				_handles[0].stop();
+			else
+				_handles[1].stop();
+		}
+		if (_handles[0].streaming()) {
+			_handles[0].fadeDown();
+			newStream = 1;
+		} else if (_handles[1].streaming()) {
+			_handles[1].fadeDown();
+			newStream = 0;
+		}
 		char fName[20];
 		sprintf(fName, "music/%s.wav", _tuneList[tuneId]);
-		_musicFile.open(fName);
-		if (_musicFile.isOpen()) {
-			if (_playing) { // do a cross fade
-				_fadeBuf = _musicBuf;
-				_fadeBufPos = _bufPos;
-				_fadeSmpInBuf = _smpInBuf;
-				_fading = true;
-				_fadeVal = 32768;
-			} else
-				_fading = false;
-			_musicBuf = (int16*)malloc(BUFSIZE * 2);
-
-			_musicFile.seek(0x28);
-			_waveSize = _musicFile.readUint32LE() / 2;
-			_wavePos = 0;
-			_smpInBuf = 0;
-			_bufPos = 0;
-			_playing = true;
-		} else {
-			_fading = true;
-			_fadeVal = 32768;
-			if (_fadeBuf) {
-				free(_fadeBuf);
-				_fadeBuf = NULL;
-			}
-		}
-	} else {
-		if (_playing)
-			fadeDown();
-		if (_musicFile.isOpen())
-			_musicFile.close();
+		_handles[newStream].play(fName, loopFlag);
+		delete _converter[newStream];
+		_converter[newStream] = makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), false);
 	}
-	_system->unlock_mutex(_mutex);
-	stream();
 }
 
-void SwordMusic::fadeDown(void) {
-	_fadeVal = 32768;
-	_fading = true;
-	if (_fadeBuf) {
-		free(_fadeBuf);
-		_fadeBuf = NULL;
-	}
+void SwordMusic::fadeDown() {
+	Common::StackLock lock(_mutex);
+	for (int i = 0; i < ARRAYSIZE(_handles); i++)
+		if (_handles[i].streaming())
+			_handles[i].fadeDown();
 }
-

Index: music.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/music.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- music.h	22 Dec 2003 02:47:43 -0000	1.3
+++ music.h	1 Jan 2004 15:22:15 -0000	1.4
@@ -25,39 +25,53 @@
 #include "scummsys.h"
 #include "common/system.h"
 #include "common/file.h"
+#include "sound/audiostream.h"
+#include "sound/rate.h"
+
 #define TOTAL_TUNES 270
 
-#define SAMPLERATE 11025
-#define BUFSIZE (6 * SAMPLERATE)
 #define WAVEHEADERSIZE 0x2C
 
 class SoundMixer;
 
+class SwordMusicHandle : public AudioInputStream {
+private:
+	File _file;
+	bool _looping;
+	int32 _fading;
+	int _rate;
+	bool _stereo;
+public:
+	SwordMusicHandle() : _looping(false), _fading(0) {}
+	virtual int readBuffer(int16 *buffer, const int numSamples);
+	int16 read();
+	bool play(const char *filename, bool loop);
+	void stop();
+	void fadeUp();
+	void fadeDown();
+	bool streaming() const { return _file.isOpen(); }
+	int32 fading() { return _fading; }
+	bool endOfData() const;
+	bool endOfStream() const { return false; }
+	bool isStereo() const { return _stereo; }
+	int getRate() const { return _rate; }
+};
+
 class SwordMusic {
 public:
 	SwordMusic(OSystem *system, SoundMixer *pMixer);
 	~SwordMusic();
-	void stream(void);
 	void startMusic(int32 tuneId, int32 loopFlag);
-	void fadeDown(void);
+	void fadeDown();
 private:
-	File _musicFile;
+	SwordMusicHandle _handles[2];
+	RateConverter *_converter[2];
 	OSystem *_system;
 	SoundMixer *_mixer;
-	bool _fading;
-	uint16 _fadeVal;
-	bool _playing;
-	bool _loop;
 	OSystem::MutexRef _mutex;
 	static void passMixerFunc(void *param, int16 *buf, uint len);
-	void mixTo(int16 *src, int16 *dst, uint32 len);
 	void mixer(int16 *buf, uint32 len);
 	static const char _tuneList[TOTAL_TUNES][8]; // in staticres.cpp
-	uint32 _waveSize, _wavePos;
-	int16 *_musicBuf; // samples for 6 seconds
-	uint32 _bufPos, _smpInBuf;
-	int16 *_fadeBuf;
-	uint32 _fadeBufPos, _fadeSmpInBuf;
 };
 
 #endif // BSMUSIC_H

Index: sword1.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/sword1.cpp,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -d -r1.25 -r1.26
--- sword1.cpp	30 Dec 2003 22:57:52 -0000	1.25
+++ sword1.cpp	1 Jan 2004 15:22:15 -0000	1.26
@@ -1116,7 +1116,6 @@
 		SwordLogic::_scriptVars[SCREEN] = SwordLogic::_scriptVars[NEW_SCREEN];
 		
 		do {
-			_music->stream();
 			uint32 frameTime = _system->get_msecs();
 			_logic->engine();
 			_logic->updateScreenParams(); // sets scrolling
@@ -1154,7 +1153,6 @@
 		if ((retCode == 0) && (SwordLogic::_scriptVars[SCREEN] != 53) && _systemVars.wantFade) {
 			_screen->fadeDownPalette();
 			while (_screen->stillFading()) {
-				_music->stream();
 				_screen->updateScreen();
 				delay(1000/12);
 			}





More information about the Scummvm-git-logs mailing list