build plugins in
[pcsx_rearmed.git] / plugins / dfsound / xa.c
CommitLineData
ef79bbde
P
1/***************************************************************************
2 xa.c - description
3 -------------------
4 begin : Wed May 15 2002
5 copyright : (C) 2002 by Pete Bernert
6 email : BlackDove@addcom.de
7 ***************************************************************************/
8/***************************************************************************
9 * *
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. *
15 * *
16 ***************************************************************************/
17
18#include "stdafx.h"
19#define _IN_XA
20#include <stdint.h>
21
22// will be included from spu.c
23#ifdef _IN_SPU
24
25////////////////////////////////////////////////////////////////////////
26// XA GLOBALS
27////////////////////////////////////////////////////////////////////////
28
29xa_decode_t * xapGlobal=0;
30
31uint32_t * XAFeed = NULL;
32uint32_t * XAPlay = NULL;
33uint32_t * XAStart = NULL;
34uint32_t * XAEnd = NULL;
35
36uint32_t XARepeat = 0;
37uint32_t XALastVal = 0;
38
39uint32_t * CDDAFeed = NULL;
40uint32_t * CDDAPlay = NULL;
41uint32_t * CDDAStart = NULL;
42uint32_t * CDDAEnd = NULL;
43
44int iLeftXAVol = 32767;
45int iRightXAVol = 32767;
46
47static int gauss_ptr = 0;
48static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0};
49
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)]
54
55////////////////////////////////////////////////////////////////////////
56// MIX XA & CDDA
57////////////////////////////////////////////////////////////////////////
58
59INLINE void MixXA(void)
60{
61 int ns;
62 uint32_t l;
63
64 for(ns=0;ns<NSSIZE && XAPlay!=XAFeed;ns++)
65 {
66 XALastVal=*XAPlay++;
67 if(XAPlay==XAEnd) XAPlay=XAStart;
68#ifdef XA_HACK
69 SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32768;
70 SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32768;
71#else
72 SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767;
73 SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
74#endif
75 }
76
77 if(XAPlay==XAFeed && XARepeat)
78 {
79 XARepeat--;
80 for(;ns<NSSIZE;ns++)
81 {
82#ifdef XA_HACK
83 SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32768;
84 SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32768;
85#else
86 SSumL[ns]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767;
87 SSumR[ns]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
88#endif
89 }
90 }
91
92 for(ns=0;ns<NSSIZE && CDDAPlay!=CDDAFeed && (CDDAPlay!=CDDAEnd-1||CDDAFeed!=CDDAStart);ns++)
93 {
94 l=*CDDAPlay++;
95 if(CDDAPlay==CDDAEnd) CDDAPlay=CDDAStart;
96 SSumL[ns]+=(((short)(l&0xffff)) * iLeftXAVol)/32767;
97 SSumR[ns]+=(((short)((l>>16)&0xffff)) * iRightXAVol)/32767;
98 }
99}
100
101////////////////////////////////////////////////////////////////////////
102// small linux time helper... only used for watchdog
103////////////////////////////////////////////////////////////////////////
104
105unsigned long timeGetTime_spu()
106{
107 struct timeval tv;
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
110}
111
112////////////////////////////////////////////////////////////////////////
113// FEED XA
114////////////////////////////////////////////////////////////////////////
115
116INLINE void FeedXA(xa_decode_t *xap)
117{
118 int sinc,spos,i,iSize,iPlace,vl,vr;
119
120 if(!bSPUIsOpen) return;
121
122 xapGlobal = xap; // store info for save states
123 XARepeat = 100; // set up repeat
124
125#ifdef XA_HACK
126 iSize=((45500*xap->nsamples)/xap->freq); // get size
127#else
128 iSize=((44100*xap->nsamples)/xap->freq); // get size
129#endif
130 if(!iSize) return; // none? bye
131
132 if(XAFeed<XAPlay) iPlace=XAPlay-XAFeed; // how much space in my buf?
133 else iPlace=(XAEnd-XAFeed) + (XAPlay-XAStart);
134
135 if(iPlace==0) return; // no place at all
136
137 //----------------------------------------------------//
138 if(iXAPitch) // pitch change option?
139 {
140 static DWORD dwLT=0;
141 static DWORD dwFPS=0;
142 static int iFPSCnt=0;
143 static int iLastSize=0;
144 static DWORD dwL1=0;
145 DWORD dw=timeGetTime_spu(),dw1,dw2;
146
147 iPlace=iSize;
148
149 dwFPS+=dw-dwLT;iFPSCnt++;
150
151 dwLT=dw;
152
153 if(iFPSCnt>=10)
154 {
155 if(!dwFPS) dwFPS=1;
156 dw1=1000000/dwFPS;
157 if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1;
158 else dwL1=dw1;
159 dw2=(xap->freq*100/xap->nsamples);
160 if((!dw1)||((dw2+100)>=dw1)) iLastSize=0;
161 else
162 {
163 iLastSize=iSize*dw2/dw1;
164 if(iLastSize>iPlace) iLastSize=iPlace;
165 iSize=iLastSize;
166 }
167 iFPSCnt=0;dwFPS=0;
168 }
169 else
170 {
171 if(iLastSize) iSize=iLastSize;
172 }
173 }
174 //----------------------------------------------------//
175
176 spos=0x10000L;
177 sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size
178
179 if(xap->stereo)
180{
181 uint32_t * pS=(uint32_t *)xap->pcm;
182 uint32_t l=0;
183
184 if(iXAPitch)
185 {
186 int32_t l1,l2;short s;
187 for(i=0;i<iSize;i++)
188 {
189 if(iUseInterpolation==2)
190 {
191 while(spos>=0x10000L)
192 {
193 l = *pS++;
194 gauss_window[gauss_ptr] = (short)LOWORD(l);
195 gauss_window[4+gauss_ptr] = (short)HIWORD(l);
196 gauss_ptr = (gauss_ptr+1) & 3;
197 spos -= 0x10000L;
198 }
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;
209 l |= vr << 5;
210 }
211 else
212 {
213 while(spos>=0x10000L)
214 {
215 l = *pS++;
216 spos -= 0x10000L;
217 }
218 }
219
220 s=(short)LOWORD(l);
221 l1=s;
222 l1=(l1*iPlace)/iSize;
223 if(l1<-32767) l1=-32767;
224 if(l1> 32767) l1=32767;
225 s=(short)HIWORD(l);
226 l2=s;
227 l2=(l2*iPlace)/iSize;
228 if(l2<-32767) l2=-32767;
229 if(l2> 32767) l2=32767;
230 l=(l1&0xffff)|(l2<<16);
231
232 *XAFeed++=l;
233
234 if(XAFeed==XAEnd) XAFeed=XAStart;
235 if(XAFeed==XAPlay)
236 {
237 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
238 break;
239 }
240
241 spos += sinc;
242 }
243 }
244 else
245 {
246 for(i=0;i<iSize;i++)
247 {
248 if(iUseInterpolation==2)
249 {
250 while(spos>=0x10000L)
251 {
252 l = *pS++;
253 gauss_window[gauss_ptr] = (short)LOWORD(l);
254 gauss_window[4+gauss_ptr] = (short)HIWORD(l);
255 gauss_ptr = (gauss_ptr+1) & 3;
256 spos -= 0x10000L;
257 }
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;
268 l |= vr << 5;
269 }
270 else
271 {
272 while(spos>=0x10000L)
273 {
274 l = *pS++;
275 spos -= 0x10000L;
276 }
277 }
278
279 *XAFeed++=l;
280
281 if(XAFeed==XAEnd) XAFeed=XAStart;
282 if(XAFeed==XAPlay)
283 {
284 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
285 break;
286 }
287
288 spos += sinc;
289 }
290 }
291 }
292 else
293 {
294 unsigned short * pS=(unsigned short *)xap->pcm;
295 uint32_t l;short s=0;
296
297 if(iXAPitch)
298 {
299 int32_t l1;
300 for(i=0;i<iSize;i++)
301 {
302 if(iUseInterpolation==2)
303 {
304 while(spos>=0x10000L)
305 {
306 gauss_window[gauss_ptr] = (short)*pS++;
307 gauss_ptr = (gauss_ptr+1) & 3;
308 spos -= 0x10000L;
309 }
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;
315 l1=s= vr >> 11;
316 l1 &= 0xffff;
317 }
318 else
319 {
320 while(spos>=0x10000L)
321 {
322 s = *pS++;
323 spos -= 0x10000L;
324 }
325 l1=s;
326 }
327
328 l1=(l1*iPlace)/iSize;
329 if(l1<-32767) l1=-32767;
330 if(l1> 32767) l1=32767;
331 l=(l1&0xffff)|(l1<<16);
332 *XAFeed++=l;
333
334 if(XAFeed==XAEnd) XAFeed=XAStart;
335 if(XAFeed==XAPlay)
336 {
337 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
338 break;
339 }
340
341 spos += sinc;
342 }
343 }
344 else
345 {
346 for(i=0;i<iSize;i++)
347 {
348 if(iUseInterpolation==2)
349 {
350 while(spos>=0x10000L)
351 {
352 gauss_window[gauss_ptr] = (short)*pS++;
353 gauss_ptr = (gauss_ptr+1) & 3;
354 spos -= 0x10000L;
355 }
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;
361 l=s= vr >> 11;
362 l &= 0xffff;
363 }
364 else
365 {
366 while(spos>=0x10000L)
367 {
368 s = *pS++;
369 spos -= 0x10000L;
370 }
371 l=s;
372 }
373
374 *XAFeed++=(l|(l<<16));
375
376 if(XAFeed==XAEnd) XAFeed=XAStart;
377 if(XAFeed==XAPlay)
378 {
379 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
380 break;
381 }
382
383 spos += sinc;
384 }
385 }
386 }
387}
388
389////////////////////////////////////////////////////////////////////////
390// FEED CDDA
391////////////////////////////////////////////////////////////////////////
392
393INLINE void FeedCDDA(unsigned char *pcm, int nBytes)
394{
395 while(nBytes>0)
396 {
397 if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart;
398 while(CDDAFeed==CDDAPlay-1||
399 (CDDAFeed==CDDAEnd-1&&CDDAPlay==CDDAStart))
400 {
401 if (!iUseTimer) usleep(1000);
402 else return;
403 }
404 *CDDAFeed++=(*pcm | (*(pcm+1)<<8) | (*(pcm+2)<<16) | (*(pcm+3)<<24));
405 nBytes-=4;
406 pcm+=4;
407 }
408}
409
410#endif