[Scummvm-cvs-logs] CVS: scummvm/sword1 music.cpp,1.26,1.27 music.h,1.11,1.12 sound.cpp,1.28,1.29 sound.h,1.14,1.15 sword1.cpp,1.53,1.54

Robert Göffringmann lavosspawn at users.sourceforge.net
Tue Oct 12 08:51:03 CEST 2004


Update of /cvsroot/scummvm/scummvm/sword1
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31165/sword1

Modified Files:
	music.cpp music.h sound.cpp sound.h sword1.cpp 
Log Message:
added mp3 and ogg vorbis playback for music and speech.
compression tool will follow soon.

Index: music.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/music.cpp,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- music.cpp	28 Jun 2004 08:45:09 -0000	1.26
+++ music.cpp	12 Oct 2004 15:50:00 -0000	1.27
@@ -24,15 +24,122 @@
 #include "sound/mixer.h"
 #include "common/util.h"
 #include "common/file.h"
+#include "sound/mp3.h"
+#include "sound/vorbis.h"
 
 namespace Sword1 {
 
+WaveAudioStream *makeWaveStream(File *source, uint32 size) {
+	return new WaveAudioStream(source, size);
+}
+
+WaveAudioStream::WaveAudioStream(File *source, uint32 pSize) {
+	uint32 size;
+	uint8 wavHeader[WAVEHEADERSIZE];
+
+	_sourceFile = source;
+	_sourceFile->incRef();
+	if (_sourceFile->isOpen()) {
+		_sourceFile->read(wavHeader, WAVEHEADERSIZE);
+		_isStereo = (READ_LE_UINT16(wavHeader + 0x16) == 2);
+		_rate = READ_LE_UINT16(wavHeader + 0x18);
+		size = ((pSize) ? pSize : READ_LE_UINT32(wavHeader + 0x28));
+		assert(size <= (source->size() - source->pos()));
+		_bitsPerSample = READ_LE_UINT16(wavHeader + 0x22);
+		_samplesLeft = (size * 8) / _bitsPerSample;
+		if ((_bitsPerSample != 16) && (_bitsPerSample != 8))
+			error("WaveAudioStream: unknown wave type");
+	} else {
+		_samplesLeft = 0;
+		_isStereo = false;
+		_bitsPerSample = 16;
+		_rate = 22050;
+	}
+}
+
+WaveAudioStream::~WaveAudioStream(void) {
+	_sourceFile->decRef();
+}
+
+int WaveAudioStream::readBuffer(int16 *buffer, const int numSamples) {
+	int samples = ((int)_samplesLeft < numSamples) ? (int)_samplesLeft : numSamples;
+	if (_bitsPerSample == 16)
+		for (int cnt = 0; cnt < samples; cnt++)
+			*buffer++ = (int16)_sourceFile->readUint16LE();
+	else
+		for (int cnt = 0; cnt < samples; cnt++)
+			*buffer++ = (int16)_sourceFile->readByte() << 8;
+	_samplesLeft -= samples;
+	return samples;
+}
+
+bool WaveAudioStream::endOfData(void) const {
+	if (_samplesLeft == 0)
+		return true;
+	else
+		return false;
+}
+
 // This means fading takes 3 seconds.
 #define FADE_LENGTH 3
 
 // These functions are only called from Music, so I'm just going to
 // assume that if locking is needed it has already been taken care of.
 
+AudioStream *MusicHandle::createAudioSource(void) {
+	_file.seek(0);
+	switch (_musicMode) {
+#ifdef USE_MAD
+		case MusicMp3:
+			printf("creating mp3 stream\n");
+			return makeMP3Stream(&_file, _file.size());			
+#endif
+#ifdef USE_VORBIS
+		case MusicVorbis:
+			return makeVorbisStream(&_file, _file.size());
+#endif
+		case MusicWave:
+			return makeWaveStream(&_file, 0);
+		case MusicNone: // shouldn't happen
+			warning("createAudioSource ran into null create\n");
+			return NULL;
+		default:
+			error("MusicHandle::createAudioSource: called with illegal MusicMode");
+	}
+	return NULL; // never reached
+}
+
+bool MusicHandle::play(const char *fileBase, bool loop) {
+	char fileName[30];
+	stop();
+	_musicMode = MusicNone;
+#ifdef USE_MAD
+	sprintf(fileName, "%s.mp3", fileBase);
+	if (_file.open(fileName))
+		_musicMode = MusicMp3;
+#endif
+#ifdef USE_VORBIS
+	if (!_file.isOpen()) { // mp3 doesn't exist (or not compiled with MAD support)
+		sprintf(fileName, "%s.ogg", fileBase);
+		if (_file.open(fileName))
+			_musicMode = MusicVorbis;
+	}
+#endif
+	if (!_file.isOpen()) {
+		sprintf(fileName, "%s.wav", fileBase);
+		if (_file.open(fileName))
+            _musicMode = MusicWave;
+		else {
+			warning("Music file %s could not be opened", fileName);
+			return false;
+		}
+	}
+	_audioSource = createAudioSource();
+	_looping = loop;
+	fadeUp();
+	return true;
+}
+
 void MusicHandle::fadeDown() {
 	if (streaming()) {
 		if (_fading < 0)
@@ -57,53 +164,67 @@
 	return !streaming();
 }
 
+// is we don't have an audiosource, return some dummy values.
+// shouldn't happen anyways.
+bool MusicHandle::streaming(void) const {
+	return (_audioSource) ? (!_audioSource->endOfStream()) : false;
+}
+
+bool MusicHandle::isStereo(void) const {
+	return (_audioSource) ? _audioSource->isStereo() : false;
+}
+
+int MusicHandle::getRate(void) const {
+	return (_audioSource) ? _audioSource->getRate() : 11025;
+}
+
 int MusicHandle::readBuffer(int16 *buffer, const int numSamples) {
-	int samples;
-	for (samples = 0; samples < numSamples && !endOfData(); samples++) {
-		int16 sample = _file.readUint16LE();
-		if (_file.ioFailed()) {
-			if (!_looping) {
-				stop();
-				sample = 0;
-			} else {
-				_file.clearIOFailed();
-				_file.seek(WAVEHEADERSIZE);
-				sample = _file.readUint16LE();
+	int totalSamples = 0;
+	int16 *bufStart = buffer;
+	if (!_audioSource)
+		return 0;
+	int expectedSamples = numSamples;
+	while ((expectedSamples > 0) && _audioSource) { // _audioSource becomes NULL if we reach EOF and aren't looping
+		int samplesReturned = _audioSource->readBuffer(buffer, expectedSamples);
+		buffer += samplesReturned;
+		totalSamples += samplesReturned;
+        expectedSamples -= samplesReturned;
+		if ((expectedSamples > 0) && _audioSource->endOfData()) {
+			debug(2, "Music reached EOF");
+			_audioSource->endOfData();
+			if (_looping) { 
+                delete _audioSource; // recreate same source.
+				_audioSource = createAudioSource();
 			}
+			if ((!_looping) || (!_audioSource))
+				stop();
 		}
-		if (_fading > 0) {
-			if (--_fading == 0) {
-				_looping = false;
-				_file.close();
-			}
-			sample = (sample * _fading) / _fadeSamples;
-		} else if (_fading < 0) {
-			_fading--;
-			sample = -(sample * _fading) / _fadeSamples;
-			if (_fading <= -_fadeSamples)
-				_fading = 0;
+	}
+	// buffer was filled, now do the fading (if necessary)
+	int samplePos = 0;
+	while ((_fading > 0) && (samplePos < totalSamples)) { // fade down
+		bufStart[samplePos] = (bufStart[samplePos] * --_fading) / _fadeSamples;
+		samplePos++;
+		if (_fading == 0) {
+			stop();
+			// clear the rest of the buffer
+            memset(bufStart + samplePos, 0, (totalSamples - samplePos) * 2);
+			return samplePos;
 		}
-		*buffer++ = sample;
 	}
-	return samples;
-}
-
-bool MusicHandle::play(const char *filename, bool loop) {
-	uint8 wavHeader[WAVEHEADERSIZE];
-	stop();
-	if (!_file.open(filename)) {
-		warning("Music file %s could not be opened", filename);
-		return false;
+	while ((_fading < 0) && (samplePos < totalSamples)) { // fade up
+        bufStart[samplePos] = -(bufStart[samplePos] * --_fading) / _fadeSamples;
+		if (_fading <= -_fadeSamples)
+			_fading = 0;
 	}
-	_file.read(wavHeader, WAVEHEADERSIZE);
-	_stereo = (READ_LE_UINT16(wavHeader + 0x16) == 2);
-	_rate = READ_LE_UINT16(wavHeader + 0x18);
-	_looping = loop;
-	fadeUp();
-	return true;
+	return totalSamples;
 }
 
 void MusicHandle::stop() {
+	if (_audioSource) {
+		delete _audioSource;
+		_audioSource = NULL;
+	}
 	if (_file.isOpen())
 		_file.close();
 	_fading = 0;
@@ -183,9 +304,7 @@
 			_handles[1].fadeDown();
 			newStream = 0;
 		}
-		char fName[20];
-		sprintf(fName, "%s.wav", _tuneList[tuneId]);
-		if (_handles[newStream].play(fName, loopFlag != 0)) {
+		if (_handles[newStream].play(_tuneList[tuneId], loopFlag != 0)) {
 			delete _converter[newStream];
 			_converter[newStream] = makeRateConverter(_handles[newStream].getRate(), _mixer->getOutputRate(), _handles[newStream].isStereo(), false);
 		}

Index: music.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/music.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- music.h	11 Jan 2004 15:47:41 -0000	1.11
+++ music.h	12 Oct 2004 15:50:00 -0000	1.12
@@ -36,27 +36,51 @@
 
 #define WAVEHEADERSIZE 0x2C
 
+enum MusicMode {
+	MusicNone = 0,
+	MusicWave,
+	MusicMp3,
+	MusicVorbis
+};
+
+class WaveAudioStream : public AudioStream {
+public:
+	WaveAudioStream(File *source, uint32 pSize);
+	virtual ~WaveAudioStream();
+	virtual int readBuffer(int16 *buffer, const int numSamples);
+	virtual bool isStereo(void) const { return _isStereo; };
+	virtual bool endOfData(void) const;
+	virtual int getRate(void) const { return _rate; };
+private:
+	File	*_sourceFile;
+	uint32	 _rate;
+	bool	 _isStereo;
+	uint32   _samplesLeft;
+	uint16	 _bitsPerSample;
+};
+
 class MusicHandle : public AudioStream {
 private:
 	File _file;
 	bool _looping;
 	int32 _fading;
 	int32 _fadeSamples;
-	int _rate;
-	bool _stereo;
+	MusicMode _musicMode;
+	AudioStream *_audioSource;
+	AudioStream *createAudioSource(void);
 public:
-	MusicHandle() : _looping(false), _fading(0) {}
+	MusicHandle() : _looping(false), _fading(0), _audioSource(NULL) {}
 	virtual int readBuffer(int16 *buffer, const int numSamples);
 	bool play(const char *filename, bool loop);
 	void stop();
 	void fadeUp();
 	void fadeDown();
-	bool streaming() const { return _file.isOpen(); }
+	bool streaming() const;
 	int32 fading() { return _fading; }
 	bool endOfData() const;
 	bool endOfStream() const { return false; }
-	bool isStereo() const { return _stereo; }
-	int getRate() const { return _rate; }
+	bool isStereo() const;
+	int getRate() const;
 };
 
 class Music {

Index: sound.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/sound.cpp,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- sound.cpp	31 Aug 2004 07:52:46 -0000	1.28
+++ sound.cpp	12 Oct 2004 15:50:00 -0000	1.29
@@ -31,7 +31,7 @@
 #define SOUND_SPEECH_ID 1
 #define SPEECH_FLAGS (SoundMixer::FLAG_16BITS | SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_LITTLE_ENDIAN)
 
-Sound::Sound(const char *searchPath, SoundMixer *mixer, ResMan *pResMan, bool isDemo) {
+Sound::Sound(const char *searchPath, SoundMixer *mixer, ResMan *pResMan) {
 	strcpy(_filePath, searchPath);
 	_mixer = mixer;
 	_resMan = pResMan;
@@ -39,7 +39,6 @@
 	_endOfQueue = 0;
 	_currentCowFile = 0;
 	_speechVolL = _speechVolR = _sfxVolL = _sfxVolR = 192;
-	_isDemo = isDemo;
 }
 
 int Sound::addToQueue(int32 fxNo) {
@@ -167,12 +166,35 @@
 	uint32 index = _cowHeader[locIndex + (localNo * 2) - 1];
 	debug(6, "startSpeech(%d, %d): locIndex %d, sampleSize %d, index %d", roomNo, localNo, locIndex, sampleSize, index);
 	if (sampleSize) {
-		uint32 size;
-		int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
 		uint8 speechVol = (_speechVolR + _speechVolL) / 2;
 		int8 speechPan = (_speechVolR - _speechVolL) / 2;
-		if (data)
-			_mixer->playRaw(&_speechHandle, data, size, 11025, SPEECH_FLAGS, SOUND_SPEECH_ID, speechVol, speechPan);
+		if (_cowMode == CowWave) {
+			uint32 size;
+			int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
+			if (data)
+				_mixer->playRaw(&_speechHandle, data, size, 11025, SPEECH_FLAGS, SOUND_SPEECH_ID, speechVol, speechPan);
+		} 
+#ifdef USE_MAD
+		else if (_cowMode == CowMp3) {
+			warning("playing mp3: Sample(%d/%d) Index %X, Size %d", roomNo, localNo, index, sampleSize);
+			_cowFile.seek(index);
+			_mixer->playMP3(&_speechHandle, &_cowFile, sampleSize, speechVol, speechPan, SOUND_SPEECH_ID);
+			// with compressed audio, we can't calculate the wave volume.
+			// so default to talking.
+			for (int cnt = 0; cnt < 480; cnt++)
+				_waveVolume[cnt] = true;
+			_waveVolPos = 0;
+		}
+#endif
+#ifdef USE_VORBIS
+		else if (_cowMode == CowVorbis) {
+			_cowFile.seek(index);
+			_mixer->playVorbis(&_speechHandle, &_cowFile, sampleSize, speechVol, speechPan, SOUND_SPEECH_ID);
+			for (int cnt = 0; cnt < 480; cnt++)
+				_waveVolume[cnt] = true;	
+			_waveVolPos = 0;
+		}
+#endif
 		return true;
 	} else
 		return false;
@@ -187,8 +209,7 @@
 		headerPos++;
 	if (headerPos < 100) {
 		int32 resSize;
-		// Demo uses slightly different headers
-		if (_isDemo) {
+		if (_cowMode == CowDemo) { // Demo uses slightly different headers
 			resSize = READ_LE_UINT32(fBuf + headerPos + 6) >> 1;
 			headerPos += 2;
 		} else
@@ -259,12 +280,40 @@
 	/* look for speech1/2.clu in the data dir
 	   and speech/speech.clu (running from cd or using cd layout)
 	*/
-	sprintf(cowName, "SPEECH%d.CLU", SwordEngine::_systemVars.currentCD);
+#ifdef USE_MAD
+	sprintf(cowName, "SPEECH%d.CL3", SwordEngine::_systemVars.currentCD);
 	_cowFile.open(cowName);
+	if (_cowFile.isOpen()) {
+		debug(1, "Using MP3 compressed Speech Cluster");
+		_cowMode = CowMp3;
+	} 
+#endif
+#ifdef USE_VORBIS
+	if (!_cowFile.isOpen()) {
+		sprintf(cowName, "SPEECH%d.CLV", SwordEngine::_systemVars.currentCD);
+		_cowFile.open(cowName);
+		if (_cowFile.isOpen()) {
+			debug(1, "Using Vorbis compressed Speech Cluster");
+			_cowMode = CowVorbis;
+		}
+	}
+#endif
+	if (!_cowFile.isOpen()) {
+		sprintf(cowName, "SPEECH%d.CLU", SwordEngine::_systemVars.currentCD);
+		_cowFile.open(cowName);
+		if (!_cowFile.isOpen()) {
+			_cowFile.open("speech.clu");
+		}
+		debug(1, "Using uncompressed Speech Cluster");
+		_cowMode = CowWave;
+	}
 	if (!_cowFile.isOpen())
 		_cowFile.open("speech.clu");
-	if (!_cowFile.isOpen())
-		_cowFile.open("cows.mad"); 
+	if (!_cowFile.isOpen()) {
+		_cowFile.open("cows.mad");
+		if (_cowFile.isOpen())
+			_cowMode = CowDemo;
+	}
 	if (_cowFile.isOpen()) {
 		_cowHeaderSize = _cowFile.readUint32LE();
 		_cowHeader = (uint32*)malloc(_cowHeaderSize);

Index: sound.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/sound.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- sound.h	31 Aug 2004 07:52:47 -0000	1.14
+++ sound.h	12 Oct 2004 15:50:00 -0000	1.15
@@ -58,9 +58,16 @@
 #define WAVE_VOL_TAB_LENGTH 480
 #define WAVE_VOL_THRESHOLD 190000 //120000
 
+enum CowMode {
+	CowWave = 0,
+	CowMp3,
+	CowVorbis,
+	CowDemo
+};
+
 class Sound {
 public:
-	Sound(const char *searchPath, SoundMixer *mixer, ResMan *pResMan, bool isDemo);
+	Sound(const char *searchPath, SoundMixer *mixer, ResMan *pResMan);
 	~Sound(void);
 	void setSpeechVol(uint8 volL, uint8 volR) { _speechVolL = volL; _speechVolR = volR; };
 	void setSfxVol(uint8 volL, uint8 volR) { _sfxVolL = volL; _sfxVolR = volR; };
@@ -93,6 +100,7 @@
 	uint32		 *_cowHeader;
 	uint32		 _cowHeaderSize;
 	uint8		 _currentCowFile;
+	CowMode		 _cowMode;
 	PlayingSoundHandle _speechHandle, _fxHandle;
 	Common::RandomSource _rnd;
 	
@@ -100,7 +108,6 @@
 	uint8		 _endOfQueue;
 	SoundMixer *_mixer;
 	ResMan *_resMan;
-	bool _isDemo;
 	char _filePath[100];
 	static const char _musicList[270];
 	static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM];

Index: sword1.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/sword1.cpp,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -d -r1.53 -r1.54
--- sword1.cpp	8 Oct 2004 16:09:50 -0000	1.53
+++ sword1.cpp	12 Oct 2004 15:50:00 -0000	1.54
@@ -138,7 +138,7 @@
 	_mouse = new Mouse(_system, _resMan, _objectMan);
 	_screen = new Screen(_system, _resMan, _objectMan);
 	_music = new Music(_system, _mixer);
-	_sound = new Sound("", _mixer, _resMan, (_features & GF_DEMO) != 0);
+	_sound = new Sound("", _mixer, _resMan);
 	_menu = new Menu(_screen, _mouse);
 	_logic = new Logic(_objectMan, _resMan, _screen, _mouse, _sound, _music, _menu, _system, _mixer);
 	_mouse->useLogicAndMenu(_logic, _menu);





More information about the Scummvm-git-logs mailing list