/*************************************************************************** xa.c - description ------------------- begin : Wed May 15 2002 copyright : (C) 2002 by Pete Bernert email : BlackDove@addcom.de ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. See also the license.txt file for * * additional informations. * * * ***************************************************************************/ #include "stdafx.h" #define _IN_XA #include // will be included from spu.c #ifdef _IN_SPU //////////////////////////////////////////////////////////////////////// // XA GLOBALS //////////////////////////////////////////////////////////////////////// xa_decode_t * xapGlobal=0; uint32_t * XAFeed = NULL; uint32_t * XAPlay = NULL; uint32_t * XAStart = NULL; uint32_t * XAEnd = NULL; uint32_t XARepeat = 0; uint32_t XALastVal = 0; uint32_t * CDDAFeed = NULL; uint32_t * CDDAPlay = NULL; uint32_t * CDDAStart = NULL; uint32_t * CDDAEnd = NULL; int iLeftXAVol = 0x8000; int iRightXAVol = 0x8000; static int gauss_ptr = 0; static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0}; #define gvall0 gauss_window[gauss_ptr] #define gvall(x) gauss_window[(gauss_ptr+x)&3] #define gvalr0 gauss_window[4+gauss_ptr] #define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)] long cdxa_dbuf_ptr; //////////////////////////////////////////////////////////////////////// // MIX XA & CDDA //////////////////////////////////////////////////////////////////////// static int lastxa_lc, lastxa_rc; static int lastcd_lc, lastcd_rc; INLINE void MixXA(void) { int ns; int lc,rc; unsigned long cdda_l; lc = 0; rc = 0; for(ns=0;ns>16) & 0xffff); if( lc < -32768 ) lc = -32768; if( rc < -32768 ) rc = -32768; if( lc > 32767 ) lc = 32767; if( rc > 32767 ) rc = 32767; SSumL[ns]+=lc; SSumR[ns]+=rc; // improve crackle - buffer under // - not update fast enough lastxa_lc = lc; lastxa_rc = rc; #if 0 if( cdxa_dbuf_ptr >= 0x400 ) cdxa_dbuf_ptr = 0; spuMem[ (cdxa_dbuf_ptr + 0)/2 ] = lc; spuMem[ (cdxa_dbuf_ptr + 0x400)/2 ] = rc; cdxa_dbuf_ptr += 2; #endif } if(XAPlay==XAFeed && XARepeat) { //XARepeat--; for(;ns= 0x400 ) cdxa_dbuf_ptr = 0; spuMem[ (cdxa_dbuf_ptr + 0)/2 ] = lastxa_rc; spuMem[ (cdxa_dbuf_ptr + 0x400)/2 ] = lastxa_rc; cdxa_dbuf_ptr += 2; #endif } } for(ns=0;ns>16) & 0xffff); if( lc < -32768 ) lc = -32768; if( rc < -32768 ) rc = -32768; if( lc > 32767 ) lc = 32767; if( rc > 32767 ) rc = 32767; SSumL[ns]+=lc; SSumR[ns]+=rc; #if 0 // Vib Ribbon - playback if( cdxa_dbuf_ptr >= 0x400 ) cdxa_dbuf_ptr = 0; spuMem[ (cdxa_dbuf_ptr + 0)/2 ] = lc; spuMem[ (cdxa_dbuf_ptr + 0x400)/2 ] = rc; cdxa_dbuf_ptr += 2; #endif // improve crackle - buffer under // - not update fast enough lastcd_lc = lc; lastcd_rc = rc; } if(CDDAPlay==CDDAFeed && XARepeat) { //XARepeat--; for(;ns= 0x400 ) cdxa_dbuf_ptr = 0; spuMem[ (cdxa_dbuf_ptr + 0)/2 ] = lastcd_lc; spuMem[ (cdxa_dbuf_ptr + 0x400)/2 ] = lastcd_rc; cdxa_dbuf_ptr += 2; #endif SSumL[ns]+=lastcd_lc; SSumR[ns]+=lastcd_rc; } } } //////////////////////////////////////////////////////////////////////// // small linux time helper... only used for watchdog //////////////////////////////////////////////////////////////////////// #ifndef _WINDOWS unsigned long timeGetTime_spu() { struct timeval tv; gettimeofday(&tv, 0); // well, maybe there are better ways return tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works } #endif //////////////////////////////////////////////////////////////////////// // FEED XA //////////////////////////////////////////////////////////////////////// INLINE void FeedXA(xa_decode_t *xap) { int sinc,spos,i,iSize,iPlace,vl,vr; if(!bSPUIsOpen) return; xapGlobal = xap; // store info for save states XARepeat = 100; // set up repeat #ifdef XA_HACK iSize=((45500*xap->nsamples)/xap->freq); // get size #else iSize=((44100*xap->nsamples)/xap->freq); // get size #endif if(!iSize) return; // none? bye if(XAFeed=10) { if(!dwFPS) dwFPS=1; dw1=1000000/dwFPS; if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1; else dwL1=dw1; dw2=(xap->freq*100/xap->nsamples); if((!dw1)||((dw2+100)>=dw1)) iLastSize=0; else { iLastSize=iSize*dw2/dw1; if(iLastSize>iPlace) iLastSize=iPlace; iSize=iLastSize; } iFPSCnt=0;dwFPS=0; } else { if(iLastSize) iSize=iLastSize; } } //----------------------------------------------------// spos=0x10000L; sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size if(xap->stereo) { uint32_t * pS=(uint32_t *)xap->pcm; uint32_t l=0; if(iXAPitch) { int32_t l1,l2;short s; for(i=0;i=0x10000L) { l = *pS++; spos -= 0x10000L; } s=(short)LOWORD(l); l1=s; l1=(l1*iPlace)/iSize; if(l1<-32767) l1=-32767; if(l1> 32767) l1=32767; s=(short)HIWORD(l); l2=s; l2=(l2*iPlace)/iSize; if(l2<-32767) l2=-32767; if(l2> 32767) l2=32767; l=(l1&0xffff)|(l2<<16); *XAFeed++=l; if(XAFeed==XAEnd) XAFeed=XAStart; if(XAFeed==XAPlay) { if(XAPlay!=XAStart) XAFeed=XAPlay-1; break; } spos += sinc; } } else { for(i=0;i=0x10000L) { l = *pS++; spos -= 0x10000L; } *XAFeed++=l; if(XAFeed==XAEnd) XAFeed=XAStart; if(XAFeed==XAPlay) { if(XAPlay!=XAStart) XAFeed=XAPlay-1; break; } spos += sinc; } } } else { unsigned short * pS=(unsigned short *)xap->pcm; uint32_t l;short s=0; if(iXAPitch) { int32_t l1; for(i=0;i=0x10000L) { s = *pS++; spos -= 0x10000L; } l1=s; l1=(l1*iPlace)/iSize; if(l1<-32767) l1=-32767; if(l1> 32767) l1=32767; l=(l1&0xffff)|(l1<<16); *XAFeed++=l; if(XAFeed==XAEnd) XAFeed=XAStart; if(XAFeed==XAPlay) { if(XAPlay!=XAStart) XAFeed=XAPlay-1; break; } spos += sinc; } } else { for(i=0;i=0x10000L) { s = *pS++; spos -= 0x10000L; } l=s; *XAFeed++=((l&0xffff)|(l<<16)); if(XAFeed==XAEnd) XAFeed=XAStart; if(XAFeed==XAPlay) { if(XAPlay!=XAStart) XAFeed=XAPlay-1; break; } spos += sinc; } } } } //////////////////////////////////////////////////////////////////////// // FEED CDDA //////////////////////////////////////////////////////////////////////// unsigned int cdda_ptr; INLINE void FeedCDDA(unsigned char *pcm, int nBytes) { while(nBytes>0) { if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart; while(CDDAFeed==CDDAPlay-1|| (CDDAFeed==CDDAEnd-1&&CDDAPlay==CDDAStart)) { #ifdef _WINDOWS if (!iUseTimer) Sleep(1); else return; #else if (!iUseTimer) usleep(1000); else return; #endif } *CDDAFeed++=(*pcm | (*(pcm+1)<<8) | (*(pcm+2)<<16) | (*(pcm+3)<<24)); nBytes-=4; pcm+=4; } } #endif