 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
cooleyes
Joined: 18 May 2006 Posts: 125
|
Posted: Thu May 17, 2007 7:33 pm Post subject: now,we can use libaudiocodec to decode atrac3 and atrac3plus |
|
|
hi, all
I just found out how to decode atrac3 and atrac3plus using libaudiocodec now!
here is some sample code for decode atrac3 and atrac3plus in AT3 or AA3 file:
AT3 file decode
| Code: |
#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>
int SetupCallbacks();
PSP_MODULE_INFO("AT3 decodeTest", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(0);
__attribute__ ((constructor))
void loaderInit(){
pspKernelSetKernelPC();
pspSdkInstallNoDeviceCheckPatch();
pspSdkInstallNoPlainModuleCheckPatch();
pspSdkInstallKernelLoadModulePatch();
}
SceCtrlData input;
#define TYPE_ATRAC3 0x270
#define TYPE_ATRAC3PLUS 0xFFFE
unsigned long at3_codec_buffer[65] __attribute__((aligned(64)));
short at3_mix_buffer[2048 * 2] __attribute__((aligned(64)));
SceUID at3_handle;
u16 at3_type;
u8* at3_data_buffer;
u16 at3_data_align;
u32 at3_sample_per_frame;
u16 at3_channel_mode;
u8 at3_at3plus_flagdata[2];
u32 at3_data_start;
u32 at3_data_size;
u8 at3_getEDRAM;
u32 at3_channels;
u32 at3_samplerate;
int main(void)
{
SetupCallbacks();
int result = pspSdkLoadStartModule("flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL);
pspSdkFixupImports(result);
SceUID at3_handle = sceIoOpen("ms0:/Test.AT3", PSP_O_RDONLY, 0777);
if ( ! at3_handle )
goto wait;
u32 riff_header[2];
if ( sceIoRead( at3_handle, riff_header, 8 ) != 8 )
goto wait;
if ( riff_header[0] != 0x46464952 )
goto wait;
u32 wavefmt_header[3];
if ( sceIoRead( at3_handle, wavefmt_header, 12 ) != 12 )
goto wait;
if ( wavefmt_header[0] != 0x45564157 || wavefmt_header[1] != 0x20746D66 )
goto wait;
u8* wavefmt_data = (u8*)malloc(wavefmt_header[2]);
if ( wavefmt_data == NULL )
goto wait;
if ( sceIoRead( at3_handle, wavefmt_data, wavefmt_header[2] ) != wavefmt_header[2] ) {
free(wavefmt_data);
goto wait;
}
at3_type = *((u16*)wavefmt_data);
at3_channels = *((u16*)(wavefmt_data+2));
at3_samplerate = *((u32*)(wavefmt_data+4));
at3_data_align = *((u16*)(wavefmt_data+12));
if ( at3_type == TYPE_ATRAC3PLUS) {
at3_at3plus_flagdata[0] = wavefmt_data[42];
at3_at3plus_flagdata[1] = wavefmt_data[43];
}
free(wavefmt_data);
u32 data_header[2];
if ( sceIoRead( at3_handle, data_header, 8 ) != 8 )
goto wait;
while(data_header[0] != 0x61746164 ) {
sceIoLseek32(at3_handle, data_header[1], PSP_SEEK_CUR);
if ( sceIoRead( at3_handle, data_header, 8 ) != 8 )
goto wait;
}
at3_data_start = sceIoLseek32(at3_handle, 0, PSP_SEEK_CUR);
at3_data_size = data_header[1];
if ( at3_data_size % at3_data_align != 0 )
goto wait;
memset(at3_codec_buffer, 0, sizeof(at3_codec_buffer));
if ( at3_type == TYPE_ATRAC3 ) {
at3_channel_mode = 0x0;
if ( at3_data_align == 0xC0 ) // atract3 have 3 bitrate, 132k,105k,66k, 132k align=0x180, 105k align = 0x130, 66k align = 0xc0
at3_channel_mode = 0x1;
at3_sample_per_frame = 1024;
at3_data_buffer = (u8*)memalign(64, 0x180);
if ( at3_data_buffer == NULL)
goto wait;
at3_codec_buffer[26] = 0x20;
if ( sceAudiocodecCheckNeedMem(at3_codec_buffer, 0x1001) < 0 )
goto wait;
if ( sceAudiocodecGetEDRAM(at3_codec_buffer, 0x1001) < 0 )
goto wait;
at3_getEDRAM = 1;
at3_codec_buffer[10] = 4;
at3_codec_buffer[44] = 2;
if ( at3_data_align == 0x130 )
at3_codec_buffer[10] = 6;
if ( sceAudiocodecInit(at3_codec_buffer, 0x1001) < 0 ) {
goto wait;
}
}
else if ( at3_type == TYPE_ATRAC3PLUS ) {
at3_sample_per_frame = 2048;
int temp_size = at3_data_align+8;
int mod_64 = temp_size & 0x3f;
if (mod_64 != 0) temp_size += 64 - mod_64;
at3_data_buffer = (u8*)memalign(64, temp_size);
if ( at3_data_buffer == NULL)
goto wait;
at3_codec_buffer[5] = 0x1;
at3_codec_buffer[10] = at3_at3plus_flagdata[1];
at3_codec_buffer[10] = (at3_codec_buffer[10] << 8 ) | at3_at3plus_flagdata[0];
at3_codec_buffer[12] = 0x1;
at3_codec_buffer[14] = 0x1;
if ( sceAudiocodecCheckNeedMem(at3_codec_buffer, 0x1000) < 0 )
goto wait;
if ( sceAudiocodecGetEDRAM(at3_codec_buffer, 0x1000) < 0 )
goto wait;
at3_getEDRAM = 1;
if ( sceAudiocodecInit(at3_codec_buffer, 0x1000) < 0 ) {
goto wait;
}
}
else
goto wait;
int eof = 0;
while( !eof ) {
int samplesdecoded;
memset(at3_mix_buffer, 0, 2048*2*2);
unsigned long decode_type = 0x1001;
if ( at3_type == TYPE_ATRAC3 ) {
memset( at3_data_buffer, 0, 0x180);
if (sceIoRead( at3_handle, at3_data_buffer, at3_data_align ) != at3_data_align) {
eof = 1;
continue;
}
if ( at3_channel_mode ) {
memcpy(at3_data_buffer+at3_data_align, at3_data_buffer, at3_data_align);
}
decode_type = 0x1001;
}
else {
memset( at3_data_buffer, 0, at3_data_align+8);
at3_data_buffer[0] = 0x0F;
at3_data_buffer[1] = 0xD0;
at3_data_buffer[2] = at3_at3plus_flagdata[0];
at3_data_buffer[3] = at3_at3plus_flagdata[1];
if (sceIoRead( at3_handle, at3_data_buffer+8, at3_data_align ) != at3_data_align) {
eof = 1;
continue;
}
decode_type = 0x1000;
}
at3_codec_buffer[6] = (unsigned long)at3_data_buffer;
at3_codec_buffer[8] = (unsigned long)at3_mix_buffer;
int res = sceAudiocodecDecode(at3_codec_buffer, decode_type);
if ( res < 0 ) {
eof = 1;
continue;
}
samplesdecoded = at3_sample_per_frame;
}
wait:
if ( at3_handle ) {
sceIoClose(at3_handle);
}
if ( at3_data_buffer) {
free(at3_data_buffer);
}
if ( at3_getEDRAM ) {
sceAudiocodecReleaseEDRAM(at3_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;
}
|
AA3 file decode:
| Code: |
#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>
int SetupCallbacks();
PSP_MODULE_INFO("AA3 decodeTest", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(0);
__attribute__ ((constructor))
void loaderInit(){
pspKernelSetKernelPC();
pspSdkInstallNoDeviceCheckPatch();
pspSdkInstallNoPlainModuleCheckPatch();
pspSdkInstallKernelLoadModulePatch();
}
SceCtrlData input;
#define TYPE_ATRAC3 0x270
#define TYPE_ATRAC3PLUS 0xFFFE
unsigned long aa3_codec_buffer[65] __attribute__((aligned(64)));
short aa3_mix_buffer[2048 * 2] __attribute__((aligned(64)));
SceUID aa3_handle;
u16 aa3_type;
u8* aa3_data_buffer;
u16 aa3_data_align;
u32 aa3_sample_per_frame;
u16 aa3_channel_mode;
u8 aa3_at3plus_flagdata[2];
u32 aa3_data_start;
u32 aa3_data_size;
u8 aa3_getEDRAM;
u32 aa3_channels;
u32 aa3_samplerate;
int main(void)
{
SetupCallbacks();
int result = pspSdkLoadStartModule("flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL);
pspSdkFixupImports(result);
SceUID aa3_handle = sceIoOpen("ms0:/Test.AA3", PSP_O_RDONLY, 0777); // or ms0:/Test.OMA
if ( ! aa3_handle )
goto wait;
sceIoLseek32(aa3_handle, 0x0C00, PSP_SEEK_SET);
u8 ea3_header[0x60];
if ( sceIoRead( aa3_handle, ea3_header, 0x60 ) != 0x60 )
goto wait;
if ( ea3_header[0] != 0x45 || ea3_header[1] != 0x41 || ea3_header[2] != 0x33 || ea3_header[3] != 0x01 )
goto wait;
aa3_at3plus_flagdata[0] = ea3_header[0x22];
aa3_at3plus_flagdata[1] = ea3_header[0x23];
aa3_type = (ea3_header[0x22] == 0x20) ? TYPE_ATRAC3 : ((ea3_header[0x22] == 0x28) ? TYPE_ATRAC3PLUS : 0x0);
if ( aa3_type != TYPE_ATRAC3 && aa3_type != TYPE_ATRAC3PLUS )
goto wait;
aa3_channels = 2;
aa3_samplerate = 44100;
if ( aa3_type == TYPE_ATRAC3 )
aa3_data_align = ea3_header[0x23]*8;
else
aa3_data_align = (ea3_header[0x23]+1)*8;
aa3_data_start = 0x0C60;
aa3_data_size = sceIoLseek32(aa3_handle, 0, PSP_SEEK_END) - aa3_data_start;
if ( aa3_data_size % aa3_data_align != 0 )
goto wait;
sceIoLseek32(aa3_handle, aa3_data_start, PSP_SEEK_SET);
memset(aa3_codec_buffer, 0, sizeof(aa3_codec_buffer));
if ( aa3_type == TYPE_ATRAC3 ) {
aa3_channel_mode = 0x0;
if ( aa3_data_align == 0xC0 ) // atract3 have 3 bitrate, 132k,105k,66k, 132k align=0x180, 105k align = 0x130, 66k align = 0xc0
aa3_channel_mode = 0x1;
aa3_sample_per_frame = 1024;
aa3_data_buffer = (u8*)memalign(64, 0x180);
if ( aa3_data_buffer == NULL)
goto wait;
aa3_codec_buffer[26] = 0x20;
if ( sceAudiocodecCheckNeedMem(aa3_codec_buffer, 0x1001) < 0 )
goto wait;
if ( sceAudiocodecGetEDRAM(aa3_codec_buffer, 0x1001) < 0 )
goto wait;
aa3_getEDRAM = 1;
aa3_codec_buffer[10] = 4;
aa3_codec_buffer[44] = 2;
if ( aa3_data_align == 0x130 )
aa3_codec_buffer[10] = 6;
if ( sceAudiocodecInit(aa3_codec_buffer, 0x1001) < 0 ) {
goto wait;
}
}
else if ( aa3_type == TYPE_ATRAC3PLUS ) {
aa3_sample_per_frame = 2048;
int temp_size = aa3_data_align+8;
int mod_64 = temp_size & 0x3f;
if (mod_64 != 0) temp_size += 64 - mod_64;
aa3_data_buffer = (u8*)memalign(64, temp_size);
if ( aa3_data_buffer == NULL)
goto wait;
aa3_codec_buffer[5] = 0x1;
aa3_codec_buffer[10] = aa3_at3plus_flagdata[1];
aa3_codec_buffer[10] = (aa3_codec_buffer[10] << 8 ) | aa3_at3plus_flagdata[0];
aa3_codec_buffer[12] = 0x1;
aa3_codec_buffer[14] = 0x1;
if ( sceAudiocodecCheckNeedMem(aa3_codec_buffer, 0x1000) < 0 )
goto wait;
if ( sceAudiocodecGetEDRAM(aa3_codec_buffer, 0x1000) < 0 )
goto wait;
aa3_getEDRAM = 1;
if ( sceAudiocodecInit(aa3_codec_buffer, 0x1000) < 0 ) {
goto wait;
}
}
else
goto wait;
int eof = 0;
while( !eof ) {
int samplesdecoded;
memset(aa3_mix_buffer, 0, 2048*2*2);
unsigned long decode_type = 0x1001;
if ( aa3_type == TYPE_ATRAC3 ) {
memset( aa3_data_buffer, 0, 0x180);
if (sceIoRead( aa3_handle, aa3_data_buffer, aa3_data_align ) != aa3_data_align) {
eof = 1;
continue;
}
if ( aa3_channel_mode ) {
memcpy(aa3_data_buffer+aa3_data_align, aa3_data_buffer, aa3_data_align);
}
decode_type = 0x1001;
}
else {
memset( aa3_data_buffer, 0, aa3_data_align+8);
aa3_data_buffer[0] = 0x0F;
aa3_data_buffer[1] = 0xD0;
aa3_data_buffer[2] = aa3_at3plus_flagdata[0];
aa3_data_buffer[3] = aa3_at3plus_flagdata[1];
if (sceIoRead( aa3_handle, aa3_data_buffer+8, aa3_data_align ) != aa3_data_align) {
eof = 1;
continue;
}
decode_type = 0x1000;
}
aa3_codec_buffer[6] = (unsigned long)aa3_data_buffer;
aa3_codec_buffer[8] = (unsigned long)aa3_mix_buffer;
int res = sceAudiocodecDecode(aa3_codec_buffer, decode_type);
if ( res < 0 ) {
eof = 1;
continue;
}
samplesdecoded = aa3_sample_per_frame;
}
wait:
if ( aa3_handle ) {
sceIoClose(aa3_handle);
}
if ( aa3_data_buffer) {
free(aa3_data_buffer);
}
if ( aa3_getEDRAM ) {
sceAudiocodecReleaseEDRAM(aa3_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;
}
|
ps :
thanks for hitchhikr's help,
he is the first one who found out how to use libaudiocodec to decode 132k atrac3. |
|
| Back to top |
|
 |
jockyw2001
Joined: 29 Sep 2005 Posts: 339
|
Posted: Thu May 17, 2007 10:05 pm Post subject: |
|
|
Very cool :)
I wonder if MP3 decoding can be done similar? |
|
| Back to top |
|
 |
cooleyes
Joined: 18 May 2006 Posts: 125
|
Posted: Thu May 17, 2007 10:20 pm Post subject: |
|
|
| jockyw2001 wrote: | Very cool :)
I wonder if MP3 decoding can be done similar? |
I am trying to find out how to decode MP3 and AAC,
but I need some time to do this. |
|
| Back to top |
|
 |
Insert_witty_name
Joined: 10 May 2006 Posts: 376
|
Posted: Thu May 17, 2007 10:23 pm Post subject: |
|
|
Excellent, another format down.
MP3 should be possible, I've tried it myself but to no avail.
Maybe that's cooleyes next step? |
|
| Back to top |
|
 |
danzel
Joined: 04 Nov 2005 Posts: 182
|
Posted: Fri May 18, 2007 6:26 am Post subject: |
|
|
| Awesome stuff :D |
|
| Back to top |
|
 |
dr_watson
Joined: 28 Nov 2005 Posts: 42
|
Posted: Sat May 19, 2007 11:41 pm Post subject: |
|
|
| Wow! This is really nice! Excellent work! |
|
| Back to top |
|
 |
Cpasjuste
Joined: 29 May 2005 Posts: 214
|
Posted: Sun May 20, 2007 8:04 am Post subject: |
|
|
| Yup, thanks for the work guys, i will probably test this in my app :) |
|
| Back to top |
|
 |
SamuraiX
Joined: 31 Jan 2006 Posts: 76 Location: USA
|
Posted: Mon May 21, 2007 3:02 am Post subject: |
|
|
| Nice one! I could definately use this in my applications. Perhaps this should be added to the SDK audio samples unless my view is out of date then I should update ;p |
|
| Back to top |
|
 |
Brunni
Joined: 08 Oct 2005 Posts: 186
|
Posted: Tue May 22, 2007 3:06 am Post subject: |
|
|
Cool :)
But does this always need KERNEL mode? I'm wondering how official games do :/ _________________ Sorry for my bad english
Oldschool library for PSP - PC version released |
|
| Back to top |
|
 |
Insert_witty_name
Joined: 10 May 2006 Posts: 376
|
Posted: Tue May 22, 2007 7:30 am Post subject: |
|
|
It needs kernel mode.
Official games load the PRX from the game disc, not flash if I recall correctly. |
|
| Back to top |
|
 |
Vincent_M
Joined: 03 Apr 2007 Posts: 73
|
Posted: Thu May 24, 2007 4:23 am Post subject: |
|
|
| Now, how do we play/stream the file? I'm a bit new to audio/video streaming atm. Now that the file is decoded, where do we go from here? Just curious, really... |
|
| Back to top |
|
 |
ACh
Joined: 03 Jun 2007 Posts: 3
|
Posted: Mon Jun 04, 2007 1:25 am Post subject: |
|
|
If you're targeting 3.xx firmware, you should be able to use sceUtilityLoadAvModule() to get at the audio/video decoders from user mode. I personally avoid ATRAC3, but here's how I set up for AVC decoding to work on both 1.50 (psplink) and 3.40 OE-A:
| Code: | int loadav_ok = 0;
int32_t firmware_version = sceKernelDevkitVersion();
if (firmware_version >= 0x02070000) {
loadav_ok = 1;
res = sceUtilityLoadAvModule(0);
if (res < 0) {
loadav_ok = 0;
}
if (loadav_ok) {
res = sceUtilityLoadAvModule(3);
if (res < 0) {
sceUtilityUnloadAvModule(0);
loadav_ok = 0;
}
}
}
if (!loadav_ok) {
res = load_start_module("flash0:/kd/audiocodec.prx", PSP_MEMORY_PARTITION_KERNEL);
if (res < 0 && res != SCE_KERNEL_ERROR_EXCLUSIVE_LOAD) {
return NULL;
}
res = load_start_module("flash0:/kd/videocodec.prx", PSP_MEMORY_PARTITION_KERNEL);
if (res < 0 && res != SCE_KERNEL_ERROR_EXCLUSIVE_LOAD) {
return NULL;
}
res = load_start_module("flash0:/kd/mpegbase.prx", PSP_MEMORY_PARTITION_KERNEL);
if (res < 0 && res != SCE_KERNEL_ERROR_EXCLUSIVE_LOAD) {
return NULL;
}
res = load_start_module("flash0:/kd/mpeg_vsh.prx", PSP_MEMORY_PARTITION_USER);
if (res < 0 && res != SCE_KERNEL_ERROR_EXCLUSIVE_LOAD) {
return NULL;
}
} |
(Note--load_start_module() is an internal routine of mine that loads and starts the given module; it's essentially a streamlined version of pspSdkLoadStartModule(), but the latter should work just as well.) |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|