From f22d26f881462a14c348ba44cf1eeaf5ad24da99 Mon Sep 17 00:00:00 2001 From: aliaspider Date: Tue, 24 Nov 2015 11:04:22 +0100 Subject: [PATCH] (3DS) rewrite the dsp audio driver to use a single looping wave buffer. --- audio/drivers/ctr_dsp_audio.c | 169 +++++++++++----------------------- 1 file changed, 53 insertions(+), 116 deletions(-) diff --git a/audio/drivers/ctr_dsp_audio.c b/audio/drivers/ctr_dsp_audio.c index bdf51aa7d6..d35f667f29 100644 --- a/audio/drivers/ctr_dsp_audio.c +++ b/audio/drivers/ctr_dsp_audio.c @@ -17,21 +17,16 @@ #include "../../general.h" #include "../../driver.h" #include "../../performance.h" - - -#define CTR_DSP_BUFFERS_COUNT (1u << 4u) -#define CTR_DSP_BUFFERS_MASK (CTR_DSP_BUFFERS_COUNT - 1) +#include "../../ctr/ctr_debug.h" typedef struct { bool nonblocking; bool playing; - int channel; - ndspWaveBuf dsp_buf[CTR_DSP_BUFFERS_COUNT]; - uint32_t dsp_buf_id; - uint8_t* linear_buffer; + ndspWaveBuf dsp_buf; + uint32_t pos; } ctr_dsp_audio_t; #define CTR_DSP_AUDIO_COUNT (1u << 11u) @@ -39,48 +34,6 @@ typedef struct #define CTR_DSP_AUDIO_SIZE (CTR_DSP_AUDIO_COUNT * sizeof(int16_t) * 2) #define CTR_DSP_AUDIO_SIZE_MASK (CTR_DSP_AUDIO_SIZE - 1u) - -#ifndef DEBUG_HOLD -void wait_for_input(void); -#define PRINTFPOS(X,Y) "\x1b["#X";"#Y"H" -#define DEBUG_HOLD() do{printf("%s@%s:%d.\n",__FUNCTION__, __FILE__, __LINE__);fflush(stdout);wait_for_input();}while(0) -#define DEBUG_VAR(X) printf( "%-20s: 0x%08X\n", #X, (u32)(X)) -#define DEBUG_VAR64(X) printf( #X"\r\t\t\t\t : 0x%016llX\n", (u64)(X)) -#endif - - -static uint32_t ctr_get_queued_samples(ctr_dsp_audio_t* ctr) -{ - uint32_t sample_pos, sample_count; - uint16_t buf_seq; - - buf_seq = ndspChnGetWaveBufSeq(ctr->channel); - - if(!buf_seq) - return 0; - - sample_pos = ndspChnGetSamplePos(ctr->channel); - sample_count = 0; - - int buf_id = ctr->dsp_buf_id; - do - { - buf_id++; - buf_id&= CTR_DSP_BUFFERS_MASK; - } - while(ctr->dsp_buf[buf_id].sequence_id != buf_seq); - ndspWaveBuf* current = &ctr->dsp_buf[buf_id]; - - sample_count = current->nsamples - sample_pos; - while((current = current->next)) - { - sample_count += current->nsamples; - } - return sample_count; -} - - - static void *ctr_dsp_audio_init(const char *device, unsigned rate, unsigned latency) { ctr_dsp_audio_t *ctr; @@ -98,34 +51,32 @@ static void *ctr_dsp_audio_init(const char *device, unsigned rate, unsigned late if (!ctr) return NULL; -// memset(ctr, 0, sizeof(*ctr)); - settings->audio.out_rate = 32730; ctr->channel = 0; - ctr->dsp_buf_id = 0; ndspSetOutputMode(NDSP_OUTPUT_STEREO); ndspSetClippingMode(NDSP_CLIP_SOFT); //?? -// ndspSetClippingMode(NDSP_CLIP_NORMAL); //?? - ndspSetOutputCount(CTR_DSP_BUFFERS_COUNT); + ndspSetOutputCount(1); ndspChnReset(ctr->channel); -// ndspChnInitParams(ctr->channel); ndspChnSetFormat(ctr->channel, NDSP_FORMAT_STEREO_PCM16); ndspChnSetInterp(ctr->channel, NDSP_INTERP_NONE); -// ndspChnSetInterp(ctr->channel, NDSP_INTERP_LINEAR); -// ndspChnSetInterp(ctr->channel, NDSP_INTERP_POLYPHASE); ndspChnSetRate(ctr->channel, 32728.0f); -// ndspChnSetRate(ctr->channel, CTR_DSP_AUDIO_RATE); -// ndspChnSetRate(ctr->channel, 0x7F00); -// ndspChnSetMix(ctr->channel, (float[12]){1.0, 1.0, 0.0}); ndspChnWaveBufClear(ctr->channel); - ctr->linear_buffer = linearAlloc(CTR_DSP_BUFFERS_COUNT * CTR_DSP_AUDIO_SIZE); + ctr->dsp_buf.data_pcm16 = linearAlloc(CTR_DSP_AUDIO_SIZE); + memset(ctr->dsp_buf.data_pcm16, 0, CTR_DSP_AUDIO_SIZE); + DSP_FlushDataCache(ctr->dsp_buf.data_pcm16, CTR_DSP_AUDIO_SIZE); - int i; - for (i = 0; i < CTR_DSP_BUFFERS_COUNT; i++) - ctr->dsp_buf[i].data_pcm16 = (uint16_t*)(ctr->linear_buffer + i * CTR_DSP_AUDIO_SIZE); + ctr->dsp_buf.looping = true; + ctr->dsp_buf.nsamples = CTR_DSP_AUDIO_COUNT; + + ndspChnWaveBufAdd(ctr->channel, &ctr->dsp_buf); + + ctr->pos = 0; + ctr->playing = true; + + ndspSetMasterVol(1.0); return ctr; } @@ -133,8 +84,8 @@ static void *ctr_dsp_audio_init(const char *device, unsigned rate, unsigned late static void ctr_dsp_audio_free(void *data) { ctr_dsp_audio_t* ctr = (ctr_dsp_audio_t*)data; - - linearFree(ctr->linear_buffer); + ndspChnWaveBufClear(ctr->channel); + linearFree(ctr->dsp_buf.data_pcm16); free(ctr); ndspExit(); } @@ -143,61 +94,51 @@ static ssize_t ctr_dsp_audio_write(void *data, const void *buf, size_t size) { static struct retro_perf_counter ctraudio_dsp_f = {0}; ctr_dsp_audio_t* ctr = (ctr_dsp_audio_t*)data; + u32 pos; + uint32_t sample_pos = ndspChnGetSamplePos(ctr->channel); - ndspWaveBuf* current_buf = &ctr->dsp_buf[ctr->dsp_buf_id]; - static int dropped=0; - uint32_t queued = ctr_get_queued_samples(ctr); - - if(size > CTR_DSP_AUDIO_SIZE) + if((((sample_pos - ctr->pos) & CTR_DSP_AUDIO_COUNT_MASK) < (CTR_DSP_AUDIO_COUNT >> 2)) || + (((ctr->pos - sample_pos ) & CTR_DSP_AUDIO_COUNT_MASK) < (CTR_DSP_AUDIO_COUNT >> 4)) || + (((sample_pos - ctr->pos) & CTR_DSP_AUDIO_COUNT_MASK) < (size >> 2))) { - DEBUG_VAR(size); - ctr_dsp_audio_write(ctr, buf, CTR_DSP_AUDIO_SIZE); - buf = (const void*)((u32)buf + CTR_DSP_AUDIO_SIZE); - size = size - CTR_DSP_AUDIO_SIZE; - } - - dropped++; - if(ctr->nonblocking) - { - if((current_buf->status == NDSP_WBUF_QUEUED) || (current_buf->status == NDSP_WBUF_PLAYING)) - return size; - - if((queued + (size>>2)) > 0x2000) - return size; - } - else - { - if(queued > (0x1000 + (size>>2))) + if (ctr->nonblocking) + ctr->pos = (sample_pos + (CTR_DSP_AUDIO_COUNT >> 1)) & CTR_DSP_AUDIO_COUNT_MASK; + else { -// printf(PRINTFPOS(24,0)"queued :0x%08X \n", ctr_get_queued_samples(ctr)); - while(ctr_get_queued_samples(ctr) > 160 ) + do{ svcSleepThread(100000); + sample_pos = ndspChnGetSamplePos(ctr->channel); + }while (((sample_pos - (ctr->pos + size >>2)) & CTR_DSP_AUDIO_COUNT_MASK) > (CTR_DSP_AUDIO_COUNT >> 1) + || (((ctr->pos - (CTR_DSP_AUDIO_COUNT >> 4) - sample_pos) & CTR_DSP_AUDIO_COUNT_MASK) > (CTR_DSP_AUDIO_COUNT >> 1))); } } - dropped--; - rarch_perf_init(&ctraudio_dsp_f, "ctraudio_dsp_f"); retro_perf_start(&ctraudio_dsp_f); - memcpy(current_buf->data_pcm16, buf, size); - current_buf->nsamples = size>>2; + pos = ctr->pos << 2; - DSP_FlushDataCache(current_buf->data_pcm16, size); - DSP_FlushDataCache(ctr->dsp_buf, sizeof(ctr->dsp_buf)); - gfxFlushBuffers(); + if((pos + size) > CTR_DSP_AUDIO_SIZE) + { + memcpy(ctr->dsp_buf.data_pcm8 + pos, buf, + (CTR_DSP_AUDIO_SIZE - pos)); + DSP_FlushDataCache(ctr->dsp_buf.data_pcm8 + pos, (CTR_DSP_AUDIO_SIZE - pos)); + + memcpy(ctr->dsp_buf.data_pcm8, (uint8_t*) buf + (CTR_DSP_AUDIO_SIZE - pos), + (pos + size - CTR_DSP_AUDIO_SIZE)); + DSP_FlushDataCache(ctr->dsp_buf.data_pcm8, (pos + size - CTR_DSP_AUDIO_SIZE)); + } + else + { + memcpy(ctr->dsp_buf.data_pcm8 + pos, buf, size); + DSP_FlushDataCache(ctr->dsp_buf.data_pcm8 + pos, size); + } + + ctr->pos += size >> 2; + ctr->pos &= CTR_DSP_AUDIO_COUNT_MASK; - ndspChnWaveBufAdd(ctr->channel, current_buf); retro_perf_stop(&ctraudio_dsp_f); -// printf(PRINTFPOS(25,0)"dropped:0x%08X queued :0x%08X \n", dropped, queued); -// printf(PRINTFPOS(26,0)"current:0x%08X nsamples:0x%08X \n", ctr->dsp_buf_id, current_buf->nsamples); -// printf(PRINTFPOS(27,0)"dropped:0x%08X count :0x%08X \n", ndspGetDroppedFrames(), ndspGetFrameCount()); -// printf(PRINTFPOS(28,0)"Pos :0x%08X Seq :0x%08X \n", ndspChnGetSamplePos(ctr->channel), ndspChnGetWaveBufSeq(ctr->channel)); - - ctr->dsp_buf_id++; - ctr->dsp_buf_id &= CTR_DSP_BUFFERS_MASK; - return size; } @@ -205,12 +146,8 @@ static bool ctr_dsp_audio_stop(void *data) { ctr_dsp_audio_t* ctr = (ctr_dsp_audio_t*)data; - ndspChnWaveBufClear(ctr->channel); + ndspSetMasterVol(0.0); ctr->playing = false; - int i; - memset(ctr->dsp_buf, 0, sizeof(ctr->dsp_buf)); - for (i = 0; i < CTR_DSP_BUFFERS_COUNT; i++) - ctr->dsp_buf[i].data_pcm16 = (uint16_t*)(ctr->linear_buffer + i * CTR_DSP_AUDIO_SIZE); return true; } @@ -232,6 +169,7 @@ static bool ctr_dsp_audio_start(void *data) if (system->shutdown) return true; + ndspSetMasterVol(1.0); ctr->playing = true; return true; @@ -253,15 +191,14 @@ static bool ctr_dsp_audio_use_float(void *data) static size_t ctr_dsp_audio_write_avail(void *data) { ctr_dsp_audio_t* ctr = (ctr_dsp_audio_t*)data; - uint32_t queued_samples = ctr_get_queued_samples(ctr); - return queued_samples < 0x1000 ? 0x1000 - queued_samples : 0; + return (ndspChnGetSamplePos(ctr->channel) - ctr->pos) & CTR_DSP_AUDIO_COUNT_MASK; } static size_t ctr_dsp_audio_buffer_size(void *data) { (void)data; - return 0x1000; + return CTR_DSP_AUDIO_COUNT; }