mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-11 14:42:05 +08:00
platform: using hw psp mp3 decoder for streams
This commit is contained in:
@@ -12,8 +12,8 @@ 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.
|
||||
*/
|
||||
|
||||
#include "soundlib.h"
|
||||
#if !XASH_PSP
|
||||
#include "libmpg/libmpg.h"
|
||||
|
||||
/*
|
||||
@@ -117,12 +117,8 @@ stream_t *Stream_OpenMPG( const char *filename )
|
||||
file_t *file;
|
||||
int ret;
|
||||
wavinfo_t sc;
|
||||
#if XASH_PSP
|
||||
// h - hold mode
|
||||
file = FS_Open( filename, "rbh", false );
|
||||
#else
|
||||
|
||||
file = FS_Open( filename, "rb", false );
|
||||
#endif
|
||||
if( !file ) return NULL;
|
||||
|
||||
// at this point we have valid stream
|
||||
@@ -190,7 +186,7 @@ int Stream_ReadMPG( stream_t *stream, int needBytes, void *buffer )
|
||||
|
||||
// check remaining size
|
||||
if( bytesWritten + stream->pos > needBytes )
|
||||
outsize = ( needBytes - bytesWritten );
|
||||
outsize = ( needBytes - bytesWritten );
|
||||
else outsize = stream->pos;
|
||||
|
||||
// copy raw sample to output buffer
|
||||
@@ -265,3 +261,485 @@ void Stream_FreeMPG( stream_t *stream )
|
||||
|
||||
Mem_Free( stream );
|
||||
}
|
||||
|
||||
#else // XASH_PSP
|
||||
#include "platform/psp/scemp3/pspmp3.h"
|
||||
|
||||
/*
|
||||
=================================================================
|
||||
|
||||
PSP MPEG decoding
|
||||
|
||||
=================================================================
|
||||
*/
|
||||
#define MP3_ID3V1_ID "TAG"
|
||||
#define MP3_ID3V1_ID_SZ 3
|
||||
#define MP3_ID3V1_SZ 128
|
||||
|
||||
#define MP3_ID3V2_ID "ID3"
|
||||
#define MP3_ID3V2_ID_SZ 3
|
||||
#define MP3_ID3V2_SIZE_OFF 6
|
||||
#define MP3_ID3V2_SIZE_SZ 4
|
||||
#define MP3_ID3V2_HEADER_SZ 10
|
||||
|
||||
#define MP3_ERRORS_MAX 3
|
||||
|
||||
#define PCM_WIDTH 2 // always 16-bit PCM
|
||||
#define PCM_CHANNELS 2 // always 2
|
||||
|
||||
#define MP3_BUFFER_SIZE ( 128 * 1024 )
|
||||
#define PCM_BUFFER_SIZE (( 1152 * PCM_WIDTH * PCM_CHANNELS ) * 2 ) // framesample * width * channels * 2(double buffer)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int handle;
|
||||
int cachePos;
|
||||
int frameCount;
|
||||
byte *pcmTempPtr;
|
||||
} mp3_decoder_t;
|
||||
|
||||
/*
|
||||
=================
|
||||
Sound_GetID3V2SizeMPG
|
||||
=================
|
||||
*/
|
||||
__inline int Sound_GetID3V2SizeMPG( const byte *tagSize )
|
||||
{
|
||||
int size;
|
||||
byte *sizePtr = (byte*)&size;
|
||||
|
||||
// 7 bit per byte, invert endian
|
||||
sizePtr[0] = (( tagSize[3] >> 0 ) & 0x7F ) | (( tagSize[2] & 0x01 ) << 7 );
|
||||
sizePtr[1] = (( tagSize[2] >> 1 ) & 0x3F ) | (( tagSize[1] & 0x03 ) << 6 );
|
||||
sizePtr[2] = (( tagSize[1] >> 2 ) & 0x1F ) | (( tagSize[0] & 0x07 ) << 5 );
|
||||
sizePtr[3] = (( tagSize[0] >> 3 ) & 0x0F );
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
=================
|
||||
Sound_FindHeadMPG
|
||||
=================
|
||||
*/
|
||||
fs_offset_t Sound_FindHeadMPG( const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
fs_offset_t result;
|
||||
|
||||
result = 0;
|
||||
if( filesize >= MP3_ID3V2_HEADER_SZ )
|
||||
{
|
||||
if( !memcmp( buffer, MP3_ID3V2_ID, MP3_ID3V2_ID_SZ ))
|
||||
result = Sound_GetID3V2SizeMPG( &buffer[MP3_ID3V2_SIZE_OFF] ) + MP3_ID3V2_HEADER_SZ;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sound_FindTailMPG
|
||||
=================
|
||||
*/
|
||||
fs_offset_t Sound_FindTailMPG( const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
fs_offset_t result;
|
||||
|
||||
result = filesize;
|
||||
if( filesize >= MP3_ID3V1_SZ )
|
||||
{
|
||||
if( !memcmp( &buffer[filesize - MP3_ID3V1_SZ], MP3_ID3V1_ID, MP3_ID3V1_ID_SZ ))
|
||||
result -= MP3_ID3V1_SZ;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
qboolean Sound_LoadMPG( const char *name, const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
#if 0
|
||||
int status;
|
||||
int handle;
|
||||
size_t bytesWrite = 0;
|
||||
byte out[PCM_BUFFER_SIZE] __attribute__((aligned(64)));
|
||||
fs_offset_t headOffset;
|
||||
fs_offset_t tailOffset;
|
||||
fs_offset_t contentSize;
|
||||
int frameSample;
|
||||
uint bps;
|
||||
int frameLen;
|
||||
int frameSize;
|
||||
int frameCount;
|
||||
|
||||
headOffset = Sound_FindHeadMPG( buffer, filesize );
|
||||
tailOffset = Sound_FindTailMPG( buffer, filesize );
|
||||
contentSize = tailOffset - headOffset;
|
||||
// TODO: read Xing header
|
||||
|
||||
handle = sceMp3ReserveMp3Handle( NULL );
|
||||
if ( handle < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3ReserveMp3Handle returned 0x%08X\n", handle );
|
||||
return false;
|
||||
}
|
||||
|
||||
status = sceMp3LowLevelInit( handle, &buffer[headOffset] );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3LowLevelInit returned 0x%08X\n", status );
|
||||
return false;
|
||||
}
|
||||
|
||||
frameSample = sceMp3GetMaxOutputSample( handle );
|
||||
frameSize = (( frameSample / 8 ) * sceMp3GetBitRate( handle ) * 1000 ) / sceMp3GetSamplingRate( handle );
|
||||
frameCount = contentSize / frameSize;
|
||||
|
||||
sound.channels = sceMp3GetMp3ChannelNum( handle );
|
||||
sound.rate = sceMp3GetSamplingRate( handle );
|
||||
sound.width = PCM_WIDTH; // always 16-bit PCM
|
||||
sound.loopstart = -1;
|
||||
sound.size = (frameCount * frameSample) * sound.channels * sound.width; // invalid for VBR
|
||||
/*
|
||||
status = sceMp3LowLevelDecode(handle, &buffer[headOffset + mp3usedsize], &mp3usedsize, pcm, &pcmoutsize);
|
||||
if(status < 0)
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3LowLevelDecode returned 0x%08X\n", status);
|
||||
}
|
||||
sceMp3ReleaseMp3Handle( handle );
|
||||
*/
|
||||
return true;
|
||||
#else
|
||||
Con_DPrintf( S_ERROR "Sound_LoadMPG unimplemented function!\n");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_FindHeadMPG
|
||||
=================
|
||||
*/
|
||||
SceOff Stream_FindHeadMPG( file_t *file )
|
||||
{
|
||||
SceOff result;
|
||||
byte tagId[MP3_ID3V2_ID_SZ];
|
||||
byte tagSize[MP3_ID3V2_SIZE_SZ];
|
||||
|
||||
result = 0;
|
||||
|
||||
FS_Seek( file, 0, SEEK_SET );
|
||||
|
||||
if( FS_Read( file, tagId, MP3_ID3V2_ID_SZ) < MP3_ID3V2_ID_SZ )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Sound_Mp3FindHead: ID3V2 ID read error\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
if( !memcmp( tagId, MP3_ID3V2_ID, MP3_ID3V2_ID_SZ ))
|
||||
{
|
||||
FS_Seek( file, MP3_ID3V2_SIZE_OFF, SEEK_SET );
|
||||
if( FS_Read( file, tagSize, MP3_ID3V2_SIZE_SZ ) < MP3_ID3V2_SIZE_SZ )
|
||||
Con_DPrintf( S_ERROR "Sound_Mp3FindHead: ID3V2 SIZE read error\n");
|
||||
else result = Sound_GetID3V2SizeMPG( tagSize ) + MP3_ID3V2_HEADER_SZ;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_FindTailMPG
|
||||
=================
|
||||
*/
|
||||
SceOff Stream_FindTailMPG( file_t *file )
|
||||
{
|
||||
SceOff result;
|
||||
byte tagId[MP3_ID3V1_ID_SZ];
|
||||
|
||||
result = FS_FileLength( file );
|
||||
|
||||
FS_Seek( file, result - MP3_ID3V1_SZ, SEEK_SET );
|
||||
|
||||
if( FS_Read( file, tagId, MP3_ID3V1_ID_SZ ) < MP3_ID3V1_ID_SZ )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Sound_Mp3FindTail: ID3V1 ID read error\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
if( !memcmp( tagId, MP3_ID3V1_ID, MP3_ID3V1_ID_SZ ))
|
||||
result -= MP3_ID3V1_SZ;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_FillBufferMPG
|
||||
=================
|
||||
*/
|
||||
int Stream_FillBufferMPG( file_t *file, mp3_decoder_t *desc )
|
||||
{
|
||||
int status;
|
||||
byte *dstPtr;
|
||||
int dstSize;
|
||||
int dstPos;
|
||||
fs_offset_t readSize;
|
||||
|
||||
if( sceMp3CheckStreamDataNeeded( desc->handle ) <= 0 )
|
||||
return 0;
|
||||
|
||||
// get Info on the stream (where to fill to, how much to fill, where to fill from)
|
||||
status = sceMp3GetInfoToAddStreamData( desc->handle, &dstPtr, &dstSize, &dstPos );
|
||||
if( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3GetInfoToAddStreamData returned 0x%08X\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
// seek file to position requested
|
||||
if( desc->cachePos != dstPos )
|
||||
{
|
||||
FS_Seek( file, dstPos, SEEK_SET );
|
||||
desc->cachePos = dstPos;
|
||||
}
|
||||
|
||||
// read the amount of data
|
||||
readSize = FS_Read( file, dstPtr, dstSize );
|
||||
desc->cachePos += ( int )readSize;
|
||||
|
||||
// notify mp3 library about how much we really wrote to the stream buffer
|
||||
status = sceMp3NotifyAddStreamData( desc->handle, ( int )readSize );
|
||||
if ( status < 0 )
|
||||
Con_DPrintf( S_ERROR "sceMp3NotifyAddStreamData returned 0x%08X\n", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_OpenMPG
|
||||
=================
|
||||
*/
|
||||
stream_t *Stream_OpenMPG( const char *filename )
|
||||
{
|
||||
stream_t *stream;
|
||||
mp3_decoder_t *desc;
|
||||
file_t *file;
|
||||
int status;
|
||||
void *bufferBase;
|
||||
|
||||
file = FS_Open( filename, "rbh", false ); // hold mode
|
||||
if( !file ) return NULL;
|
||||
|
||||
// at this point we have valid stream
|
||||
stream = Mem_Calloc( host.soundpool, sizeof( stream_t ));
|
||||
stream->file = file;
|
||||
stream->pos = 0;
|
||||
|
||||
desc = Mem_Calloc( host.soundpool, sizeof( mp3_decoder_t ) + MP3_BUFFER_SIZE + PCM_BUFFER_SIZE + 63 );
|
||||
bufferBase = (void *)(((( uintptr_t )desc + sizeof( mp3_decoder_t )) & (~( 64 - 1 ))) + 64 );
|
||||
|
||||
// reserve a mp3 handle
|
||||
SceMp3InitArg mp3Init;
|
||||
mp3Init.mp3StreamStart = Stream_FindHeadMPG( file );
|
||||
mp3Init.mp3StreamEnd = Stream_FindTailMPG( file );
|
||||
mp3Init.mp3Buf = bufferBase;
|
||||
mp3Init.mp3BufSize = MP3_BUFFER_SIZE;
|
||||
mp3Init.pcmBuf = (void *)(( uintptr_t )bufferBase + MP3_BUFFER_SIZE );
|
||||
mp3Init.pcmBufSize = PCM_BUFFER_SIZE;
|
||||
|
||||
desc->cachePos = 0;
|
||||
desc->pcmTempPtr = mp3Init.pcmBuf;
|
||||
desc->handle = sceMp3ReserveMp3Handle( &mp3Init );
|
||||
if ( desc->handle < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3ReserveMp3Handle returned 0x%08X\n", desc->handle );
|
||||
Mem_Free( stream );
|
||||
Mem_Free( desc );
|
||||
FS_Close( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Fill the stream buffer with some data so that sceMp3Init has something to work with
|
||||
if( Stream_FillBufferMPG( file, desc ) != 0 )
|
||||
{
|
||||
Mem_Free( stream );
|
||||
Mem_Free( desc );
|
||||
FS_Close( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = sceMp3Init( desc->handle );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3Init returned 0x%08X\n", status );
|
||||
Mem_Free( stream );
|
||||
Mem_Free( desc );
|
||||
FS_Close( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
desc->frameCount = sceMp3GetFrameNum( desc->handle );
|
||||
|
||||
stream->buffsize = 0; // how many samples left from previous frame
|
||||
stream->channels = PCM_CHANNELS; // always 2 PCM channels
|
||||
stream->rate = sceMp3GetSamplingRate( desc->handle );
|
||||
stream->width = PCM_WIDTH; // always 16 bit PCM
|
||||
stream->ptr = (void *)desc;
|
||||
stream->type = WF_MPGDATA;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_ReadMPG
|
||||
|
||||
assume stream is valid
|
||||
=================
|
||||
*/
|
||||
int Stream_ReadMPG( stream_t *stream, int needBytes, void *buffer )
|
||||
{
|
||||
// buffer handling
|
||||
int bytesWritten = 0;
|
||||
mp3_decoder_t *desc;
|
||||
int errdec;
|
||||
|
||||
desc = ( mp3_decoder_t* )stream->ptr;
|
||||
|
||||
while(1)
|
||||
{
|
||||
byte *data;
|
||||
int outsize;
|
||||
|
||||
if( !stream->buffsize )
|
||||
{
|
||||
// Check if we need to fill our stream buffer
|
||||
if( Stream_FillBufferMPG( stream->file, desc ) != 0 )
|
||||
return 0;
|
||||
|
||||
for( errdec = 0; errdec < MP3_ERRORS_MAX; errdec++ )
|
||||
{
|
||||
stream->pos = sceMp3Decode( desc->handle, (SceShort16**)&desc->pcmTempPtr );
|
||||
if(( int )stream->pos >= 0 ) // decoding successful
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if( stream->pos == 0x80671402 ) // next frame header
|
||||
{
|
||||
if( Stream_FillBufferMPG( stream->file, desc ) != 0 )
|
||||
return 0;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
if(( int )stream->pos < 0 )
|
||||
{
|
||||
if( stream->pos != 0x80671402 )
|
||||
Con_DPrintf( S_ERROR "sceMp3Decode returned 0x%08X\n", stream->pos );
|
||||
return 0; // ???
|
||||
}
|
||||
}
|
||||
|
||||
// check remaining size
|
||||
if( bytesWritten + stream->pos > needBytes )
|
||||
outsize = ( needBytes - bytesWritten );
|
||||
else outsize = stream->pos;
|
||||
|
||||
// copy raw sample to output buffer
|
||||
data = (byte *)buffer + bytesWritten;
|
||||
memcpy( data, &desc->pcmTempPtr[stream->buffsize], outsize );
|
||||
bytesWritten += outsize;
|
||||
stream->pos -= outsize;
|
||||
stream->buffsize += outsize;
|
||||
|
||||
// continue from this sample on a next call
|
||||
if( bytesWritten >= needBytes )
|
||||
return bytesWritten;
|
||||
|
||||
stream->buffsize = 0; // no bytes remaining
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_SetPosMPG
|
||||
|
||||
assume stream is valid
|
||||
=================
|
||||
*/
|
||||
int Stream_SetPosMPG( stream_t *stream, int newpos )
|
||||
{
|
||||
mp3_decoder_t *desc;
|
||||
int frame;
|
||||
int status;
|
||||
|
||||
desc = ( mp3_decoder_t* )stream->ptr;
|
||||
|
||||
// get frame num
|
||||
frame = newpos / sceMp3GetMaxOutputSample( desc->handle ); // VBR?
|
||||
|
||||
if( frame < 1 || frame >= desc->frameCount - 1 )
|
||||
return false;
|
||||
|
||||
status = sceMp3ResetPlayPositionByFrame( desc->handle, frame );
|
||||
if( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3ResetPlayPositionByFrame returned 0x%08X\n", status );
|
||||
|
||||
// failed to seek for some reasons
|
||||
return false;
|
||||
}
|
||||
|
||||
// flush any previous data
|
||||
stream->buffsize = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_GetPosMPG
|
||||
|
||||
assume stream is valid
|
||||
=================
|
||||
*/
|
||||
int Stream_GetPosMPG( stream_t *stream )
|
||||
{
|
||||
mp3_decoder_t *desc;
|
||||
|
||||
desc = ( mp3_decoder_t * )stream->ptr;
|
||||
|
||||
return sceMp3GetSumDecodedSample( desc->handle );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_FreeMPG
|
||||
|
||||
assume stream is valid
|
||||
=================
|
||||
*/
|
||||
void Stream_FreeMPG( stream_t *stream )
|
||||
{
|
||||
mp3_decoder_t *desc;
|
||||
|
||||
desc = ( mp3_decoder_t * )stream->ptr;
|
||||
if( desc )
|
||||
{
|
||||
sceMp3ReleaseMp3Handle( desc->handle );
|
||||
Mem_Free( desc );
|
||||
stream->ptr = NULL;
|
||||
}
|
||||
|
||||
if( stream->file )
|
||||
{
|
||||
FS_Close( stream->file );
|
||||
stream->file = NULL;
|
||||
}
|
||||
|
||||
Mem_Free( stream );
|
||||
}
|
||||
#endif // XASH_PSP
|
||||
|
||||
@@ -74,7 +74,9 @@ struct stream_s
|
||||
|
||||
// current stream state
|
||||
void *ptr; // internal decoder state
|
||||
#if !XASH_PSP
|
||||
char temp[OUTBUF_SIZE]; // mpeg decoder stuff
|
||||
#endif
|
||||
size_t pos; // actual track position (or actual buffer remains)
|
||||
int buffsize; // cached buffer size
|
||||
};
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* pspmp3.h - Prototypes for the sceMp3 library
|
||||
*
|
||||
* Copyright (c) 2008 David Perry <tias_dp@hotmail.com>
|
||||
* Copyright (c) 2008 Alexander Berl <raphael@fx-world.org>
|
||||
* Copyright (c) 2022 Sergey Galushko
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SCELIBMP3_H__
|
||||
#define __SCELIBMP3_H__
|
||||
|
||||
#include <psptypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct SceMp3InitArg {
|
||||
/** Stream start position */
|
||||
SceOff mp3StreamStart;
|
||||
/** Stream end position */
|
||||
SceOff mp3StreamEnd;
|
||||
/** Pointer to a buffer to contain raw mp3 stream data (+1472 bytes workspace) */
|
||||
SceUChar8* mp3Buf;
|
||||
/** Size of mp3Buf buffer (must be >= 8192) */
|
||||
SceInt32 mp3BufSize;
|
||||
/** Pointer to decoded pcm samples buffer */
|
||||
SceUChar8* pcmBuf;
|
||||
/** Size of pcmBuf buffer (must be >= 9216) */
|
||||
SceInt32 pcmBufSize;
|
||||
} SceMp3InitArg;
|
||||
|
||||
/**
|
||||
* sceMp3ReserveMp3Handle
|
||||
*
|
||||
* @param args - Pointer to SceMp3InitArg structure
|
||||
*
|
||||
* @return sceMp3 handle on success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3ReserveMp3Handle(SceMp3InitArg* args);
|
||||
|
||||
/**
|
||||
* sceMp3ReleaseMp3Handle
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3ReleaseMp3Handle(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3InitResource
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3InitResource();
|
||||
|
||||
/**
|
||||
* sceMp3TermResource
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3TermResource();
|
||||
|
||||
/**
|
||||
* sceMp3Init
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3Init(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3Decode
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param dst - Pointer to destination pcm samples buffer
|
||||
*
|
||||
* @return number of bytes in decoded pcm buffer, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3Decode(SceInt32 handle, SceShort16** dst);
|
||||
|
||||
/**
|
||||
* sceMp3GetInfoToAddStreamData
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param dst - Pointer to stream data buffer
|
||||
* @param towrite - Space remaining in stream data buffer
|
||||
* @param srcpos - Position in source stream to start reading from
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3GetInfoToAddStreamData(SceInt32 handle, SceUChar8** dst, SceInt32* towrite, SceInt32* srcpos);
|
||||
|
||||
/**
|
||||
* sceMp3NotifyAddStreamData
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param size - number of bytes added to the stream data buffer
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3NotifyAddStreamData(SceInt32 handle, SceInt32 size);
|
||||
|
||||
/**
|
||||
* sceMp3CheckStreamDataNeeded
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return 1 if more stream data is needed, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3CheckStreamDataNeeded(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3SetLoopNum
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param loop - Number of loops
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3SetLoopNum(SceInt32 handle, SceInt32 loop);
|
||||
|
||||
/**
|
||||
* sceMp3GetLoopNum
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Number of loops
|
||||
*/
|
||||
SceInt32 sceMp3GetLoopNum(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetSumDecodedSample
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Number of decoded samples
|
||||
*/
|
||||
SceInt32 sceMp3GetSumDecodedSample(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetMaxOutputSample
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Number of max samples to output
|
||||
*/
|
||||
SceInt32 sceMp3GetMaxOutputSample(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetSamplingRate
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Sampling rate of the mp3
|
||||
*/
|
||||
SceInt32 sceMp3GetSamplingRate(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetBitRate
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Bitrate of the mp3
|
||||
*/
|
||||
SceInt32 sceMp3GetBitRate(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetMp3ChannelNum
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Number of channels of the mp3
|
||||
*/
|
||||
SceInt32 sceMp3GetMp3ChannelNum(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3ResetPlayPosition
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3ResetPlayPosition(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetFrameNum
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3GetFrameNum(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3ResetPlayPositionByFrame
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param frame - frame
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3ResetPlayPositionByFrame(SceInt32 handle, SceUInt32 frame);
|
||||
|
||||
/**
|
||||
* sceMp3GetMPEGVersion
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3GetMPEGVersion(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3LowLevelInit
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param src - Pointer to a buffer to contain raw mp3 stream data
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3LowLevelInit(SceInt32 handle, SceUChar8* src);
|
||||
|
||||
/**
|
||||
* sceMp3LowLevelDecode
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param mp3src -
|
||||
* @param mp3srcused -
|
||||
* @param pcmdst -
|
||||
* @param pcmdstoutsz -
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3LowLevelDecode(SceInt32 handle, SceUChar8* mp3src, SceUInt32* mp3srcused, SceShort16* pcmdst, SceUInt32* pcmdstoutsz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
.set noreorder
|
||||
|
||||
#include "pspimport.s"
|
||||
|
||||
IMPORT_START "sceMp3",0x00090011
|
||||
IMPORT_FUNC "sceMp3",0x07EC321A,sceMp3ReserveMp3Handle
|
||||
IMPORT_FUNC "sceMp3",0x0DB149F4,sceMp3NotifyAddStreamData
|
||||
IMPORT_FUNC "sceMp3",0x2A368661,sceMp3ResetPlayPosition
|
||||
IMPORT_FUNC "sceMp3",0x354D27EA,sceMp3GetSumDecodedSample
|
||||
IMPORT_FUNC "sceMp3",0x35750070,sceMp3InitResource
|
||||
IMPORT_FUNC "sceMp3",0x3C2FA058,sceMp3TermResource
|
||||
IMPORT_FUNC "sceMp3",0x3CEF484F,sceMp3SetLoopNum
|
||||
IMPORT_FUNC "sceMp3",0x44E07129,sceMp3Init
|
||||
IMPORT_FUNC "sceMp3",0x732B042A,sceMp3EndEntry
|
||||
IMPORT_FUNC "sceMp3",0x7F696782,sceMp3GetMp3ChannelNum
|
||||
IMPORT_FUNC "sceMp3",0x87677E40,sceMp3GetBitRate
|
||||
IMPORT_FUNC "sceMp3",0x87C263D1,sceMp3GetMaxOutputSample
|
||||
IMPORT_FUNC "sceMp3",0x8AB81558,sceMp3StartEntry
|
||||
IMPORT_FUNC "sceMp3",0x8F450998,sceMp3GetSamplingRate
|
||||
IMPORT_FUNC "sceMp3",0xA703FE0F,sceMp3GetInfoToAddStreamData
|
||||
IMPORT_FUNC "sceMp3",0xD021C0FB,sceMp3Decode
|
||||
IMPORT_FUNC "sceMp3",0xD0A56296,sceMp3CheckStreamDataNeeded
|
||||
IMPORT_FUNC "sceMp3",0xD8F54A51,sceMp3GetLoopNum
|
||||
IMPORT_FUNC "sceMp3",0xF5478233,sceMp3ReleaseMp3Handle
|
||||
IMPORT_FUNC "sceMp3",0xAE6D2027,sceMp3GetMPEGVersion
|
||||
IMPORT_FUNC "sceMp3",0x3548AEC8,sceMp3GetFrameNum
|
||||
IMPORT_FUNC "sceMp3",0x0840E808,sceMp3ResetPlayPositionByFrame
|
||||
IMPORT_FUNC "sceMp3",0x1B839B83,sceMp3LowLevelInit
|
||||
IMPORT_FUNC "sceMp3",0xE3EE2C81,sceMp3LowLevelDecode
|
||||
@@ -15,12 +15,14 @@ GNU General Public License for more details.
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platform/psp/ka/ka.h"
|
||||
#include "platform/psp/scemp3/pspmp3.h"
|
||||
#include <pspsdk.h>
|
||||
#include <pspkernel.h>
|
||||
#include <psppower.h>
|
||||
#include <psprtc.h>
|
||||
#include <pspprof.h>
|
||||
#include <pspctrl.h>
|
||||
#include <psputility.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
@@ -30,6 +32,8 @@ PSP_MAIN_THREAD_ATTR( PSP_THREAD_ATTR_USER | PSP_THREAD_ATTR_VFPU );
|
||||
PSP_MAIN_THREAD_STACK_SIZE_KB( 512 );
|
||||
PSP_HEAP_SIZE_KB( -3 * 1024 ); /* 3 MB for prx modules */
|
||||
|
||||
static qboolean psp_audiolib_init = false;
|
||||
|
||||
static int Platform_ExitCallback( int count, int arg, void *common )
|
||||
{
|
||||
host.crashed = true;
|
||||
@@ -251,10 +255,68 @@ int Platform_UnloadModule( SceUID modid, int *sce_code )
|
||||
return ( ( ( *sce_code ) < 0 ) ? -2 : 0 );
|
||||
}
|
||||
|
||||
int Platform_InitAudioLibs( void )
|
||||
{
|
||||
int status;
|
||||
|
||||
if( psp_audiolib_init )
|
||||
return -1;
|
||||
|
||||
status = sceUtilityLoadModule( PSP_MODULE_AV_AVCODEC );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceUtilityLoadModule(PSP_MODULE_AV_AVCODEC) returned 0x%08X\n", status );
|
||||
return status;
|
||||
}
|
||||
|
||||
status = sceUtilityLoadModule( PSP_MODULE_AV_MP3 );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceUtilityLoadModule(PSP_MODULE_AV_MP3) returned 0x%08X\n", status );
|
||||
return status;
|
||||
}
|
||||
|
||||
// init mp3 resources
|
||||
status = sceMp3InitResource();
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3InitResource returned 0x%08X\n", status );
|
||||
return status;
|
||||
}
|
||||
|
||||
psp_audiolib_init = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Platform_ShutdownAudioLibs( void )
|
||||
{
|
||||
int status;
|
||||
|
||||
if( !psp_audiolib_init )
|
||||
return -1;
|
||||
|
||||
status = sceMp3TermResource();
|
||||
if ( status < 0 )
|
||||
Con_DPrintf( S_ERROR "sceMp3TermResource returned 0x%08X\n", status );
|
||||
|
||||
status = sceUtilityUnloadModule( PSP_MODULE_AV_MP3 );
|
||||
if ( status < 0 )
|
||||
Con_DPrintf( S_ERROR "sceUtilityUnloadModule(PSP_MODULE_AV_MP3) returned 0x%08X\n", status );
|
||||
|
||||
status = sceUtilityUnloadModule( PSP_MODULE_AV_AVCODEC );
|
||||
if ( status < 0 )
|
||||
Con_DPrintf( S_ERROR "sceUtilityUnloadModule(PSP_MODULE_AV_AVCODEC) returned 0x%08X\n", status );
|
||||
|
||||
psp_audiolib_init = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Platform_Init( void )
|
||||
{
|
||||
SceUID kamID;
|
||||
int result;
|
||||
SceUID kamID;
|
||||
int result;
|
||||
|
||||
// disable fpu exceptions (division by zero and etc...)
|
||||
pspSdkDisableFPUExceptions();
|
||||
@@ -275,13 +337,16 @@ void Platform_Init( void )
|
||||
Platform_UnloadModule( kamID, &result );
|
||||
}
|
||||
|
||||
Platform_InitAudioLibs();
|
||||
|
||||
// P5 Ram init
|
||||
P5Ram_Init();
|
||||
P5Ram_Init();
|
||||
}
|
||||
|
||||
void Platform_Shutdown( void )
|
||||
{
|
||||
P5Ram_Shutdown();
|
||||
Platform_ShutdownAudioLibs();
|
||||
#if XASH_PROFILING
|
||||
gprof_cleanup();
|
||||
#endif
|
||||
|
||||
+3
-1
@@ -95,9 +95,11 @@ def build(bld):
|
||||
'common/*.c',
|
||||
'common/imagelib/*.c',
|
||||
'common/soundlib/*.c',
|
||||
'common/soundlib/libmpg/*.c',
|
||||
'server/*.c'])
|
||||
|
||||
if bld.env.DEST_OS != 'psp':
|
||||
source += bld.path.ant_glob(['common/soundlib/libmpg/*.c'])
|
||||
|
||||
# basic build: dedicated only, no dependencies
|
||||
if bld.env.DEST_OS == 'win32':
|
||||
libs += ['USER32', 'SHELL32', 'GDI32', 'ADVAPI32', 'DBGHELP', 'PSAPI', 'WS2_32' ]
|
||||
|
||||
Reference in New Issue
Block a user