From 9cf790343a0788535b4ab2b2ce576662860d0188 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 6 Sep 2022 18:25:42 +0300 Subject: [PATCH] spu: sync on xa playback start this avoids nasty underflows at the start of the stream --- frontend/plugin.c | 8 ++++---- libpcsxcore/cdrom.c | 9 +++++---- libpcsxcore/plugins.h | 4 ++-- plugins/dfsound/freeze.c | 2 +- plugins/dfsound/spu.c | 14 ++++++++++---- plugins/dfsound/spu.h | 4 ++-- plugins/dfsound/xa.c | 2 +- 7 files changed, 25 insertions(+), 18 deletions(-) diff --git a/frontend/plugin.c b/frontend/plugin.c index 196c9802..5f9c5ffb 100644 --- a/frontend/plugin.c +++ b/frontend/plugin.c @@ -35,7 +35,7 @@ extern void CALLBACK SPUwriteDMA(unsigned short); extern unsigned short CALLBACK SPUreadDMA(void); extern void CALLBACK SPUwriteDMAMem(unsigned short *, int, unsigned int); extern void CALLBACK SPUreadDMAMem(unsigned short *, int, unsigned int); -extern void CALLBACK SPUplayADPCMchannel(void *); +extern void CALLBACK SPUplayADPCMchannel(void *, unsigned int, int); extern void CALLBACK SPUregisterCallback(void (*cb)(void)); extern void CALLBACK SPUregisterScheduleCb(void (*cb)(unsigned int)); extern long CALLBACK SPUconfigure(void); @@ -43,7 +43,7 @@ extern long CALLBACK SPUtest(void); extern void CALLBACK SPUabout(void); extern long CALLBACK SPUfreeze(unsigned int, void *, unsigned int); extern void CALLBACK SPUasync(unsigned int, unsigned int); -extern int CALLBACK SPUplayCDDAchannel(short *, int); +extern int CALLBACK SPUplayCDDAchannel(short *, int, unsigned int, int); /* PAD */ static long CALLBACK PADreadPort1(PadDataS *pad) @@ -266,9 +266,9 @@ pc_hook_func (SPU_writeDMA, (unsigned short a0), (a0), PCNT_SPU) pc_hook_func_ret(unsigned short,SPU_readDMA, (void), (), PCNT_SPU) pc_hook_func (SPU_writeDMAMem, (unsigned short *a0, int a1, uint32_t a2), (a0, a1, a2), PCNT_SPU) pc_hook_func (SPU_readDMAMem, (unsigned short *a0, int a1, uint32_t a2), (a0, a1, a2), PCNT_SPU) -pc_hook_func (SPU_playADPCMchannel, (void *a0), (a0), PCNT_SPU) +pc_hook_func (SPU_playADPCMchannel, (void *a0, unsigned int a1, int a2), (a0, a1, a2), PCNT_SPU) pc_hook_func (SPU_async, (uint32_t a0, uint32_t a1), (a0, a1), PCNT_SPU) -pc_hook_func_ret(int, SPU_playCDDAchannel, (short *a0, int a1), (a0, a1), PCNT_SPU) +pc_hook_func_ret(int, SPU_playCDDAchannel, (short *a0, int a1, unsigned int a2, int a3), (a0, a1, a2, a3), PCNT_SPU) #define hook_it(name) { \ o_##name = name; \ diff --git a/libpcsxcore/cdrom.c b/libpcsxcore/cdrom.c index 07b13649..fb526b40 100644 --- a/libpcsxcore/cdrom.c +++ b/libpcsxcore/cdrom.c @@ -624,10 +624,10 @@ void cdrPlaySeekReadInterrupt(void) if (!cdr.Irq && !cdr.Stat && (cdr.Mode & (MODE_AUTOPAUSE|MODE_REPORT))) cdrPlayInterrupt_Autopause(); - if (CDR_readCDDA && !cdr.Muted && !Config.Cdda) { + if (!cdr.Muted && !Config.Cdda) { cdrAttenuate(read_buf, CD_FRAMESIZE_RAW / 4, 1); - if (SPU_playCDDAchannel) - SPU_playCDDAchannel(read_buf, CD_FRAMESIZE_RAW); + SPU_playCDDAchannel(read_buf, CD_FRAMESIZE_RAW, psxRegs.cycle, cdr.FirstSector); + cdr.FirstSector = 0; } cdr.SetSectorPlay[2]++; @@ -756,6 +756,7 @@ void cdrInterrupt(void) { Find_CurTrack(cdr.SetSectorPlay); ReadTrack(cdr.SetSectorPlay); cdr.TrackChanged = FALSE; + cdr.FirstSector = 1; if (!Config.Cdda) CDR_play(cdr.SetSectorPlay); @@ -1215,7 +1216,7 @@ static void cdrReadInterrupt(void) int ret = xa_decode_sector(&cdr.Xa, cdr.Transfer+4, cdr.FirstSector); if (!ret) { cdrAttenuate(cdr.Xa.pcm, cdr.Xa.nsamples, cdr.Xa.stereo); - SPU_playADPCMchannel(&cdr.Xa); + SPU_playADPCMchannel(&cdr.Xa, psxRegs.cycle, cdr.FirstSector); cdr.FirstSector = 0; } else cdr.FirstSector = -1; diff --git a/libpcsxcore/plugins.h b/libpcsxcore/plugins.h index 34f062e2..38c41ca7 100644 --- a/libpcsxcore/plugins.h +++ b/libpcsxcore/plugins.h @@ -172,7 +172,7 @@ typedef void (CALLBACK* SPUwriteDMA)(unsigned short); typedef unsigned short (CALLBACK* SPUreadDMA)(void); typedef void (CALLBACK* SPUwriteDMAMem)(unsigned short *, int, unsigned int); typedef void (CALLBACK* SPUreadDMAMem)(unsigned short *, int, unsigned int); -typedef void (CALLBACK* SPUplayADPCMchannel)(xa_decode_t *); +typedef void (CALLBACK* SPUplayADPCMchannel)(xa_decode_t *, unsigned int, int); typedef void (CALLBACK* SPUregisterCallback)(void (CALLBACK *callback)(void)); typedef void (CALLBACK* SPUregisterScheduleCb)(void (CALLBACK *callback)(unsigned int cycles_after)); typedef long (CALLBACK* SPUconfigure)(void); @@ -189,7 +189,7 @@ typedef struct { } SPUFreeze_t; typedef long (CALLBACK* SPUfreeze)(uint32_t, SPUFreeze_t *, uint32_t); typedef void (CALLBACK* SPUasync)(uint32_t, uint32_t); -typedef int (CALLBACK* SPUplayCDDAchannel)(short *, int); +typedef int (CALLBACK* SPUplayCDDAchannel)(short *, int, unsigned int, int); // SPU function pointers extern SPUconfigure SPU_configure; diff --git a/plugins/dfsound/freeze.c b/plugins/dfsound/freeze.c index 4866df89..a400cf7c 100644 --- a/plugins/dfsound/freeze.c +++ b/plugins/dfsound/freeze.c @@ -284,7 +284,7 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF, spu.bMemDirty = 1; if(pF->xaS.nsamples<=4032) // start xa again - SPUplayADPCMchannel(&pF->xaS); + SPUplayADPCMchannel(&pF->xaS, spu.cycles_played, 0); spu.xapGlobal=0; diff --git a/plugins/dfsound/spu.c b/plugins/dfsound/spu.c index fbd555b1..3aaf53a4 100644 --- a/plugins/dfsound/spu.c +++ b/plugins/dfsound/spu.c @@ -1298,20 +1298,26 @@ void CALLBACK SPUupdate(void) // XA AUDIO -void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap) +void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap, unsigned int cycle, int is_start) { if(!xap) return; - if(!xap->freq) return; // no xa freq ? bye + if(!xap->freq) return; // no xa freq ? bye - FeedXA(xap); // call main XA feeder + if (is_start) + do_samples(cycle, 1); // catch up to prevent source underflows later + + FeedXA(xap); // call main XA feeder } // CDDA AUDIO -int CALLBACK SPUplayCDDAchannel(short *pcm, int nbytes) +int CALLBACK SPUplayCDDAchannel(short *pcm, int nbytes, unsigned int cycle, int is_start) { if (!pcm) return -1; if (nbytes<=0) return -1; + if (is_start) + do_samples(cycle, 1); // catch up to prevent source underflows later + return FeedCDDA((unsigned char *)pcm, nbytes); } diff --git a/plugins/dfsound/spu.h b/plugins/dfsound/spu.h index d42425d6..8a0f2d2e 100644 --- a/plugins/dfsound/spu.h +++ b/plugins/dfsound/spu.h @@ -16,5 +16,5 @@ ***************************************************************************/ void ClearWorkingState(void); -void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap); -int CALLBACK SPUplayCDDAchannel(short *pcm, int bytes); +void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap, unsigned int cycle, int is_start); +int CALLBACK SPUplayCDDAchannel(short *pcm, int bytes, unsigned int cycle, int is_start); diff --git a/plugins/dfsound/xa.c b/plugins/dfsound/xa.c index d63e83cc..f62a12d2 100644 --- a/plugins/dfsound/xa.c +++ b/plugins/dfsound/xa.c @@ -120,7 +120,7 @@ INLINE void FeedXA(xa_decode_t *xap) if(!spu.bSPUIsOpen) return; spu.xapGlobal = xap; // store info for save states - spu.XARepeat = 100; // set up repeat + spu.XARepeat = 3; // set up repeat #if 0//def XA_HACK iSize=((45500*xap->nsamples)/xap->freq); // get size -- 2.39.5