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
27 ////////////////////////////////////////////////////////////////////////
29 ////////////////////////////////////////////////////////////////////////
31 xa_decode_t * xapGlobal=0;
33 uint32_t * XAFeed = NULL;
34 uint32_t * XAPlay = NULL;
35 uint32_t * XAStart = NULL;
36 uint32_t * XAEnd = NULL;
38 uint32_t XARepeat = 0;
39 uint32_t XALastVal = 0;
41 uint32_t * CDDAFeed = NULL;
42 uint32_t * CDDAPlay = NULL;
43 uint32_t * CDDAStart = NULL;
44 uint32_t * CDDAEnd = NULL;
46 int iLeftXAVol = 32767;
47 int iRightXAVol = 32767;
49 static int gauss_ptr = 0;
50 static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0};
52 #define gvall0 gauss_window[gauss_ptr]
53 #define gvall(x) gauss_window[(gauss_ptr+x)&3]
54 #define gvalr0 gauss_window[4+gauss_ptr]
55 #define gvalr(x) gauss_window[4+((gauss_ptr+x)&3)]
57 ////////////////////////////////////////////////////////////////////////
59 ////////////////////////////////////////////////////////////////////////
61 INLINE void MixXA(void)
66 for(ns=0;ns<NSSIZE*2 && XAPlay!=XAFeed;)
69 if(XAPlay==XAEnd) XAPlay=XAStart;
71 SSumLR[ns++]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32768;
72 SSumLR[ns++]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32768;
74 SSumLR[ns++]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767;
75 SSumLR[ns++]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
79 if(XAPlay==XAFeed && XARepeat)
85 SSumLR[ns++]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32768;
86 SSumLR[ns++]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32768;
88 SSumLR[ns++]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767;
89 SSumLR[ns++]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
94 for(ns=0;ns<NSSIZE*2 && CDDAPlay!=CDDAFeed && (CDDAPlay!=CDDAEnd-1||CDDAFeed!=CDDAStart);)
97 if(CDDAPlay==CDDAEnd) CDDAPlay=CDDAStart;
98 SSumLR[ns++]+=(((short)(l&0xffff)) * iLeftXAVol) >> 15;
99 SSumLR[ns++]+=(((short)((l>>16)&0xffff)) * iRightXAVol) >> 15;
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 void FeedCDDA(unsigned char *pcm, int nBytes)
396 if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart;
397 while(CDDAFeed==CDDAPlay-1||
398 (CDDAFeed==CDDAEnd-1&&CDDAPlay==CDDAStart))
400 if (!iUseTimer) usleep(1000);
403 *CDDAFeed++=(*pcm | (*(pcm+1)<<8) | (*(pcm+2)<<16) | (*(pcm+3)<<24));