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;
82 spuMem[cursor + 0x400/2] = r;
83 cursor = (cursor + 1) & 0x1ff;
88 for(ns=0;ns<NSSIZE*2 && CDDAPlay!=CDDAFeed && (CDDAPlay!=CDDAEnd-1||CDDAFeed!=CDDAStart);)
91 if(CDDAPlay==CDDAEnd) CDDAPlay=CDDAStart;
93 l = ((int)(short)v * iLeftXAVol) >> 15;
94 r = ((int)(short)(v >> 16) * iLeftXAVol) >> 15;
98 spuMem[cursor + 0x400/2] = r;
99 cursor = (cursor + 1) & 0x1ff;
103 ////////////////////////////////////////////////////////////////////////
104 // small linux time helper... only used for watchdog
105 ////////////////////////////////////////////////////////////////////////
107 unsigned long timeGetTime_spu()
110 gettimeofday(&tv, 0); // well, maybe there are better ways
111 return tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works
114 ////////////////////////////////////////////////////////////////////////
116 ////////////////////////////////////////////////////////////////////////
118 INLINE void FeedXA(xa_decode_t *xap)
120 int sinc,spos,i,iSize,iPlace,vl,vr;
122 if(!bSPUIsOpen) return;
124 xapGlobal = xap; // store info for save states
125 XARepeat = 100; // set up repeat
128 iSize=((45500*xap->nsamples)/xap->freq); // get size
130 iSize=((44100*xap->nsamples)/xap->freq); // get size
132 if(!iSize) return; // none? bye
134 if(XAFeed<XAPlay) iPlace=XAPlay-XAFeed; // how much space in my buf?
135 else iPlace=(XAEnd-XAFeed) + (XAPlay-XAStart);
137 if(iPlace==0) return; // no place at all
139 //----------------------------------------------------//
140 if(iXAPitch) // pitch change option?
143 static DWORD dwFPS=0;
144 static int iFPSCnt=0;
145 static int iLastSize=0;
147 DWORD dw=timeGetTime_spu(),dw1,dw2;
151 dwFPS+=dw-dwLT;iFPSCnt++;
159 if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1;
161 dw2=(xap->freq*100/xap->nsamples);
162 if((!dw1)||((dw2+100)>=dw1)) iLastSize=0;
165 iLastSize=iSize*dw2/dw1;
166 if(iLastSize>iPlace) iLastSize=iPlace;
173 if(iLastSize) iSize=iLastSize;
176 //----------------------------------------------------//
179 sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size
183 uint32_t * pS=(uint32_t *)xap->pcm;
188 int32_t l1,l2;short s;
191 if(iUseInterpolation==2)
193 while(spos>=0x10000L)
196 gauss_window[gauss_ptr] = (short)LOWORD(l);
197 gauss_window[4+gauss_ptr] = (short)HIWORD(l);
198 gauss_ptr = (gauss_ptr+1) & 3;
201 vl = (spos >> 6) & ~3;
202 vr=(gauss[vl]*gvall0)&~2047;
203 vr+=(gauss[vl+1]*gvall(1))&~2047;
204 vr+=(gauss[vl+2]*gvall(2))&~2047;
205 vr+=(gauss[vl+3]*gvall(3))&~2047;
206 l= (vr >> 11) & 0xffff;
207 vr=(gauss[vl]*gvalr0)&~2047;
208 vr+=(gauss[vl+1]*gvalr(1))&~2047;
209 vr+=(gauss[vl+2]*gvalr(2))&~2047;
210 vr+=(gauss[vl+3]*gvalr(3))&~2047;
215 while(spos>=0x10000L)
224 l1=(l1*iPlace)/iSize;
228 l2=(l2*iPlace)/iSize;
230 l=(l1&0xffff)|(l2<<16);
234 if(XAFeed==XAEnd) XAFeed=XAStart;
237 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
248 if(iUseInterpolation==2)
250 while(spos>=0x10000L)
253 gauss_window[gauss_ptr] = (short)LOWORD(l);
254 gauss_window[4+gauss_ptr] = (short)HIWORD(l);
255 gauss_ptr = (gauss_ptr+1) & 3;
258 vl = (spos >> 6) & ~3;
259 vr=(gauss[vl]*gvall0)&~2047;
260 vr+=(gauss[vl+1]*gvall(1))&~2047;
261 vr+=(gauss[vl+2]*gvall(2))&~2047;
262 vr+=(gauss[vl+3]*gvall(3))&~2047;
263 l= (vr >> 11) & 0xffff;
264 vr=(gauss[vl]*gvalr0)&~2047;
265 vr+=(gauss[vl+1]*gvalr(1))&~2047;
266 vr+=(gauss[vl+2]*gvalr(2))&~2047;
267 vr+=(gauss[vl+3]*gvalr(3))&~2047;
272 while(spos>=0x10000L)
281 if(XAFeed==XAEnd) XAFeed=XAStart;
284 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
294 unsigned short * pS=(unsigned short *)xap->pcm;
295 uint32_t l;short s=0;
302 if(iUseInterpolation==2)
304 while(spos>=0x10000L)
306 gauss_window[gauss_ptr] = (short)*pS++;
307 gauss_ptr = (gauss_ptr+1) & 3;
310 vl = (spos >> 6) & ~3;
311 vr=(gauss[vl]*gvall0)&~2047;
312 vr+=(gauss[vl+1]*gvall(1))&~2047;
313 vr+=(gauss[vl+2]*gvall(2))&~2047;
314 vr+=(gauss[vl+3]*gvall(3))&~2047;
320 while(spos>=0x10000L)
328 l1=(l1*iPlace)/iSize;
330 l=(l1&0xffff)|(l1<<16);
333 if(XAFeed==XAEnd) XAFeed=XAStart;
336 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
347 if(iUseInterpolation==2)
349 while(spos>=0x10000L)
351 gauss_window[gauss_ptr] = (short)*pS++;
352 gauss_ptr = (gauss_ptr+1) & 3;
355 vl = (spos >> 6) & ~3;
356 vr=(gauss[vl]*gvall0)&~2047;
357 vr+=(gauss[vl+1]*gvall(1))&~2047;
358 vr+=(gauss[vl+2]*gvall(2))&~2047;
359 vr+=(gauss[vl+3]*gvall(3))&~2047;
364 while(spos>=0x10000L)
373 *XAFeed++=(l|(l<<16));
375 if(XAFeed==XAEnd) XAFeed=XAStart;
378 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
388 ////////////////////////////////////////////////////////////////////////
390 ////////////////////////////////////////////////////////////////////////
392 INLINE int FeedCDDA(unsigned char *pcm, int nBytes)
395 space=(CDDAPlay-CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1);
397 return 0x7761; // rearmed_wait
401 if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart;
402 space=(CDDAPlay-CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1);
403 if(CDDAFeed+space/4>CDDAEnd)
404 space=(CDDAEnd-CDDAFeed)*4;
408 memcpy(CDDAFeed,pcm,space);
414 return 0x676f; // rearmed_go