#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <pspdisplay.h>
#include <pspaudio.h>
#include <pspaudiolib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define PSPSAMPLERATE 44100
PSP_MODULE_INFO("WAV Player",0,1,1);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
int exit_callback(int arg1, int arg2, void *common)
{
sceKernelExitGame();
return 0;
}
int CallbackThread(SceSize args, void *argp)
{
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
int SetupCallbacks(void)
{
int thid = 0;
thid=sceKernelCreateThread("update_thread",CallbackThread,0x11,0xFA0,0,0);
if (thid >= 0)
{
sceKernelStartThread(thid,0,0);
}
return thid;
}
short* data;
int dataLength=0,fmtSize=0,dataPos=0,sigBytes=0,numChannels=0,sampleRate=0,BPS=0,dataLocation=0;
int pause=0;
SceCtrlData pad,lastPad;
FILE* f;
void Seek(int time)
{
dataPos=(int)(time*BPS);
fseek(f,dataPos+dataLocation,SEEK_SET);
}
void updateAudio(void* buf, unsigned int length, void *userdata)
{
int i;
short* mbuf=(short*)buf;
if (pause)
{
for(i=0;i<2*length;i++) mbuf[i]=0;
return;
}
if ((dataPos+numChannels*length)>(dataLength)) sceKernelExitGame();
for(i=0;i<length;i++)
{
mbuf[2*i]=data[numChannels*(int)(i*sampleRate/PSPSAMPLERATE)];
mbuf[2*i+1]=data[numChannels*(int)(i*sampleRate/PSPSAMPLERATE)+((numChannels==2)?1:0)];
}
dataPos+=(length*sigBytes*numChannels*sampleRate/PSPSAMPLERATE);
fread((char*)data,1,length*sigBytes*numChannels*sampleRate/PSPSAMPLERATE,f);
pspDebugScreenSetXY(0,14);
pspDebugScreenPrintf("Time: %i / %i \n",(int)(dataPos/BPS),(int)(dataLength/BPS));
}
int main(void)
{
pspDebugScreenInit();
pspAudioInit();
SetupCallbacks();
int chunksRead=0;
char c[5];
c[4]='\0';
int* i=(int*) malloc(sizeof(int));
f=fopen("./testcase.wav","r");
fread(c,1,4,f);
if (strcmp(c,"RIFF"))
sceKernelExitGame();
else
pspDebugScreenPrintf("'RIFF' Header\n");
fread((char*)i,1,4,f);
pspDebugScreenPrintf("Size: %i Bytes\n",*i);
fread(c,1,4,f);
if (strcmp(c,"WAVE"))
sceKernelExitGame();
else
pspDebugScreenPrintf("RIFF Type: %s\n",c);
while(chunksRead<2)
{
fread(c,1,4,f);
if (!strcmp(c,"fmt "))
{
pspDebugScreenPrintf("'fmt ' Header\n");
fread((char*)i,1,4,f);
pspDebugScreenPrintf("Size: %i Bytes\n",*i);
fmtSize=*i;
*i=0;
fread((char*)i,1,2,f);
if ((*i!=0) && (*i!=1))
sceKernelExitGame();
pspDebugScreenPrintf("Compression Code: %i\n",*i);
*i=0;
fread((char*)i,1,2,f);
pspDebugScreenPrintf("Channels: %i\n",*i);
numChannels=*i;
fread((char*)i,1,4,f);
pspDebugScreenPrintf("Sample Rate: %i\n",*i);
sampleRate=*i;
fread((char*)i,1,4,f);
pspDebugScreenPrintf("Bytes Per Second: %i\n",*i);
BPS=*i;
*i=0;
fread((char*)i,1,2,f);
pspDebugScreenPrintf("Block Align: %i\n",*i);
*i=0;
fread((char*)i,1,2,f);
pspDebugScreenPrintf("Significant Bits Per Sample: %i\n",*i);
sigBytes=*i>>3;
fread(c,1,fmtSize-16,f);
chunksRead++;
continue;
}
if (!strcmp(c,"data"))
{
if (chunksRead==0)
sceKernelExitGame();
pspDebugScreenPrintf("'data' Header\n");
fread((char*)i,1,4,f);
dataLength=*i;
dataLocation=ftell(f);
pspDebugScreenPrintf("Size: %i",dataLength);
data=(short*) malloc(1024*sigBytes*numChannels*sampleRate/PSPSAMPLERATE);
fread((char*)data,1,1024*sigBytes*numChannels*sampleRate/PSPSAMPLERATE,f);
chunksRead++;
continue;
}
fread((char*)i,1,4,f);
fread(c,1,*i,f);
}
pspAudioSetChannelCallback(0,updateAudio,NULL);
while(1)
{
sceCtrlReadBufferPositive(&pad,1);
if((pad.Buttons&PSP_CTRL_SQUARE)&&(!(lastPad.Buttons&PSP_CTRL_SQUARE))) Seek(10);
if((pad.Buttons&PSP_CTRL_START)&&(!(lastPad.Buttons&PSP_CTRL_START))) pause=!pause;
lastPad=pad;
}
return 0;
}