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 for(ns=0;ns<NSSIZE && XAPlay!=XAFeed;ns++)
67 if(XAPlay==XAEnd) XAPlay=XAStart;
69 SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32768;
70 SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32768;
72 SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767;
73 SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
77 if(XAPlay==XAFeed && XARepeat)
83 SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32768;
84 SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32768;
86 SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767;
87 SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
92 for(ns=0;ns<NSSIZE && CDDAPlay!=CDDAFeed && (CDDAPlay!=CDDAEnd-1||CDDAFeed!=CDDAStart);ns++)
95 if(CDDAPlay==CDDAEnd) CDDAPlay=CDDAStart;
96 SSumL[ns]+=(((short)(l&0xffff)) * iLeftXAVol)/32767;
97 SSumR[ns]+=(((short)((l>>16)&0xffff)) * iRightXAVol)/32767;
101 ////////////////////////////////////////////////////////////////////////
102 // small linux time helper... only used for watchdog
103 ////////////////////////////////////////////////////////////////////////
105 unsigned long timeGetTime_spu()
108 gettimeofday(&tv, 0); // well, maybe there are better ways
109 return tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works
112 ////////////////////////////////////////////////////////////////////////
114 ////////////////////////////////////////////////////////////////////////
116 INLINE void FeedXA(xa_decode_t *xap)
118 int sinc,spos,i,iSize,iPlace,vl,vr;
120 if(!bSPUIsOpen) return;
122 xapGlobal = xap; // store info for save states
123 XARepeat = 100; // set up repeat
126 iSize=((45500*xap->nsamples)/xap->freq); // get size
128 iSize=((44100*xap->nsamples)/xap->freq); // get size
130 if(!iSize) return; // none? bye
132 if(XAFeed<XAPlay) iPlace=XAPlay-XAFeed; // how much space in my buf?
133 else iPlace=(XAEnd-XAFeed) + (XAPlay-XAStart);
135 if(iPlace==0) return; // no place at all
137 //----------------------------------------------------//
138 if(iXAPitch) // pitch change option?
141 static DWORD dwFPS=0;
142 static int iFPSCnt=0;
143 static int iLastSize=0;
145 DWORD dw=timeGetTime_spu(),dw1,dw2;
149 dwFPS+=dw-dwLT;iFPSCnt++;
157 if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1;
159 dw2=(xap->freq*100/xap->nsamples);
160 if((!dw1)||((dw2+100)>=dw1)) iLastSize=0;
163 iLastSize=iSize*dw2/dw1;
164 if(iLastSize>iPlace) iLastSize=iPlace;
171 if(iLastSize) iSize=iLastSize;
174 //----------------------------------------------------//
177 sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size
181 uint32_t * pS=(uint32_t *)xap->pcm;
186 int32_t l1,l2;short s;
189 if(iUseInterpolation==2)
191 while(spos>=0x10000L)
194 gauss_window[gauss_ptr] = (short)LOWORD(l);
195 gauss_window[4+gauss_ptr] = (short)HIWORD(l);
196 gauss_ptr = (gauss_ptr+1) & 3;
199 vl = (spos >> 6) & ~3;
200 vr=(gauss[vl]*gvall0)&~2047;
201 vr+=(gauss[vl+1]*gvall(1))&~2047;
202 vr+=(gauss[vl+2]*gvall(2))&~2047;
203 vr+=(gauss[vl+3]*gvall(3))&~2047;
204 l= (vr >> 11) & 0xffff;
205 vr=(gauss[vl]*gvalr0)&~2047;
206 vr+=(gauss[vl+1]*gvalr(1))&~2047;
207 vr+=(gauss[vl+2]*gvalr(2))&~2047;
208 vr+=(gauss[vl+3]*gvalr(3))&~2047;
213 while(spos>=0x10000L)
222 l1=(l1*iPlace)/iSize;
223 if(l1<-32767) l1=-32767;
224 if(l1> 32767) l1=32767;
227 l2=(l2*iPlace)/iSize;
228 if(l2<-32767) l2=-32767;
229 if(l2> 32767) l2=32767;
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;
329 if(l1<-32767) l1=-32767;
330 if(l1> 32767) l1=32767;
331 l=(l1&0xffff)|(l1<<16);
334 if(XAFeed==XAEnd) XAFeed=XAStart;
337 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
348 if(iUseInterpolation==2)
350 while(spos>=0x10000L)
352 gauss_window[gauss_ptr] = (short)*pS++;
353 gauss_ptr = (gauss_ptr+1) & 3;
356 vl = (spos >> 6) & ~3;
357 vr=(gauss[vl]*gvall0)&~2047;
358 vr+=(gauss[vl+1]*gvall(1))&~2047;
359 vr+=(gauss[vl+2]*gvall(2))&~2047;
360 vr+=(gauss[vl+3]*gvall(3))&~2047;
365 while(spos>=0x10000L)
374 *XAFeed++=(l|(l<<16));
376 if(XAFeed==XAEnd) XAFeed=XAStart;
379 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
389 ////////////////////////////////////////////////////////////////////////
391 ////////////////////////////////////////////////////////////////////////
393 INLINE void FeedCDDA(unsigned char *pcm, int nBytes)
397 if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart;
398 while(CDDAFeed==CDDAPlay-1||
399 (CDDAFeed==CDDAEnd-1&&CDDAPlay==CDDAStart))
401 if (!iUseTimer) usleep(1000);
404 *CDDAFeed++=(*pcm | (*(pcm+1)<<8) | (*(pcm+2)<<16) | (*(pcm+3)<<24));