From 301309304a70118ea783fb4764c13cfbbb56679c Mon Sep 17 00:00:00 2001 From: aliaspider Date: Fri, 10 Apr 2015 19:10:34 +0100 Subject: [PATCH] (3DS) implement the audio driver. --- audio/drivers/ctr_audio.c | 156 +++++++++++++++++++++++++++++--- frontend/drivers/platform_ctr.c | 20 +++- 2 files changed, 156 insertions(+), 20 deletions(-) diff --git a/audio/drivers/ctr_audio.c b/audio/drivers/ctr_audio.c index 0c5be48b1f..b307487437 100644 --- a/audio/drivers/ctr_audio.c +++ b/audio/drivers/ctr_audio.c @@ -16,17 +16,84 @@ #include "../../general.h" #include "../../driver.h" + +typedef struct +{ + bool nonblocking; + int16_t* l; + int16_t* r; + int16_t* silence; + + uint32_t l_paddr; + uint32_t r_paddr; + uint32_t silence_paddr; + + uint32_t pos; + int rate; + +} ctr_audio_t; + +#define CTR_AUDIO_COUNT (1u << 12u) +#define CTR_AUDIO_COUNT_MASK (CTR_AUDIO_COUNT - 1u) +#define CTR_AUDIO_SIZE (CTR_AUDIO_COUNT * sizeof(int16_t)) +#define CTR_AUDIO_SIZE_MASK (CTR_AUDIO_SIZE - 1u) + static void *ctr_audio_init(const char *device, unsigned rate, unsigned latency) { + + (void)device; (void)rate; (void)latency; - return (void*)-1; + +// if(!csndInit()) +// return NULL; + + ctr_audio_t *ctr = (ctr_audio_t*)calloc(1, sizeof(ctr_audio_t)); + + ctr->l = linearAlloc(CTR_AUDIO_SIZE); + ctr->r = linearAlloc(CTR_AUDIO_SIZE); + ctr->silence = linearAlloc(CTR_AUDIO_SIZE); + + memset(ctr->l, 0, CTR_AUDIO_SIZE); + memset(ctr->r, 0, CTR_AUDIO_SIZE); + memset(ctr->silence, 0, CTR_AUDIO_SIZE); + + ctr->l_paddr = osConvertVirtToPhys((u32)ctr->l); + ctr->r_paddr = osConvertVirtToPhys((u32)ctr->r); + ctr->silence_paddr = osConvertVirtToPhys((u32)ctr->silence); + + ctr->pos = 0; + ctr->rate = rate; + + GSPGPU_FlushDataCache(NULL, (u8*)ctr->silence, CTR_AUDIO_SIZE); + csndPlaySound(0x8, SOUND_LOOPMODE(CSND_LOOPMODE_NORMAL)| SOUND_FORMAT(CSND_ENCODING_PCM16), + rate, ctr->silence, ctr->silence, CTR_AUDIO_SIZE); + + csndPlaySound(0x9, SOUND_LOOPMODE(CSND_LOOPMODE_NORMAL)| SOUND_FORMAT(CSND_ENCODING_PCM16), + rate, ctr->silence, ctr->silence, CTR_AUDIO_SIZE); + + CSND_SetVol(0x8, 0xFFFF, 0); + CSND_SetVol(0x9, 0, 0xFFFF); + csndExecCmds(true); + + return ctr; } static void ctr_audio_free(void *data) { - (void)data; + ctr_audio_t* ctr = (ctr_audio_t*)data; + +// csndExit(); + CSND_SetPlayState(0x8, 0); + CSND_SetPlayState(0x9, 0); + csndExecCmds(true); + + linearFree(ctr->l); + linearFree(ctr->r); + linearFree(ctr->silence); + + free(ctr); } static ssize_t ctr_audio_write(void *data, const void *buf, size_t size) @@ -34,12 +101,67 @@ static ssize_t ctr_audio_write(void *data, const void *buf, size_t size) (void)data; (void)buf; + ctr_audio_t* ctr = (ctr_audio_t*)data; + + int i; + const uint16_t* src = buf; + + CSND_ChnInfo channel_info; + csndGetState(0x8, &channel_info); + + uint32_t playpos; + if((channel_info.samplePAddr >= (ctr->l_paddr)) && + (channel_info.samplePAddr < (ctr->l_paddr + CTR_AUDIO_SIZE))) + { + playpos = (channel_info.samplePAddr - ctr->l_paddr) / sizeof(uint16_t); + } + else + { + CSND_SetBlock(0x8, 1, ctr->l_paddr, CTR_AUDIO_SIZE); + CSND_SetBlock(0x9, 1, ctr->r_paddr, CTR_AUDIO_SIZE); + csndExecCmds(true); + playpos = 0; + } + + if((((playpos - ctr->pos) & CTR_AUDIO_COUNT_MASK) < (CTR_AUDIO_COUNT >> 2)) || + (((ctr->pos - playpos ) & CTR_AUDIO_COUNT_MASK) < (CTR_AUDIO_COUNT >> 4)) || + (((playpos - ctr->pos) & CTR_AUDIO_COUNT_MASK) < (size >> 2))) + { + if (ctr->nonblocking) + ctr->pos = (playpos + (CTR_AUDIO_COUNT >> 1)) & CTR_AUDIO_COUNT_MASK; + else + { + do{ + svcSleepThread(100000); +// svcSleepThread(((s64)(CTR_AUDIO_COUNT >> 8) * 1000000000) / ctr->rate); + csndGetState(0x8, &channel_info); + playpos = (channel_info.samplePAddr - ctr->l_paddr) / sizeof(uint16_t); + }while (((playpos - ctr->pos) & CTR_AUDIO_COUNT_MASK) < (CTR_AUDIO_COUNT >> 1) + || (((ctr->pos - playpos) & CTR_AUDIO_COUNT_MASK) < (CTR_AUDIO_COUNT >> 4))); + } + } + + + for (i = 0; i < (size >> 1); i += 2) + { + ctr->l[ctr->pos] = src[i]; + ctr->r[ctr->pos] = src[i + 1]; + ctr->pos++; + ctr->pos &= CTR_AUDIO_COUNT_MASK; + } + + return size; } static bool ctr_audio_stop(void *data) -{ - (void)data; +{ + ctr_audio_t* ctr = (ctr_audio_t*)data; + + CSND_SetBlock(0x8, 1, ctr->silence_paddr, CTR_AUDIO_SIZE); + CSND_SetBlock(0x9, 1, ctr->silence_paddr, CTR_AUDIO_SIZE); + csndExecCmds(true); + return true; } @@ -51,26 +173,30 @@ static bool ctr_audio_alive(void *data) static bool ctr_audio_start(void *data) { - (void)data; + ctr_audio_t* ctr = (ctr_audio_t*)data; + +// csndPlaySound(0x8, SOUND_LOOPMODE(CSND_LOOPMODE_NORMAL)| SOUND_FORMAT(CSND_ENCODING_PCM16), +// ctr->rate, ctr->l_paddr + ((ctr->pos + (CTR_AUDIO_SIZE / 2)) & CTR_AUDIO_SIZE_MASK), +// (u32*)ctr->silence_paddr, CTR_AUDIO_SIZE); + + CSND_SetBlock(0x8, 1, ctr->l_paddr, CTR_AUDIO_SIZE); + CSND_SetBlock(0x9, 1, ctr->r_paddr, CTR_AUDIO_SIZE); + csndExecCmds(true); + return true; } static void ctr_audio_set_nonblock_state(void *data, bool state) { - (void)data; - (void)state; + ctr_audio_t* ctr = (ctr_audio_t*)data; + if (ctr) + ctr->nonblocking = state; } static bool ctr_audio_use_float(void *data) { (void)data; - return true; -} - -static size_t ctr_audio_write_avail(void *data) -{ - (void)data; - return 0; + return false; } audio_driver_t audio_ctr = { @@ -83,6 +209,6 @@ audio_driver_t audio_ctr = { ctr_audio_free, ctr_audio_use_float, "ctr", - ctr_audio_write_avail, + NULL, NULL }; diff --git a/frontend/drivers/platform_ctr.c b/frontend/drivers/platform_ctr.c index af57c8ee69..e5aea45e7f 100644 --- a/frontend/drivers/platform_ctr.c +++ b/frontend/drivers/platform_ctr.c @@ -122,12 +122,14 @@ static void frontend_ctr_deinit(void *data) wait_for_input(); + csndExit(); gfxExit(); - // sdmcExit(); - // fsExit(); - // hidExit(); - // aptExit(); - // srvExit(); + +// sdmcExit(); +// fsExit(); +// hidExit(); +// aptExit(); +// srvExit(); #endif } @@ -145,8 +147,16 @@ static void frontend_ctr_init(void *data) global_t *global = global_get_ptr(); global->verbosity = true; +// srvInit(); +// aptInit(); +// hidInit(); +// fsInit(); +// sdmcInit(); + +// APT_SetAppCpuTimeLimit(NULL, 80); // gfxInitDefault(); gfxInit(GSP_BGR8_OES,GSP_RGB565_OES,false); + csndInit(); gfxSet3D(false); consoleInit(GFX_BOTTOM, NULL); #endif