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.
extern void SPUabout(void);
extern long SPUfreeze(unsigned int, void *);
extern void SPUasync(unsigned int);
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)
/* PAD */
static long PADreadPort1(PadDataS *pad)
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_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; \
#define hook_it(name) { \
o_##name = name; \
static void *playthread(void *param)
#endif
{
static void *playthread(void *param)
#endif
{
+ long osleep, d, t, i, s;
t = GetTickCount();
while (playing) {
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);
s = 0;
for (i = 0; i < sizeof(sndbuffer) / CD_FRAMESIZE_RAW; i++) {
d = cdimg_read_func(cddaHandle, sndbuffer + s, cdda_cur_sector, 0);
- 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;
+ }
+
} SPUFreeze_t;\r
typedef long (CALLBACK* SPUfreeze)(uint32_t, SPUFreeze_t *);\r
typedef void (CALLBACK* SPUasync)(uint32_t);\r
} 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
\r
// SPU function pointers\r
extern SPUconfigure SPU_configure;\r
static int lastns=0; // last ns pos
static int iSecureStart=0; // secure start counter
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
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// CODE AREA
////////////////////////////////////////////////////////////////////////
-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
}
// SETUPTIMER: init of certain buffers and threads/timers
XAFeed = XAStart;
CDDAStart = // alloc cdda buffer
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;
CDDAEnd = CDDAStart + 16384;
CDDAPlay = CDDAStart;
CDDAFeed = CDDAStart;
void SetupTimer(void);\r
void RemoveTimer(void);\r
void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap);\r
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
// FEED CDDA
////////////////////////////////////////////////////////////////////////
// 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(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
\r
INLINE void MixXA(void);\r
INLINE void FeedXA(xa_decode_t *xap);\r
\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);
-void SPUplayCDDAchannel(short *pcm, int nbytes)
+int SPUplayCDDAchannel(short *pcm, int nbytes)
}
////////////////////////////////////////////////////////////////////////
}
////////////////////////////////////////////////////////////////////////