#include #include #include #include #include #include #include "vita_audio.h" static vitaWav vitaWavInfo[VITA_WAV_MAX_SLOTS]; static int vitaWavPlaying[VITA_WAV_MAX_SLOTS]; static int vitaWavId[VITA_WAV_MAX_SLOTS]; static short *vitaWavSamples; static unsigned long vitaWavReq; static int vitaWavIdFlag = 0; static int vitaWavInitFlag = 0; typedef struct { int threadHandle; int handle; int volumeLeft; int volumeRight; vitaAudioCallback callback; void *data; } vitaAudioChannelInfo; static int vitaAudioReady = 0; static short vitaAudioSoundBuffer[VITA_NUM_AUDIO_CHANNELS][2][VITA_NUM_AUDIO_SAMPLES][2]; static vitaAudioChannelInfo vitaAudioStatus[VITA_NUM_AUDIO_CHANNELS]; static volatile int vitaAudioTerminate = 0; void vitaAudioSetVolume(int channel, int left, int right) { vitaAudioStatus[channel].volumeLeft = left; vitaAudioStatus[channel].volumeRight = right; } int vitaAudioSetFrequency(int channel, unsigned short freq) { return sceAudioOutSetConfig(vitaAudioStatus[channel].handle, VITA_NUM_AUDIO_SAMPLES, freq, SCE_AUDIO_OUT_MODE_STEREO); } void vitaAudioSetChannelCallback(int channel, vitaAudioCallback callback, void *data) { volatile vitaAudioChannelInfo *pci = &vitaAudioStatus[channel]; if (callback == 0) pci->callback = 0; else { pci->callback = callback; } } static int vitaAudioOutBlocking(unsigned int channel, unsigned int left, unsigned int right, void *data) { if (!vitaAudioReady) return(-1); if (channel >= VITA_NUM_AUDIO_CHANNELS) return(-1); if (left > VITA_VOLUME_MAX) left = VITA_VOLUME_MAX; if (right > VITA_VOLUME_MAX) right = VITA_VOLUME_MAX; int vols2[2] = { left, right }; sceAudioOutSetVolume(vitaAudioStatus[channel].handle, SCE_AUDIO_VOLUME_FLAG_L_CH | SCE_AUDIO_VOLUME_FLAG_R_CH, vols2); return sceAudioOutOutput(vitaAudioStatus[channel].handle, data); } static int vitaAudioChannelThread(int args, void *argp) { volatile int bufidx = 0; int channel = *(int *) argp; while (vitaAudioTerminate == 0) { void *bufptr = &vitaAudioSoundBuffer[channel][bufidx]; vitaAudioCallback callback; callback = vitaAudioStatus[channel].callback; if (callback) { callback(bufptr, VITA_NUM_AUDIO_SAMPLES, vitaAudioStatus[channel].data); } else { unsigned int *ptr=bufptr; int i; for (i=0; iplayPtr_frac + wi->rateRatio; wi->playPtr = ptr = wi->playPtr + (frac>>16); wi->playPtr_frac = (frac & 0xffff); if(ptr >= wi->sampleCount) { if(wi->loop) { wi->playPtr = 0; wi->playPtr_frac = 0; ptr = 0; } else { vitaWavPlaying[slot] = 0; break; } } short *src16 = (short *)wi->data; unsigned char *src8 = (unsigned char *)wi->data; if(wi->channels == 1) { if(wi->bitPerSample == 8) { outl += (src8[ptr] * 256) - 32768; outr += (src8[ptr] * 256) - 32768; } else { outl += src16[ptr]; outr += src16[ptr]; } } else { if(wi->bitPerSample == 8) { outl += (src8[ptr*2] * 256) - 32768; outr += (src8[ptr*2+1] * 256) - 32768; } else { outl += src16[ptr*2]; outr += src16[ptr*2+1]; } } } if(outl < -32768) outl = -32768; else if (outl > 32767) outl = 32767; if(outr < -32768) outr = -32768; else if (outr > 32767) outr = 32767; *(buf++) = outl; *(buf++) = outr; } } int vitaWavInit(void) { int i; vitaAudioInit(0x40); vitaAudioSetChannelCallback(0, wavout_snd_callback, 0); for(i = 0; i < VITA_WAV_MAX_SLOTS; i++) vitaWavPlaying[i] = 0; vitaWavInitFlag = 1; return(1); } void vitaWavShutdown(void) { if(vitaWavInitFlag) vitaAudioShutdown(); } void vitaWavStop(vitaWav *wav) { int i; for(i = 0; i < VITA_WAV_MAX_SLOTS; i++) { if(wav->id == vitaWavId[i]) vitaWavPlaying[i] = 0; } } void vitaWavStopAll(void) { int i; for(i = 0; i < VITA_WAV_MAX_SLOTS; i++) vitaWavPlaying[i] = 0; } void vitaWavLoop(vitaWav *wav, unsigned int loop) { wav->loop = loop; } int vitaWavPlay(vitaWav *wav) { if(!vitaWavInitFlag) return(0); int i; vitaWav *wid; for(i = 0;i < VITA_WAV_MAX_SLOTS;i++) { if(vitaWavPlaying[i] == 0) break; } if(i == VITA_WAV_MAX_SLOTS) return(0); wid = &vitaWavInfo[i]; wid->channels = wav->channels; wid->sampleRate = wav->sampleRate; wid->sampleCount = wav->sampleCount; wid->dataLength = wav->dataLength; wid->data = wav->data; wid->rateRatio = wav->rateRatio; wid->playPtr = 0; wid->playPtr_frac = 0; wid->loop = wav->loop; wid->id = wav->id; vitaWavPlaying[i] = 1; vitaWavId[i] = wav->id; wid->bitPerSample = wav->bitPerSample; return(1); } static vitaWav *vitaWavLoadInternal(vitaWav *wav, unsigned char *wavfile, int size) { unsigned long channels; unsigned long samplerate; unsigned long blocksize; unsigned long bitpersample; unsigned long datalength; unsigned long samplecount; if(memcmp(wavfile, "RIFF", 4) != 0) { free(wav); return NULL; } channels = *(short *)(wavfile+0x16); samplerate = *(long *)(wavfile+0x18); blocksize = *(short *)(wavfile+0x20); bitpersample = *(short *)(wavfile+0x22); int i; for(i = 0; memcmp(wavfile + 0x24 + i, "data", 4) != 0; i++) { if(i == 0xFF) { free(wav); return NULL; } } datalength = *(unsigned long *)(wavfile + 0x28 + i); if(datalength + 0x2c > size) { free(wav); return NULL; } if(channels != 2 && channels != 1) { free(wav); return NULL; } if(samplerate > 100000 || samplerate < 2000) { free(wav); return NULL; } if(channels == 2) { samplecount = datalength/(bitpersample>>2); } else { samplecount = datalength/((bitpersample>>2)>>1); } if(samplecount <= 0) { free(wav); return NULL; } wav->channels = channels; wav->sampleRate = samplerate; wav->sampleCount = samplecount; wav->dataLength = datalength; wav->data = wavfile + 0x2c; wav->rateRatio = (samplerate*0x4000)/11025; wav->playPtr = 0; wav->playPtr_frac= 0; wav->loop = 0; vitaWavIdFlag++; wav->id = vitaWavIdFlag; wav->bitPerSample = bitpersample; return wav; } vitaWav *vitaWavLoad(const char *filename) { unsigned long filelen; unsigned char *wavfile; vitaWav *wav; int fd = sceIoOpen(filename, SCE_O_RDONLY, 0777); if(fd < 0) return NULL; long lSize; lSize = sceIoLseek32(fd, 0, SCE_SEEK_END); sceIoLseek32(fd, 0, SCE_SEEK_SET); wav = malloc(lSize + sizeof(vitaWav)); wavfile = (unsigned char*)(wav) + sizeof(vitaWav); filelen = sceIoRead(fd, wavfile, lSize); sceIoClose(fd); return(vitaWavLoadInternal(wav, wavfile, filelen)); } vitaWav *vitaWavLoadMemory(const unsigned char *buffer, int size) { unsigned char *wavfile; vitaWav *wav; wav = malloc(size + sizeof(wav)); wavfile = (unsigned char*)(wav) + sizeof(wav); memcpy(wavfile, (unsigned char*)buffer, size); return(vitaWavLoadInternal(wav, wavfile, size)); } void vitaWavUnload(vitaWav *wav) { if(wav != NULL) free(wav); }