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)/32767;
99 SSumLR[ns++]+=(((short)((l>>16)&0xffff)) * iRightXAVol)/32767;
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;
225 if(l1<-32767) l1=-32767;
226 if(l1> 32767) l1=32767;
229 l2=(l2*iPlace)/iSize;
230 if(l2<-32767) l2=-32767;
231 if(l2> 32767) l2=32767;
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;
331 if(l1<-32767) l1=-32767;
332 if(l1> 32767) l1=32767;
333 l=(l1&0xffff)|(l1<<16);
336 if(XAFeed==XAEnd) XAFeed=XAStart;
339 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
350 if(iUseInterpolation==2)
352 while(spos>=0x10000L)
354 gauss_window[gauss_ptr] = (short)*pS++;
355 gauss_ptr = (gauss_ptr+1) & 3;
358 vl = (spos >> 6) & ~3;
359 vr=(gauss[vl]*gvall0)&~2047;
360 vr+=(gauss[vl+1]*gvall(1))&~2047;
361 vr+=(gauss[vl+2]*gvall(2))&~2047;
362 vr+=(gauss[vl+3]*gvall(3))&~2047;
367 while(spos>=0x10000L)
376 *XAFeed++=(l|(l<<16));
378 if(XAFeed==XAEnd) XAFeed=XAStart;
381 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
391 ////////////////////////////////////////////////////////////////////////
393 ////////////////////////////////////////////////////////////////////////
395 INLINE void FeedCDDA(unsigned char *pcm, int nBytes)
399 if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart;
400 while(CDDAFeed==CDDAPlay-1||
401 (CDDAFeed==CDDAEnd-1&&CDDAPlay==CDDAStart))
403 if (!iUseTimer) usleep(1000);
406 *CDDAFeed++=(*pcm | (*(pcm+1)<<8) | (*(pcm+2)<<16) | (*(pcm+3)<<24));