From: notaz <notasas@gmail.com>
Date: Tue, 4 Oct 2011 23:11:18 +0000 (+0300)
Subject: spu/cdda: sync cdda to spu playback
X-Git-Tag: r10~14
X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=983a7cfdccceaa612267a1b045110b4f831d1495;p=pcsx_rearmed.git

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.
---

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(space<nBytes)
+  return 0x7761; // rearmed_wait
+
  while(nBytes>0)
   {
    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;
 }
 
 ////////////////////////////////////////////////////////////////////////