drc: merge Ari64's patch: 14_dont_save_or_restore_temporary
[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
97ea4077 25#define XA_HACK
26
ef79bbde
P
27////////////////////////////////////////////////////////////////////////
28// XA GLOBALS
29////////////////////////////////////////////////////////////////////////
30
31xa_decode_t * xapGlobal=0;
32
33uint32_t * XAFeed = NULL;
34uint32_t * XAPlay = NULL;
35uint32_t * XAStart = NULL;
36uint32_t * XAEnd = NULL;
37
38uint32_t XARepeat = 0;
39uint32_t XALastVal = 0;
40
41uint32_t * CDDAFeed = NULL;
42uint32_t * CDDAPlay = NULL;
43uint32_t * CDDAStart = NULL;
44uint32_t * CDDAEnd = NULL;
45
46int iLeftXAVol = 32767;
47int iRightXAVol = 32767;
48
49static int gauss_ptr = 0;
50static int gauss_window[8] = {0, 0, 0, 0, 0, 0, 0, 0};
51
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)]
56
57////////////////////////////////////////////////////////////////////////
58// MIX XA & CDDA
59////////////////////////////////////////////////////////////////////////
60
61INLINE void MixXA(void)
62{
63 int ns;
64 uint32_t l;
65
97ea4077 66 for(ns=0;ns<NSSIZE*2 && XAPlay!=XAFeed;)
ef79bbde
P
67 {
68 XALastVal=*XAPlay++;
69 if(XAPlay==XAEnd) XAPlay=XAStart;
70#ifdef XA_HACK
97ea4077 71 SSumLR[ns++]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32768;
72 SSumLR[ns++]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32768;
ef79bbde 73#else
97ea4077 74 SSumLR[ns++]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767;
75 SSumLR[ns++]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
ef79bbde
P
76#endif
77 }
78
79 if(XAPlay==XAFeed && XARepeat)
80 {
81 XARepeat--;
97ea4077 82 for(;ns<NSSIZE*2;)
ef79bbde
P
83 {
84#ifdef XA_HACK
97ea4077 85 SSumLR[ns++]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32768;
86 SSumLR[ns++]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32768;
ef79bbde 87#else
97ea4077 88 SSumLR[ns++]+=(((short)(XALastVal&0xffff)) * iLeftXAVol)/32767;
89 SSumLR[ns++]+=(((short)((XALastVal>>16)&0xffff)) * iRightXAVol)/32767;
ef79bbde
P
90#endif
91 }
92 }
93
97ea4077 94 for(ns=0;ns<NSSIZE*2 && CDDAPlay!=CDDAFeed && (CDDAPlay!=CDDAEnd-1||CDDAFeed!=CDDAStart);)
ef79bbde
P
95 {
96 l=*CDDAPlay++;
97 if(CDDAPlay==CDDAEnd) CDDAPlay=CDDAStart;
97ea4077 98 SSumLR[ns++]+=(((short)(l&0xffff)) * iLeftXAVol)/32767;
99 SSumLR[ns++]+=(((short)((l>>16)&0xffff)) * iRightXAVol)/32767;
ef79bbde
P
100 }
101}
102
103////////////////////////////////////////////////////////////////////////
104// small linux time helper... only used for watchdog
105////////////////////////////////////////////////////////////////////////
106
107unsigned long timeGetTime_spu()
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;
225 if(l1<-32767) l1=-32767;
226 if(l1> 32767) l1=32767;
227 s=(short)HIWORD(l);
228 l2=s;
229 l2=(l2*iPlace)/iSize;
230 if(l2<-32767) l2=-32767;
231 if(l2> 32767) l2=32767;
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;
331 if(l1<-32767) l1=-32767;
332 if(l1> 32767) l1=32767;
333 l=(l1&0xffff)|(l1<<16);
334 *XAFeed++=l;
335
336 if(XAFeed==XAEnd) XAFeed=XAStart;
337 if(XAFeed==XAPlay)
338 {
339 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
340 break;
341 }
342
343 spos += sinc;
344 }
345 }
346 else
347 {
348 for(i=0;i<iSize;i++)
349 {
350 if(iUseInterpolation==2)
351 {
352 while(spos>=0x10000L)
353 {
354 gauss_window[gauss_ptr] = (short)*pS++;
355 gauss_ptr = (gauss_ptr+1) & 3;
356 spos -= 0x10000L;
357 }
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;
363 l=s= vr >> 11;
ef79bbde
P
364 }
365 else
366 {
367 while(spos>=0x10000L)
368 {
369 s = *pS++;
370 spos -= 0x10000L;
371 }
372 l=s;
373 }
374
9098b863 375 l &= 0xffff;
ef79bbde
P
376 *XAFeed++=(l|(l<<16));
377
378 if(XAFeed==XAEnd) XAFeed=XAStart;
379 if(XAFeed==XAPlay)
380 {
381 if(XAPlay!=XAStart) XAFeed=XAPlay-1;
382 break;
383 }
384
385 spos += sinc;
386 }
387 }
388 }
389}
390
391////////////////////////////////////////////////////////////////////////
392// FEED CDDA
393////////////////////////////////////////////////////////////////////////
394
395INLINE void FeedCDDA(unsigned char *pcm, int nBytes)
396{
397 while(nBytes>0)
398 {
399 if(CDDAFeed==CDDAEnd) CDDAFeed=CDDAStart;
400 while(CDDAFeed==CDDAPlay-1||
401 (CDDAFeed==CDDAEnd-1&&CDDAPlay==CDDAStart))
402 {
403 if (!iUseTimer) usleep(1000);
404 else return;
405 }
406 *CDDAFeed++=(*pcm | (*(pcm+1)<<8) | (*(pcm+2)<<16) | (*(pcm+3)<<24));
407 nBytes-=4;
408 pcm+=4;
409 }
410}
411
412#endif