1 /***************************************************************************
4 begin : Wed May 15 2002
5 copyright : (C) 2002 by Pete Bernert
6 email : BlackDove@addcom.de
7 ***************************************************************************/
8 /***************************************************************************
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. See also the license.txt file for *
14 * additional informations. *
16 ***************************************************************************/
22 // will be included from spu.c
25 ////////////////////////////////////////////////////////////////////////
27 ////////////////////////////////////////////////////////////////////////
29 xa_decode_t * xapGlobal=0;
31 uint32_t * XAFeed = NULL;
32 uint32_t * XAPlay = NULL;
33 uint32_t * XAStart = NULL;
34 uint32_t * XAEnd = NULL;
36 uint32_t XARepeat = 0;
37 uint32_t XALastVal = 0;
39 uint32_t * CDDAFeed = NULL;
40 uint32_t * CDDAPlay = NULL;
41 uint32_t * CDDAStart = NULL;
42 uint32_t * CDDAEnd = NULL;
44 int iLeftXAVol = 32767;
45 int iRightXAVol = 32767;
47 static int gauss_ptr = 0;
48 static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0};
50 #define gvall0 gauss_window[gauss_ptr]
51 #define gvall(x) gauss_window[(gauss_ptr+x)&3]
52 #define gvalr0 gauss_window[4+gauss_ptr]
53 #define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)]
55 ////////////////////////////////////////////////////////////////////////
57 ////////////////////////////////////////////////////////////////////////
59 INLINE void MixXA(void)
64 int cursor = decode_pos;
66 if(XAPlay != XAFeed || XARepeat > 0)
72 for(ns=0;ns<NSSIZE*2;)
74 if(XAPlay != XAFeed) v=*XAPlay++;
75 if(XAPlay == XAEnd) XAPlay=XAStart;
77 l = ((int)(short)v * iLeftXAVol) >> 15;
78 r = ((int)(short)(v >> 16) * iLeftXAVol) >> 15;
83 spuMem[cursor + 0x400/2] = v >> 16;
84 cursor = (cursor + 1) & 0x1ff;
89 for(ns=0;ns<NSSIZE*2 && CDDAPlay!=CDDAFeed && (CDDAPlay!=CDDAEnd-1||CDDAFeed!=CDDAStart);)
92 if(CDDAPlay==CDDAEnd) CDDAPlay=CDDAStart;
94 l = ((int)(short)v * iLeftXAVol) >> 15;
95 r = ((int)(short)(v >> 16) * iLeftXAVol) >> 15;
100 spuMem[cursor + 0x400/2] = v >> 16;
101 cursor = (cursor + 1) & 0x1ff;
105 ////////////////////////////////////////////////////////////////////////
106 // small linux time helper... only used for watchdog
107 ////////////////////////////////////////////////////////////////////////
109 static unsigned long timeGetTime_spu()
112 gettimeofday(&tv, 0); // well, maybe there are better ways
113 return tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works
116 ////////////////////////////////////////////////////////////////////////
118 ////////////////////////////////////////////////////////////////////////
120 INLINE void FeedXA(xa_decode_t *xap)
122 int sinc,spos,i,iSize,iPlace,vl,vr;
124 if(!bSPUIsOpen) return;
126 xapGlobal = xap; // store info for save states
127 XARepeat = 100; // set up repeat
130 iSize=((45500*xap->nsamples)/xap->freq); // get size
132 iSize=((44100*xap->nsamples)/xap->freq); // get size
134 if(!iSize) return; // none? bye
136 if(XAFeed<XAPlay) iPlace=XAPlay-XAFeed; // how much space in my buf?
137 else iPlace=(XAEnd-XAFeed) + (XAPlay-XAStart);
139 if(iPlace==0) return; // no place at all
141 //----------------------------------------------------//
142 if(iXAPitch) // pitch change option?
145 static DWORD dwFPS=0;
146 static int iFPSCnt=0;
147 static int iLastSize=0;
149 DWORD dw=timeGetTime_spu(),dw1,dw2;
153 dwFPS+=dw-dwLT;iFPSCnt++;
161 if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1;
163 dw2=(xap->freq*100/xap->nsamples);
164 if((!dw1)||((dw2+100)>=dw1)) iLastSize=0;
167 iLastSize=iSize*dw2/dw1;
168 if(iLastSize>iPlace) iLastSize=iPlace;
175 if(iLastSize) iSize=iLastSize;
178 //----------------------------------------------------//
181 sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size
185 uint32_t * pS=(uint32_t *)xap->pcm;
190 int32_t l1,l2;short s;
193 if(iUseInterpolation==2)
195 while(spos>=0x10000L)
198 gauss_window[gauss_ptr] = (short)LOWORD(l);
199 gauss_window[4+gauss_ptr] = (short)HIWORD(l);
200 gauss_ptr = (gauss_ptr+1) & 3;
203 vl = (spos >> 6) & ~3;
204 vr=(gauss[vl]*gvall0)&~2047;
205 vr+=(gauss[vl+1]*gvall(1))&~2047;
206 vr+=(gauss[vl+2]*gvall(2))&~2047;
207 vr+=(gauss[vl+3]*gvall(3))&~2047;
208 l= (vr >> 11) & 0xffff;
209 vr=(gauss[vl]*gvalr0)&~2047;
210 vr+=(gauss[vl+1]*gvalr(1))&~2047;
211 vr+=(gauss[vl+2]*gvalr(2))&~2047;
212 vr+=(gauss[vl+3]*gvalr(3))&~2047;
217 while(spos>=0x10000L)
226 l1=(l1*iPlace)/iSize;
230 l2=(l2*iPlace)/iSize;
232 l=(l1&0xffff)|(l2<<16);
236 if(XAFeed==XAEnd) XAFeed=XAStart;
239 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
250 if(iUseInterpolation==2)
252 while(spos>=0x10000L)
255 gauss_window[gauss_ptr] = (short)LOWORD(l);
256 gauss_window[4+gauss_ptr] = (short)HIWORD(l);
257 gauss_ptr = (gauss_ptr+1) & 3;
260 vl = (spos >> 6) & ~3;
261 vr=(gauss[vl]*gvall0)&~2047;
262 vr+=(gauss[vl+1]*gvall(1))&~2047;
263 vr+=(gauss[vl+2]*gvall(2))&~2047;
264 vr+=(gauss[vl+3]*gvall(3))&~2047;
265 l= (vr >> 11) & 0xffff;
266 vr=(gauss[vl]*gvalr0)&~2047;
267 vr+=(gauss[vl+1]*gvalr(1))&~2047;
268 vr+=(gauss[vl+2]*gvalr(2))&~2047;
269 vr+=(gauss[vl+3]*gvalr(3))&~2047;
274 while(spos>=0x10000L)
283 if(XAFeed==XAEnd) XAFeed=XAStart;
286 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
296 unsigned short * pS=(unsigned short *)xap->pcm;
297 uint32_t l;short s=0;
304 if(iUseInterpolation==2)
306 while(spos>=0x10000L)
308 gauss_window[gauss_ptr] = (short)*pS++;
309 gauss_ptr = (gauss_ptr+1) & 3;
312 vl = (spos >> 6) & ~3;
313 vr=(gauss[vl]*gvall0)&~2047;
314 vr+=(gauss[vl+1]*gvall(1))&~2047;
315 vr+=(gauss[vl+2]*gvall(2))&~2047;
316 vr+=(gauss[vl+3]*gvall(3))&~2047;
322 while(spos>=0x10000L)
330 l1=(l1*iPlace)/iSize;
332 l=(l1&0xffff)|(l1<<16);
335 if(XAFeed==XAEnd) XAFeed=XAStart;
338 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
349 if(iUseInterpolation==2)
351 while(spos>=0x10000L)
353 gauss_window[gauss_ptr] = (short)*pS++;
354 gauss_ptr = (gauss_ptr+1) & 3;
357 vl = (spos >> 6) & ~3;
358 vr=(gauss[vl]*gvall0)&~2047;
359 vr+=(gauss[vl+1]*gvall(1))&~2047;
360 vr+=(gauss[vl+2]*gvall(2))&~2047;
361 vr+=(gauss[vl+3]*gvall(3))&~2047;
366 while(spos>=0x10000L)
375 *XAFeed++=(l|(l<<16));
377 if(XAFeed==XAEnd) XAFeed=XAStart;
380 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
390 ////////////////////////////////////////////////////////////////////////
392 ////////////////////////////////////////////////////////////////////////
394 INLINE int FeedCDDA(unsigned char *pcm, int nBytes)
397 space=(CDDAPlay-CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1);
399 return 0x7761; // rearmed_wait
403 if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart;
404 space=(CDDAPlay-CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1);
405 if(CDDAFeed+space/4>CDDAEnd)
406 space=(CDDAEnd-CDDAFeed)*4;
410 memcpy(CDDAFeed,pcm,space);
416 return 0x676f; // rearmed_go