diff options
Diffstat (limited to 'backends/platform/psp/mp3.cpp')
-rw-r--r-- | backends/platform/psp/mp3.cpp | 487 |
1 files changed, 0 insertions, 487 deletions
diff --git a/backends/platform/psp/mp3.cpp b/backends/platform/psp/mp3.cpp deleted file mode 100644 index 972c5a8ba8..0000000000 --- a/backends/platform/psp/mp3.cpp +++ /dev/null @@ -1,487 +0,0 @@ -/* 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 "common/debug.h" -#include "common/stream.h" -#include "common/util.h" -#include "common/singleton.h" -#include "common/mutex.h" - -#include "sound/audiostream.h" - -#include <pspaudiocodec.h> -#include <psputility_modules.h> -#include <pspthreadman.h> -#include <pspsysmem.h> -#include <pspmodulemgr.h> -#include <psputility_avmodules.h> -#include <mad.h> -#include "backends/platform/psp/mp3.h" - -//#define DISABLE_PSP_MP3 // to make us use the regular MAD decoder instead - -//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ -//#define __PSP_DEBUG_PRINT__ -#include "backends/platform/psp/trace.h" - -//#define PRINT_BUFFERS /* to debug MP3 buffers */ - -namespace Audio { - -class Mp3PspStream; - -bool Mp3PspStream::_decoderInit = false; // has the decoder been initialized -#ifdef DISABLE_PSP_MP3 -bool Mp3PspStream::_decoderFail = true; // pretend the decoder failed -#else -bool Mp3PspStream::_decoderFail = false; // has the decoder failed to load -#endif - -bool Mp3PspStream::initDecoder() { - DEBUG_ENTER_FUNC(); - - if (_decoderInit) { - PSP_ERROR("Already initialized!"); - return true; - } - - // Based on PSP firmware version, we need to do different things to do Media Engine processing - uint32 firmware = sceKernelDevkitVersion(); - PSP_DEBUG_PRINT("Firmware version 0x%x\n", firmware); - if (firmware == 0x01050001){ - if (!loadStartAudioModule((char *)(void *)"flash0:/kd/me_for_vsh.prx", - PSP_MEMORY_PARTITION_KERNEL)) { - PSP_ERROR("failed to load me_for_vsh.prx. ME cannot start.\n"); - _decoderFail = true; - return false; - } - if (!loadStartAudioModule((char *)(void *)"flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL)) { - PSP_ERROR("failed to load audiocodec.prx. ME cannot start.\n"); - _decoderFail = true; - return false; - } - } else { - if (sceUtilityLoadAvModule(PSP_AV_MODULE_AVCODEC) < 0) { - PSP_ERROR("failed to load AVCODEC module.\n"); - _decoderFail = true; - return false; - } - } - - PSP_INFO_PRINT("Using PSP's ME for MP3\n"); // important to know this is happening - - _decoderInit = true; - return true; -} - -bool Mp3PspStream::stopDecoder() { - DEBUG_ENTER_FUNC(); - - if (!_decoderInit) - return true; - - // Based on PSP firmware version, we need to do different things to do Media Engine processing - if (sceKernelDevkitVersion() == 0x01050001){ -/* if (!unloadAudioModule("flash0:/kd/me_for_vsh.prx", PSP_MEMORY_PARTITION_KERNEL) || - !unloadAudioModule("flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL) { - PSP_ERROR("failed to unload audio module\n"); - return false; - } -*/ - }else{ - if (sceUtilityUnloadModule(PSP_MODULE_AV_AVCODEC) < 0) { - PSP_ERROR("failed to unload avcodec module\n"); - return false; - } - } - - _decoderInit = false; - return true; -} - -//Load a PSP audio module -bool Mp3PspStream::loadStartAudioModule(const char *modname, int partition){ - DEBUG_ENTER_FUNC(); - - SceKernelLMOption option; - SceUID modid; - - memset(&option, 0, sizeof(option)); - option.size = sizeof(option); - option.mpidtext = partition; - option.mpiddata = partition; - option.position = 0; - option.access = 1; - - modid = sceKernelLoadModule(modname, 0, &option); - if (modid < 0) { - PSP_ERROR("Failed to load module %s. Got error 0x%x\n", modname, modid); - return false; - } - - int ret = sceKernelStartModule(modid, 0, NULL, NULL, NULL); - if (ret < 0) { - PSP_ERROR("Failed to start module %s. Got error 0x%x\n", modname, ret); - return false; - } - return true; -} - -// TODO: make parallel function for unloading the 1.50 modules - -Mp3PspStream::Mp3PspStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose) : - _inStream(inStream), - _disposeAfterUse(dispose), - _pcmLength(0), - _posInFrame(0), - _state(MP3_STATE_INIT), - _length(0, 1000), - _sampleRate(0), - _totalTime(mad_timer_zero) { - - DEBUG_ENTER_FUNC(); - - assert(_decoderInit); // must be initialized by now - - // let's leave the buffer guard -- who knows, it may be good? - memset(_buf, 0, sizeof(_buf)); - memset(_codecInBuffer, 0, sizeof(_codecInBuffer)); - - initStream(); // init needed stuff for the stream - - while (_state != MP3_STATE_EOS) - findValidHeader(); // get a first header so we can read basic stuff - - _sampleRate = _header.samplerate; // copy it before it gets destroyed - - _length = Timestamp(mad_timer_count(_totalTime, MAD_UNITS_MILLISECONDS), getRate()); - - //initStreamME(); // init the stuff needed for the ME to work - - deinitStream(); - //releaseStreamME(); - - _state = MP3_STATE_INIT; -} - -int Mp3PspStream::initStream() { - DEBUG_ENTER_FUNC(); - - if (_state != MP3_STATE_INIT) - deinitStream(); - - // Init MAD - mad_stream_init(&_stream); - mad_header_init(&_header); - - // Reset the stream data - _inStream->seek(0, SEEK_SET); - _totalTime = mad_timer_zero; - _posInFrame = 0; - - // Update state - _state = MP3_STATE_READY; - - // Read the first few sample bytes into the buffer - readMP3DataIntoBuffer(); - - return true; -} - -bool Mp3PspStream::initStreamME() { - // The following will eventually go into the thread - sceAudiocodecReleaseEDRAM(_codecParams); // do we need this? - - memset(_codecParams, 0, sizeof(_codecParams)); - - // Init the MP3 hardware - int ret = 0; - ret = sceAudiocodecCheckNeedMem(_codecParams, 0x1002); - if (ret < 0) { - PSP_ERROR("failed to init MP3 ME module. sceAudiocodecCheckNeedMem returned 0x%x.\n", ret); - return false; - } - PSP_DEBUG_PRINT("sceAudiocodecCheckNeedMem returned %d\n", ret); - ret = sceAudiocodecGetEDRAM(_codecParams, 0x1002); - if (ret < 0) { - PSP_ERROR("failed to init MP3 ME module. sceAudiocodecGetEDRAM returned 0x%x.\n", ret); - return false; - } - PSP_DEBUG_PRINT("sceAudioCodecGetEDRAM returned %d\n", ret); - - PSP_DEBUG_PRINT("samplerate[%d]\n", _sampleRate); - _codecParams[10] = _sampleRate; - - ret = sceAudiocodecInit(_codecParams, 0x1002); - if (ret < 0) { - PSP_ERROR("failed to init MP3 ME module. sceAudiocodecInit returned 0x%x.\n", ret); - return false; - } - - return true; -} - -Mp3PspStream::~Mp3PspStream() { - DEBUG_ENTER_FUNC(); - - deinitStream(); - releaseStreamME(); // free the memory used for this stream - - if (_disposeAfterUse == DisposeAfterUse::YES) - delete _inStream; -} - -void Mp3PspStream::deinitStream() { - DEBUG_ENTER_FUNC(); - - if (_state == MP3_STATE_INIT) - return; - - // Deinit MAD - mad_header_finish(&_header); - mad_stream_finish(&_stream); - - _state = MP3_STATE_EOS; -} - -void Mp3PspStream::releaseStreamME() { - sceAudiocodecReleaseEDRAM(_codecParams); -} - -void Mp3PspStream::decodeMP3Data() { - DEBUG_ENTER_FUNC(); - - do { - if (_state == MP3_STATE_INIT) { - initStream(); - initStreamME(); - } - - if (_state == MP3_STATE_EOS) - return; - - findValidHeader(); // seach for next valid header - - while (_state == MP3_STATE_READY) { - _stream.error = MAD_ERROR_NONE; - - uint32 frame_size = _stream.next_frame - _stream.this_frame; - uint32 samplesPerFrame = _header.layer == MAD_LAYER_III ? 576 : 1152; // Varies by layer - // calculate frame size -- try - //uint32 calc_frame_size = ((144 * _header.bitrate) / 22050) + (_header.flags & MAD_FLAG_PADDING ? 1 : 0); - - // Get stereo/mono - uint32 multFactor = 1; - if (_header.mode != MAD_MODE_SINGLE_CHANNEL) // mono - x2 for 16bit - multFactor *= 2; // stereo - x4 for 16bit - - PSP_DEBUG_PRINT("MP3 frame size[%d]. Samples[%d]. Multfactor[%d] pad[%d]\n", frame_size, samplesPerFrame, multFactor, _header.flags & MAD_FLAG_PADDING); - memcpy(_codecInBuffer, _stream.this_frame, frame_size); // we need it aligned - - // set up parameters for ME - _codecParams[6] = (unsigned long)_codecInBuffer; - _codecParams[8] = (unsigned long)_pcmSamples; - _codecParams[7] = frame_size; - _codecParams[9] = samplesPerFrame * multFactor; // x2 for stereo - - // debug -#ifdef PRINT_BUFFERS - PSP_DEBUG_PRINT("mp3 frame:\n"); - for (int i=0; i < (int)frame_size; i++) { - PSP_DEBUG_PRINT_SAMELN("%x ", _codecInBuffer[i]); - } - PSP_DEBUG_PRINT("\n"); -#endif - // Decode the next frame - // This function blocks. We'll want to put it in a thread - int ret = sceAudiocodecDecode(_codecParams, 0x1002); - if (ret < 0) { - PSP_ERROR("failed to decode MP3 data in ME. sceAudiocodecDecode returned 0x%x\n", ret); - // handle error here - } - -#ifdef PRINT_BUFFERS - PSP_DEBUG_PRINT("PCM frame:\n"); - for (int i=0; i < (int)_codecParams[9]; i+=2) { // changed from i+=2 - PSP_DEBUG_PRINT_SAMELN("%d ", (int16)_pcmSamples[i]); - } - PSP_DEBUG_PRINT("\n"); -#endif - _pcmLength = samplesPerFrame; - _posInFrame = 0; - break; - } - } while (_state != MP3_STATE_EOS && _stream.error == MAD_ERROR_BUFLEN); - - if (_stream.error != MAD_ERROR_NONE) // catch EOS - _state = MP3_STATE_EOS; -} - -void Mp3PspStream::readMP3DataIntoBuffer() { - DEBUG_ENTER_FUNC(); - - uint32 remaining = 0; - - // Give up immediately if we already used up all data in the stream - if (_inStream->eos()) { - _state = MP3_STATE_EOS; - return; - } - - if (_stream.next_frame) { - // If there is still data in the MAD stream, we need to preserve it. - // Note that we use memmove, as we are reusing the same buffer, - // and hence the data regions we copy from and to may overlap. - remaining = _stream.bufend - _stream.next_frame; - assert(remaining < BUFFER_SIZE); // Paranoia check - memmove(_buf, _stream.next_frame, remaining); // TODO: may want another buffer - } - - // Try to read the next block - uint32 size = _inStream->read(_buf + remaining, BUFFER_SIZE - remaining); - if (size <= 0) { - _state = MP3_STATE_EOS; - return; - } - - // Feed the data we just read into the stream decoder - _stream.error = MAD_ERROR_NONE; - mad_stream_buffer(&_stream, _buf, size + remaining); // just setup the pointers -} - -bool Mp3PspStream::seek(const Timestamp &where) { - DEBUG_ENTER_FUNC(); - - if (where == _length) { - _state = MP3_STATE_EOS; - return true; - } else if (where > _length) { - return false; - } - - const uint32 time = where.msecs(); - - mad_timer_t destination; - mad_timer_set(&destination, time / 1000, time % 1000, 1000); - - // Check if we need to rewind - if (_state != MP3_STATE_READY || mad_timer_compare(destination, _totalTime) < 0) { - initStream(); - initStreamME(); - } - - // The ME will need clear data no matter what once we seek? - //if (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS) - // initStreamME(); - - // Skip ahead - while (mad_timer_compare(destination, _totalTime) > 0 && _state != MP3_STATE_EOS) - findValidHeader(); - - return (_state != MP3_STATE_EOS); -} - -// Seek in the stream, finding the next valid header -void Mp3PspStream::findValidHeader() { - DEBUG_ENTER_FUNC(); - - if (_state != MP3_STATE_READY) - return; - - // If necessary, load more data into the stream decoder - if (_stream.error == MAD_ERROR_BUFLEN) - readMP3DataIntoBuffer(); - - while (_state != MP3_STATE_EOS) { - _stream.error = MAD_ERROR_NONE; - - // Decode the next header. - if (mad_header_decode(&_header, &_stream) == -1) { - if (_stream.error == MAD_ERROR_BUFLEN) { - readMP3DataIntoBuffer(); // Read more data - continue; - } else if (MAD_RECOVERABLE(_stream.error)) { - debug(6, "MP3PSPStream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream)); - continue; - } else { - warning("MP3PSPStream: Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream)); - break; - } - } - - // Sum up the total playback time so far - mad_timer_add(&_totalTime, _header.duration); - break; - } - - if (_stream.error != MAD_ERROR_NONE) - _state = MP3_STATE_EOS; -} - -int Mp3PspStream::readBuffer(int16 *buffer, const int numSamples) { - DEBUG_ENTER_FUNC(); - - int samples = 0; -#ifdef PRINT_BUFFERS - int16 *debugBuffer = buffer; -#endif - - // Keep going as long as we have input available - while (samples < numSamples && _state != MP3_STATE_EOS) { - const int len = MIN(numSamples, samples + (int)(_pcmLength - _posInFrame) * MAD_NCHANNELS(&_header)); - - while (samples < len) { - *buffer++ = _pcmSamples[_posInFrame << 1]; - samples++; - if (MAD_NCHANNELS(&_header) == 2) { - *buffer++ = _pcmSamples[(_posInFrame << 1) + 1]; - samples++; - } - _posInFrame++; // always skip an extra sample since ME always outputs stereo - } - - //memcpy(buffer, &_pcmSamples[_posInFrame], len << 1); // 16 bits - //_posInFrame += len; // next time we start from the middle - - if (_posInFrame >= _pcmLength) { - // We used up all PCM data in the current frame -- read & decode more - decodeMP3Data(); - } - } - -#ifdef PRINT_BUFFERS - PSP_INFO_PRINT("buffer:\n"); - for (int i = 0; i<numSamples; i++) - PSP_INFO_PRINT("%d ", debugBuffer[i]); - PSP_INFO_PRINT("\n\n"); -#endif - - return samples; -} - -} // End of namespace Audio - - |