[Scummvm-cvs-logs] SF.net SVN: scummvm: [33075] scummvm/trunk

fingolfin at users.sourceforge.net fingolfin at users.sourceforge.net
Tue Jul 15 19:13:06 CEST 2008


Revision: 33075
          http://scummvm.svn.sourceforge.net/scummvm/?rev=33075&view=rev
Author:   fingolfin
Date:     2008-07-15 10:13:06 -0700 (Tue, 15 Jul 2008)

Log Message:
-----------
Implemented audio double buffering (for now OSX only)

Modified Paths:
--------------
    scummvm/trunk/NEWS
    scummvm/trunk/backends/platform/sdl/sdl.cpp
    scummvm/trunk/backends/platform/sdl/sdl.h

Modified: scummvm/trunk/NEWS
===================================================================
--- scummvm/trunk/NEWS	2008-07-15 15:39:20 UTC (rev 33074)
+++ scummvm/trunk/NEWS	2008-07-15 17:13:06 UTC (rev 33075)
@@ -3,20 +3,23 @@
 
 0.12.0 (????-??-??)
  New Games:
-   - Added support for The Legend of Kyrandia: Book Two: Hand of Fate
-   - Added support for The Legend of Kyrandia: Book Three: Malcolm's Revenge
-   - Added support for Lost in Time
-   - Added support for The Bizarre Adventures of Woodruff and the Schnibble
-   - Added support for the PC version of Waxworks
+   - Added support for The Legend of Kyrandia: Book Two: Hand of Fate.
+   - Added support for The Legend of Kyrandia: Book Three: Malcolm's Revenge.
+   - Added support for Lost in Time.
+   - Added support for The Bizarre Adventures of Woodruff and the Schnibble.
+   - Added support for the PC version of Waxworks.
    - Added support for the Macintosh version of I Have no Mouth, and I
-     must Scream
-   - Added support for Drascula: The Vampire Strikes Back
+     must Scream.
+   - Added support for Drascula: The Vampire Strikes Back.
    
  General:
    - Added CAMD MIDI driver for AmigaOS4.
    - Revived the PS2 port (was already in 0.11.1 but was forgotten in the
      release notes).
-   - Plugged numerous memory leaks in all engines (part of GSoC'08 task)
+   - Plugged numerous memory leaks in all engines (part of GSoC'08 task),
+   - Added audio double buffering to the SDL backend, which fixes the 
+     problems with the MT-32 emulator on Mac OS X (for now only enabled
+     on Mac OS X).
 
  AGOS:
    - Fixed palette issues in Amiga versions of Simon the Sorcerer 1.

Modified: scummvm/trunk/backends/platform/sdl/sdl.cpp
===================================================================
--- scummvm/trunk/backends/platform/sdl/sdl.cpp	2008-07-15 15:39:20 UTC (rev 33074)
+++ scummvm/trunk/backends/platform/sdl/sdl.cpp	2008-07-15 17:13:06 UTC (rev 33075)
@@ -191,7 +191,7 @@
 
 OSystem_SDL::~OSystem_SDL() {
 	SDL_RemoveTimer(_timerID);
-	SDL_CloseAudio();
+	closeMixer();
 
 	free(_dirtyChecksums);
 	free(_currentPalette);
@@ -199,7 +199,6 @@
 	free(_mouseData);
 
 	delete _savefile;
-	delete _mixer;
 	delete _timer;
 }
 
@@ -306,7 +305,7 @@
 	SDL_ShowCursor(SDL_ENABLE);
 
 	SDL_RemoveTimer(_timerID);
-	SDL_CloseAudio();
+	closeMixer();
 
 	free(_dirtyChecksums);
 	free(_currentPalette);
@@ -314,7 +313,6 @@
 	free(_mouseData);
 
 	delete _savefile;
-	delete _mixer;
 	delete _timer;
 
 	SDL_Quit();
@@ -389,14 +387,110 @@
 #pragma mark --- Audio ---
 #pragma mark -
 
+#ifdef MIXER_DOUBLE_BUFFERING
+
+void OSystem_SDL::mixerProducerThread() {
+	byte nextSoundBuffer;
+
+	SDL_LockMutex(_soundMutex);
+	while (true) {
+		// Wait till we are allowed to produce data
+		SDL_CondWait(_soundCond, _soundMutex);
+
+		if (_soundThreadShouldQuit)
+			break;
+
+		// Generate samples and put them into the next buffer
+		nextSoundBuffer = _activeSoundBuf ^ 1;
+		_mixer->mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize);
+		
+		// Swap buffers
+		_activeSoundBuf = nextSoundBuffer;
+	}
+	SDL_UnlockMutex(_soundMutex);
+}
+
+int SDLCALL OSystem_SDL::mixerProducerThreadEntry(void *arg) {
+	OSystem_SDL *this_ = (OSystem_SDL *)arg;
+	assert(this_);
+	this_->mixerProducerThread();
+	return 0;
+}
+
+
+void OSystem_SDL::initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize) {
+	_soundThreadIsRunning = false;
+	_soundThreadShouldQuit = false;
+
+	// Create mutex and condition variable
+	_soundMutex = SDL_CreateMutex();
+	_soundCond = SDL_CreateCond();
+
+	// Create two sound buffers
+	_activeSoundBuf = 0;
+	_soundBufSize = bufSize;
+	_soundBuffers[0] = (byte *)calloc(1, bufSize);
+	_soundBuffers[1] = (byte *)calloc(1, bufSize);
+
+	_soundThreadIsRunning = true;
+
+	// Finally start the thread
+	_soundThread = SDL_CreateThread(mixerProducerThreadEntry, this);
+}
+
+void OSystem_SDL::deinitThreadedMixer() {
+	// Kill thread?? _soundThread
+
+	if (_soundThreadIsRunning) {
+		// Signal the producer thread to end, and wait for it to actually finish.
+		_soundThreadShouldQuit = true;
+		SDL_CondBroadcast(_soundCond);
+		SDL_WaitThread(_soundThread, NULL);
+
+		// Kill the mutex & cond variables. 
+		// Attention: AT this point, the mixer callback must not be running
+		// anymore, else we will crash!
+		SDL_DestroyMutex(_soundMutex);
+		SDL_DestroyCond(_soundCond);
+
+		_soundThreadIsRunning = false;
+
+		free(_soundBuffers[0]);
+		free(_soundBuffers[1]);
+	}
+}
+
+
+void OSystem_SDL::mixCallback(void *arg, byte *samples, int len) {
+	OSystem_SDL *this_ = (OSystem_SDL *)arg;
+	assert(this_);
+	assert(this_->_mixer);
+
+	assert((int)this_->_soundBufSize == len);
+
+	// Lock mutex, to ensure our data is not overwritten by the producer thread
+	SDL_LockMutex(this_->_soundMutex);
+	
+	// Copy data from the current sound buffer
+	memcpy(samples, this_->_soundBuffers[this_->_activeSoundBuf], len);
+	
+	// Unlock mutex and wake up the produced thread
+	SDL_UnlockMutex(this_->_soundMutex);
+	SDL_CondSignal(this_->_soundCond);
+}
+
+#else
+
 void OSystem_SDL::mixCallback(void *sys, byte *samples, int len) {
 	OSystem_SDL *this_ = (OSystem_SDL *)sys;
 	assert(this_);
+	assert(this_->_mixer);
 
-	if (this_->_mixer)
-		this_->_mixer->mixCallback(samples, len);
+	this_->_mixer->mixCallback(samples, len);
 }
 
+#endif
+
 void OSystem_SDL::setupMixer() {
 	SDL_AudioSpec desired;
 	SDL_AudioSpec obtained;
@@ -443,10 +537,30 @@
 		// Tell the mixer that we are ready and start the sound processing
 		_mixer->setOutputRate(_samplesPerSec);
 		_mixer->setReady(true);
+
+#ifdef MIXER_DOUBLE_BUFFERING
+		initThreadedMixer(_mixer, obtained.samples * 4);
+#endif
+
+		// start the sound system
 		SDL_PauseAudio(0);
 	}
 }
 
+void OSystem_SDL::closeMixer() {
+	if (_mixer)
+		_mixer->setReady(false);
+	delete _mixer;
+	_mixer = 0;
+
+	SDL_CloseAudio();
+
+#ifdef MIXER_DOUBLE_BUFFERING
+	deinitThreadedMixer();
+#endif
+
+}
+
 Audio::Mixer *OSystem_SDL::getMixer() {
 	assert(_mixer);
 	return _mixer;

Modified: scummvm/trunk/backends/platform/sdl/sdl.h
===================================================================
--- scummvm/trunk/backends/platform/sdl/sdl.h	2008-07-15 15:39:20 UTC (rev 33074)
+++ scummvm/trunk/backends/platform/sdl/sdl.h	2008-07-15 17:13:06 UTC (rev 33075)
@@ -51,7 +51,16 @@
 #define USE_OSD	1
 #endif
 
+#if defined(MACOSX)
+// On Mac OS X, we need to double buffer the audio buffer, else anything
+// which produces sampled data with high latency (like the MT-32 emulator)
+// will sound terribly.
+// This could be enabled for more / most ports in the future, but needs some
+// testing.
+#define MIXER_DOUBLE_BUFFERING 1
+#endif
 
+
 enum {
 	GFX_NORMAL = 0,
 	GFX_DOUBLESIZE = 1,
@@ -137,6 +146,8 @@
 	virtual void setupMixer();
 	static void mixCallback(void *s, byte *samples, int len);
 
+	virtual void closeMixer();
+
 	virtual Audio::Mixer *getMixer();
 
 	// Poll CD status
@@ -369,7 +380,24 @@
 	 */
 	MutexRef _graphicsMutex;
 
+#ifdef MIXER_DOUBLE_BUFFERING
+	SDL_mutex *_soundMutex;
+	SDL_cond *_soundCond;
+	SDL_Thread *_soundThread;
+	bool _soundThreadIsRunning;
+	bool _soundThreadShouldQuit;
+	
+	byte _activeSoundBuf;
+	uint _soundBufSize;
+	byte *_soundBuffers[2];
 
+	void mixerProducerThread();
+	static int SDLCALL mixerProducerThreadEntry(void *arg);
+	void initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize);
+	void deinitThreadedMixer();
+#endif
+
+
 	Common::SaveFileManager *_savefile;
 	Audio::MixerImpl *_mixer;
 
@@ -377,7 +405,7 @@
 	Common::TimerManager *_timer;
 
 
-
+protected:
 	void addDirtyRgnAuto(const byte *buf);
 	void makeChecksums(const byte *buf);
 


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