From 983a7cfdccceaa612267a1b045110b4f831d1495 Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 5 Oct 2011 02:11:18 +0300 Subject: [PATCH] spu/cdda: sync cdda to spu playback this will probably make cdrom/vsync timing desync situation worse (those were never in sync anyway) but fix some cdda related sound stuttering. Those magic values are used trying to preserve other SPU plugin compatibility. --- frontend/plugin.c | 4 +-- libpcsxcore/cdriso.c | 55 +++++++++++++++++++++++---------------- libpcsxcore/plugins.h | 2 +- plugins/dfsound/spu.c | 12 +++++---- plugins/dfsound/spu.h | 2 +- plugins/dfsound/xa.c | 28 +++++++++++++------- plugins/dfsound/xa.h | 2 +- plugins/spunull/spunull.c | 3 ++- 8 files changed, 64 insertions(+), 44 deletions(-) diff --git a/frontend/plugin.c b/frontend/plugin.c index 853fb154..2492f4ae 100644 --- a/frontend/plugin.c +++ b/frontend/plugin.c @@ -38,7 +38,7 @@ extern long SPUtest(void); extern void SPUabout(void); extern long SPUfreeze(unsigned int, void *); extern void SPUasync(unsigned int); -extern void SPUplayCDDAchannel(short *, int); +extern int SPUplayCDDAchannel(short *, int); /* PAD */ static long PADreadPort1(PadDataS *pad) @@ -262,7 +262,7 @@ pc_hook_func (SPU_writeDMAMem, (unsigned short *a0, int a1), (a0, a pc_hook_func (SPU_readDMAMem, (unsigned short *a0, int a1), (a0, a1), PCNT_SPU) pc_hook_func (SPU_playADPCMchannel, (void *a0), (a0), PCNT_SPU) pc_hook_func (SPU_async, (unsigned int a0), (a0), PCNT_SPU) -pc_hook_func (SPU_playCDDAchannel, (short *a0, int a1), (a0, a1), PCNT_SPU) +pc_hook_func_ret(int, SPU_playCDDAchannel, (short *a0, int a1), (a0, a1), PCNT_SPU) #define hook_it(name) { \ o_##name = name; \ diff --git a/libpcsxcore/cdriso.c b/libpcsxcore/cdriso.c index c29fd775..aa6e47f4 100644 --- a/libpcsxcore/cdriso.c +++ b/libpcsxcore/cdriso.c @@ -164,33 +164,13 @@ static void playthread(void *param) static void *playthread(void *param) #endif { - long d, t, i, s; + long osleep, d, t, i, s; unsigned char tmp; + int ret = 0; t = GetTickCount(); while (playing) { - d = t - (long)GetTickCount(); - if (d <= 0) { - d = 1; - } - else if (d > CDDA_FRAMETIME) { - d = CDDA_FRAMETIME; - } -#ifdef _WIN32 - Sleep(d); -#else - usleep(d * 1000); -#endif - // HACK: stop feeding data while emu is paused - extern int stop; - if (stop) { - usleep(100000); - continue; - } - - t = GetTickCount() + CDDA_FRAMETIME; - s = 0; for (i = 0; i < sizeof(sndbuffer) / CD_FRAMESIZE_RAW; i++) { d = cdimg_read_func(cddaHandle, sndbuffer + s, cdda_cur_sector, 0); @@ -223,8 +203,37 @@ static void *playthread(void *param) } } - SPU_playCDDAchannel((short *)sndbuffer, s); + do { + ret = SPU_playCDDAchannel((short *)sndbuffer, s); + if (ret == 0x7761) + usleep(6 * 1000); + } while (ret == 0x7761 && playing); // rearmed_wait } + + if (ret != 0x676f) { // !rearmed_go + // do approx sleep + long now; + + // HACK: stop feeding data while emu is paused + extern int stop; + while (stop && playing) + usleep(10000); + + now = GetTickCount(); + osleep = t - now; + if (osleep <= 0) { + osleep = 1; + t = now; + } + else if (osleep > CDDA_FRAMETIME) { + osleep = CDDA_FRAMETIME; + t = now; + } + + usleep(osleep * 1000); + t += CDDA_FRAMETIME; + } + } #ifdef _WIN32 diff --git a/libpcsxcore/plugins.h b/libpcsxcore/plugins.h index 42028eaf..91253915 100644 --- a/libpcsxcore/plugins.h +++ b/libpcsxcore/plugins.h @@ -206,7 +206,7 @@ typedef struct { } SPUFreeze_t; typedef long (CALLBACK* SPUfreeze)(uint32_t, SPUFreeze_t *); typedef void (CALLBACK* SPUasync)(uint32_t); -typedef void (CALLBACK* SPUplayCDDAchannel)(short *, int); +typedef int (CALLBACK* SPUplayCDDAchannel)(short *, int); // SPU function pointers extern SPUconfigure SPU_configure; diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index f84ef77c..b3bd0579 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -132,6 +132,8 @@ int lastch=-1; // last channel processed on spu irq in timer mode static int lastns=0; // last ns pos static int iSecureStart=0; // secure start counter +#define CDDA_BUFFER_SIZE (16384 * sizeof(uint32_t)) // must be power of 2 + //////////////////////////////////////////////////////////////////////// // CODE AREA //////////////////////////////////////////////////////////////////////// @@ -948,12 +950,12 @@ void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap) } // CDDA AUDIO -void CALLBACK SPUplayCDDAchannel(short *pcm, int nbytes) +int CALLBACK SPUplayCDDAchannel(short *pcm, int nbytes) { - if (!pcm) return; - if (nbytes<=0) return; + if (!pcm) return -1; + if (nbytes<=0) return -1; - FeedCDDA((unsigned char *)pcm, nbytes); + return FeedCDDA((unsigned char *)pcm, nbytes); } // SETUPTIMER: init of certain buffers and threads/timers @@ -1011,7 +1013,7 @@ void SetupStreams(void) XAFeed = XAStart; CDDAStart = // alloc cdda buffer - (uint32_t *)malloc(16384 * sizeof(uint32_t)); + (uint32_t *)malloc(CDDA_BUFFER_SIZE); CDDAEnd = CDDAStart + 16384; CDDAPlay = CDDAStart; CDDAFeed = CDDAStart; diff --git a/plugins/dfsound/spu.h b/plugins/dfsound/spu.h index 8912684b..048f6434 100644 --- a/plugins/dfsound/spu.h +++ b/plugins/dfsound/spu.h @@ -18,4 +18,4 @@ void SetupTimer(void); void RemoveTimer(void); void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap); -void CALLBACK SPUplayCDDAchannel(short *pcm, int bytes); \ No newline at end of file +int CALLBACK SPUplayCDDAchannel(short *pcm, int bytes); diff --git a/plugins/dfsound/xa.c b/plugins/dfsound/xa.c index b45aef27..b1efe10d 100644 --- a/plugins/dfsound/xa.c +++ b/plugins/dfsound/xa.c @@ -389,21 +389,29 @@ INLINE void FeedXA(xa_decode_t *xap) // FEED CDDA //////////////////////////////////////////////////////////////////////// -INLINE void FeedCDDA(unsigned char *pcm, int nBytes) +INLINE int FeedCDDA(unsigned char *pcm, int nBytes) { + int space; + space=(CDDAPlay-CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1); + if(space0) { if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart; - while(CDDAFeed==CDDAPlay-1|| - (CDDAFeed==CDDAEnd-1&&CDDAPlay==CDDAStart)) - { - if (!iUseTimer) usleep(1000); - else return; - } - *CDDAFeed++=(*pcm | (*(pcm+1)<<8) | (*(pcm+2)<<16) | (*(pcm+3)<<24)); - nBytes-=4; - pcm+=4; + space=(CDDAPlay-CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1); + if(CDDAFeed+space/4>CDDAEnd) + space=(CDDAEnd-CDDAFeed)*4; + if(space>nBytes) + space=nBytes; + + memcpy(CDDAFeed,pcm,space); + CDDAFeed+=space/4; + nBytes-=space; + pcm+=space; } + + return 0x676f; // rearmed_go } #endif diff --git a/plugins/dfsound/xa.h b/plugins/dfsound/xa.h index 0928eba2..cbf2843f 100644 --- a/plugins/dfsound/xa.h +++ b/plugins/dfsound/xa.h @@ -17,4 +17,4 @@ INLINE void MixXA(void); INLINE void FeedXA(xa_decode_t *xap); -INLINE void FeedCDDA(unsigned char *pcm, int nBytes); +INLINE int FeedCDDA(unsigned char *pcm, int nBytes); diff --git a/plugins/spunull/spunull.c b/plugins/spunull/spunull.c index be798c5c..4390be30 100644 --- a/plugins/spunull/spunull.c +++ b/plugins/spunull/spunull.c @@ -347,8 +347,9 @@ void SPUasync(unsigned int cycle) { } -void SPUplayCDDAchannel(short *pcm, int nbytes) +int SPUplayCDDAchannel(short *pcm, int nbytes) { + return -1; } //////////////////////////////////////////////////////////////////////// -- 2.39.5