Upss then I'm so sorry DookFook :( I thought it was like saying the code was very bad or something similar. My apologize. Thank you ufoz for telling me, you don't go to bed without knowing something else.
It's up to us to make this thing sound. Thank you I don't know if I'll be able to play it but thank you ;).
now,we can use libaudiocodec to decode mp3 and aac
new demo code, it can play ms0:/Test.mp3
Makefile
Code: Select all
#include <pspkernel.h>
#include <pspctrl.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>
#include <pspmpeg.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_buffer[1152 * 2] __attribute__((aligned(64)));
short mp3_output_buffer[4][1152 * 2] __attribute__((aligned(64)));
int mp3_output_index = 0;
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 main(void)
{
SetupCallbacks();
int result = pspSdkLoadStartModule("flash0:/kd/me_for_vsh.prx", PSP_MEMORY_PARTITION_KERNEL);
result = pspSdkLoadStartModule("flash0:/kd/videocodec.prx", PSP_MEMORY_PARTITION_KERNEL);
result = pspSdkLoadStartModule("flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL);
result = pspSdkLoadStartModule("flash0:/kd/mpegbase.prx", PSP_MEMORY_PARTITION_KERNEL);
result = pspSdkLoadStartModule("flash0:/kd/mpeg_vsh.prx", PSP_MEMORY_PARTITION_USER);
pspSdkFixupImports(result);
sceMpegInit();
mp3_handle = sceIoOpen("ms0:/Test.MP3", PSP_O_RDONLY, 0777);
if ( ! mp3_handle )
goto wait;
mp3_channels = 2;
mp3_samplerate = 44100; //this is mp3 file's samplerate, also can be 48000,....
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 ( sceAudiocodecCheckNeedMem(mp3_codec_buffer, 0x1002) < 0 )
goto wait;
if ( sceAudiocodecGetEDRAM(mp3_codec_buffer, 0x1002) < 0 )
goto wait;
mp3_getEDRAM = 1;
if ( sceAudiocodecInit(mp3_codec_buffer, 0x1002) < 0 ) {
goto wait;
}
int audio_channel = sceAudioChReserve(0, mp3_sample_per_frame , PSP_AUDIO_FORMAT_STEREO);
int eof = 0;
while( !eof ) {
int samplesdecoded;
memset(mp3_mix_buffer, 0, mp3_sample_per_frame*2*2);
unsigned char mp3_header_buf[4];
if ( sceIoRead( mp3_handle, mp3_header_buf, 4 ) != 4 ) {
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 ) {
eof = 1;
continue;
}
mp3_data_start += frame_size;
mp3_codec_buffer[6] = (unsigned long)mp3_data_buffer;
mp3_codec_buffer[8] = (unsigned long)mp3_mix_buffer;
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 ) {
eof = 1;
continue;
}
memcpy(mp3_output_buffer[mp3_output_index], mp3_mix_buffer, 1152*4);
sceAudioOutputBlocking(audio_channel, PSP_AUDIO_VOLUME_MAX, mp3_output_buffer[mp3_output_index]);
mp3_output_index = (mp3_output_index+1)%4;
samplesdecoded = mp3_sample_per_frame;
}
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;
}
Code: Select all
TARGET = mp3decoderdemo
OBJS = main.o
CFLAGS = -G0 -Wall -O2
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LIBDIR =
LDFLAGS =
LIBS= -lpsppower -lpspmpeg -lpspaudiocodec -lpspaudio -lm
EXTRA_TARGETS = EBOOT.PBP SCEkxploit
PSP_EBOOT_TITLE = mp3 decoder demo
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
Thank you very much! I've done a driver for the OldSchool Library (currently mp3 only). It's composed from simple functions such as init, load file, play, decode, etc. The rest is identical to a normal wave output.
Code: Select all
#include "oslib.h"
#include <pspaudiocodec.h>
#include <pspsdk.h>
typedef struct MP3_INFO {
VIRTUAL_FILE *handle;
unsigned long *codecBuffer;
u8* dataBuffer;
u32 channels;
u32 samplerate;
u32 sample_per_frame;
u32 data_start;
u32 data_start_init;
u8 getEDRAM;
//Codec specific
} MP3_INFO;
#define NUMBLOCKS 4
static int osl_at3Inited = 0, osl_mp3Inited = 0;
static int osl_at3Init() {
int result = 0;
if (!osl_at3Inited) {
int result = pspSdkLoadStartModule("flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL);
pspSdkFixupImports(result);
}
osl_at3Inited = 1;
return result;
}
static int osl_mp3Init() {
int result = 0;
if (!osl_mp3Inited) {
sceMpegInit();
result = pspSdkLoadStartModule("flash0:/kd/me_for_vsh.prx", PSP_MEMORY_PARTITION_KERNEL);
pspSdkFixupImports(result);
result = pspSdkLoadStartModule("flash0:/kd/videocodec.prx", PSP_MEMORY_PARTITION_KERNEL);
pspSdkFixupImports(result);
result = osl_at3Init();
result = pspSdkLoadStartModule("flash0:/kd/mpegbase.prx", PSP_MEMORY_PARTITION_KERNEL);
pspSdkFixupImports(result);
result = pspSdkLoadStartModule("flash0:/kd/mpeg_vsh.prx", PSP_MEMORY_PARTITION_USER);
pspSdkFixupImports(result);
}
osl_mp3Inited = 1;
return result;
}
static void osl_mp3DestroyInfo(MP3_INFO *info) {
if (info->codecBuffer)
free(info->codecBuffer);
if (info->dataBuffer)
free(info->dataBuffer);
if (info->handle)
VirtualFileClose(info->handle);
if (info->getEDRAM)
sceAudiocodecReleaseEDRAM(info->codecBuffer);
if (info->codecBuffer)
free(info->codecBuffer);
if (info)
free(info);
}
static MP3_INFO *osl_mp3CreateInfo() {
int success = 0;
MP3_INFO *info;
info = (MP3_INFO*)malloc(sizeof(MP3_INFO));
if (info) {
memset(info, 0, sizeof(MP3_INFO));
//Allocate memory for the codec param buffer
info->codecBuffer = memalign(64, 65 * sizeof(unsigned long));
if (info->codecBuffer) {
memset(info->codecBuffer, 0, sizeof(info->codecBuffer));
success = 1;
}
}
//Clean up if failed
if (!success) {
osl_mp3DestroyInfo(info);
info = NULL;
}
return info;
}
static int osl_mp3Load(const char *fileName, MP3_INFO *info) {
int success = 0;
//Try to load the file
info->handle = VirtualFileOpen((char*)fileName, 0, PSP_O_RDONLY, 0777);
if (info->handle) {
info->channels = 2;
info->samplerate = 44100; //this is mp3 file's samplerate, also can be 48000,....
info->sample_per_frame = 1152;
info->data_start_init = VirtualFileTell(info->handle);
//Initialize the codec
if (sceAudiocodecCheckNeedMem(info->codecBuffer, 0x1002) >= 0) {
if (sceAudiocodecGetEDRAM(info->codecBuffer, 0x1002) >= 0) {
info->getEDRAM = 1;
if (sceAudiocodecInit(info->codecBuffer, 0x1002) >= 0)
success = 1;
}
}
}
return success;
}
/*
Callbacks standard
*/
void oslAudioCallback_PlaySound_ME(OSL_SOUND *s) {
MP3_INFO *info = (MP3_INFO*)s->data;
info->data_start = info->data_start_init;
}
void oslAudioCallback_StopSound_ME(OSL_SOUND *s) {
//Do nothing
}
int oslAudioCallback_AudioCallback_ME(unsigned int i, void* buf, unsigned int length) {
static int bitrates[] = {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 };
int eof = 0;
MP3_INFO *info = (MP3_INFO*)osl_audioVoices[i].data;
unsigned long decode_type = 0x1002;
unsigned char mp3_header_buf[4];
if (VirtualFileRead(mp3_header_buf, 4, 1, info->handle) != 4) {
eof = 1;
goto end;
}
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]/info->samplerate + padding;
if (info->dataBuffer)
free(info->dataBuffer);
info->dataBuffer = (u8*)memalign(64, frame_size);
VirtualFileSeek(info->handle, info->data_start, PSP_SEEK_SET); //seek back
if ( VirtualFileRead(info->dataBuffer, frame_size, 1, info->handle) != frame_size) {
eof = 1;
goto end;
}
info->data_start += frame_size;
info->codecBuffer[7] = info->codecBuffer[10] = frame_size;
info->codecBuffer[9] = info->sample_per_frame * 4;
info->codecBuffer[6] = (unsigned long)info->dataBuffer;
info->codecBuffer[8] = (unsigned long)buf;
int res = sceAudiocodecDecode(info->codecBuffer, decode_type);
if ( res < 0 )
eof = 1;
end:
if (eof) {
// osl_mp3CleanUp();
//Efface le channel
return 0;
}
return 1;
}
VIRTUAL_FILE **oslAudioCallback_ReactiveSound_ME(OSL_SOUND *s, VIRTUAL_FILE *f) {
MP3_INFO *info = (MP3_INFO*)s->data;
VIRTUAL_FILE **w = &info->handle;
return w;
}
VIRTUAL_FILE *oslAudioCallback_StandBy_ME(OSL_SOUND *s) {
MP3_INFO *info = (MP3_INFO*)s->data;
return info->handle;
}
void oslAudioCallback_DeleteSound_ME(OSL_SOUND *s) {
osl_mp3DestroyInfo((MP3_INFO*)s->data);
s->data = NULL;
}
OSL_SOUND *oslLoadSoundFileMP3(const char *filename, int stream) {
OSL_SOUND *s = NULL;
MP3_INFO *info;
int success = 0;
//Mp3 must be streamed for now
if (!stream & OSL_FMT_STREAM)
return NULL;
osl_mp3Init();
s = (OSL_SOUND*)malloc(sizeof(OSL_SOUND));
if (s) {
//Never forget that! If any member is added to OSL_SOUND, it is assumed to be zero!
memset(s, 0, sizeof(OSL_SOUND));
//Allocate the size of a mp3 info structure
info = osl_mp3CreateInfo();
if (info) {
if (osl_mp3Load(filename, info)) {
s->data = (void*)info;
s->endCallback = NULL;
s->volumeLeft = s->volumeRight = OSL_VOLUME_MAX;
//No special format
s->format = 0;
//Always stereo output
s->mono = 0;
s->divider = OSL_FMT_44K;
//MP3 files are always streamed for now
s->isStreamed = 1;
s->numSamples = info->sample_per_frame;
s->audioCallback = oslAudioCallback_AudioCallback_ME;
s->playSound = oslAudioCallback_PlaySound_ME;
s->stopSound = oslAudioCallback_StopSound_ME;
s->standBySound = oslAudioCallback_StandBy_ME;
s->reactiveSound = oslAudioCallback_ReactiveSound_ME;
s->deleteSound = oslAudioCallback_DeleteSound_ME;
success = 1;
}
else {
osl_mp3DestroyInfo(info);
info = NULL;
}
}
}
if (!success) {
if (s)
free(s);
s = NULL;
}
if (!s)
oslHandleLoadNoFailError(filename);
return s;
}
Sorry for my bad english
Oldschool library for PSP - PC version released
Oldschool library for PSP - PC version released
Thank you cooleyes
First of all thank you for your effort cooleyes, you are not only a great programmer, but also a great guide!
I was looking the code inside PPA (¡¡¡it's incredible!!!), specifically inside mod folder where I have seen the code of cooleyes and trying to follow it to know which were the next steps to make it play, but I admit I'm still too newbee for moving inside all this hole thing without sinking in it.
I know that a sound file is composed of headers+"data of music" , this code of cooleyes transform (decode) that mp3 "data of music" to samples that can be given to another sce functions that can play them, but this is quite simple and a little far from the reality.
Do you now a website or pdf book where I can understand it or study in depth all this process and especially how relating it with c programming language?
I was looking the code inside PPA (¡¡¡it's incredible!!!), specifically inside mod folder where I have seen the code of cooleyes and trying to follow it to know which were the next steps to make it play, but I admit I'm still too newbee for moving inside all this hole thing without sinking in it.
I know that a sound file is composed of headers+"data of music" , this code of cooleyes transform (decode) that mp3 "data of music" to samples that can be given to another sce functions that can play them, but this is quite simple and a little far from the reality.
Do you now a website or pdf book where I can understand it or study in depth all this process and especially how relating it with c programming language?
Hi! :)
Is there a way I can find the frame duration to know how many seconds have been played (like libMad Header.duration)?
Many thanks. :)
EDIT:
I think I found it:
but the 36 value should not work with all mp3s (can be also 12 or 18).
Do someone knows ho to find the correct value?
Ciaooo
Sakya
Is there a way I can find the frame duration to know how many seconds have been played (like libMad Header.duration)?
Many thanks. :)
EDIT:
I think I found it:
Code: Select all
float duration = 32.0*36.0/(float)samplerate;
Do someone knows ho to find the correct value?
Ciaooo
Sakya