[Scummvm-cvs-logs] SF.net SVN: scummvm:[49149] scummvm/trunk/backends/platform/psp

Bluddy at users.sourceforge.net Bluddy at users.sourceforge.net
Sun May 23 07:51:33 CEST 2010


Revision: 49149
          http://scummvm.svn.sourceforge.net/scummvm/?rev=49149&view=rev
Author:   Bluddy
Date:     2010-05-23 05:51:32 +0000 (Sun, 23 May 2010)

Log Message:
-----------
PSP: switched from SDL's audio to my own thread. Removed needless blocking while playing and made it generally more efficient. To deactivate, simply comment out USE_PSP_AUDIO

Modified Paths:
--------------
    scummvm/trunk/backends/platform/psp/Makefile
    scummvm/trunk/backends/platform/psp/module.mk
    scummvm/trunk/backends/platform/psp/osys_psp.cpp
    scummvm/trunk/backends/platform/psp/osys_psp.h

Added Paths:
-----------
    scummvm/trunk/backends/platform/psp/audio.cpp
    scummvm/trunk/backends/platform/psp/audio.h

Modified: scummvm/trunk/backends/platform/psp/Makefile
===================================================================
--- scummvm/trunk/backends/platform/psp/Makefile	2010-05-22 21:46:40 UTC (rev 49148)
+++ scummvm/trunk/backends/platform/psp/Makefile	2010-05-23 05:51:32 UTC (rev 49149)
@@ -147,9 +147,9 @@
 	cursor.o \
 	trace.o \
 	psploader.o \
-	pspkeyboard.o
+	pspkeyboard.o \
+	audio.o
 
-
 # Include common Scummvm makefile
 include $(srcdir)/Makefile.common
 

Added: scummvm/trunk/backends/platform/psp/audio.cpp
===================================================================
--- scummvm/trunk/backends/platform/psp/audio.cpp	                        (rev 0)
+++ scummvm/trunk/backends/platform/psp/audio.cpp	2010-05-23 05:51:32 UTC (rev 49149)
@@ -0,0 +1,228 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $
+ * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $
+ *
+ */
+
+#include <SDL.h> 
+#include <pspthreadman.h> 
+#include <pspaudio.h>
+ 
+#include "common/scummsys.h" 
+#include "backends/platform/psp/audio.h"
+
+//#define __PSP_DEBUG_FUNCS__	/* For debugging function calls */
+//#define __PSP_DEBUG_PRINT__	/* For debug printouts */
+
+#include "backends/platform/psp/trace.h"
+
+bool PspAudio::open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, callbackFunc callback, void *userData) {
+	DEBUG_ENTER_FUNC();
+	if (_init) {
+		PSP_ERROR("audio device already initialized\n");
+		return true;
+	}		
+
+	PSP_DEBUG_PRINT("freq[%d], numOfChannels[%d], numOfSamples[%d], callback[%p], userData[%x]\n", 
+			freq, numOfChannels, numOfSamples, callback, (uint32)userData);
+	
+	numOfSamples = PSP_AUDIO_SAMPLE_ALIGN(numOfSamples);
+	uint32 bufLen = numOfSamples * numOfChannels * NUM_BUFFERS * sizeof(uint16);
+	
+	PSP_DEBUG_PRINT("total buffer size[%d]\n", bufLen);
+		
+	_buffers[0] = (byte *)memalign(64, bufLen);
+	if (!_buffers[0]) {
+		PSP_ERROR("failed to allocate memory for audio buffers\n");
+		return false;
+	}
+	memset(_buffers[0], 0, bufLen);	// clean the buffer
+	
+	// Fill in the rest of the buffer pointers
+	byte *pBuffer = _buffers[0];
+	for (int i = 1; i < NUM_BUFFERS; i++) {
+		pBuffer += numOfSamples * numOfChannels * sizeof(uint16);
+		_buffers[i] = pBuffer;
+	}
+	
+	// Reserve a HW channel for our audio
+	_pspChannel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, numOfSamples, numOfChannels == 2 ? PSP_AUDIO_FORMAT_STEREO : PSP_AUDIO_FORMAT_MONO);
+	if (_pspChannel < 0) {
+		PSP_ERROR("failed to reserve audio channel\n");
+		return false;
+	}
+	
+	PSP_DEBUG_PRINT("reserved channel[%d] for audio\n", _pspChannel);
+
+	// Save our data
+	_numOfChannels = numOfChannels;
+	_numOfSamples = numOfSamples;
+	_bufferSize = numOfSamples * numOfChannels * sizeof(uint16);	// should be the right size to send the app
+	_callback = callback;
+	_userData = userData;
+	_emptyBuffers = NUM_BUFFERS;
+	_bufferToFill = 0;
+	_bufferToPlay = 0;
+	
+	_init = true;
+	_paused = true;	// start in paused mode
+	
+	createThread();
+	
+	return true;
+}
+
+bool PspAudio::createThread() {
+	DEBUG_ENTER_FUNC();
+	int threadId = sceKernelCreateThread("audioThread", thread, 30, 16*1024, THREAD_ATTR_USER, 0); 
+	
+	if (threadId < 0) {	// error
+		PSP_ERROR("failed to create audio thread. Error code %d\n", threadId);
+		return false;
+	}
+	
+	PspAudio *_this = this;	// trick to get into context when the thread starts
+	
+	if (sceKernelStartThread(threadId, sizeof(uint32 *), &_this) < 0) {
+		PSP_ERROR("failed to start thread %d\n", threadId);
+		return false;
+	}
+	
+	PSP_DEBUG_PRINT("created audio thread[%x]\n", threadId);
+	
+	return true;
+}
+
+// Static function to be called upon thread startup. Will call a non-static function	
+int PspAudio::thread(SceSize, void *__this) {
+	DEBUG_ENTER_FUNC();
+	PspAudio *_this = *(PspAudio **)__this;		// get our this for the context
+	
+	_this->audioThread();
+	return 0;
+};
+
+// The real thread function
+void PspAudio::audioThread() {
+	bool isPlaying = false;
+	int remainingSamples = 0;
+	
+	assert(_callback);
+	PSP_DEBUG_PRINT_FUNC("audio thread started\n");
+
+	while (_init) {		// Keep looping so long as we haven't been told to stop
+		if (_paused)
+			PSP_DEBUG_PRINT("audio thread paused\n");
+		while (_paused) {	// delay until we stop pausing
+			SDL_Delay(100);
+		}
+		if (!_paused)
+			PSP_DEBUG_PRINT("audio thread unpaused\n");
+
+		// check if the audio is playing
+		remainingSamples = sceAudioGetChannelRestLen(_pspChannel);
+		if (remainingSamples < 0) {
+			PSP_ERROR("failed to get remaining samples\n");
+			return;
+		}
+		isPlaying = remainingSamples ? true : false;
+		
+		PSP_DEBUG_PRINT("remaining samples[%d]\n", remainingSamples);
+		
+		while (true) {	// really only execute once. this just helps write the logic
+			if (isPlaying) {
+				_stoppedPlayingOnceFlag = false;
+			
+				// check if a buffer is empty
+				if (_emptyBuffers)	{ // we have some empty buffers
+					PSP_DEBUG_PRINT("sound playing & an empty buffer. filling buffer[%d]. empty buffers[%d]\n", _bufferToFill, _emptyBuffers);
+					_callback(_userData, _buffers[_bufferToFill], _bufferSize); // ask mixer to fill in
+					nextBuffer(_bufferToFill);
+					_emptyBuffers--;
+					break;
+				} else { // we have no empty buffers
+					// calculate how long we need to sleep. time(us) = samples * 1000000 / freq
+					// since frequency is always 44100, we can do a shortcut:
+					// time(us) = samples * (10000 / 441)
+					uint32 sleepTime = (remainingSamples * 10000) / 441;
+					if (!sleepTime)
+						break;
+					PSP_DEBUG_PRINT("sound playing & no empty buffers. sleeping for %d samples for %dus\n", remainingSamples, sleepTime);	
+					sceKernelDelayThread(sleepTime);
+					break;
+				}
+			} else {	// we're not playing right now
+				if (_stoppedPlayingOnceFlag == false) {	// we only want to do this when we finish playing
+					nextBuffer(_bufferToPlay);
+					_emptyBuffers++;
+					_stoppedPlayingOnceFlag = true;
+				}	
+			
+				if (_emptyBuffers == NUM_BUFFERS) { // problem: we have only empty buffers!
+					PSP_DEBUG_PRINT("no sound playing & no full buffer. filling buffer[%d]. empty buffers[%d]\n", _bufferToFill, _emptyBuffers);
+					_callback(_userData, _buffers[_bufferToFill], _bufferSize);
+					nextBuffer(_bufferToFill);
+					_emptyBuffers--;
+					break;
+				} else { // we have at least one non-empty buffer
+					PSP_DEBUG_PRINT("no sound playing & a full buffer. playing buffer[%d]. empty buffers[%d]\n", _bufferToPlay, _emptyBuffers);
+					playBuffer();
+					break;
+				}
+			}
+		} // while true	
+	} // while _init
+	
+	// destroy everything
+	free(_buffers[0]);
+	sceAudioChRelease(_pspChannel);
+	PSP_DEBUG_PRINT("audio thread exiting. ****************************\n");
+}
+
+// Much faster than using %
+inline void PspAudio::nextBuffer(int &bufferIdx) {
+	DEBUG_ENTER_FUNC();
+	bufferIdx++;
+	if (bufferIdx >= NUM_BUFFERS)
+		bufferIdx = 0;
+}
+
+// Don't do it with blocking
+inline bool PspAudio::playBuffer() {
+	DEBUG_ENTER_FUNC();
+	int ret;
+	if (_numOfChannels == 1)
+		ret = sceAudioOutput(_pspChannel, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]);
+	else
+		ret = sceAudioOutputPanned(_pspChannel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]);
+	
+	if (ret < 0) {
+		PSP_ERROR("failed to output audio. Error[%d]\n", ret);
+		return false;
+	}
+	return true;
+}
+
+void PspAudio::close() {
+	PSP_DEBUG_PRINT("close had been called ***************\n");
+	_init = false; 
+}


Property changes on: scummvm/trunk/backends/platform/psp/audio.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: scummvm/trunk/backends/platform/psp/audio.h
===================================================================
--- scummvm/trunk/backends/platform/psp/audio.h	                        (rev 0)
+++ scummvm/trunk/backends/platform/psp/audio.h	2010-05-23 05:51:32 UTC (rev 49149)
@@ -0,0 +1,71 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $
+ * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $
+ *
+ */
+
+#ifndef PSP_AUDIO_H
+#define PSP_AUDIO_H
+
+class PspAudio {
+public:
+	enum {
+		NUM_BUFFERS = 2,
+		FREQUENCY = 44100	/* only frequency we allow */
+	};
+	typedef void (* callbackFunc)(void *userData, byte *samples, int len);
+	PspAudio() : _pspChannel(0), 
+			_numOfChannels(0), _numOfSamples(0), _callback(0), 
+			_bufferToPlay(0), _bufferToFill(0), _emptyBuffers(NUM_BUFFERS), 
+			_init(false), _paused(true), _stoppedPlayingOnceFlag(true) {
+		for (int i=0; i<NUM_BUFFERS; i++)
+			_buffers[i] = 0;
+	}
+	~PspAudio() { close(); }
+	bool playBuffer();
+	void nextBuffer(int &bufferIdx);
+	static int thread(SceSize, void *);
+	void audioThread();
+	bool open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, callbackFunc callback, void *userData);
+	bool createThread();
+	void close();
+	uint32 getFrequency() { return FREQUENCY; }
+	void pause() { _paused = true; }
+	void unpause() { _paused = false; }
+	
+private:
+	int _pspChannel;				// chosen hardware output channel
+	uint32 _numOfChannels;			// 1 for mono; 2 for stereo
+	uint32 _numOfSamples;
+	callbackFunc _callback;			// the callback to call between outputting audio
+	void *_userData;				// userData to send with callback
+	byte *_buffers[NUM_BUFFERS];
+	int _bufferToPlay;				// the next buffer to output
+	int _bufferToFill;
+	int _bufferSize;
+	int _emptyBuffers;
+	bool _init;						// flag for initialization
+	bool _paused;
+	bool _stoppedPlayingOnceFlag;		// used to make sure we know when the playing stopped
+};
+
+#endif /* PSP_AUDIO_H */


Property changes on: scummvm/trunk/backends/platform/psp/audio.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Modified: scummvm/trunk/backends/platform/psp/module.mk
===================================================================
--- scummvm/trunk/backends/platform/psp/module.mk	2010-05-22 21:46:40 UTC (rev 49148)
+++ scummvm/trunk/backends/platform/psp/module.mk	2010-05-23 05:51:32 UTC (rev 49149)
@@ -12,7 +12,8 @@
 	cursor.o \
 	trace.o \
 	psploader.o \
-	pspkeyboard.o
+	pspkeyboard.o \
+	audio.o
 
 MODULE_DIRS += \
 	backends/platform/psp/

Modified: scummvm/trunk/backends/platform/psp/osys_psp.cpp
===================================================================
--- scummvm/trunk/backends/platform/psp/osys_psp.cpp	2010-05-22 21:46:40 UTC (rev 49148)
+++ scummvm/trunk/backends/platform/psp/osys_psp.cpp	2010-05-23 05:51:32 UTC (rev 49149)
@@ -48,6 +48,7 @@
 
 #include "backends/platform/psp/trace.h"
 
+#define USE_PSP_AUDIO
 
 #define	SAMPLES_PER_SEC	44100
 
@@ -58,7 +59,11 @@
 }
 
 void OSystem_PSP::initSDL() {
+#ifdef USE_PSP_AUDIO
+	SDL_Init(SDL_INIT_TIMER);
+#else
 	SDL_Init(SDL_INIT_AUDIO | SDL_INIT_TIMER);
+#endif
 }
 
 OSystem_PSP::~OSystem_PSP() {}
@@ -331,8 +336,6 @@
 }
 
 void OSystem_PSP::setupMixer(void) {
-	SDL_AudioSpec desired;
-	SDL_AudioSpec obtained;
 
 	// Determine the desired output sampling frequency.
 	uint32 samplesPerSec = 0;
@@ -349,6 +352,22 @@
 	while (samples * 16 > samplesPerSec * 2)
 		samples >>= 1;
 
+	assert(!_mixer);
+
+#ifdef USE_PSP_AUDIO
+	if (!_audio.open(samplesPerSec, 2, samples, mixCallback, this)) {
+		PSP_ERROR("failed to open audio\n");
+		return;
+	}
+	samplesPerSec = _audio.getFrequency();	// may have been changed by audio system
+	_mixer = new Audio::MixerImpl(this, samplesPerSec);
+	assert(_mixer);
+	_mixer->setReady(true);
+	_audio.unpause();
+#else
+	SDL_AudioSpec obtained;
+	SDL_AudioSpec desired;
+
 	memset(&desired, 0, sizeof(desired));
 	desired.freq = samplesPerSec;
 	desired.format = AUDIO_S16SYS;
@@ -356,8 +375,7 @@
 	desired.samples = samples;
 	desired.callback = mixCallback;
 	desired.userdata = this;
-
-	assert(!_mixer);
+	
 	if (SDL_OpenAudio(&desired, &obtained) != 0) {
 		warning("Could not open audio: %s", SDL_GetError());
 		_mixer = new Audio::MixerImpl(this, samplesPerSec);
@@ -376,10 +394,15 @@
 
 		SDL_PauseAudio(0);
 	}
+#endif /* USE_PSP_AUDIO */
 }
 
 void OSystem_PSP::quit() {
+#ifdef USE_PSP_AUDIO
+	_audio.close();
+#else
 	SDL_CloseAudio();
+#endif
 	SDL_Quit();
 	sceKernelExitGame();
 }

Modified: scummvm/trunk/backends/platform/psp/osys_psp.h
===================================================================
--- scummvm/trunk/backends/platform/psp/osys_psp.h	2010-05-22 21:46:40 UTC (rev 49148)
+++ scummvm/trunk/backends/platform/psp/osys_psp.h	2010-05-23 05:51:32 UTC (rev 49149)
@@ -38,6 +38,7 @@
 #include "backends/platform/psp/pspkeyboard.h"
 #include "backends/platform/psp/display_manager.h"
 #include "backends/platform/psp/input.h"
+#include "backends/platform/psp/audio.h"
 
 #include <SDL.h>
 
@@ -55,6 +56,7 @@
 	DisplayManager _displayManager;
 	PSPKeyboard _keyboard;
 	InputHandler _inputHandler;
+	PspAudio _audio;
 
 	void initSDL();
 


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