asm: fix incorrect offsets
[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;
1d753163 81
82 spuMem[cursor] = v;
83 spuMem[cursor + 0x400/2] = v >> 16;
efce366c 84 cursor = (cursor + 1) & 0x1ff;
85 }
86 XALastVal = v;
87 }
ef79bbde 88
97ea4077 89 for(ns=0;ns<NSSIZE*2 && CDDAPlay!=CDDAFeed && (CDDAPlay!=CDDAEnd-1||CDDAFeed!=CDDAStart);)
ef79bbde 90 {
efce366c 91 v=*CDDAPlay++;
ef79bbde 92 if(CDDAPlay==CDDAEnd) CDDAPlay=CDDAStart;
efce366c 93
94 l = ((int)(short)v * iLeftXAVol) >> 15;
95 r = ((int)(short)(v >> 16) * iLeftXAVol) >> 15;
96 SSumLR[ns++] += l;
97 SSumLR[ns++] += r;
1d753163 98
99 spuMem[cursor] = v;
100 spuMem[cursor + 0x400/2] = v >> 16;
efce366c 101 cursor = (cursor + 1) & 0x1ff;
ef79bbde
P
102 }
103}
104
105////////////////////////////////////////////////////////////////////////
106// small linux time helper... only used for watchdog
107////////////////////////////////////////////////////////////////////////
108
f05d6ca2 109static unsigned long timeGetTime_spu()
ef79bbde
P
110{
111 struct timeval tv;
112 gettimeofday(&tv, 0); // well, maybe there are better ways
113 return tv.tv_sec * 1000 + tv.tv_usec/1000; // to do that, but at least it works
114}
115
116////////////////////////////////////////////////////////////////////////
117// FEED XA
118////////////////////////////////////////////////////////////////////////
119
120INLINE void FeedXA(xa_decode_t *xap)
121{
122 int sinc,spos,i,iSize,iPlace,vl,vr;
123
124 if(!bSPUIsOpen) return;
125
126 xapGlobal = xap; // store info for save states
127 XARepeat = 100; // set up repeat
128
97ea4077 129#if 0//def XA_HACK
ef79bbde
P
130 iSize=((45500*xap->nsamples)/xap->freq); // get size
131#else
132 iSize=((44100*xap->nsamples)/xap->freq); // get size
133#endif
134 if(!iSize) return; // none? bye
135
136 if(XAFeed<XAPlay) iPlace=XAPlay-XAFeed; // how much space in my buf?
137 else iPlace=(XAEnd-XAFeed) + (XAPlay-XAStart);
138
139 if(iPlace==0) return; // no place at all
140
141 //----------------------------------------------------//
142 if(iXAPitch) // pitch change option?
143 {
144 static DWORD dwLT=0;
145 static DWORD dwFPS=0;
146 static int iFPSCnt=0;
147 static int iLastSize=0;
148 static DWORD dwL1=0;
149 DWORD dw=timeGetTime_spu(),dw1,dw2;
150
151 iPlace=iSize;
152
153 dwFPS+=dw-dwLT;iFPSCnt++;
154
155 dwLT=dw;
156
157 if(iFPSCnt>=10)
158 {
159 if(!dwFPS) dwFPS=1;
160 dw1=1000000/dwFPS;
161 if(dw1>=(dwL1-100) && dw1<=(dwL1+100)) dw1=dwL1;
162 else dwL1=dw1;
163 dw2=(xap->freq*100/xap->nsamples);
164 if((!dw1)||((dw2+100)>=dw1)) iLastSize=0;
165 else
166 {
167 iLastSize=iSize*dw2/dw1;
168 if(iLastSize>iPlace) iLastSize=iPlace;
169 iSize=iLastSize;
170 }
171 iFPSCnt=0;dwFPS=0;
172 }
173 else
174 {
175 if(iLastSize) iSize=iLastSize;
176 }
177 }
178 //----------------------------------------------------//
179
180 spos=0x10000L;
181 sinc = (xap->nsamples << 16) / iSize; // calc freq by num / size
182
183 if(xap->stereo)
184{
185 uint32_t * pS=(uint32_t *)xap->pcm;
186 uint32_t l=0;
187
188 if(iXAPitch)
189 {
190 int32_t l1,l2;short s;
191 for(i=0;i<iSize;i++)
192 {
193 if(iUseInterpolation==2)
194 {
195 while(spos>=0x10000L)
196 {
197 l = *pS++;
198 gauss_window[gauss_ptr] = (short)LOWORD(l);
199 gauss_window[4+gauss_ptr] = (short)HIWORD(l);
200 gauss_ptr = (gauss_ptr+1) & 3;
201 spos -= 0x10000L;
202 }
203 vl = (spos >> 6) & ~3;
204 vr=(gauss[vl]*gvall0)&~2047;
205 vr+=(gauss[vl+1]*gvall(1))&~2047;
206 vr+=(gauss[vl+2]*gvall(2))&~2047;
207 vr+=(gauss[vl+3]*gvall(3))&~2047;
208 l= (vr >> 11) & 0xffff;
209 vr=(gauss[vl]*gvalr0)&~2047;
210 vr+=(gauss[vl+1]*gvalr(1))&~2047;
211 vr+=(gauss[vl+2]*gvalr(2))&~2047;
212 vr+=(gauss[vl+3]*gvalr(3))&~2047;
213 l |= vr << 5;
214 }
215 else
216 {
217 while(spos>=0x10000L)
218 {
219 l = *pS++;
220 spos -= 0x10000L;
221 }
222 }
223
224 s=(short)LOWORD(l);
225 l1=s;
226 l1=(l1*iPlace)/iSize;
381ea103 227 ssat32_to_16(l1);
ef79bbde
P
228 s=(short)HIWORD(l);
229 l2=s;
230 l2=(l2*iPlace)/iSize;
381ea103 231 ssat32_to_16(l2);
ef79bbde
P
232 l=(l1&0xffff)|(l2<<16);
233
234 *XAFeed++=l;
235
236 if(XAFeed==XAEnd) XAFeed=XAStart;
237 if(XAFeed==XAPlay)
238 {
239 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
240 break;
241 }
242
243 spos += sinc;
244 }
245 }
246 else
247 {
248 for(i=0;i<iSize;i++)
249 {
250 if(iUseInterpolation==2)
251 {
252 while(spos>=0x10000L)
253 {
254 l = *pS++;
255 gauss_window[gauss_ptr] = (short)LOWORD(l);
256 gauss_window[4+gauss_ptr] = (short)HIWORD(l);
257 gauss_ptr = (gauss_ptr+1) & 3;
258 spos -= 0x10000L;
259 }
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;
270 l |= vr << 5;
271 }
272 else
273 {
274 while(spos>=0x10000L)
275 {
276 l = *pS++;
277 spos -= 0x10000L;
278 }
279 }
280
281 *XAFeed++=l;
282
283 if(XAFeed==XAEnd) XAFeed=XAStart;
284 if(XAFeed==XAPlay)
285 {
286 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
287 break;
288 }
289
290 spos += sinc;
291 }
292 }
293 }
294 else
295 {
296 unsigned short * pS=(unsigned short *)xap->pcm;
297 uint32_t l;short s=0;
298
299 if(iXAPitch)
300 {
301 int32_t l1;
302 for(i=0;i<iSize;i++)
303 {
304 if(iUseInterpolation==2)
305 {
306 while(spos>=0x10000L)
307 {
308 gauss_window[gauss_ptr] = (short)*pS++;
309 gauss_ptr = (gauss_ptr+1) & 3;
310 spos -= 0x10000L;
311 }
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;
317 l1=s= vr >> 11;
318 l1 &= 0xffff;
319 }
320 else
321 {
322 while(spos>=0x10000L)
323 {
324 s = *pS++;
325 spos -= 0x10000L;
326 }
327 l1=s;
328 }
329
330 l1=(l1*iPlace)/iSize;
381ea103 331 ssat32_to_16(l1);
ef79bbde
P
332 l=(l1&0xffff)|(l1<<16);
333 *XAFeed++=l;
334
335 if(XAFeed==XAEnd) XAFeed=XAStart;
336 if(XAFeed==XAPlay)
337 {
338 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
339 break;
340 }
341
342 spos += sinc;
343 }
344 }
345 else
346 {
347 for(i=0;i<iSize;i++)
348 {
349 if(iUseInterpolation==2)
350 {
351 while(spos>=0x10000L)
352 {
353 gauss_window[gauss_ptr] = (short)*pS++;
354 gauss_ptr = (gauss_ptr+1) & 3;
355 spos -= 0x10000L;
356 }
357 vl = (spos >> 6) & ~3;
358 vr=(gauss[vl]*gvall0)&~2047;
359 vr+=(gauss[vl+1]*gvall(1))&~2047;
360 vr+=(gauss[vl+2]*gvall(2))&~2047;
361 vr+=(gauss[vl+3]*gvall(3))&~2047;
362 l=s= vr >> 11;
ef79bbde
P
363 }
364 else
365 {
366 while(spos>=0x10000L)
367 {
368 s = *pS++;
369 spos -= 0x10000L;
370 }
371 l=s;
372 }
373
9098b863 374 l &= 0xffff;
ef79bbde
P
375 *XAFeed++=(l|(l<<16));
376
377 if(XAFeed==XAEnd) XAFeed=XAStart;
378 if(XAFeed==XAPlay)
379 {
380 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
381 break;
382 }
383
384 spos += sinc;
385 }
386 }
387 }
388}
389
390////////////////////////////////////////////////////////////////////////
391// FEED CDDA
392////////////////////////////////////////////////////////////////////////
393
983a7cfd 394INLINE int FeedCDDA(unsigned char *pcm, int nBytes)
ef79bbde 395{
983a7cfd 396 int space;
397 space=(CDDAPlay-CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1);
398 if(space<nBytes)
399 return 0x7761; // rearmed_wait
400
ef79bbde
P
401 while(nBytes>0)
402 {
403 if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart;
983a7cfd 404 space=(CDDAPlay-CDDAFeed-1)*4 & (CDDA_BUFFER_SIZE - 1);
405 if(CDDAFeed+space/4>CDDAEnd)
406 space=(CDDAEnd-CDDAFeed)*4;
407 if(space>nBytes)
408 space=nBytes;
409
410 memcpy(CDDAFeed,pcm,space);
411 CDDAFeed+=space/4;
412 nBytes-=space;
413 pcm+=space;
ef79bbde 414 }
983a7cfd 415
416 return 0x676f; // rearmed_go
ef79bbde
P
417}
418
419#endif