spu: sync on xa playback start
authornotaz <notasas@gmail.com>
Tue, 6 Sep 2022 15:25:42 +0000 (18:25 +0300)
committernotaz <notasas@gmail.com>
Thu, 8 Sep 2022 21:20:05 +0000 (00:20 +0300)
this avoids nasty underflows at the start of the stream

frontend/plugin.c
libpcsxcore/cdrom.c
libpcsxcore/plugins.h
plugins/dfsound/freeze.c
plugins/dfsound/spu.c
plugins/dfsound/spu.h
plugins/dfsound/xa.c

index 812e503..a273985 100644 (file)
@@ -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) {
@@ -308,9 +308,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; \
index 1f57350..f729abc 100644 (file)
@@ -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;
index 34f062e..38c41ca 100644 (file)
@@ -172,7 +172,7 @@ typedef void (CALLBACK* SPUwriteDMA)(unsigned short);
 typedef unsigned short (CALLBACK* SPUreadDMA)(void);\r
 typedef void (CALLBACK* SPUwriteDMAMem)(unsigned short *, int, unsigned int);\r
 typedef void (CALLBACK* SPUreadDMAMem)(unsigned short *, int, unsigned int);\r
-typedef void (CALLBACK* SPUplayADPCMchannel)(xa_decode_t *);\r
+typedef void (CALLBACK* SPUplayADPCMchannel)(xa_decode_t *, unsigned int, int);\r
 typedef void (CALLBACK* SPUregisterCallback)(void (CALLBACK *callback)(void));\r
 typedef void (CALLBACK* SPUregisterScheduleCb)(void (CALLBACK *callback)(unsigned int cycles_after));\r
 typedef long (CALLBACK* SPUconfigure)(void);\r
@@ -189,7 +189,7 @@ typedef struct {
 } SPUFreeze_t;\r
 typedef long (CALLBACK* SPUfreeze)(uint32_t, SPUFreeze_t *, uint32_t);\r
 typedef void (CALLBACK* SPUasync)(uint32_t, uint32_t);\r
-typedef int  (CALLBACK* SPUplayCDDAchannel)(short *, int);\r
+typedef int  (CALLBACK* SPUplayCDDAchannel)(short *, int, unsigned int, int);\r
 \r
 // SPU function pointers\r
 extern SPUconfigure        SPU_configure;\r
index 4866df8..a400cf7 100644 (file)
@@ -284,7 +284,7 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
  spu.bMemDirty = 1;\r
 \r
  if(pF->xaS.nsamples<=4032)                            // start xa again\r
-  SPUplayADPCMchannel(&pF->xaS);\r
+  SPUplayADPCMchannel(&pF->xaS, spu.cycles_played, 0);\r
 \r
  spu.xapGlobal=0;\r
 \r
index ebc5446..8099a03 100644 (file)
@@ -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);
 }
 
index 23425d9..0cef652 100644 (file)
@@ -19,7 +19,7 @@
 #define __P_SPU_H__\r
 \r
 void ClearWorkingState(void);\r
-void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap);\r
-int  CALLBACK SPUplayCDDAchannel(short *pcm, int bytes);\r
+void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap, unsigned int cycle, int is_start);\r
+int  CALLBACK SPUplayCDDAchannel(short *pcm, int bytes, unsigned int cycle, int is_start);\r
 \r
 #endif /* __P_SPU_H__ */\r
index c93612f..c7a84fd 100644 (file)
@@ -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