psx_gpu: flush render buffer before move/cppy/fill
[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;
381ea103 98 SSumLR[ns++]+=(((short)(l&0xffff)) * iLeftXAVol) >> 15;
99 SSumLR[ns++]+=(((short)((l>>16)&0xffff)) * iRightXAVol) >> 15;
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;
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