Mercurial > audlegacy
comparison Plugins/Input/sexypsf/spu/spu.c @ 854:61e7332e0652 trunk
[svn] - PSF2 support (everything is BORKED right now)
author | nenolod |
---|---|
date | Sun, 19 Mar 2006 12:51:03 -0800 |
parents | d539e5c5f730 |
children |
comparison
equal
deleted
inserted
replaced
853:74576869a506 | 854:61e7332e0652 |
---|---|
17 ***************************************************************************/ | 17 ***************************************************************************/ |
18 | 18 |
19 //*************************************************************************// | 19 //*************************************************************************// |
20 // History of changes: | 20 // History of changes: |
21 // | 21 // |
22 // 2005/08/29 - Pete | |
23 // - changed to 48Khz output | |
24 // | |
25 // 2004/12/25 - Pete | |
26 // - inc'd version for pcsx2-0.7 | |
27 // | |
28 // 2004/04/18 - Pete | |
29 // - changed all kind of things in the plugin | |
30 // | |
31 // 2004/04/04 - Pete | |
32 // - changed plugin to emulate PS2 spu | |
33 // | |
34 // 2003/04/07 - Eric | |
35 // - adjusted cubic interpolation algorithm | |
36 // | |
37 // 2003/03/16 - Eric | |
38 // - added cubic interpolation | |
39 // | |
22 // 2003/03/01 - linuzappz | 40 // 2003/03/01 - linuzappz |
23 // - libraryName changes using ALSA | 41 // - libraryName changes using ALSA |
24 // | 42 // |
25 // 2003/02/28 - Pete | 43 // 2003/02/28 - Pete |
26 // - added option for type of interpolation | 44 // - added option for type of interpolation |
75 // 2002/05/15 - Pete | 93 // 2002/05/15 - Pete |
76 // - generic cleanup for the Peops release | 94 // - generic cleanup for the Peops release |
77 // | 95 // |
78 //*************************************************************************// | 96 //*************************************************************************// |
79 | 97 |
98 #include "stdafx.h" | |
99 | |
80 #define _IN_SPU | 100 #define _IN_SPU |
81 | 101 |
82 #include "stdafx.h" | |
83 #include "externals.h" | 102 #include "externals.h" |
84 #include "spu.h" | 103 #include "cfg.h" |
104 #include "dsoundoss.h" | |
85 #include "regs.h" | 105 #include "regs.h" |
86 #include "registers.h" | 106 #include "debug.h" |
87 | 107 #include "record.h" |
88 #include "PsxMem.h" | 108 #include "resource.h" |
89 #include "driver.h" | 109 #include "dma.h" |
110 | |
111 //////////////////////////////////////////////////////////////////////// | |
112 // spu version infos/name | |
113 //////////////////////////////////////////////////////////////////////// | |
114 | |
115 const unsigned char version = 4; | |
116 const unsigned char revision = 1; | |
117 const unsigned char build = 3; | |
118 #ifdef _WINDOWS | |
119 static char * libraryName = "P.E.Op.S. SPU2 DSound Driver"; | |
120 #else | |
121 #ifndef USEALSA | |
122 static char * libraryName = "P.E.Op.S. SPU2 OSS Driver"; | |
123 #else | |
124 static char * libraryName = "P.E.Op.S. SPU2 ALSA Driver"; | |
125 #endif | |
126 #endif | |
127 static char * libraryInfo = "P.E.Op.S. SPU2 Driver V1.3\nCoded by Pete Bernert and the P.E.Op.S. team\n"; | |
90 | 128 |
91 //////////////////////////////////////////////////////////////////////// | 129 //////////////////////////////////////////////////////////////////////// |
92 // globals | 130 // globals |
93 //////////////////////////////////////////////////////////////////////// | 131 //////////////////////////////////////////////////////////////////////// |
94 | 132 |
95 // psx buffer / addresses | 133 // psx buffer / addresses |
96 | 134 |
97 static u16 regArea[0x200]; | 135 unsigned short regArea[32*1024]; |
98 static u16 spuMem[256*1024]; | 136 unsigned short spuMem[1*1024*1024]; |
99 static u8 * spuMemC; | 137 unsigned char * spuMemC; |
100 static u8 * pSpuIrq=0; | 138 unsigned char * pSpuIrq[2]; |
101 static u8 * pSpuBuffer; | 139 unsigned char * pSpuBuffer; |
102 | 140 |
103 // user settings | 141 // sexypsf tracking stuff |
104 static int iVolume; | 142 |
105 | 143 static unsigned long seektime; |
106 // MAIN infos struct for each channel | 144 static unsigned long sampcount; |
107 | 145 static unsigned long decaybegin; |
108 static SPUCHAN s_chan[MAXCHAN+1]; // channel + 1 infos (1 is security for fmod handling) | 146 static unsigned long decayend; |
109 static REVERBInfo rvb; | 147 |
110 | 148 void SPUsetlength(long stop, long fade) |
111 static u32 dwNoiseVal=1; // global noise generator | |
112 | |
113 static u16 spuCtrl=0; // some vars to store psx reg infos | |
114 static u16 spuStat=0; | |
115 static u16 spuIrq=0; | |
116 static u32 spuAddr=0xffffffff; // address into spu mem | |
117 static int bSPUIsOpen=0; | |
118 | |
119 static const int f[5][2] = { | |
120 { 0, 0 }, | |
121 { 60, 0 }, | |
122 { 115, -52 }, | |
123 { 98, -55 }, | |
124 { 122, -60 } }; | |
125 s16 * pS; | |
126 | |
127 //////////////////////////////////////////////////////////////////////// | |
128 // CODE AREA | |
129 //////////////////////////////////////////////////////////////////////// | |
130 | |
131 // dirty inline func includes | |
132 | |
133 #include "reverb.c" | |
134 #include "adsr.c" | |
135 | |
136 // Try this to increase speed. | |
137 #include "registers.c" | |
138 #include "dma.c" | |
139 | |
140 //////////////////////////////////////////////////////////////////////// | |
141 // helpers for so-called "gauss interpolation" | |
142 | |
143 #define gval0 (((int *)(&s_chan[ch].SB[29]))[gpos]) | |
144 #define gval(x) (((int *)(&s_chan[ch].SB[29]))[(gpos+x)&3]) | |
145 | |
146 #include "gauss_i.h" | |
147 | |
148 //////////////////////////////////////////////////////////////////////// | |
149 | |
150 //////////////////////////////////////////////////////////////////////// | |
151 // START SOUND... called by main thread to setup a new sound on a channel | |
152 //////////////////////////////////////////////////////////////////////// | |
153 | |
154 static INLINE void StartSound(int ch) | |
155 { | |
156 StartADSR(ch); | |
157 | |
158 s_chan[ch].pCurr=s_chan[ch].pStart; // set sample start | |
159 | |
160 s_chan[ch].s_1=0; // init mixing vars | |
161 s_chan[ch].s_2=0; | |
162 s_chan[ch].iSBPos=28; | |
163 | |
164 s_chan[ch].bNew=0; // init channel flags | |
165 s_chan[ch].bStop=0; | |
166 s_chan[ch].bOn=1; | |
167 | |
168 s_chan[ch].SB[29]=0; // init our interpolation helpers | |
169 s_chan[ch].SB[30]=0; | |
170 | |
171 s_chan[ch].spos=0x40000L;s_chan[ch].SB[28]=0; // -> start with more decoding | |
172 } | |
173 | |
174 //////////////////////////////////////////////////////////////////////// | |
175 // MAIN SPU FUNCTION | |
176 // here is the main job handler... thread, timer or direct func call | |
177 // basically the whole sound processing is done in this fat func! | |
178 //////////////////////////////////////////////////////////////////////// | |
179 | |
180 static u32 sampcount; | |
181 static u32 decaybegin; | |
182 static u32 decayend; | |
183 | |
184 // Counting to 65536 results in full volume offage. | |
185 void SPUsetlength(s32 stop, s32 fade) | |
186 { | 149 { |
187 if(stop==~0) | 150 if(stop==~0) |
188 { | 151 { |
189 decaybegin=~0; | 152 decaybegin=~0; |
190 } | 153 } |
196 decaybegin=stop; | 159 decaybegin=stop; |
197 decayend=stop+fade; | 160 decayend=stop+fade; |
198 } | 161 } |
199 } | 162 } |
200 | 163 |
201 static u32 seektime; | 164 // user settings |
202 static s32 poo; | 165 |
203 int sexypsf_seek(u32 t) | 166 int iUseXA=1; |
204 { | 167 int iVolume=3; |
205 seektime=t*441/10; | 168 int iXAPitch=1; |
206 if(seektime>sampcount) return(1); | 169 int iUseTimer=2; |
207 return(0); | 170 int iSPUIRQWait=1; |
208 } | 171 int iDebugMode=0; |
209 | 172 int iRecordMode=0; |
210 #define CLIP(_x) {if(_x>32767) _x=32767; if(_x<-32767) _x=-32767;} | 173 int iUseReverb=0; |
211 int SPUasync(u32 cycles) | 174 int iUseInterpolation=2; |
212 { | 175 int iDisStereo=0; |
213 int volmul=iVolume; | 176 |
214 static s32 dosampies; | 177 // MAIN infos struct for each channel |
215 s32 temp; | 178 |
216 | 179 SPUCHAN s_chan[MAXCHAN+1]; // channel + 1 infos (1 is security for fmod handling) |
217 poo+=cycles; | 180 REVERBInfo rvb[2]; |
218 dosampies=poo/384; | 181 |
219 if(!dosampies) return(1); | 182 unsigned long dwNoiseVal=1; // global noise generator |
220 poo-=dosampies*384; | 183 |
221 temp=dosampies; | 184 unsigned short spuCtrl2[2]; // some vars to store psx reg infos |
222 | 185 unsigned short spuStat2[2]; |
223 while(temp) | 186 unsigned long spuIrq2[2]; |
224 { | 187 unsigned long spuAddr2[2]; // address into spu mem |
225 s32 revLeft=0, revRight=0; | 188 unsigned long spuRvbAddr2[2]; |
226 s32 sl=0, sr=0; | 189 unsigned long spuRvbAEnd2[2]; |
227 int ch,fa; | 190 int bEndThread=0; // thread handlers |
228 | 191 int bThreadEnded=0; |
229 temp--; | 192 int bSpuInit=0; |
193 int bSPUIsOpen=0; | |
194 | |
195 #ifdef _WINDOWS | |
196 HWND hWMain=0; // window handle | |
197 HWND hWDebug=0; | |
198 HWND hWRecord=0; | |
199 static HANDLE hMainThread; | |
200 #else | |
201 // 2003/06/07 - Pete | |
202 #ifndef NOTHREADLIB | |
203 static pthread_t thread = -1; // thread id (linux) | |
204 #endif | |
205 #endif | |
206 | |
207 unsigned long dwNewChannel2[2]; // flags for faster testing, if new channel starts | |
208 unsigned long dwEndChannel2[2]; | |
209 | |
210 // UNUSED IN PS2 YET | |
211 void (CALLBACK *irqCallback)(void)=0; // func of main emu, called on spu irq | |
212 void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0; | |
213 | |
214 // certain globals (were local before, but with the new timeproc I need em global) | |
215 | |
216 const int f[5][2] = { { 0, 0 }, | |
217 { 60, 0 }, | |
218 { 115, -52 }, | |
219 { 98, -55 }, | |
220 { 122, -60 } }; | |
221 int SSumR[NSSIZE]; | |
222 int SSumL[NSSIZE]; | |
223 int iCycle=0; | |
224 short * pS; | |
225 | |
226 static int lastch=-1; // last channel processed on spu irq in timer mode | |
227 static int lastns=0; // last ns pos | |
228 static int iSecureStart=0; // secure start counter | |
229 | |
230 //////////////////////////////////////////////////////////////////////// | |
231 // CODE AREA | |
232 //////////////////////////////////////////////////////////////////////// | |
233 | |
234 // dirty inline func includes | |
235 | |
236 #include "reverb.c" | |
237 #include "adsr.c" | |
238 | |
239 //////////////////////////////////////////////////////////////////////// | |
240 // helpers for simple interpolation | |
241 | |
242 // | |
243 // easy interpolation on upsampling, no special filter, just "Pete's common sense" tm | |
244 // | |
245 // instead of having n equal sample values in a row like: | |
246 // ____ | |
247 // |____ | |
248 // | |
249 // we compare the current delta change with the next delta change. | |
250 // | |
251 // if curr_delta is positive, | |
252 // | |
253 // - and next delta is smaller (or changing direction): | |
254 // \. | |
255 // -__ | |
256 // | |
257 // - and next delta significant (at least twice) bigger: | |
258 // --_ | |
259 // \. | |
260 // | |
261 // - and next delta is nearly same: | |
262 // \. | |
263 // \. | |
264 // | |
265 // | |
266 // if curr_delta is negative, | |
267 // | |
268 // - and next delta is smaller (or changing direction): | |
269 // _-- | |
270 // / | |
271 // | |
272 // - and next delta significant (at least twice) bigger: | |
273 // / | |
274 // __- | |
275 // | |
276 // - and next delta is nearly same: | |
277 // / | |
278 // / | |
279 // | |
280 | |
281 static unsigned long long SexyTime64(void) | |
282 { | |
283 struct timeval tv; | |
284 unsigned long long ret; | |
285 | |
286 gettimeofday(&tv,0); | |
287 ret=tv.tv_sec; | |
288 ret*=1000000; | |
289 ret+=tv.tv_usec; | |
290 return(ret); | |
291 } | |
292 | |
293 INLINE void InterpolateUp(int ch) | |
294 { | |
295 if(s_chan[ch].SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass | |
296 { | |
297 const int id1=s_chan[ch].SB[30]-s_chan[ch].SB[29]; // curr delta to next val | |
298 const int id2=s_chan[ch].SB[31]-s_chan[ch].SB[30]; // and next delta to next-next val :) | |
299 | |
300 s_chan[ch].SB[32]=0; | |
301 | |
302 if(id1>0) // curr delta positive | |
303 { | |
304 if(id2<id1) | |
305 {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;} | |
306 else | |
307 if(id2<(id1<<1)) | |
308 s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L; | |
309 else | |
310 s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L; | |
311 } | |
312 else // curr delta negative | |
313 { | |
314 if(id2>id1) | |
315 {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;} | |
316 else | |
317 if(id2>(id1<<1)) | |
318 s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L; | |
319 else | |
320 s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L; | |
321 } | |
322 } | |
323 else | |
324 if(s_chan[ch].SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass | |
325 { | |
326 s_chan[ch].SB[32]=0; | |
327 | |
328 s_chan[ch].SB[28]=(s_chan[ch].SB[28]*s_chan[ch].sinc)/0x20000L; | |
329 if(s_chan[ch].sinc<=0x8000) | |
330 s_chan[ch].SB[29]=s_chan[ch].SB[30]-(s_chan[ch].SB[28]*((0x10000/s_chan[ch].sinc)-1)); | |
331 else s_chan[ch].SB[29]+=s_chan[ch].SB[28]; | |
332 } | |
333 else // no flags? add bigger val (if possible), calc smaller step, set flag1 | |
334 s_chan[ch].SB[29]+=s_chan[ch].SB[28]; | |
335 } | |
336 | |
337 // | |
338 // even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm | |
339 // | |
340 | |
341 INLINE void InterpolateDown(int ch) | |
342 { | |
343 if(s_chan[ch].sinc>=0x20000L) // we would skip at least one val? | |
344 { | |
345 s_chan[ch].SB[29]+=(s_chan[ch].SB[30]-s_chan[ch].SB[29])/2; // add easy weight | |
346 if(s_chan[ch].sinc>=0x30000L) // we would skip even more vals? | |
347 s_chan[ch].SB[29]+=(s_chan[ch].SB[31]-s_chan[ch].SB[30])/2;// add additional next weight | |
348 } | |
349 } | |
350 | |
351 //////////////////////////////////////////////////////////////////////// | |
352 // helpers for gauss interpolation | |
353 | |
354 #define gval0 (((short*)(&s_chan[ch].SB[29]))[gpos]) | |
355 #define gval(x) (((short*)(&s_chan[ch].SB[29]))[(gpos+x)&3]) | |
356 | |
357 #include "gauss_i.h" | |
358 | |
359 //////////////////////////////////////////////////////////////////////// | |
360 | |
361 #include "xa.c" | |
362 | |
363 //////////////////////////////////////////////////////////////////////// | |
364 // START SOUND... called by main thread to setup a new sound on a channel | |
365 //////////////////////////////////////////////////////////////////////// | |
366 | |
367 INLINE void StartSound(int ch) | |
368 { | |
369 dwNewChannel2[ch/24]&=~(1<<(ch%24)); // clear new channel bit | |
370 dwEndChannel2[ch/24]&=~(1<<(ch%24)); // clear end channel bit | |
371 | |
372 StartADSR(ch); | |
373 StartREVERB(ch); | |
374 | |
375 s_chan[ch].pCurr=s_chan[ch].pStart; // set sample start | |
376 | |
377 s_chan[ch].s_1=0; // init mixing vars | |
378 s_chan[ch].s_2=0; | |
379 s_chan[ch].iSBPos=28; | |
380 | |
381 s_chan[ch].bNew=0; // init channel flags | |
382 s_chan[ch].bStop=0; | |
383 s_chan[ch].bOn=1; | |
384 | |
385 s_chan[ch].SB[29]=0; // init our interpolation helpers | |
386 s_chan[ch].SB[30]=0; | |
387 | |
388 if(iUseInterpolation>=2) // gauss interpolation? | |
389 {s_chan[ch].spos=0x30000L;s_chan[ch].SB[28]=0;} // -> start with more decoding | |
390 else {s_chan[ch].spos=0x10000L;s_chan[ch].SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding | |
391 } | |
392 | |
393 //////////////////////////////////////////////////////////////////////// | |
394 // MAIN SPU FUNCTION | |
395 // here is the main job handler... thread, timer or direct func call | |
396 // basically the whole sound processing is done in this fat func! | |
397 //////////////////////////////////////////////////////////////////////// | |
398 | |
399 // 5 ms waiting phase, if buffer is full and no new sound has to get started | |
400 // .. can be made smaller (smallest val: 1 ms), but bigger waits give | |
401 // better performance | |
402 | |
403 #define PAUSE_W 5 | |
404 #define PAUSE_L 5000 | |
405 | |
406 //////////////////////////////////////////////////////////////////////// | |
407 | |
408 int iSpuAsyncWait=0; | |
409 | |
410 #ifdef _WINDOWS | |
411 static VOID CALLBACK MAINProc(UINT nTimerId,UINT msg,DWORD dwUser,DWORD dwParam1, DWORD dwParam2) | |
412 #else | |
413 static void *MAINThread(void *arg) | |
414 #endif | |
415 { | |
416 int s_1,s_2,fa,ns,voldiv=iVolume; | |
417 unsigned char * start;unsigned int nSample; | |
418 int ch,predict_nr,shift_factor,flags,d,s; | |
419 int gpos,bIRQReturn=0; | |
420 | |
421 while(!bEndThread) // until we are shutting down | |
422 { | |
423 //--------------------------------------------------// | |
424 // ok, at the beginning we are looking if there is | |
425 // enuff free place in the dsound/oss buffer to | |
426 // fill in new data, or if there is a new channel to start. | |
427 // if not, we wait (thread) or return (timer/spuasync) | |
428 // until enuff free place is available/a new channel gets | |
429 // started | |
430 | |
431 if(dwNewChannel2[0] || dwNewChannel2[1]) // new channel should start immedately? | |
432 { // (at least one bit 0 ... MAXCHANNEL is set?) | |
433 iSecureStart++; // -> set iSecure | |
434 if(iSecureStart>5) iSecureStart=0; // (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance) | |
435 } | |
436 else iSecureStart=0; // 0: no new channel should start | |
437 | |
438 while(!iSecureStart && !bEndThread // no new start? no thread end? | |
439 #if 0 | |
440 && (SoundGetBytesBuffered()>TESTSIZE) | |
441 #endif | |
442 ) // and still enuff data in sound buffer? | |
443 { | |
444 iSecureStart=0; // reset secure | |
445 | |
446 #ifdef _WINDOWS | |
447 if(iUseTimer) // no-thread mode? | |
448 { | |
449 if(iUseTimer==1) // -> ok, timer mode 1: setup a oneshot timer of x ms to wait | |
450 timeSetEvent(PAUSE_W,1,MAINProc,0,TIME_ONESHOT); | |
451 return; // -> and done this time (timer mode 1 or 2) | |
452 } | |
453 // win thread mode: | |
454 Sleep(PAUSE_W); // sleep for x ms (win) | |
455 #else | |
456 if(iUseTimer) return 0; // linux no-thread mode? bye | |
457 usleep(PAUSE_L); // else sleep for x ms (linux) | |
458 #endif | |
459 | |
460 if(dwNewChannel2[0] || dwNewChannel2[1]) | |
461 iSecureStart=1; // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop | |
462 } | |
463 | |
464 //--------------------------------------------------// continue from irq handling in timer mode? | |
465 | |
466 if(lastch>=0) // will be -1 if no continue is pending | |
467 { | |
468 ch=lastch; ns=lastns; lastch=-1; // -> setup all kind of vars to continue | |
469 goto GOON; // -> directly jump to the continue point | |
470 } | |
471 | |
230 //--------------------------------------------------// | 472 //--------------------------------------------------// |
231 //- main channel loop -// | 473 //- main channel loop -// |
232 //--------------------------------------------------// | 474 //--------------------------------------------------// |
233 { | 475 { |
234 for(ch=0;ch<MAXCHAN;ch++) // loop em all. | 476 for(ch=0;ch<MAXCHAN;ch++) // loop em all... we will collect 1 ms of sound of each playing channel |
235 { | 477 { |
236 if(s_chan[ch].bNew) StartSound(ch); // start new sound | 478 if(s_chan[ch].bNew) StartSound(ch); // start new sound |
237 if(!s_chan[ch].bOn) continue; // channel not playing? next | 479 if(!s_chan[ch].bOn) continue; // channel not playing? next |
238 | |
239 | 480 |
240 if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq) // new psx frequency? | 481 if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq) // new psx frequency? |
241 { | 482 { |
242 s_chan[ch].iUsedFreq=s_chan[ch].iActFreq; // -> take it and calc steps | 483 s_chan[ch].iUsedFreq=s_chan[ch].iActFreq; // -> take it and calc steps |
243 s_chan[ch].sinc=s_chan[ch].iRawPitch<<4; | 484 s_chan[ch].sinc=s_chan[ch].iRawPitch<<4; |
244 if(!s_chan[ch].sinc) s_chan[ch].sinc=1; | 485 if(!s_chan[ch].sinc) s_chan[ch].sinc=1; |
486 if(iUseInterpolation==1) s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag | |
245 } | 487 } |
246 | 488 |
489 ns=0; | |
490 while(ns<NSSIZE) // loop until 1 ms of data is reached | |
491 { | |
247 while(s_chan[ch].spos>=0x10000L) | 492 while(s_chan[ch].spos>=0x10000L) |
248 { | 493 { |
249 if(s_chan[ch].iSBPos==28) // 28 reached? | 494 if(s_chan[ch].iSBPos==28) // 28 reached? |
250 { | 495 { |
251 int predict_nr,shift_factor,flags,d,s; | |
252 u8* start;unsigned int nSample; | |
253 int s_1,s_2; | |
254 | |
255 start=s_chan[ch].pCurr; // set up the current pos | 496 start=s_chan[ch].pCurr; // set up the current pos |
256 | 497 |
257 if (start == (u8*)-1) // special "stop" sign | 498 if (start == (unsigned char*)-1) // special "stop" sign |
258 { | 499 { |
259 s_chan[ch].bOn=0; // -> turn everything off | 500 s_chan[ch].bOn=0; // -> turn everything off |
260 s_chan[ch].ADSRX.lVolume=0; | 501 s_chan[ch].ADSRX.lVolume=0; |
261 s_chan[ch].ADSRX.EnvelopeVol=0; | 502 s_chan[ch].ADSRX.EnvelopeVol=0; |
262 goto ENDX; // -> and done for this channel | 503 goto ENDX; // -> and done for this channel |
263 } | 504 } |
264 | 505 |
265 s_chan[ch].iSBPos=0; // Reset buffer play index. | 506 s_chan[ch].iSBPos=0; |
266 | 507 |
267 //////////////////////////////////////////// spu irq handler here? mmm... do it later | 508 //////////////////////////////////////////// spu irq handler here? mmm... do it later |
268 | 509 |
269 s_1=s_chan[ch].s_1; | 510 s_1=s_chan[ch].s_1; |
270 s_2=s_chan[ch].s_2; | 511 s_2=s_chan[ch].s_2; |
271 | 512 |
272 predict_nr=(int)*start;start++; | 513 predict_nr=(int)*start;start++; |
273 shift_factor=predict_nr&0xf; | 514 shift_factor=predict_nr&0xf; |
274 predict_nr >>= 4; | 515 predict_nr >>= 4; |
275 flags=(int)*start;start++; | 516 flags=(int)*start;start++; |
276 | 517 |
277 // -------------------------------------- // | 518 // -------------------------------------- // |
278 // Decode new samples into s_chan[ch].SB[0 through 27] | 519 |
279 for (nSample=0;nSample<28;start++) | 520 for (nSample=0;nSample<28;start++) |
280 { | 521 { |
281 d=(int)*start; | 522 d=(int)*start; |
282 s=((d&0xf)<<12); | 523 s=((d&0xf)<<12); |
283 if(s&0x8000) s|=0xffff0000; | 524 if(s&0x8000) s|=0xffff0000; |
297 s_chan[ch].SB[nSample++]=fa; | 538 s_chan[ch].SB[nSample++]=fa; |
298 } | 539 } |
299 | 540 |
300 //////////////////////////////////////////// irq check | 541 //////////////////////////////////////////// irq check |
301 | 542 |
302 if(spuCtrl&0x40) // irq active? | 543 if(spuCtrl2[ch/24]&0x40) // some irq active? |
303 { | 544 { |
304 if((pSpuIrq > start-16 && // irq address reached? | 545 if((pSpuIrq[ch/24] > start-16 && // irq address reached? |
305 pSpuIrq <= start) || | 546 pSpuIrq[ch/24] <= start) || |
306 ((flags&1) && // special: irq on looping addr, when stop/loop flag is set | 547 ((flags&1) && // special: irq on looping addr, when stop/loop flag is set |
307 (pSpuIrq > s_chan[ch].pLoop-16 && | 548 (pSpuIrq[ch/24] > s_chan[ch].pLoop-16 && |
308 pSpuIrq <= s_chan[ch].pLoop))) | 549 pSpuIrq[ch/24] <= s_chan[ch].pLoop))) |
309 { | 550 { |
310 //extern s32 spuirqvoodoo; | |
311 s_chan[ch].iIrqDone=1; // -> debug flag | 551 s_chan[ch].iIrqDone=1; // -> debug flag |
312 SPUirq(); | 552 |
313 //puts("IRQ"); | 553 if(irqCallback) irqCallback(); // -> call main emu (not supported in SPU2 right now) |
314 //if(spuirqvoodoo!=-1) | 554 else |
315 //{ | 555 { |
316 // spuirqvoodoo=temp*384; | 556 if(ch<24) InterruptDMA4(); // -> let's see what is happening if we call our irqs instead ;) |
317 // temp=0; | 557 else InterruptDMA7(); |
318 //} | 558 } |
559 | |
560 if(iSPUIRQWait) // -> option: wait after irq for main emu | |
561 { | |
562 iSpuAsyncWait=1; | |
563 bIRQReturn=1; | |
564 } | |
319 } | 565 } |
320 } | 566 } |
321 | 567 |
322 //////////////////////////////////////////// flag handler | 568 //////////////////////////////////////////// flag handler |
323 | 569 |
324 if((flags&4) && (!s_chan[ch].bIgnoreLoop)) | 570 if((flags&4) && (!s_chan[ch].bIgnoreLoop)) |
325 s_chan[ch].pLoop=start-16; // loop adress | 571 s_chan[ch].pLoop=start-16; // loop adress |
326 | 572 |
327 if(flags&1) // 1: stop/loop | 573 if(flags&1) // 1: stop/loop |
328 { | 574 { |
575 dwEndChannel2[ch/24]|=(1<<(ch%24)); | |
576 | |
329 // We play this block out first... | 577 // We play this block out first... |
330 //if(!(flags&2)) // 1+2: do loop... otherwise: stop | 578 //if(!(flags&2)|| s_chan[ch].pLoop==NULL) |
579 // 1+2: do loop... otherwise: stop | |
331 if(flags!=3 || s_chan[ch].pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example) | 580 if(flags!=3 || s_chan[ch].pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example) |
332 { // and checking if pLoop is set avoids crashes, yeah | 581 { // and checking if pLoop is set avoids crashes, yeah |
333 start = (u8*)-1; | 582 start = (unsigned char*)-1; |
334 } | 583 } |
335 else | 584 else |
336 { | 585 { |
337 start = s_chan[ch].pLoop; | 586 start = s_chan[ch].pLoop; |
338 } | 587 } |
341 s_chan[ch].pCurr=start; // store values for next cycle | 590 s_chan[ch].pCurr=start; // store values for next cycle |
342 s_chan[ch].s_1=s_1; | 591 s_chan[ch].s_1=s_1; |
343 s_chan[ch].s_2=s_2; | 592 s_chan[ch].s_2=s_2; |
344 | 593 |
345 //////////////////////////////////////////// | 594 //////////////////////////////////////////// |
595 | |
596 if(bIRQReturn) // special return for "spu irq - wait for cpu action" | |
597 { | |
598 bIRQReturn=0; | |
599 if(iUseTimer!=2) | |
600 { | |
601 DWORD dwWatchTime=SexyTime64()+2500; | |
602 | |
603 while(iSpuAsyncWait && !bEndThread && | |
604 SexyTime64()<dwWatchTime) | |
605 #ifdef _WINDOWS | |
606 Sleep(1); | |
607 #else | |
608 usleep(1000L); | |
609 #endif | |
610 | |
611 } | |
612 else | |
613 { | |
614 lastch=ch; | |
615 lastns=ns; | |
616 | |
617 #ifdef _WINDOWS | |
618 return; | |
619 #else | |
620 return 0; | |
621 #endif | |
622 } | |
623 } | |
624 | |
625 //////////////////////////////////////////// | |
626 | |
627 GOON: ; | |
628 | |
346 } | 629 } |
347 | 630 |
348 fa=s_chan[ch].SB[s_chan[ch].iSBPos++]; // get sample data | 631 fa=s_chan[ch].SB[s_chan[ch].iSBPos++]; // get sample data |
349 | 632 |
350 if((spuCtrl&0x4000)==0) fa=0; // muted? | 633 if((spuCtrl2[ch/24]&0x4000)==0) fa=0; // muted? |
351 else CLIP(fa); | 634 else // else adjust |
352 | 635 { |
353 { | 636 if(fa>32767L) fa=32767L; |
354 int gpos; | 637 if(fa<-32767L) fa=-32767L; |
638 } | |
639 | |
640 if(iUseInterpolation>=2) // gauss/cubic interpolation | |
641 { | |
355 gpos = s_chan[ch].SB[28]; | 642 gpos = s_chan[ch].SB[28]; |
356 gval0 = fa; | 643 gval0 = fa; |
357 gpos = (gpos+1) & 3; | 644 gpos = (gpos+1) & 3; |
358 s_chan[ch].SB[28] = gpos; | 645 s_chan[ch].SB[28] = gpos; |
359 } | 646 } |
647 else | |
648 if(iUseInterpolation==1) // simple interpolation | |
649 { | |
650 s_chan[ch].SB[28] = 0; | |
651 s_chan[ch].SB[29] = s_chan[ch].SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour' | |
652 s_chan[ch].SB[30] = s_chan[ch].SB[31]; | |
653 s_chan[ch].SB[31] = fa; | |
654 s_chan[ch].SB[32] = 1; // -> flag: calc new interolation | |
655 } | |
656 else s_chan[ch].SB[29]=fa; // no interpolation | |
657 | |
360 s_chan[ch].spos -= 0x10000L; | 658 s_chan[ch].spos -= 0x10000L; |
361 } | 659 } |
362 | 660 |
363 //////////////////////////////////////////////// | 661 //////////////////////////////////////////////// |
364 // noise handler... just produces some noise data | 662 // noise handler... just produces some noise data |
365 // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used... | 663 // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used... |
366 // and sometimes the noise will be used as fmod modulation... pfff | 664 // and sometimes the noise will be used as fmod modulation... pfff |
367 | 665 |
368 if(s_chan[ch].bNoise) | 666 if(s_chan[ch].bNoise) |
369 { | 667 { |
370 //puts("Noise"); | |
371 if((dwNoiseVal<<=1)&0x80000000L) | 668 if((dwNoiseVal<<=1)&0x80000000L) |
372 { | 669 { |
373 dwNoiseVal^=0x0040001L; | 670 dwNoiseVal^=0x0040001L; |
374 fa=((dwNoiseVal>>2)&0x7fff); | 671 fa=((dwNoiseVal>>2)&0x7fff); |
375 fa=-fa; | 672 fa=-fa; |
376 } | 673 } |
377 else fa=(dwNoiseVal>>2)&0x7fff; | 674 else fa=(dwNoiseVal>>2)&0x7fff; |
378 | 675 |
379 // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val | 676 // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val |
380 fa=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl&0x3f00)>>9))+1)); | 677 fa=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl2[ch/24]&0x3f00)>>9))+1)); |
381 if(fa>32767L) fa=32767L; | 678 if(fa>32767L) fa=32767L; |
382 if(fa<-32767L) fa=-32767L; | 679 if(fa<-32767L) fa=-32767L; |
383 s_chan[ch].iOldNoise=fa; | 680 s_chan[ch].iOldNoise=fa; |
384 | 681 |
682 if(iUseInterpolation<2) // no gauss/cubic interpolation? | |
683 s_chan[ch].SB[29] = fa; // -> store noise val in "current sample" slot | |
385 } //---------------------------------------- | 684 } //---------------------------------------- |
386 else // NO NOISE (NORMAL SAMPLE DATA) HERE | 685 else // NO NOISE (NORMAL SAMPLE DATA) HERE |
387 { | 686 {//------------------------------------------// |
388 int vl, vr, gpos; | 687 if(iUseInterpolation==3) // cubic interpolation |
688 { | |
689 long xd; | |
690 xd = ((s_chan[ch].spos) >> 1)+1; | |
691 gpos = s_chan[ch].SB[28]; | |
692 | |
693 fa = gval(3) - 3*gval(2) + 3*gval(1) - gval0; | |
694 fa *= (xd - (2<<15)) / 6; | |
695 fa >>= 15; | |
696 fa += gval(2) - gval(1) - gval(1) + gval0; | |
697 fa *= (xd - (1<<15)) >> 1; | |
698 fa >>= 15; | |
699 fa += gval(1) - gval0; | |
700 fa *= xd; | |
701 fa >>= 15; | |
702 fa = fa + gval0; | |
703 } | |
704 //------------------------------------------// | |
705 else | |
706 if(iUseInterpolation==2) // gauss interpolation | |
707 { | |
708 int vl, vr; | |
389 vl = (s_chan[ch].spos >> 6) & ~3; | 709 vl = (s_chan[ch].spos >> 6) & ~3; |
390 gpos = s_chan[ch].SB[28]; | 710 gpos = s_chan[ch].SB[28]; |
711 vr=(gauss[vl]*gval0)&~2047; | |
712 vr+=(gauss[vl+1]*gval(1))&~2047; | |
713 vr+=(gauss[vl+2]*gval(2))&~2047; | |
714 vr+=(gauss[vl+3]*gval(3))&~2047; | |
715 fa = vr>>11; | |
716 /* | |
391 vr=(gauss[vl]*gval0)>>9; | 717 vr=(gauss[vl]*gval0)>>9; |
392 vr+=(gauss[vl+1]*gval(1))>>9; | 718 vr+=(gauss[vl+1]*gval(1))>>9; |
393 vr+=(gauss[vl+2]*gval(2))>>9; | 719 vr+=(gauss[vl+2]*gval(2))>>9; |
394 vr+=(gauss[vl+3]*gval(3))>>9; | 720 vr+=(gauss[vl+3]*gval(3))>>9; |
395 fa = vr>>2; | 721 fa = vr>>2; |
722 */ | |
723 } | |
724 //------------------------------------------// | |
725 else | |
726 if(iUseInterpolation==1) // simple interpolation | |
727 { | |
728 if(s_chan[ch].sinc<0x10000L) // -> upsampling? | |
729 InterpolateUp(ch); // --> interpolate up | |
730 else InterpolateDown(ch); // --> else down | |
731 fa=s_chan[ch].SB[29]; | |
732 } | |
733 //------------------------------------------// | |
734 else fa=s_chan[ch].SB[29]; // no interpolation | |
396 } | 735 } |
397 | 736 |
398 s_chan[ch].sval = (MixADSR(ch) * fa)>>10; // / 1023; // add adsr | 737 s_chan[ch].sval = (MixADSR(ch) * fa) / 1023; // add adsr |
738 | |
399 if(s_chan[ch].bFMod==2) // fmod freq channel | 739 if(s_chan[ch].bFMod==2) // fmod freq channel |
400 { | 740 { |
401 int NP=s_chan[ch+1].iRawPitch; | 741 int NP=s_chan[ch+1].iRawPitch; |
402 NP=((32768L+s_chan[ch].sval)*NP)>>15; ///32768L; | 742 |
743 NP=((32768L+s_chan[ch].sval)*NP)/32768L; // mmm... I still need to adjust that to 1/48 khz... we will wait for the first game/demo using it to decide how to do it :) | |
403 | 744 |
404 if(NP>0x3fff) NP=0x3fff; | 745 if(NP>0x3fff) NP=0x3fff; |
405 if(NP<0x1) NP=0x1; | 746 if(NP<0x1) NP=0x1; |
406 | 747 |
407 // mmmm... if I do this, all is screwed | |
408 // s_chan[ch+1].iRawPitch=NP; | |
409 | |
410 NP=(44100L*NP)/(4096L); // calc frequency | 748 NP=(44100L*NP)/(4096L); // calc frequency |
411 | 749 |
412 s_chan[ch+1].iActFreq=NP; | 750 s_chan[ch+1].iActFreq=NP; |
413 s_chan[ch+1].iUsedFreq=NP; | 751 s_chan[ch+1].iUsedFreq=NP; |
414 s_chan[ch+1].sinc=(((NP/10)<<16)/4410); | 752 s_chan[ch+1].sinc=(((NP/10)<<16)/4410); |
415 if(!s_chan[ch+1].sinc) s_chan[ch+1].sinc=1; | 753 if(!s_chan[ch+1].sinc) s_chan[ch+1].sinc=1; |
416 | 754 if(iUseInterpolation==1) // freq change in sipmle interpolation mode |
417 // mmmm... set up freq decoding positions? | 755 s_chan[ch+1].SB[32]=1; |
418 // s_chan[ch+1].iSBPos=28; | 756 |
419 // s_chan[ch+1].spos=0x10000L; | 757 // mmmm... set up freq decoding positions? |
758 // s_chan[ch+1].iSBPos=28; | |
759 // s_chan[ch+1].spos=0x10000L; | |
420 } | 760 } |
421 else | 761 else |
422 { | 762 { |
423 ////////////////////////////////////////////// | 763 ////////////////////////////////////////////// |
424 // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff) | 764 // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff) |
425 int tmpl,tmpr; | 765 |
426 | 766 if(s_chan[ch].iMute) |
427 tmpl=(s_chan[ch].sval*s_chan[ch].iLeftVolume)>>14; | 767 s_chan[ch].sval=0; // debug mute |
428 tmpr=(s_chan[ch].sval*s_chan[ch].iRightVolume)>>14; | 768 else |
429 | 769 { |
430 sl+=tmpl; | 770 if(s_chan[ch].bVolumeL) |
431 sr+=tmpr; | 771 SSumL[ns]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000L; |
432 | 772 if(s_chan[ch].bVolumeR) |
433 if(((rvb.Enabled>>ch)&1) && (spuCtrl&0x80)) | 773 SSumR[ns]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000L; |
434 { | 774 } |
435 revLeft+=tmpl; | 775 |
436 revRight+=tmpr; | 776 ////////////////////////////////////////////// |
437 } | 777 // now let us store sound data for reverb |
778 | |
779 if(s_chan[ch].bRVBActive) StoreREVERB(ch,ns); | |
438 } | 780 } |
439 | 781 |
782 //////////////////////////////////////////////// | |
783 // ok, go on until 1 ms data of this channel is collected | |
784 | |
785 ns++; | |
440 s_chan[ch].spos += s_chan[ch].sinc; | 786 s_chan[ch].spos += s_chan[ch].sinc; |
441 ENDX: ; | 787 |
788 } | |
789 ENDX: ; | |
442 } | 790 } |
443 } | 791 } |
444 | 792 |
793 //---------------------------------------------------// | |
794 //- here we have another 1 ms of sound data | |
795 //---------------------------------------------------// | |
796 // mix XA infos (if any) | |
797 sampcount++; | |
798 | |
799 | |
800 if(XAPlay!=XAFeed || XARepeat) MixXA(); | |
801 | |
445 /////////////////////////////////////////////////////// | 802 /////////////////////////////////////////////////////// |
446 // mix all channels (including reverb) into one buffer | 803 // mix all channels (including reverb) into one buffer |
447 MixREVERBLeftRight(&sl,&sr,revLeft,revRight); | 804 |
448 if(sampcount>=decaybegin) | 805 if(iDisStereo) // no stereo? |
449 { | |
450 s32 dmul; | |
451 if(decaybegin!=(u32)~0) // Is anyone REALLY going to be playing a song | |
452 // for 13 hours? | |
453 { | 806 { |
454 if(sampcount>=decayend) return(0); | 807 int dl,dr; |
455 dmul=256-(256*(sampcount-decaybegin)/(decayend-decaybegin)); | 808 for(ns=0;ns<NSSIZE;ns++) |
456 sl=(sl*dmul)>>8; | 809 { |
457 sr=(sr*dmul)>>8; | 810 SSumL[ns]+=MixREVERBLeft(ns,0); |
811 SSumL[ns]+=MixREVERBLeft(ns,1); | |
812 | |
813 dl=SSumL[ns]/voldiv;SSumL[ns]=0; | |
814 if(dl<-32767) dl=-32767;if(dl>32767) dl=32767; | |
815 | |
816 SSumR[ns]+=MixREVERBRight(0); | |
817 SSumR[ns]+=MixREVERBRight(1); | |
818 | |
819 dr=SSumR[ns]/voldiv;SSumR[ns]=0; | |
820 if(dr<-32767) dr=-32767;if(dr>32767) dr=32767; | |
821 *pS++=(dl+dr)/2; | |
822 } | |
458 } | 823 } |
459 } | 824 else // stereo: |
460 sampcount++; | 825 for(ns=0;ns<NSSIZE;ns++) |
461 sl=(sl*volmul)>>8; | 826 { |
462 sr=(sr*volmul)>>8; | 827 SSumL[ns]+=MixREVERBLeft(ns,0); |
463 | 828 SSumL[ns]+=MixREVERBLeft(ns,1); |
464 //{ | 829 |
465 // static double asl=0; | 830 d=SSumL[ns]/voldiv;SSumL[ns]=0; |
466 // static double asr=0; | 831 if(d<-32767) d=-32767;if(d>32767) d=32767; |
467 | 832 *pS++=d; |
468 // asl+=(sl-asl)/5; | 833 |
469 // asr+=(sl-asr)/5; | 834 SSumR[ns]+=MixREVERBRight(0); |
470 | 835 SSumR[ns]+=MixREVERBRight(1); |
471 //sl-=asl; | 836 |
472 //sr-=asr; | 837 d=SSumR[ns]/voldiv;SSumR[ns]=0; |
473 | 838 if(d<-32767) d=-32767;if(d>32767) d=32767; |
474 // if(sl>32767 || sl < -32767) printf("Left: %d, %f\n",sl,asl); | 839 *pS++=d; |
475 // if(sr>32767 || sr < -32767) printf("Right: %d, %f\n",sl,asl); | 840 } |
476 //} | 841 |
477 | 842 InitREVERB(); |
478 if(sl>32767) sl=32767; if(sl<-32767) sl=-32767; | 843 |
479 if(sr>32767) sr=32767; if(sr<-32767) sr=-32767; | |
480 *pS++=sl; | |
481 *pS++=sr; | |
482 } | 844 } |
483 | 845 |
484 return(1); | 846 // end of big main loop... |
847 | |
848 bThreadEnded=1; | |
849 | |
850 #ifndef _WINDOWS | |
851 return 0; | |
852 #endif | |
485 } | 853 } |
486 | 854 |
487 void sexypsf_stop(void) | 855 void sexypsf_stop(void) |
488 { | 856 { |
489 decaybegin=decayend=0; | 857 decaybegin=decayend=0; |
490 } | 858 } |
491 | 859 |
492 void SPUendflush(void) | 860 void SPUendflush(void) |
493 { | 861 { |
494 if((seektime!=(u32)~0) && seektime>sampcount) | 862 if((seektime!=~0) && seektime>sampcount) |
495 { | 863 { |
496 pS=(s16 *)pSpuBuffer; | 864 pS=(short *)pSpuBuffer; |
497 sexypsf_update(0,0); | 865 sexypsf_update(0,0); |
498 } | 866 } |
499 else if((u8*)pS>((u8*)pSpuBuffer+1024)) | 867 else if((unsigned short *)pS>((unsigned short *)pSpuBuffer+1024)) |
500 { | 868 { |
501 sexypsf_update((u8*)pSpuBuffer,(u8*)pS-(u8*)pSpuBuffer); | 869 sexypsf_update((unsigned short *)pSpuBuffer,(unsigned short *)pS-(unsigned short*)pSpuBuffer); |
502 pS=(s16 *)pSpuBuffer; | 870 pS=(short *)pSpuBuffer; |
503 } | 871 } |
504 } | 872 } |
505 | 873 |
506 #ifdef TIMEO | 874 //////////////////////////////////////////////////////////////////////// |
507 static u64 begintime; | 875 // WINDOWS THREAD... simply calls the timer func and stays forever :) |
508 static u64 SexyTime64(void) | 876 //////////////////////////////////////////////////////////////////////// |
509 { | 877 |
510 struct timeval tv; | 878 #ifdef _WINDOWS |
511 u64 ret; | 879 |
512 | 880 DWORD WINAPI MAINThreadEx(LPVOID lpParameter) |
513 gettimeofday(&tv,0); | 881 { |
514 ret=tv.tv_sec; | 882 MAINProc(0,0,0,0,0); |
515 ret*=1000000; | 883 return 0; |
516 ret+=tv.tv_usec; | 884 } |
517 return(ret); | 885 |
518 } | 886 #endif |
519 #endif | 887 |
888 //////////////////////////////////////////////////////////////////////// | |
889 //////////////////////////////////////////////////////////////////////// | |
890 //////////////////////////////////////////////////////////////////////// | |
891 | |
892 //////////////////////////////////////////////////////////////////////// | |
893 // SPU ASYNC... even newer epsxe func | |
894 // 1 time every 'cycle' cycles... harhar | |
895 //////////////////////////////////////////////////////////////////////// | |
896 | |
897 int sexypsf_seek(unsigned long t) | |
898 { | |
899 seektime=t*441/10; | |
900 if(seektime>sampcount) return(1); | |
901 return(0); | |
902 } | |
903 | |
904 EXPORT_GCC void CALLBACK SPU2async(unsigned long cycle) | |
905 { | |
906 if(iSpuAsyncWait) | |
907 { | |
908 iSpuAsyncWait++; | |
909 if(iSpuAsyncWait<=64) return; | |
910 iSpuAsyncWait=0; | |
911 } | |
912 | |
913 #ifdef _WINDOWS | |
914 if(iDebugMode==2) | |
915 { | |
916 if(IsWindow(hWDebug)) DestroyWindow(hWDebug); | |
917 hWDebug=0;iDebugMode=0; | |
918 } | |
919 if(iRecordMode==2) | |
920 { | |
921 if(IsWindow(hWRecord)) DestroyWindow(hWRecord); | |
922 hWRecord=0;iRecordMode=0; | |
923 } | |
924 #endif | |
925 | |
926 if(iUseTimer==2) // special mode, only used in Linux by this spu (or if you enable the experimental Windows mode) | |
927 { | |
928 if(!bSpuInit) return; // -> no init, no call | |
929 | |
930 #ifdef _WINDOWS | |
931 MAINProc(0,0,0,0,0); // -> experimental win mode... not really tested... don't like the drawbacks | |
932 #else | |
933 MAINThread(0); // -> linux high-compat mode | |
934 #endif | |
935 } | |
936 } | |
937 | |
938 //////////////////////////////////////////////////////////////////////// | |
939 // XA AUDIO | |
940 //////////////////////////////////////////////////////////////////////// | |
941 | |
942 // dummy func... not used yet | |
943 EXPORT_GCC void CALLBACK SPU2playADPCMchannel(xa_decode_t *xap) | |
944 { | |
945 if(!iUseXA) return; // no XA? bye | |
946 if(!xap) return; | |
947 if(!xap->freq) return; // no xa freq ? bye | |
948 | |
949 FeedXA(xap); // call main XA feeder | |
950 } | |
951 | |
520 //////////////////////////////////////////////////////////////////////// | 952 //////////////////////////////////////////////////////////////////////// |
521 // INIT/EXIT STUFF | 953 // INIT/EXIT STUFF |
522 //////////////////////////////////////////////////////////////////////// | 954 //////////////////////////////////////////////////////////////////////// |
523 | 955 |
524 //////////////////////////////////////////////////////////////////////// | 956 //////////////////////////////////////////////////////////////////////// |
525 // SPUINIT: this func will be called first by the main emu | 957 // SPUINIT: this func will be called first by the main emu |
526 //////////////////////////////////////////////////////////////////////// | 958 //////////////////////////////////////////////////////////////////////// |
959 | |
960 #ifdef _WINDOWS | |
961 static HINSTANCE hIRE = NULL; | |
962 #endif | |
527 | 963 |
528 int SPUinit(void) | 964 EXPORT_GCC long CALLBACK SPU2init(void) |
529 { | 965 { |
530 spuMemC=(u8*)spuMem; // just small setup | 966 spuMemC=(unsigned char *)spuMem; // just small setup |
531 memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN)); | 967 memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN)); |
532 memset((void *)&rvb,0,sizeof(REVERBInfo)); | 968 memset(rvb,0,2*sizeof(REVERBInfo)); |
533 memset(regArea,0,sizeof(regArea)); | 969 |
534 memset(spuMem,0,sizeof(spuMem)); | |
535 InitADSR(); | 970 InitADSR(); |
536 sampcount=poo=0; | 971 |
537 seektime=(u32)~0; | 972 #ifdef _WINDOWS |
538 #ifdef TIMEO | 973 if(hIRE==NULL) hIRE=LoadLibrary("Riched32.dll "); // needed for debug output |
539 begintime=SexyTime64(); | 974 #endif |
540 #endif | 975 |
541 return 0; | 976 return 0; |
977 } | |
978 | |
979 //////////////////////////////////////////////////////////////////////// | |
980 // SETUPTIMER: init of certain buffers and threads/timers | |
981 //////////////////////////////////////////////////////////////////////// | |
982 | |
983 void SetupTimer(void) | |
984 { | |
985 memset(SSumR,0,NSSIZE*sizeof(int)); // init some mixing buffers | |
986 memset(SSumL,0,NSSIZE*sizeof(int)); | |
987 pS=(short *)pSpuBuffer; // setup soundbuffer pointer | |
988 | |
989 bEndThread=0; // init thread vars | |
990 bThreadEnded=0; | |
991 bSpuInit=1; // flag: we are inited | |
992 | |
993 #ifdef _WINDOWS | |
994 | |
995 if(iUseTimer==1) // windows: use timer | |
996 { | |
997 timeBeginPeriod(1); | |
998 timeSetEvent(1,1,MAINProc,0,TIME_ONESHOT); | |
999 } | |
1000 else | |
1001 if(iUseTimer==0) // windows: use thread | |
1002 { | |
1003 //_beginthread(MAINThread,0,NULL); | |
1004 DWORD dw; | |
1005 hMainThread=CreateThread(NULL,0,MAINThreadEx,0,0,&dw); | |
1006 SetThreadPriority(hMainThread, | |
1007 //THREAD_PRIORITY_TIME_CRITICAL); | |
1008 THREAD_PRIORITY_HIGHEST); | |
1009 } | |
1010 | |
1011 #else | |
1012 | |
1013 #ifndef NOTHREADLIB | |
1014 if(!iUseTimer) // linux: use thread | |
1015 { | |
1016 pthread_create(&thread, NULL, MAINThread, NULL); | |
1017 } | |
1018 #endif | |
1019 | |
1020 #endif | |
1021 } | |
1022 | |
1023 //////////////////////////////////////////////////////////////////////// | |
1024 // REMOVETIMER: kill threads/timers | |
1025 //////////////////////////////////////////////////////////////////////// | |
1026 | |
1027 void RemoveTimer(void) | |
1028 { | |
1029 bEndThread=1; // raise flag to end thread | |
1030 | |
1031 #ifdef _WINDOWS | |
1032 | |
1033 if(iUseTimer!=2) // windows thread? | |
1034 { | |
1035 while(!bThreadEnded) {Sleep(5L);} // -> wait till thread has ended | |
1036 Sleep(5L); | |
1037 } | |
1038 if(iUseTimer==1) timeEndPeriod(1); // windows timer? stop it | |
1039 | |
1040 #else | |
1041 | |
1042 #ifndef NOTHREADLIB | |
1043 if(!iUseTimer) // linux tread? | |
1044 { | |
1045 int i=0; | |
1046 while(!bThreadEnded && i<2000) {usleep(1000L);i++;} // -> wait until thread has ended | |
1047 if(thread!=-1) {pthread_cancel(thread);thread=-1;} // -> cancel thread anyway | |
1048 } | |
1049 #endif | |
1050 | |
1051 #endif | |
1052 | |
1053 bThreadEnded=0; // no more spu is running | |
1054 bSpuInit=0; | |
542 } | 1055 } |
543 | 1056 |
544 //////////////////////////////////////////////////////////////////////// | 1057 //////////////////////////////////////////////////////////////////////// |
545 // SETUPSTREAMS: init most of the spu buffers | 1058 // SETUPSTREAMS: init most of the spu buffers |
546 //////////////////////////////////////////////////////////////////////// | 1059 //////////////////////////////////////////////////////////////////////// |
547 | 1060 |
548 void SetupStreams(void) | 1061 void SetupStreams(void) |
549 { | 1062 { |
550 int i; | 1063 int i; |
551 | 1064 |
552 pSpuBuffer=(u8*)malloc(32768); // alloc mixing buffer | 1065 pSpuBuffer=(unsigned char *)malloc(32768); // alloc mixing buffer |
553 pS=(s16 *)pSpuBuffer; | 1066 |
1067 i=NSSIZE*2; | |
1068 | |
1069 sRVBStart[0] = (int *)malloc(i*4); // alloc reverb buffer | |
1070 memset(sRVBStart[0],0,i*4); | |
1071 sRVBEnd[0] = sRVBStart[0] + i; | |
1072 sRVBPlay[0] = sRVBStart[0]; | |
1073 sRVBStart[1] = (int *)malloc(i*4); // alloc reverb buffer | |
1074 memset(sRVBStart[1],0,i*4); | |
1075 sRVBEnd[1] = sRVBStart[1] + i; | |
1076 sRVBPlay[1] = sRVBStart[1]; | |
1077 | |
1078 XAStart = // alloc xa buffer (not used here anyway) | |
1079 (unsigned long *)malloc(48000*4); | |
1080 XAPlay = XAStart; | |
1081 XAFeed = XAStart; | |
1082 XAEnd = XAStart + 48000; | |
554 | 1083 |
555 for(i=0;i<MAXCHAN;i++) // loop sound channels | 1084 for(i=0;i<MAXCHAN;i++) // loop sound channels |
556 { | 1085 { |
1086 // we don't use mutex sync... not needed, would only | |
1087 // slow us down: | |
1088 // s_chan[i].hMutex=CreateMutex(NULL,FALSE,NULL); | |
557 s_chan[i].ADSRX.SustainLevel = 1024; // -> init sustain | 1089 s_chan[i].ADSRX.SustainLevel = 1024; // -> init sustain |
1090 s_chan[i].iMute=0; | |
558 s_chan[i].iIrqDone=0; | 1091 s_chan[i].iIrqDone=0; |
559 s_chan[i].pLoop=spuMemC; | 1092 s_chan[i].pLoop=spuMemC; |
560 s_chan[i].pStart=spuMemC; | 1093 s_chan[i].pStart=spuMemC; |
561 s_chan[i].pCurr=spuMemC; | 1094 s_chan[i].pCurr=spuMemC; |
562 } | 1095 } |
568 | 1101 |
569 void RemoveStreams(void) | 1102 void RemoveStreams(void) |
570 { | 1103 { |
571 free(pSpuBuffer); // free mixing buffer | 1104 free(pSpuBuffer); // free mixing buffer |
572 pSpuBuffer=NULL; | 1105 pSpuBuffer=NULL; |
573 | 1106 free(sRVBStart[0]); // free reverb buffer |
574 #ifdef TIMEO | 1107 sRVBStart[0]=0; |
575 { | 1108 free(sRVBStart[1]); // free reverb buffer |
576 u64 tmp; | 1109 sRVBStart[1]=0; |
577 tmp=SexyTime64(); | 1110 free(XAStart); // free XA buffer |
578 tmp-=begintime; | 1111 XAStart=0; |
579 if(tmp) | 1112 |
580 tmp=(u64)sampcount*1000000/tmp; | 1113 /* |
581 printf("%lld samples per second\n",tmp); | 1114 int i; |
582 } | 1115 for(i=0;i<MAXCHAN;i++) |
583 #endif | 1116 { |
1117 WaitForSingleObject(s_chan[i].hMutex,2000); | |
1118 ReleaseMutex(s_chan[i].hMutex); | |
1119 if(s_chan[i].hMutex) | |
1120 {CloseHandle(s_chan[i].hMutex);s_chan[i].hMutex=0;} | |
1121 } | |
1122 */ | |
584 } | 1123 } |
585 | 1124 |
586 | 1125 |
587 //////////////////////////////////////////////////////////////////////// | 1126 //////////////////////////////////////////////////////////////////////// |
588 // SPUOPEN: called by main emu after init | 1127 // SPUOPEN: called by main emu after init |
589 //////////////////////////////////////////////////////////////////////// | 1128 //////////////////////////////////////////////////////////////////////// |
590 | 1129 |
591 int SPUopen(void) | 1130 EXPORT_GCC long CALLBACK SPU2open(void *pDsp) |
592 { | 1131 { |
1132 #ifdef _WINDOWS | |
1133 HWND hW=0; | |
1134 #endif | |
1135 | |
593 if(bSPUIsOpen) return 0; // security for some stupid main emus | 1136 if(bSPUIsOpen) return 0; // security for some stupid main emus |
594 spuIrq=0; | 1137 |
595 | 1138 iUseXA=1; // just small setup |
596 spuStat=spuCtrl=0; | 1139 iVolume=3; |
597 spuAddr=0xffffffff; | 1140 bEndThread=0; |
598 dwNoiseVal=1; | 1141 bThreadEnded=0; |
599 | 1142 spuMemC=(unsigned char *)spuMem; |
600 spuMemC=(u8*)spuMem; | |
601 memset((void *)s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN)); | 1143 memset((void *)s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN)); |
602 pSpuIrq=0; | 1144 pSpuIrq[0]=0; |
603 | 1145 pSpuIrq[1]=0; |
604 iVolume=128; //85; | 1146 iSPUIRQWait=1; |
1147 dwNewChannel2[0]=0; | |
1148 dwNewChannel2[1]=0; | |
1149 dwEndChannel2[0]=0; | |
1150 dwEndChannel2[1]=0; | |
1151 spuCtrl2[0]=0; | |
1152 spuCtrl2[1]=0; | |
1153 spuStat2[0]=0; | |
1154 spuStat2[1]=0; | |
1155 spuIrq2[0]=0; | |
1156 spuIrq2[1]=0; | |
1157 spuAddr2[0]=0xffffffff; | |
1158 spuAddr2[1]=0xffffffff; | |
1159 spuRvbAddr2[0]=0; | |
1160 spuRvbAddr2[1]=0; | |
1161 spuRvbAEnd2[0]=0; | |
1162 spuRvbAEnd2[1]=0; | |
1163 | |
1164 #ifdef _WINDOWS | |
1165 LastWrite=0xffffffff;LastPlay=0; // init some play vars | |
1166 if(!IsWindow(hW)) hW=GetActiveWindow(); | |
1167 hWMain = hW; // store hwnd | |
1168 #endif | |
1169 | |
605 SetupStreams(); // prepare streaming | 1170 SetupStreams(); // prepare streaming |
606 | 1171 |
1172 SetupTimer(); // timer for feeding data | |
1173 | |
607 bSPUIsOpen=1; | 1174 bSPUIsOpen=1; |
608 | 1175 |
609 return 1; | 1176 #ifdef _WINDOWS |
610 } | 1177 if(iDebugMode) // windows debug dialog |
611 | 1178 { |
612 //////////////////////////////////////////////////////////////////////// | 1179 hWDebug=CreateDialog(hInst,MAKEINTRESOURCE(IDD_DEBUG), |
1180 NULL,(DLGPROC)DebugDlgProc); | |
1181 SetWindowPos(hWDebug,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); | |
1182 UpdateWindow(hWDebug); | |
1183 SetFocus(hWMain); | |
1184 } | |
1185 | |
1186 if(iRecordMode) // windows recording dialog | |
1187 { | |
1188 hWRecord=CreateDialog(hInst,MAKEINTRESOURCE(IDD_RECORD), | |
1189 NULL,(DLGPROC)RecordDlgProc); | |
1190 SetWindowPos(hWRecord,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOACTIVATE); | |
1191 UpdateWindow(hWRecord); | |
1192 SetFocus(hWMain); | |
1193 } | |
1194 #endif | |
1195 | |
1196 return 0; | |
1197 } | |
1198 | |
1199 //////////////////////////////////////////////////////////////////////// | |
1200 | |
1201 // not used yet | |
1202 #ifndef _WINDOWS | |
1203 void SPU2setConfigFile(char * pCfg) | |
1204 { | |
1205 | |
1206 } | |
1207 #endif | |
613 | 1208 |
614 //////////////////////////////////////////////////////////////////////// | 1209 //////////////////////////////////////////////////////////////////////// |
615 // SPUCLOSE: called before shutdown | 1210 // SPUCLOSE: called before shutdown |
616 //////////////////////////////////////////////////////////////////////// | 1211 //////////////////////////////////////////////////////////////////////// |
617 | 1212 |
618 int SPUclose(void) | 1213 EXPORT_GCC void CALLBACK SPU2close(void) |
619 { | 1214 { |
620 if(!bSPUIsOpen) return 0; // some security | 1215 if(!bSPUIsOpen) return; // some security |
621 | 1216 |
622 bSPUIsOpen=0; // no more open | 1217 bSPUIsOpen=0; // no more open |
623 | 1218 |
1219 #ifdef _WINDOWS | |
1220 if(IsWindow(hWDebug)) DestroyWindow(hWDebug); | |
1221 hWDebug=0; | |
1222 if(IsWindow(hWRecord)) DestroyWindow(hWRecord); | |
1223 hWRecord=0; | |
1224 #endif | |
1225 | |
1226 RemoveTimer(); // no more feeding | |
1227 | |
624 RemoveStreams(); // no more streaming | 1228 RemoveStreams(); // no more streaming |
625 | 1229 } |
1230 | |
1231 //////////////////////////////////////////////////////////////////////// | |
1232 // SPUSHUTDOWN: called by main emu on final exit | |
1233 //////////////////////////////////////////////////////////////////////// | |
1234 | |
1235 EXPORT_GCC void CALLBACK SPU2shutdown(void) | |
1236 { | |
1237 #ifdef _WINDOWS | |
1238 if(hIRE!=NULL) {FreeLibrary(hIRE);hIRE=NULL;} | |
1239 #endif | |
1240 | |
1241 return; | |
1242 } | |
1243 | |
1244 //////////////////////////////////////////////////////////////////////// | |
1245 // SPUTEST: we don't test, we are always fine ;) | |
1246 //////////////////////////////////////////////////////////////////////// | |
1247 | |
1248 EXPORT_GCC long CALLBACK SPU2test(void) | |
1249 { | |
626 return 0; | 1250 return 0; |
627 } | 1251 } |
628 | 1252 |
629 //////////////////////////////////////////////////////////////////////// | 1253 //////////////////////////////////////////////////////////////////////// |
630 // SPUSHUTDOWN: called by main emu on final exit | 1254 // SPUCONFIGURE: call config dialog |
631 //////////////////////////////////////////////////////////////////////// | 1255 //////////////////////////////////////////////////////////////////////// |
632 | 1256 |
633 int SPUshutdown(void) | 1257 EXPORT_GCC void CALLBACK SPU2configure(void) |
634 { | 1258 { |
635 return 0; | 1259 |
636 } | 1260 } |
637 | 1261 |
1262 //////////////////////////////////////////////////////////////////////// | |
1263 // SPUABOUT: show about window | |
1264 //////////////////////////////////////////////////////////////////////// | |
1265 | |
1266 EXPORT_GCC void CALLBACK SPU2about(void) | |
1267 { | |
1268 | |
1269 } | |
1270 | |
1271 //////////////////////////////////////////////////////////////////////// | |
1272 // SETUP CALLBACKS | |
1273 // this functions will be called once, | |
1274 // passes a callback that should be called on SPU-IRQ/cdda volume change | |
1275 //////////////////////////////////////////////////////////////////////// | |
1276 | |
1277 // not used yet | |
1278 EXPORT_GCC void CALLBACK SPU2irqCallback(void (CALLBACK *callback)(void)) | |
1279 { | |
1280 irqCallback = callback; | |
1281 } | |
1282 | |
1283 // not used yet | |
1284 EXPORT_GCC void CALLBACK SPU2registerCallback(void (CALLBACK *callback)(void)) | |
1285 { | |
1286 irqCallback = callback; | |
1287 } | |
1288 | |
1289 // not used yet | |
1290 EXPORT_GCC void CALLBACK SPU2registerCDDAVolume(void (CALLBACK *CDDAVcallback)(unsigned short,unsigned short)) | |
1291 { | |
1292 cddavCallback = CDDAVcallback; | |
1293 } | |
1294 | |
1295 //////////////////////////////////////////////////////////////////////// | |
1296 // COMMON PLUGIN INFO FUNCS | |
1297 //////////////////////////////////////////////////////////////////////// | |
1298 | |
1299 EXPORT_GCC char * CALLBACK PS2EgetLibName(void) | |
1300 { | |
1301 return libraryName; | |
1302 } | |
1303 | |
1304 #define PS2E_LT_SPU2 0x4 | |
1305 | |
1306 EXPORT_GCC unsigned long CALLBACK PS2EgetLibType(void) | |
1307 { | |
1308 return PS2E_LT_SPU2; | |
1309 } | |
1310 | |
1311 EXPORT_GCC unsigned long CALLBACK PS2EgetLibVersion2(unsigned long type) | |
1312 { | |
1313 unsigned char v=version; | |
1314 | |
1315 // key hack to fake a lower version: | |
1316 //if(GetAsyncKeyState(VK_SHIFT)&0x8000) v--; | |
1317 | |
1318 // compile hack to set lib version to PCSX2 0.6 standards | |
1319 //v=2; | |
1320 | |
1321 return v<<16|revision<<8|build; | |
1322 } | |
1323 | |
1324 // not used yet | |
1325 char * SPU2getLibInfos(void) | |
1326 { | |
1327 return libraryInfo; | |
1328 } | |
1329 | |
1330 //////////////////////////////////////////////////////////////////////// | |
1331 |