sort out 32/64bit savestate compat issues
[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;
efce366c 62 short l, r;
63 uint32_t v;
64 int cursor = decode_pos;
ef79bbde 65
efce366c 66 if(XAPlay != XAFeed || XARepeat > 0)
67 {
68 if(XAPlay == XAFeed)
ef79bbde 69 XARepeat--;
efce366c 70
71 v = XALastVal;
72 for(ns=0;ns<NSSIZE*2;)
73 {
74 if(XAPlay != XAFeed) v=*XAPlay++;
75 if(XAPlay == XAEnd) XAPlay=XAStart;
76
77 l = ((int)(short)v * iLeftXAVol) >> 15;
78 r = ((int)(short)(v >> 16) * iLeftXAVol) >> 15;
79 SSumLR[ns++] += l;
80 SSumLR[ns++] += r;
81 spuMem[cursor] = l;
82 spuMem[cursor + 0x400/2] = r;
83 cursor = (cursor + 1) & 0x1ff;
84 }
85 XALastVal = v;
86 }
ef79bbde 87
97ea4077 88 for(ns=0;ns<NSSIZE*2 && CDDAPlay!=CDDAFeed && (CDDAPlay!=CDDAEnd-1||CDDAFeed!=CDDAStart);)
ef79bbde 89 {
efce366c 90 v=*CDDAPlay++;
ef79bbde 91 if(CDDAPlay==CDDAEnd) CDDAPlay=CDDAStart;
efce366c 92
93 l = ((int)(short)v * iLeftXAVol) >> 15;
94 r = ((int)(short)(v >> 16) * iLeftXAVol) >> 15;
95 SSumLR[ns++] += l;
96 SSumLR[ns++] += r;
97 spuMem[cursor] = l;
98 spuMem[cursor + 0x400/2] = r;
99 cursor = (cursor + 1) & 0x1ff;
ef79bbde
P
100 }
101}
102
103////////////////////////////////////////////////////////////////////////
104// small linux time helper... only used for watchdog
105////////////////////////////////////////////////////////////////////////
106
f05d6ca2 107static unsigned long timeGetTime_spu()
ef79bbde
P
108{
109 struct timeval tv;
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
112}
113
114////////////////////////////////////////////////////////////////////////
115// FEED XA
116////////////////////////////////////////////////////////////////////////
117
118INLINE void FeedXA(xa_decode_t *xap)
119{
120 int sinc,spos,i,iSize,iPlace,vl,vr;
121
122 if(!bSPUIsOpen) return;
123
124 xapGlobal = xap; // store info for save states
125 XARepeat = 100; // set up repeat
126
97ea4077 127#if 0//def XA_HACK
ef79bbde
P
128 iSize=((45500*xap->nsamples)/xap->freq); // get size
129#else
130 iSize=((44100*xap->nsamples)/xap->freq); // get size
131#endif
132 if(!iSize) return; // none? bye
133
134 if(XAFeed<XAPlay) iPlace=XAPlay-XAFeed; // how much space in my buf?
135 else iPlace=(XAEnd-XAFeed) + (XAPlay-XAStart);
136
137 if(iPlace==0) return; // no place at all
138
139 //----------------------------------------------------//
140 if(iXAPitch) // pitch change option?
141 {
142 static DWORD dwLT=0;
143 static DWORD dwFPS=0;
144 static int iFPSCnt=0;
145 static int iLastSize=0;
146 static DWORD dwL1=0;
147 DWORD dw=timeGetTime_spu(),dw1,dw2;
148
149 iPlace=iSize;
150
151 dwFPS+=dw-dwLT;iFPSCnt++;
152
153 dwLT=dw;
154
155 if(iFPSCnt>=10)
156 {
157 if(!dwFPS) dwFPS=1;
158 dw1=1000000/dwFPS;
159 if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1;
160 else dwL1=dw1;
161 dw2=(xap->freq*100/xap->nsamples);
162 if((!dw1)||((dw2+100)>=dw1)) iLastSize=0;
163 else
164 {
165 iLastSize=iSize*dw2/dw1;
166 if(iLastSize>iPlace) iLastSize=iPlace;
167 iSize=iLastSize;
168 }
169 iFPSCnt=0;dwFPS=0;
170 }
171 else
172 {
173 if(iLastSize) iSize=iLastSize;
174 }
175 }
176 //----------------------------------------------------//
177
178 spos=0x10000L;
179 sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size
180
181 if(xap->stereo)
182{
183 uint32_t * pS=(uint32_t *)xap->pcm;
184 uint32_t l=0;
185
186 if(iXAPitch)
187 {
188 int32_t l1,l2;short s;
189 for(i=0;i<iSize;i++)
190 {
191 if(iUseInterpolation==2)
192 {
193 while(spos>=0x10000L)
194 {
195 l = *pS++;
196 gauss_window[gauss_ptr] = (short)LOWORD(l);
197 gauss_window[4+gauss_ptr] = (short)HIWORD(l);
198 gauss_ptr = (gauss_ptr+1) & 3;
199 spos -= 0x10000L;
200 }
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;
211 l |= vr << 5;
212 }
213 else
214 {
215 while(spos>=0x10000L)
216 {
217 l = *pS++;
218 spos -= 0x10000L;
219 }
220 }
221
222 s=(short)LOWORD(l);
223 l1=s;
224 l1=(l1*iPlace)/iSize;
381ea103 225 ssat32_to_16(l1);
ef79bbde
P
226 s=(short)HIWORD(l);
227 l2=s;
228 l2=(l2*iPlace)/iSize;
381ea103 229 ssat32_to_16(l2);
ef79bbde
P
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;
381ea103 329 ssat32_to_16(l1);
ef79bbde
P
330 l=(l1&0xffff)|(l1<<16);
331 *XAFeed++=l;
332
333 if(XAFeed==XAEnd) XAFeed=XAStart;
334 if(XAFeed==XAPlay)
335 {
336 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
337 break;
338 }
339
340 spos += sinc;
341 }
342 }
343 else
344 {
345 for(i=0;i<iSize;i++)
346 {
347 if(iUseInterpolation==2)
348 {
349 while(spos>=0x10000L)
350 {
351 gauss_window[gauss_ptr] = (short)*pS++;
352 gauss_ptr = (gauss_ptr+1) & 3;
353 spos -= 0x10000L;
354 }
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;
360 l=s= vr >> 11;
ef79bbde
P
361 }
362 else
363 {
364 while(spos>=0x10000L)
365 {
366 s = *pS++;
367 spos -= 0x10000L;
368 }
369 l=s;
370 }
371
9098b863 372 l &= 0xffff;
ef79bbde
P
373 *XAFeed++=(l|(l<<16));
374
375 if(XAFeed==XAEnd) XAFeed=XAStart;
376 if(XAFeed==XAPlay)
377 {
378 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
379 break;
380 }
381
382 spos += sinc;
383 }
384 }
385 }
386}
387
388////////////////////////////////////////////////////////////////////////
389// FEED CDDA
390////////////////////////////////////////////////////////////////////////
391
983a7cfd 392INLINE int FeedCDDA(unsigned char *pcm, int nBytes)
ef79bbde 393{
983a7cfd 394 int space;
395 space=(CDDAPlay-CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1);
396 if(space<nBytes)
397 return 0x7761; // rearmed_wait
398
ef79bbde
P
399 while(nBytes>0)
400 {
401 if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart;
983a7cfd 402 space=(CDDAPlay-CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1);
403 if(CDDAFeed+space/4>CDDAEnd)
404 space=(CDDAEnd-CDDAFeed)*4;
405 if(space>nBytes)
406 space=nBytes;
407
408 memcpy(CDDAFeed,pcm,space);
409 CDDAFeed+=space/4;
410 nBytes-=space;
411 pcm+=space;
ef79bbde 412 }
983a7cfd 413
414 return 0x676f; // rearmed_go
ef79bbde
P
415}
416
417#endif