aboutsummaryrefslogtreecommitdiff
path: root/backends/platform/psp/audio.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/platform/psp/audio.cpp')
-rw-r--r--backends/platform/psp/audio.cpp150
1 files changed, 150 insertions, 0 deletions
diff --git a/backends/platform/psp/audio.cpp b/backends/platform/psp/audio.cpp
new file mode 100644
index 0000000000..14691befee
--- /dev/null
+++ b/backends/platform/psp/audio.cpp
@@ -0,0 +1,150 @@
+/* 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$
+ * $Id$
+ *
+ */
+
+#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;
+ _bufferToFill = 0;
+ _bufferToPlay = 0;
+
+ _init = true;
+ _paused = true; // start in paused mode
+
+ threadCreateAndStart("audioThread", PRIORITY_AUDIO_THREAD, STACK_AUDIO_THREAD); // start the consumer thread
+
+ return true;
+}
+
+// The real thread function
+void PspAudio::threadFunction() {
+ 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
+ PspThread::delayMicros(100000); // 100ms
+ if (!_paused)
+ PSP_DEBUG_PRINT("audio thread unpaused\n");
+ }
+
+ PSP_DEBUG_PRINT("remaining samples[%d]\n", _remainingSamples);
+
+ PSP_DEBUG_PRINT("filling buffer[%d]\n", _bufferToFill);
+ _callback(_userData, _buffers[_bufferToFill], _bufferSize); // ask mixer to fill in data
+ nextBuffer(_bufferToFill);
+
+ PSP_DEBUG_PRINT("playing buffer[%d].\n", _bufferToPlay);
+ playBuffer();
+ nextBuffer(_bufferToPlay);
+ } // while _init
+
+ // destroy everything
+ free(_buffers[0]);
+ sceAudioChRelease(_pspChannel);
+ PSP_DEBUG_PRINT("audio thread exiting. ****************************\n");
+}
+
+// Much faster than using %, especially with conditional moves (MIPS)
+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 = sceAudioOutputBlocking(_pspChannel, PSP_AUDIO_VOLUME_MAX, _buffers[_bufferToPlay]);
+ else
+ ret = sceAudioOutputPannedBlocking(_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 has been called ***************\n");
+ _init = false;
+}