l3VGV
01.07.2007, 18:22
Итак, рабочий пример без внешних либ, тока средцтвами самой консольки.
#include <pspkernel.h>
#include <pspctrl.h>
#include <pspmpeg.h>
#include <pspdisplay.h>
#include <pspdebug.h>
#include <psppower.h>
#include <stdio.h>
#include <stdlib.h>
#include <pspkernel.h>
#include <pspctrl.h>
#include <psppower.h>
#include <pspdebug.h>
#include <psprtc.h>
#include <pspsdk.h>
#include <pspaudiocodec.h>
#include <pspaudio.h>
#include <string.h>
#include <malloc.h>
int SetupCallbacks();
PSP_MODULE_INFO("MP3 decodeTest", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(0);
__attribute__ ((constructor))
void loaderInit(){
pspKernelSetKernelPC();
pspSdkInstallNoDeviceCheckPatch();
pspSdkInstallNoPlainModuleCheckPatch();
pspSdkInstallKernelLoadModulePatch();
}
SceCtrlData input;
static int bitrates[] = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 };
unsigned long mp3_codec_buffer[65] __attribute__((aligned(64)));
short mp3_mix_buffer1[1152 * 2] __attribute__((aligned(64)));
short mp3_mix_buffer2[1152 * 2] __attribute__((aligned(64)));
SceUID mp3_handle;
u8* mp3_data_buffer;
u16 mp3_data_align;
u32 mp3_sample_per_frame;
u16 mp3_channel_mode;
u32 mp3_data_start;
u32 mp3_data_size;
u8 mp3_getEDRAM;
u32 mp3_channels;
u32 mp3_samplerate;
int donext, bc, eof;
SceCtrlData pad;
int decode_thread(SceSize args, void *argp)
{
eof = 0;
fprintf(stderr,"$>entering main loop\n");
while( !eof ) {
if (!donext)
{
sceKernelDelayThread(1);
continue;
}
int samplesdecoded;
if (!bc)
memset(mp3_mix_buffer1, 0, mp3_sample_per_frame*2*2);
else
memset(mp3_mix_buffer2, 0, mp3_sample_per_frame*2*2);
unsigned char mp3_header_buf[4];
if ( sceIoRead( mp3_handle, mp3_header_buf, 4 ) != 4 ) {
fprintf(stderr,"$>mp3_header_buf < 4 exitin \n");
eof = 1;
continue;
}
int mp3_header = mp3_header_buf[0];
mp3_header = (mp3_header<<8) | mp3_header_buf[1];
mp3_header = (mp3_header<<8) | mp3_header_buf[2];
mp3_header = (mp3_header<<8) | mp3_header_buf[3];
int bitrate = (mp3_header & 0xf000) >> 12;
int padding = (mp3_header & 0x200) >> 9;
int frame_size = 144000*bitrates[bitrate]/mp3_samplerate + padding;
if ( mp3_data_buffer )
free(mp3_data_buffer);
mp3_data_buffer = (u8*)memalign(64, frame_size);
sceIoLseek32(mp3_handle, mp3_data_start, PSP_SEEK_SET); //seek back
if ( sceIoRead( mp3_handle, mp3_data_buffer, frame_size ) != frame_size ) {
fprintf(stderr,"$>sceIoRead frame_size < frame_size exitin \n");
eof = 1;
continue;
}
mp3_data_start += frame_size;
mp3_codec_buffer[6] = (unsigned long)mp3_data_buffer;
if (!bc)
mp3_codec_buffer[8] = (unsigned long)mp3_mix_buffer1;
else
mp3_codec_buffer[8] = (unsigned long)mp3_mix_buffer2;
mp3_codec_buffer[7] = mp3_codec_buffer[10] = frame_size;
mp3_codec_buffer[9] = mp3_sample_per_frame * 4;
int res = sceAudiocodecDecode(mp3_codec_buffer, 0x1002);
if ( res < 0 ) {
fprintf(stderr,"$>sceAudiocodecDecode < 0< (%d) exitin \n", res);
eof = 1;
continue;
}
samplesdecoded = mp3_sample_per_frame;
donext-=1;
if (bc)
bc=0;
else
bc=1;
}
}
int InputThread(SceSize args, void *argp)
{
while(!eof)
{
sceCtrlPeekBufferPositive(&pad, 1);
if( pad.Buttons & PSP_CTRL_TRIANGLE )
{
eof=1;
}
sceKernelDelayThread(1);
}
return 0;
}
void SetupInput( void)
{
SceUID itid = sceKernelCreateThread("Input thread",
InputThread,
0x18, 256 * 1024, PSP_THREAD_ATTR_USER, 0);
if (itid >= 0)
sceKernelStartThread(itid, 0, 0);
}
int main(void)
{
SetupCallbacks();
eof=0;
int result = pspSdkLoadStartModule("flash0:/kd/me_for_vsh.prx", PSP_MEMORY_PARTITION_KERNEL);
fprintf(stderr,"$>me_for_vsh %d\n", result);
result = pspSdkLoadStartModule("flash0:/kd/videocodec.prx", PSP_MEMORY_PARTITION_KERNEL);
fprintf(stderr,"$>videocodec %d\n", result);
result = pspSdkLoadStartModule("flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL);
fprintf(stderr,"$>audiocodec %d\n", result);
result = pspSdkLoadStartModule("flash0:/kd/mpegbase.prx", PSP_MEMORY_PARTITION_KERNEL);
fprintf(stderr,"$>mpegbase %d\n", result);
result = pspSdkLoadStartModule("flash0:/kd/mpeg_vsh.prx", PSP_MEMORY_PARTITION_USER);
fprintf(stderr,"$>mpeg_vsh %d\n", result);
SetupInput();
pspSdkFixupImports(result);
sceMpegInit();
mp3_handle = sceIoOpen("ms0:/test.mp3", PSP_O_RDONLY, 0777);
if ( ! mp3_handle )
goto wait;
fprintf(stderr,"$>mp3_handle %d\n", mp3_handle);
mp3_channels = 2; //довольно некрасивое ограничение, ну ладно нам для примера потянет....
mp3_samplerate = 44100; //таже фигня
mp3_sample_per_frame = 1152;
mp3_data_start = sceIoLseek32(mp3_handle, 0, PSP_SEEK_CUR);
memset(mp3_codec_buffer, 0, sizeof(mp3_codec_buffer));
if ( sceAudiocodeCheckNeedMem(mp3_codec_buffer, 0x1002) < 0 )
{
fprintf(stderr,"$>sceAudiocodeCheckNeedMem <0 going to wait \n");
goto wait;
}
if ( sceAudiocodecGetEDRAM(mp3_codec_buffer, 0x1002) < 0 )
{
fprintf(stderr,"$>sceAudiocodecGetEDRAM <0 going to wait \n");
goto wait;
}
mp3_getEDRAM = 1;
if ( sceAudiocodecInit(mp3_codec_buffer, 0x1002) < 0 ) {
fprintf(stderr,"$>sceAudiocodecInit <0 going to wait \n");
goto wait;
}
int channel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, 1152, PSP_AUDIO_FORMAT_STEREO);
if (channel < 0)
{
fprintf(stderr,"Error reserving channel\n");
goto wait;
}
bc=0;
donext=0;
int decodth = sceKernelCreateThread("decode thread", decode_thread, 0x8, 0x10000, PSP_THREAD_ATTR_USER, NULL);
if (decodth < 0)
{
fprintf(stderr, "failed create decode thread\n");
goto wait;
}
sceKernelStartThread(decodth, 0, 0);
fprintf(stderr, "decode thread %d\n", decodth);
donext=1;
while (!eof){
donext=1;
if (!bc)
sceAudioOutputBlocking(channel, 0x8000, mp3_mix_buffer1);
else
sceAudioOutputBlocking(channel, 0x8000, mp3_mix_buffer2);
}
wait:
if ( mp3_handle ) {
sceIoClose(mp3_handle);
}
if ( mp3_data_buffer) {
free(mp3_data_buffer);
}
if ( mp3_getEDRAM ) {
sceAudiocodecReleaseEDRAM(mp3_codec_buffer);
}
sceCtrlReadBufferPositive(&input, 1);
while(!(input.Buttons & PSP_CTRL_TRIANGLE))
{
sceKernelDelayThread(10000); // wait 10 milliseconds
sceCtrlReadBufferPositive(&input, 1);
}
sceKernelExitGame();
return 0;
}
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common)
{
sceKernelExitGame();
return 0;
}
/* Callback thread */
int CallbackThread(SceSize args, void *argp)
{
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void)
{
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
if(thid >= 0)
{
sceKernelStartThread(thid, 0, 0);
}
return thid;
} пусть оно и выглядит неказисто зато играет даже VBR. основано на примере с ps2dev, добавлено потоковое декодирование в два типа буфера.
#include <pspkernel.h>
#include <pspctrl.h>
#include <pspmpeg.h>
#include <pspdisplay.h>
#include <pspdebug.h>
#include <psppower.h>
#include <stdio.h>
#include <stdlib.h>
#include <pspkernel.h>
#include <pspctrl.h>
#include <psppower.h>
#include <pspdebug.h>
#include <psprtc.h>
#include <pspsdk.h>
#include <pspaudiocodec.h>
#include <pspaudio.h>
#include <string.h>
#include <malloc.h>
int SetupCallbacks();
PSP_MODULE_INFO("MP3 decodeTest", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(0);
__attribute__ ((constructor))
void loaderInit(){
pspKernelSetKernelPC();
pspSdkInstallNoDeviceCheckPatch();
pspSdkInstallNoPlainModuleCheckPatch();
pspSdkInstallKernelLoadModulePatch();
}
SceCtrlData input;
static int bitrates[] = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 };
unsigned long mp3_codec_buffer[65] __attribute__((aligned(64)));
short mp3_mix_buffer1[1152 * 2] __attribute__((aligned(64)));
short mp3_mix_buffer2[1152 * 2] __attribute__((aligned(64)));
SceUID mp3_handle;
u8* mp3_data_buffer;
u16 mp3_data_align;
u32 mp3_sample_per_frame;
u16 mp3_channel_mode;
u32 mp3_data_start;
u32 mp3_data_size;
u8 mp3_getEDRAM;
u32 mp3_channels;
u32 mp3_samplerate;
int donext, bc, eof;
SceCtrlData pad;
int decode_thread(SceSize args, void *argp)
{
eof = 0;
fprintf(stderr,"$>entering main loop\n");
while( !eof ) {
if (!donext)
{
sceKernelDelayThread(1);
continue;
}
int samplesdecoded;
if (!bc)
memset(mp3_mix_buffer1, 0, mp3_sample_per_frame*2*2);
else
memset(mp3_mix_buffer2, 0, mp3_sample_per_frame*2*2);
unsigned char mp3_header_buf[4];
if ( sceIoRead( mp3_handle, mp3_header_buf, 4 ) != 4 ) {
fprintf(stderr,"$>mp3_header_buf < 4 exitin \n");
eof = 1;
continue;
}
int mp3_header = mp3_header_buf[0];
mp3_header = (mp3_header<<8) | mp3_header_buf[1];
mp3_header = (mp3_header<<8) | mp3_header_buf[2];
mp3_header = (mp3_header<<8) | mp3_header_buf[3];
int bitrate = (mp3_header & 0xf000) >> 12;
int padding = (mp3_header & 0x200) >> 9;
int frame_size = 144000*bitrates[bitrate]/mp3_samplerate + padding;
if ( mp3_data_buffer )
free(mp3_data_buffer);
mp3_data_buffer = (u8*)memalign(64, frame_size);
sceIoLseek32(mp3_handle, mp3_data_start, PSP_SEEK_SET); //seek back
if ( sceIoRead( mp3_handle, mp3_data_buffer, frame_size ) != frame_size ) {
fprintf(stderr,"$>sceIoRead frame_size < frame_size exitin \n");
eof = 1;
continue;
}
mp3_data_start += frame_size;
mp3_codec_buffer[6] = (unsigned long)mp3_data_buffer;
if (!bc)
mp3_codec_buffer[8] = (unsigned long)mp3_mix_buffer1;
else
mp3_codec_buffer[8] = (unsigned long)mp3_mix_buffer2;
mp3_codec_buffer[7] = mp3_codec_buffer[10] = frame_size;
mp3_codec_buffer[9] = mp3_sample_per_frame * 4;
int res = sceAudiocodecDecode(mp3_codec_buffer, 0x1002);
if ( res < 0 ) {
fprintf(stderr,"$>sceAudiocodecDecode < 0< (%d) exitin \n", res);
eof = 1;
continue;
}
samplesdecoded = mp3_sample_per_frame;
donext-=1;
if (bc)
bc=0;
else
bc=1;
}
}
int InputThread(SceSize args, void *argp)
{
while(!eof)
{
sceCtrlPeekBufferPositive(&pad, 1);
if( pad.Buttons & PSP_CTRL_TRIANGLE )
{
eof=1;
}
sceKernelDelayThread(1);
}
return 0;
}
void SetupInput( void)
{
SceUID itid = sceKernelCreateThread("Input thread",
InputThread,
0x18, 256 * 1024, PSP_THREAD_ATTR_USER, 0);
if (itid >= 0)
sceKernelStartThread(itid, 0, 0);
}
int main(void)
{
SetupCallbacks();
eof=0;
int result = pspSdkLoadStartModule("flash0:/kd/me_for_vsh.prx", PSP_MEMORY_PARTITION_KERNEL);
fprintf(stderr,"$>me_for_vsh %d\n", result);
result = pspSdkLoadStartModule("flash0:/kd/videocodec.prx", PSP_MEMORY_PARTITION_KERNEL);
fprintf(stderr,"$>videocodec %d\n", result);
result = pspSdkLoadStartModule("flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL);
fprintf(stderr,"$>audiocodec %d\n", result);
result = pspSdkLoadStartModule("flash0:/kd/mpegbase.prx", PSP_MEMORY_PARTITION_KERNEL);
fprintf(stderr,"$>mpegbase %d\n", result);
result = pspSdkLoadStartModule("flash0:/kd/mpeg_vsh.prx", PSP_MEMORY_PARTITION_USER);
fprintf(stderr,"$>mpeg_vsh %d\n", result);
SetupInput();
pspSdkFixupImports(result);
sceMpegInit();
mp3_handle = sceIoOpen("ms0:/test.mp3", PSP_O_RDONLY, 0777);
if ( ! mp3_handle )
goto wait;
fprintf(stderr,"$>mp3_handle %d\n", mp3_handle);
mp3_channels = 2; //довольно некрасивое ограничение, ну ладно нам для примера потянет....
mp3_samplerate = 44100; //таже фигня
mp3_sample_per_frame = 1152;
mp3_data_start = sceIoLseek32(mp3_handle, 0, PSP_SEEK_CUR);
memset(mp3_codec_buffer, 0, sizeof(mp3_codec_buffer));
if ( sceAudiocodeCheckNeedMem(mp3_codec_buffer, 0x1002) < 0 )
{
fprintf(stderr,"$>sceAudiocodeCheckNeedMem <0 going to wait \n");
goto wait;
}
if ( sceAudiocodecGetEDRAM(mp3_codec_buffer, 0x1002) < 0 )
{
fprintf(stderr,"$>sceAudiocodecGetEDRAM <0 going to wait \n");
goto wait;
}
mp3_getEDRAM = 1;
if ( sceAudiocodecInit(mp3_codec_buffer, 0x1002) < 0 ) {
fprintf(stderr,"$>sceAudiocodecInit <0 going to wait \n");
goto wait;
}
int channel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, 1152, PSP_AUDIO_FORMAT_STEREO);
if (channel < 0)
{
fprintf(stderr,"Error reserving channel\n");
goto wait;
}
bc=0;
donext=0;
int decodth = sceKernelCreateThread("decode thread", decode_thread, 0x8, 0x10000, PSP_THREAD_ATTR_USER, NULL);
if (decodth < 0)
{
fprintf(stderr, "failed create decode thread\n");
goto wait;
}
sceKernelStartThread(decodth, 0, 0);
fprintf(stderr, "decode thread %d\n", decodth);
donext=1;
while (!eof){
donext=1;
if (!bc)
sceAudioOutputBlocking(channel, 0x8000, mp3_mix_buffer1);
else
sceAudioOutputBlocking(channel, 0x8000, mp3_mix_buffer2);
}
wait:
if ( mp3_handle ) {
sceIoClose(mp3_handle);
}
if ( mp3_data_buffer) {
free(mp3_data_buffer);
}
if ( mp3_getEDRAM ) {
sceAudiocodecReleaseEDRAM(mp3_codec_buffer);
}
sceCtrlReadBufferPositive(&input, 1);
while(!(input.Buttons & PSP_CTRL_TRIANGLE))
{
sceKernelDelayThread(10000); // wait 10 milliseconds
sceCtrlReadBufferPositive(&input, 1);
}
sceKernelExitGame();
return 0;
}
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common)
{
sceKernelExitGame();
return 0;
}
/* Callback thread */
int CallbackThread(SceSize args, void *argp)
{
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void)
{
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
if(thid >= 0)
{
sceKernelStartThread(thid, 0, 0);
}
return thid;
} пусть оно и выглядит неказисто зато играет даже VBR. основано на примере с ps2dev, добавлено потоковое декодирование в два типа буфера.