spu/cdda: sync cdda to spu playback
authornotaz <notasas@gmail.com>
Tue, 4 Oct 2011 23:11:18 +0000 (02:11 +0300)
committernotaz <notasas@gmail.com>
Sat, 8 Oct 2011 00:29:24 +0000 (03:29 +0300)
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
libpcsxcore/cdriso.c
libpcsxcore/plugins.h
plugins/dfsound/spu.c
plugins/dfsound/spu.h
plugins/dfsound/xa.c
plugins/dfsound/xa.h
plugins/spunull/spunull.c

index 853fb15..2492f4a 100644 (file)
@@ -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; \
index c29fd77..aa6e47f 100644 (file)
@@ -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
index 42028ea..9125391 100644 (file)
@@ -206,7 +206,7 @@ typedef struct {
 } SPUFreeze_t;\r
 typedef long (CALLBACK* SPUfreeze)(uint32_t, SPUFreeze_t *);\r
 typedef void (CALLBACK* SPUasync)(uint32_t);\r
-typedef void (CALLBACK* SPUplayCDDAchannel)(short *, int);\r
+typedef int  (CALLBACK* SPUplayCDDAchannel)(short *, int);\r
 \r
 // SPU function pointers\r
 extern SPUconfigure        SPU_configure;\r
index f84ef77..b3bd057 100644 (file)
@@ -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;
index 8912684..048f643 100644 (file)
@@ -18,4 +18,4 @@
 void SetupTimer(void);\r
 void RemoveTimer(void);\r
 void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap);\r
-void CALLBACK SPUplayCDDAchannel(short *pcm, int bytes);
\ No newline at end of file
+int  CALLBACK SPUplayCDDAchannel(short *pcm, int bytes);\r
index b45aef2..b1efe10 100644 (file)
@@ -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
index 0928eba..cbf2843 100644 (file)
@@ -17,4 +17,4 @@
 \r
 INLINE void MixXA(void);\r
 INLINE void FeedXA(xa_decode_t *xap);\r
-INLINE void FeedCDDA(unsigned char *pcm, int nBytes);
+INLINE int  FeedCDDA(unsigned char *pcm, int nBytes);
index be798c5..4390be3 100644 (file)
@@ -347,8 +347,9 @@ void SPUasync(unsigned int cycle)
 {
 }
 
-void SPUplayCDDAchannel(short *pcm, int nbytes)
+int SPUplayCDDAchannel(short *pcm, int nbytes)
 {
+ return -1;
 }
 
 ////////////////////////////////////////////////////////////////////////