gpu_neon: add some intelace mode handling
[pcsx_rearmed.git] / plugins / dfsound / spu.c
1 /***************************************************************************
2                             spu.c  -  description
3                              -------------------
4     begin                : Wed May 15 2002
5     copyright            : (C) 2002 by Pete Bernert
6     email                : BlackDove@addcom.de
7
8  Portions (C) GraÅžvydas "notaz" Ignotas, 2010-2011
9
10  ***************************************************************************/
11 /***************************************************************************
12  *                                                                         *
13  *   This program is free software; you can redistribute it and/or modify  *
14  *   it under the terms of the GNU General Public License as published by  *
15  *   the Free Software Foundation; either version 2 of the License, or     *
16  *   (at your option) any later version. See also the license.txt file for *
17  *   additional informations.                                              *
18  *                                                                         *
19  ***************************************************************************/
20
21 #include "stdafx.h"
22
23 #define _IN_SPU
24
25 #include "externals.h"
26 #include "registers.h"
27 #include "cfg.h"
28 #include "dsoundoss.h"
29
30 #ifdef ENABLE_NLS
31 #include <libintl.h>
32 #include <locale.h>
33 #define _(x)  gettext(x)
34 #define N_(x) (x)
35 #else
36 #define _(x)  (x)
37 #define N_(x) (x)
38 #endif
39
40 #ifdef __ARM_ARCH_7A__
41  #define ssat32_to_16(v) \
42   asm("ssat %0,#16,%1" : "=r" (v) : "r" (v))
43 #else
44  #define ssat32_to_16(v) do { \
45   if (v < -32768) v = -32768; \
46   else if (v > 32767) v = 32767; \
47  } while (0)
48 #endif
49
50 /*
51 #if defined (USEMACOSX)
52 static char * libraryName     = N_("Mac OS X Sound");
53 #elif defined (USEALSA)
54 static char * libraryName     = N_("ALSA Sound");
55 #elif defined (USEOSS)
56 static char * libraryName     = N_("OSS Sound");
57 #elif defined (USESDL)
58 static char * libraryName     = N_("SDL Sound");
59 #elif defined (USEPULSEAUDIO)
60 static char * libraryName     = N_("PulseAudio Sound");
61 #else
62 static char * libraryName     = N_("NULL Sound");
63 #endif
64
65 static char * libraryInfo     = N_("P.E.Op.S. Sound Driver V1.7\nCoded by Pete Bernert and the P.E.Op.S. team\n");
66 */
67
68 // globals
69
70 // psx buffer / addresses
71
72 unsigned short  regArea[10000];
73 unsigned short  spuMem[256*1024];
74 unsigned char * spuMemC;
75 unsigned char * pSpuIrq=0;
76 unsigned char * pSpuBuffer;
77 unsigned char * pMixIrq=0;
78
79 // user settings
80
81 int             iVolume=768; // 1024 is 1.0
82 int             iXAPitch=1;
83 int             iUseTimer=2;
84 int             iSPUIRQWait=1;
85 int             iDebugMode=0;
86 int             iRecordMode=0;
87 int             iUseReverb=2;
88 int             iUseInterpolation=2;
89
90 // MAIN infos struct for each channel
91
92 SPUCHAN         s_chan[MAXCHAN+1];                     // channel + 1 infos (1 is security for fmod handling)
93 REVERBInfo      rvb;
94
95 unsigned int    dwNoiseVal;                            // global noise generator
96 unsigned int    dwNoiseCount;
97 int             iSpuAsyncWait=0;
98
99 unsigned short  spuCtrl=0;                             // some vars to store psx reg infos
100 unsigned short  spuStat=0;
101 unsigned short  spuIrq=0;
102 unsigned long   spuAddr=0xffffffff;                    // address into spu mem
103 int             bEndThread=0;                          // thread handlers
104 int             bThreadEnded=0;
105 int             bSpuInit=0;
106 int             bSPUIsOpen=0;
107
108 static pthread_t thread = (pthread_t)-1;               // thread id (linux)
109
110 unsigned int dwNewChannel=0;                           // flags for faster testing, if new channel starts
111 unsigned int dwChannelOn=0;                            // not silent channels
112 unsigned int dwPendingChanOff=0;
113 unsigned int dwChannelDead=0;                          // silent+not useful channels
114
115 void (CALLBACK *irqCallback)(void)=0;                  // func of main emu, called on spu irq
116 void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0;
117
118 // certain globals (were local before, but with the new timeproc I need em global)
119
120 static const int f[8][2] = {   {    0,  0  },
121                         {   60,  0  },
122                         {  115, -52 },
123                         {   98, -55 },
124                         {  122, -60 } };
125 int ChanBuf[NSSIZE+3];
126 int SSumLR[(NSSIZE+3)*2];
127 int iFMod[NSSIZE];
128 int iCycle = 0;
129 short * pS;
130
131 int lastch=-1;             // last channel processed on spu irq in timer mode
132 static int lastns=0;       // last ns pos
133 static int iSecureStart=0; // secure start counter
134
135 #define CDDA_BUFFER_SIZE (16384 * sizeof(uint32_t)) // must be power of 2
136
137 ////////////////////////////////////////////////////////////////////////
138 // CODE AREA
139 ////////////////////////////////////////////////////////////////////////
140
141 // dirty inline func includes
142
143 #include "reverb.c"
144 #include "adsr.c"
145
146 ////////////////////////////////////////////////////////////////////////
147 // helpers for simple interpolation
148
149 //
150 // easy interpolation on upsampling, no special filter, just "Pete's common sense" tm
151 //
152 // instead of having n equal sample values in a row like:
153 //       ____
154 //           |____
155 //
156 // we compare the current delta change with the next delta change.
157 //
158 // if curr_delta is positive,
159 //
160 //  - and next delta is smaller (or changing direction):
161 //         \.
162 //          -__
163 //
164 //  - and next delta significant (at least twice) bigger:
165 //         --_
166 //            \.
167 //
168 //  - and next delta is nearly same:
169 //          \.
170 //           \.
171 //
172 //
173 // if curr_delta is negative,
174 //
175 //  - and next delta is smaller (or changing direction):
176 //          _--
177 //         /
178 //
179 //  - and next delta significant (at least twice) bigger:
180 //            /
181 //         __- 
182 //
183 //  - and next delta is nearly same:
184 //           /
185 //          /
186 //
187
188
189 INLINE void InterpolateUp(int ch)
190 {
191  if(s_chan[ch].SB[32]==1)                              // flag == 1? calc step and set flag... and don't change the value in this pass
192   {
193    const int id1=s_chan[ch].SB[30]-s_chan[ch].SB[29];  // curr delta to next val
194    const int id2=s_chan[ch].SB[31]-s_chan[ch].SB[30];  // and next delta to next-next val :)
195
196    s_chan[ch].SB[32]=0;
197
198    if(id1>0)                                           // curr delta positive
199     {
200      if(id2<id1)
201       {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;}
202      else
203      if(id2<(id1<<1))
204       s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L;
205      else
206       s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L; 
207     }
208    else                                                // curr delta negative
209     {
210      if(id2>id1)
211       {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;}
212      else
213      if(id2>(id1<<1))
214       s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L;
215      else
216       s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L; 
217     }
218   }
219  else
220  if(s_chan[ch].SB[32]==2)                              // flag 1: calc step and set flag... and don't change the value in this pass
221   {
222    s_chan[ch].SB[32]=0;
223
224    s_chan[ch].SB[28]=(s_chan[ch].SB[28]*s_chan[ch].sinc)/0x20000L;
225    //if(s_chan[ch].sinc<=0x8000)
226    //     s_chan[ch].SB[29]=s_chan[ch].SB[30]-(s_chan[ch].SB[28]*((0x10000/s_chan[ch].sinc)-1));
227    //else
228    s_chan[ch].SB[29]+=s_chan[ch].SB[28];
229   }
230  else                                                  // no flags? add bigger val (if possible), calc smaller step, set flag1
231   s_chan[ch].SB[29]+=s_chan[ch].SB[28];
232 }
233
234 //
235 // even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm
236 //
237
238 INLINE void InterpolateDown(int ch)
239 {
240  if(s_chan[ch].sinc>=0x20000L)                                 // we would skip at least one val?
241   {
242    s_chan[ch].SB[29]+=(s_chan[ch].SB[30]-s_chan[ch].SB[29])/2; // add easy weight
243    if(s_chan[ch].sinc>=0x30000L)                               // we would skip even more vals?
244     s_chan[ch].SB[29]+=(s_chan[ch].SB[31]-s_chan[ch].SB[30])/2;// add additional next weight
245   }
246 }
247
248 ////////////////////////////////////////////////////////////////////////
249 // helpers for gauss interpolation
250
251 #define gval0 (((short*)(&s_chan[ch].SB[29]))[gpos])
252 #define gval(x) (((short*)(&s_chan[ch].SB[29]))[(gpos+x)&3])
253
254 #include "gauss_i.h"
255
256 ////////////////////////////////////////////////////////////////////////
257
258 #include "xa.c"
259
260 ////////////////////////////////////////////////////////////////////////
261 // START SOUND... called by main thread to setup a new sound on a channel
262 ////////////////////////////////////////////////////////////////////////
263
264 INLINE void StartSound(int ch)
265 {
266  StartADSR(ch);
267  StartREVERB(ch);
268
269  // fussy timing issues - do in VoiceOn
270  //s_chan[ch].pCurr=s_chan[ch].pStart;                   // set sample start
271  //s_chan[ch].bStop=0;
272  //s_chan[ch].bOn=1;
273
274  s_chan[ch].SB[26]=0;                                  // init mixing vars
275  s_chan[ch].SB[27]=0;
276  s_chan[ch].iSBPos=28;
277
278  s_chan[ch].SB[29]=0;                                  // init our interpolation helpers
279  s_chan[ch].SB[30]=0;
280
281  if(iUseInterpolation>=2)                              // gauss interpolation?
282       {s_chan[ch].spos=0x30000L;s_chan[ch].SB[28]=0;}  // -> start with more decoding
283  else {s_chan[ch].spos=0x10000L;s_chan[ch].SB[31]=0;}  // -> no/simple interpolation starts with one 44100 decoding
284
285  dwNewChannel&=~(1<<ch);                               // clear new channel bit
286 }
287
288 ////////////////////////////////////////////////////////////////////////
289 // ALL KIND OF HELPERS
290 ////////////////////////////////////////////////////////////////////////
291
292 INLINE int FModChangeFrequency(int ch,int ns)
293 {
294  unsigned int NP=s_chan[ch].iRawPitch;
295  int sinc;
296
297  NP=((32768L+iFMod[ns])*NP)/32768L;
298
299  if(NP>0x3fff) NP=0x3fff;
300  if(NP<0x1)    NP=0x1;
301
302  sinc=NP<<4;                                           // calc frequency
303  if(iUseInterpolation==1)                              // freq change in simple interpolation mode
304   s_chan[ch].SB[32]=1;
305  iFMod[ns]=0;
306
307  return sinc;
308 }                    
309
310 ////////////////////////////////////////////////////////////////////////
311
312 INLINE void StoreInterpolationVal(int ch,int fa)
313 {
314  if(s_chan[ch].bFMod==2)                               // fmod freq channel
315   s_chan[ch].SB[29]=fa;
316  else
317   {
318    ssat32_to_16(fa);
319
320    if(iUseInterpolation>=2)                            // gauss/cubic interpolation
321     {     
322      int gpos = s_chan[ch].SB[28];
323      gval0 = fa;          
324      gpos = (gpos+1) & 3;
325      s_chan[ch].SB[28] = gpos;
326     }
327    else
328    if(iUseInterpolation==1)                            // simple interpolation
329     {
330      s_chan[ch].SB[28] = 0;                    
331      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'
332      s_chan[ch].SB[30] = s_chan[ch].SB[31];
333      s_chan[ch].SB[31] = fa;
334      s_chan[ch].SB[32] = 1;                            // -> flag: calc new interolation
335     }
336    else s_chan[ch].SB[29]=fa;                          // no interpolation
337   }
338 }
339
340 ////////////////////////////////////////////////////////////////////////
341
342 INLINE int iGetInterpolationVal(int ch, int spos)
343 {
344  int fa;
345
346  if(s_chan[ch].bFMod==2) return s_chan[ch].SB[29];
347
348  switch(iUseInterpolation)
349   {   
350    //--------------------------------------------------//
351    case 3:                                             // cubic interpolation
352     {
353      long xd;int gpos;
354      xd = (spos >> 1)+1;
355      gpos = s_chan[ch].SB[28];
356
357      fa  = gval(3) - 3*gval(2) + 3*gval(1) - gval0;
358      fa *= (xd - (2<<15)) / 6;
359      fa >>= 15;
360      fa += gval(2) - gval(1) - gval(1) + gval0;
361      fa *= (xd - (1<<15)) >> 1;
362      fa >>= 15;
363      fa += gval(1) - gval0;
364      fa *= xd;
365      fa >>= 15;
366      fa = fa + gval0;
367
368     } break;
369    //--------------------------------------------------//
370    case 2:                                             // gauss interpolation
371     {
372      int vl, vr;int gpos;
373      vl = (spos >> 6) & ~3;
374      gpos = s_chan[ch].SB[28];
375      vr=(gauss[vl]*gval0)&~2047;
376      vr+=(gauss[vl+1]*gval(1))&~2047;
377      vr+=(gauss[vl+2]*gval(2))&~2047;
378      vr+=(gauss[vl+3]*gval(3))&~2047;
379      fa = vr>>11;
380     } break;
381    //--------------------------------------------------//
382    case 1:                                             // simple interpolation
383     {
384      if(s_chan[ch].sinc<0x10000L)                      // -> upsampling?
385           InterpolateUp(ch);                           // --> interpolate up
386      else InterpolateDown(ch);                         // --> else down
387      fa=s_chan[ch].SB[29];
388     } break;
389    //--------------------------------------------------//
390    default:                                            // no interpolation
391     {
392      fa=s_chan[ch].SB[29];                  
393     } break;
394    //--------------------------------------------------//
395   }
396
397  return fa;
398 }
399
400 static void do_irq(void)
401 {
402  if(!(spuStat & STAT_IRQ))
403  {
404   spuStat |= STAT_IRQ;
405   if(irqCallback) irqCallback();
406  }
407 }
408
409 static void decode_block_data(int *dest, const unsigned char *src, int predict_nr, int shift_factor)
410 {
411  int nSample;
412  int fa, s_1, s_2, d, s;
413
414  s_1 = dest[27];
415  s_2 = dest[26];
416
417  for (nSample = 0; nSample < 28; src++)
418  {
419   d = (int)*src;
420   s = (int)(signed short)((d & 0x0f) << 12);
421
422   fa = s >> shift_factor;
423   fa += ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
424   s_2=s_1;s_1=fa;
425
426   dest[nSample++] = fa;
427
428   s = (int)(signed short)((d & 0xf0) << 8);
429   fa = s >> shift_factor;
430   fa += ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
431   s_2=s_1;s_1=fa;
432
433   dest[nSample++] = fa;
434  }
435 }
436
437 static int decode_block(int ch)
438 {
439  unsigned char *start;
440  int predict_nr,shift_factor,flags;
441  int ret = 0;
442
443  start=s_chan[ch].pCurr;                   // set up the current pos
444  if(dwPendingChanOff&(1<<ch))
445  {
446   dwChannelOn&=~(1<<ch);                   // -> turn everything off
447   dwPendingChanOff&=~(1<<ch);
448   s_chan[ch].bStop=1;
449   s_chan[ch].ADSRX.EnvelopeVol=0;
450  }
451
452  //////////////////////////////////////////// irq check
453
454  if(spuCtrl&CTRL_IRQ)
455  {
456   if(pSpuIrq == start)                     // irq address reached?
457   {
458    do_irq();                               // -> call main emu
459    ret = 1;
460   }
461  }
462
463  predict_nr=(int)start[0];
464  shift_factor=predict_nr&0xf;
465  predict_nr >>= 4;
466
467  decode_block_data(s_chan[ch].SB, start + 2, predict_nr, shift_factor);
468
469  //////////////////////////////////////////// flag handler
470
471  flags=(int)start[1];
472  if(flags&4)
473   s_chan[ch].pLoop=start;                  // loop adress
474
475  start+=16;
476  if(flags&1)                               // 1: stop/loop
477  {
478   if(!(flags&2))
479    dwPendingChanOff|=1<<ch;
480
481   start = s_chan[ch].pLoop;
482  }
483
484  if (start - spuMemC >= 0x80000) {
485   // most likely wrong
486   start = spuMemC;
487   printf("ch%d oflow\n", ch);
488  }
489
490  s_chan[ch].pCurr = start;                 // store values for next cycle
491  s_chan[ch].bJump = flags & 1;
492
493  return ret;
494 }
495
496 // do block, but ignore sample data
497 static int skip_block(int ch)
498 {
499  unsigned char *start = s_chan[ch].pCurr;
500  int flags = start[1];
501  int ret = 0;
502
503  if(start == pSpuIrq)
504  {
505   do_irq();
506   ret = 1;
507  }
508
509  if(flags & 4)
510   s_chan[ch].pLoop = start;
511
512  s_chan[ch].pCurr += 16;
513
514  if(flags & 1)
515   s_chan[ch].pCurr = s_chan[ch].pLoop;
516
517  s_chan[ch].bJump = flags & 1;
518  return ret;
519 }
520
521 #define make_do_samples(name, fmod_code, interp_start, interp1_code, interp2_code, interp_end) \
522 static int do_samples_##name(int ch, int ns, int ns_to) \
523 {                                            \
524  int sinc = s_chan[ch].sinc;                 \
525  int spos = s_chan[ch].spos;                 \
526  int sbpos = s_chan[ch].iSBPos;              \
527  int *SB = s_chan[ch].SB;                    \
528  int ret = -1;                               \
529  int d, fa;                                  \
530  interp_start;                               \
531                                              \
532  for (; ns < ns_to; ns++)                    \
533  {                                           \
534   fmod_code;                                 \
535                                              \
536   while (spos >= 0x10000)                    \
537   {                                          \
538    if(sbpos == 28)                           \
539    {                                         \
540     sbpos = 0;                               \
541     d = decode_block(ch);                    \
542     if(d && iSPUIRQWait)                     \
543     {                                        \
544      ret = ns;                               \
545      goto out;                               \
546     }                                        \
547    }                                         \
548                                              \
549    fa = SB[sbpos++];                         \
550    interp1_code;                             \
551    spos -= 0x10000;                          \
552   }                                          \
553                                              \
554   interp2_code;                              \
555   spos += sinc;                              \
556  }                                           \
557                                              \
558 out:                                         \
559  s_chan[ch].sinc = sinc;                     \
560  s_chan[ch].spos = spos;                     \
561  s_chan[ch].iSBPos = sbpos;                  \
562  interp_end;                                 \
563                                              \
564  return ret;                                 \
565 }
566
567 #define fmod_recv_check \
568   if(s_chan[ch].bFMod==1 && iFMod[ns]) \
569     sinc = FModChangeFrequency(ch,ns)
570
571 make_do_samples(default, fmod_recv_check, ,
572   StoreInterpolationVal(ch, fa),
573   ChanBuf[ns] = iGetInterpolationVal(ch, spos), )
574 make_do_samples(noint, , fa = s_chan[ch].SB[29], , ChanBuf[ns] = fa, s_chan[ch].SB[29] = fa)
575
576 #define simple_interp_store \
577   s_chan[ch].SB[28] = 0; \
578   s_chan[ch].SB[29] = s_chan[ch].SB[30]; \
579   s_chan[ch].SB[30] = s_chan[ch].SB[31]; \
580   s_chan[ch].SB[31] = fa; \
581   s_chan[ch].SB[32] = 1
582
583 #define simple_interp_get \
584   if(sinc<0x10000)          /* -> upsampling? */ \
585        InterpolateUp(ch);   /* --> interpolate up */ \
586   else InterpolateDown(ch); /* --> else down */ \
587   ChanBuf[ns] = s_chan[ch].SB[29]
588
589 make_do_samples(simple, , ,
590   simple_interp_store, simple_interp_get, )
591
592 static int do_samples_noise(int ch, int ns, int ns_to)
593 {
594  int level, shift, bit;
595
596  s_chan[ch].spos += s_chan[ch].sinc * (ns_to - ns);
597  while (s_chan[ch].spos >= 28*0x10000)
598  {
599   skip_block(ch);
600   s_chan[ch].spos -= 28*0x10000;
601  }
602
603  // modified from DrHell/shalma, no fraction
604  level = (spuCtrl >> 10) & 0x0f;
605  level = 0x8000 >> level;
606
607  for (; ns < ns_to; ns++)
608  {
609   dwNoiseCount += 2;
610   if (dwNoiseCount >= level)
611   {
612    dwNoiseCount -= level;
613    shift = (dwNoiseVal >> 10) & 0x1f;
614    bit = (0x69696969 >> shift) & 1;
615    if (dwNoiseVal & 0x8000)
616     bit ^= 1;
617    dwNoiseVal = (dwNoiseVal << 1) | bit;
618   }
619
620   ChanBuf[ns] = (signed short)dwNoiseVal;
621  }
622
623  return -1;
624 }
625
626 #ifdef __arm__
627 // asm code; lv and rv must be 0-3fff
628 extern void mix_chan(int start, int count, int lv, int rv);
629 extern void mix_chan_rvb(int start, int count, int lv, int rv);
630 #else
631 static void mix_chan(int start, int count, int lv, int rv)
632 {
633  int *dst = SSumLR + start * 2;
634  const int *src = ChanBuf + start;
635  int l, r;
636
637  while (count--)
638   {
639    int sval = *src++;
640
641    l = (sval * lv) >> 14;
642    r = (sval * rv) >> 14;
643    *dst++ += l;
644    *dst++ += r;
645   }
646 }
647
648 static void mix_chan_rvb(int start, int count, int lv, int rv)
649 {
650  int *dst = SSumLR + start * 2;
651  int *drvb = sRVBStart + start * 2;
652  const int *src = ChanBuf + start;
653  int l, r;
654
655  while (count--)
656   {
657    int sval = *src++;
658
659    l = (sval * lv) >> 14;
660    r = (sval * rv) >> 14;
661    *dst++ += l;
662    *dst++ += r;
663    *drvb++ += l;
664    *drvb++ += r;
665   }
666 }
667 #endif
668
669 ////////////////////////////////////////////////////////////////////////
670 // MAIN SPU FUNCTION
671 // here is the main job handler... thread, timer or direct func call
672 // basically the whole sound processing is done in this fat func!
673 ////////////////////////////////////////////////////////////////////////
674
675 // 5 ms waiting phase, if buffer is full and no new sound has to get started
676 // .. can be made smaller (smallest val: 1 ms), but bigger waits give
677 // better performance
678
679 #define PAUSE_W 5
680 #define PAUSE_L 5000
681
682 ////////////////////////////////////////////////////////////////////////
683
684 static void *MAINThread(void *arg)
685 {
686  int volmult = iVolume;
687  int ns,ns_from,ns_to;
688  int ch,d,silentch;
689  int bIRQReturn=0;
690
691  while(!bEndThread)                                    // until we are shutting down
692   {
693    // ok, at the beginning we are looking if there is
694    // enuff free place in the dsound/oss buffer to
695    // fill in new data, or if there is a new channel to start.
696    // if not, we wait (thread) or return (timer/spuasync)
697    // until enuff free place is available/a new channel gets
698    // started
699
700    if(dwNewChannel)                                    // new channel should start immedately?
701     {                                                  // (at least one bit 0 ... MAXCHANNEL is set?)
702      iSecureStart++;                                   // -> set iSecure
703      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)
704     }
705    else iSecureStart=0;                                // 0: no new channel should start
706
707    while(!iSecureStart && !bEndThread &&               // no new start? no thread end?
708          (SoundGetBytesBuffered()>TESTSIZE))           // and still enuff data in sound buffer?
709     {
710      iSecureStart=0;                                   // reset secure
711
712      if(iUseTimer) return 0;                           // linux no-thread mode? bye
713      usleep(PAUSE_L);                                  // else sleep for x ms (linux)
714
715      if(dwNewChannel) iSecureStart=1;                  // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop
716     }
717
718    //--------------------------------------------------// continue from irq handling in timer mode? 
719
720    ns_from=0;
721    ns_to=NSSIZE;
722    ch=0;
723    if(lastch>=0)                                       // will be -1 if no continue is pending
724     {
725      ch=lastch; ns_from=lastns; lastch=-1;             // -> setup all kind of vars to continue
726     }
727
728    silentch=~(dwChannelOn|dwNewChannel);
729
730    //--------------------------------------------------//
731    //- main channel loop                              -// 
732    //--------------------------------------------------//
733     {
734      for(;ch<MAXCHAN;ch++)                             // loop em all... we will collect 1 ms of sound of each playing channel
735       {
736        if(dwNewChannel&(1<<ch)) StartSound(ch);        // start new sound
737        if(!(dwChannelOn&(1<<ch))) continue;            // channel not playing? next
738
739        if(s_chan[ch].bNoise)
740         d=do_samples_noise(ch, ns_from, ns_to);
741        else if(s_chan[ch].bFMod==2 || (s_chan[ch].bFMod==0 && iUseInterpolation==0))
742         d=do_samples_noint(ch, ns_from, ns_to);
743        else if(s_chan[ch].bFMod==0 && iUseInterpolation==1)
744         d=do_samples_simple(ch, ns_from, ns_to);
745        else
746         d=do_samples_default(ch, ns_from, ns_to);
747        if(d>=0)
748         {
749          bIRQReturn=1;
750          lastch=ch; 
751          lastns=ns_to=d;
752          if(d==0)
753           break;
754         }
755
756        MixADSR(ch, ns_from, ns_to);
757
758        if(s_chan[ch].bFMod==2)                         // fmod freq channel
759         memcpy(iFMod, ChanBuf, sizeof(iFMod));
760        else if(s_chan[ch].bRVBActive)
761         mix_chan_rvb(ns_from,ns_to-ns_from,s_chan[ch].iLeftVolume,s_chan[ch].iRightVolume);
762        else
763         mix_chan(ns_from,ns_to-ns_from,s_chan[ch].iLeftVolume,s_chan[ch].iRightVolume);
764       }
765     }
766
767     // advance "stopped" channels that can cause irqs
768     // (all chans are always playing on the real thing..)
769     if(!bIRQReturn && (spuCtrl&CTRL_IRQ))
770      for(ch=0;ch<MAXCHAN;ch++)
771       {
772        if(!(silentch&(1<<ch))) continue;               // already handled
773        if(dwChannelDead&(1<<ch)) continue;
774        if(s_chan[ch].pCurr > pSpuIrq && s_chan[ch].pLoop > pSpuIrq)
775         continue;
776
777        s_chan[ch].spos += s_chan[ch].sinc * NSSIZE;
778        while(s_chan[ch].spos >= 28 * 0x10000)
779         {
780          unsigned char *start = s_chan[ch].pCurr;
781
782          // no need for bIRQReturn since the channel is silent
783          iSpuAsyncWait |= skip_block(ch);
784          if(start == s_chan[ch].pCurr)
785           {
786            // looping on self
787            dwChannelDead |= 1<<ch;
788            s_chan[ch].spos = 0;
789            break;
790           }
791
792          s_chan[ch].spos -= 28 * 0x10000;
793         }
794       }
795
796     if(bIRQReturn && iSPUIRQWait)                      // special return for "spu irq - wait for cpu action"
797      {
798       iSpuAsyncWait=1;
799       bIRQReturn=0;
800       if(iUseTimer!=2)
801        { 
802         DWORD dwWatchTime=timeGetTime_spu()+2500;
803
804         while(iSpuAsyncWait && !bEndThread && 
805               timeGetTime_spu()<dwWatchTime)
806             usleep(1000L);
807         continue;
808        }
809       else
810        {
811         return 0;
812        }
813      }
814
815
816   //---------------------------------------------------//
817   //- here we have another 1 ms of sound data
818   //---------------------------------------------------//
819   // mix XA infos (if any)
820
821   MixXA();
822   
823   ///////////////////////////////////////////////////////
824   // mix all channels (including reverb) into one buffer
825
826   if(iUseReverb)
827    REVERBDo();
828
829   if((spuCtrl&0x4000)==0) // muted? (rare, don't optimize for this)
830    {
831     memset(pS, 0, NSSIZE * 2 * sizeof(pS[0]));
832     pS += NSSIZE*2;
833    }
834   else
835   for (ns = 0; ns < NSSIZE*2; )
836    {
837     d = SSumLR[ns]; SSumLR[ns] = 0;
838     d = d * volmult >> 10;
839     ssat32_to_16(d);
840     *pS++ = d;
841     ns++;
842
843     d = SSumLR[ns]; SSumLR[ns] = 0;
844     d = d * volmult >> 10;
845     ssat32_to_16(d);
846     *pS++ = d;
847     ns++;
848    }
849
850   //////////////////////////////////////////////////////                   
851   // special irq handling in the decode buffers (0x0000-0x1000)
852   // we know: 
853   // the decode buffers are located in spu memory in the following way:
854   // 0x0000-0x03ff  CD audio left
855   // 0x0400-0x07ff  CD audio right
856   // 0x0800-0x0bff  Voice 1
857   // 0x0c00-0x0fff  Voice 3
858   // and decoded data is 16 bit for one sample
859   // we assume: 
860   // even if voices 1/3 are off or no cd audio is playing, the internal
861   // play positions will move on and wrap after 0x400 bytes.
862   // Therefore: we just need a pointer from spumem+0 to spumem+3ff, and 
863   // increase this pointer on each sample by 2 bytes. If this pointer
864   // (or 0x400 offsets of this pointer) hits the spuirq address, we generate
865   // an IRQ. Only problem: the "wait for cpu" option is kinda hard to do here
866   // in some of Peops timer modes. So: we ignore this option here (for now).
867
868   if(pMixIrq)
869    {
870     for(ns=0;ns<NSSIZE;ns++)
871      {
872       if((spuCtrl&0x40) && pSpuIrq && pSpuIrq<spuMemC+0x1000)                 
873        {
874         for(ch=0;ch<4;ch++)
875          {
876           if(pSpuIrq>=pMixIrq+(ch*0x400) && pSpuIrq<pMixIrq+(ch*0x400)+2)
877            do_irq();
878          }
879        }
880       pMixIrq+=2;if(pMixIrq>spuMemC+0x3ff) pMixIrq=spuMemC;
881      }
882    }
883
884   InitREVERB();
885
886   // feed the sound
887   // wanna have around 1/60 sec (16.666 ms) updates
888   if (iCycle++ > 16/FRAG_MSECS)
889    {
890     SoundFeedStreamData((unsigned char *)pSpuBuffer,
891                         ((unsigned char *)pS) - ((unsigned char *)pSpuBuffer));
892     pS = (short *)pSpuBuffer;
893     iCycle = 0;
894    }
895  }
896
897  // end of big main loop...
898
899  bThreadEnded = 1;
900
901  return 0;
902 }
903
904 // SPU ASYNC... even newer epsxe func
905 //  1 time every 'cycle' cycles... harhar
906
907 // rearmed: called every 2ms now
908
909 void CALLBACK SPUasync(unsigned long cycle)
910 {
911  if(iSpuAsyncWait)
912   {
913    iSpuAsyncWait++;
914    if(iSpuAsyncWait<=16/2) return;
915    iSpuAsyncWait=0;
916   }
917
918  if(iUseTimer==2)                                      // special mode, only used in Linux by this spu (or if you enable the experimental Windows mode)
919   {
920    if(!bSpuInit) return;                               // -> no init, no call
921
922    MAINThread(0);                                      // -> linux high-compat mode
923
924    // abuse iSpuAsyncWait mechanism to reduce calls to above function
925    // to make it do larger chunks
926    // note: doing it less often than once per frame causes skips
927    iSpuAsyncWait=1;
928   }
929 }
930
931 // SPU UPDATE... new epsxe func
932 //  1 time every 32 hsync lines
933 //  (312/32)x50 in pal
934 //  (262/32)x60 in ntsc
935
936 // since epsxe 1.5.2 (linux) uses SPUupdate, not SPUasync, I will
937 // leave that func in the linux port, until epsxe linux is using
938 // the async function as well
939
940 void CALLBACK SPUupdate(void)
941 {
942  SPUasync(0);
943 }
944
945 // XA AUDIO
946
947 void CALLBACK SPUplayADPCMchannel(xa_decode_t *xap)
948 {
949  if(!xap)       return;
950  if(!xap->freq) return;                                // no xa freq ? bye
951
952  FeedXA(xap);                                          // call main XA feeder
953 }
954
955 // CDDA AUDIO
956 int CALLBACK SPUplayCDDAchannel(short *pcm, int nbytes)
957 {
958  if (!pcm)      return -1;
959  if (nbytes<=0) return -1;
960
961  return FeedCDDA((unsigned char *)pcm, nbytes);
962 }
963
964 // SETUPTIMER: init of certain buffers and threads/timers
965 void SetupTimer(void)
966 {
967  memset(SSumLR,0,sizeof(SSumLR));                      // init some mixing buffers
968  memset(iFMod,0,NSSIZE*sizeof(int));
969  pS=(short *)pSpuBuffer;                               // setup soundbuffer pointer
970
971  bEndThread=0;                                         // init thread vars
972  bThreadEnded=0; 
973  bSpuInit=1;                                           // flag: we are inited
974
975  if(!iUseTimer)                                        // linux: use thread
976   {
977    pthread_create(&thread, NULL, MAINThread, NULL);
978   }
979 }
980
981 // REMOVETIMER: kill threads/timers
982 void RemoveTimer(void)
983 {
984  bEndThread=1;                                         // raise flag to end thread
985
986  if(!iUseTimer)                                        // linux tread?
987   {
988    int i=0;
989    while(!bThreadEnded && i<2000) {usleep(1000L);i++;} // -> wait until thread has ended
990    if(thread!=(pthread_t)-1) {pthread_cancel(thread);thread=(pthread_t)-1;}  // -> cancel thread anyway
991   }
992
993  bThreadEnded=0;                                       // no more spu is running
994  bSpuInit=0;
995 }
996
997 // SETUPSTREAMS: init most of the spu buffers
998 void SetupStreams(void)
999
1000  int i;
1001
1002  pSpuBuffer=(unsigned char *)malloc(32768);            // alloc mixing buffer
1003
1004  if(iUseReverb==1) i=88200*2;
1005  else              i=NSSIZE*2;
1006
1007  sRVBStart = (int *)malloc(i*4);                       // alloc reverb buffer
1008  memset(sRVBStart,0,i*4);
1009  sRVBEnd  = sRVBStart + i;
1010  sRVBPlay = sRVBStart;
1011
1012  XAStart =                                             // alloc xa buffer
1013   (uint32_t *)malloc(44100 * sizeof(uint32_t));
1014  XAEnd   = XAStart + 44100;
1015  XAPlay  = XAStart;
1016  XAFeed  = XAStart;
1017
1018  CDDAStart =                                           // alloc cdda buffer
1019   (uint32_t *)malloc(CDDA_BUFFER_SIZE);
1020  CDDAEnd   = CDDAStart + 16384;
1021  CDDAPlay  = CDDAStart;
1022  CDDAFeed  = CDDAStart;
1023
1024  for(i=0;i<MAXCHAN;i++)                                // loop sound channels
1025   {
1026 // we don't use mutex sync... not needed, would only 
1027 // slow us down:
1028 //   s_chan[i].hMutex=CreateMutex(NULL,FALSE,NULL);
1029    s_chan[i].ADSRX.SustainLevel = 0xf;                 // -> init sustain
1030    s_chan[i].pLoop=spuMemC;
1031    s_chan[i].pCurr=spuMemC;
1032   }
1033
1034   pMixIrq=spuMemC;                                     // enable decoded buffer irqs by setting the address
1035 }
1036
1037 // REMOVESTREAMS: free most buffer
1038 void RemoveStreams(void)
1039
1040  free(pSpuBuffer);                                     // free mixing buffer
1041  pSpuBuffer = NULL;
1042  free(sRVBStart);                                      // free reverb buffer
1043  sRVBStart = NULL;
1044  free(XAStart);                                        // free XA buffer
1045  XAStart = NULL;
1046  free(CDDAStart);                                      // free CDDA buffer
1047  CDDAStart = NULL;
1048 }
1049
1050 // INIT/EXIT STUFF
1051
1052 // SPUINIT: this func will be called first by the main emu
1053 long CALLBACK SPUinit(void)
1054 {
1055  spuMemC = (unsigned char *)spuMem;                    // just small setup
1056  memset((void *)&rvb, 0, sizeof(REVERBInfo));
1057  InitADSR();
1058
1059  spuIrq = 0;
1060  spuAddr = 0xffffffff;
1061  bEndThread = 0;
1062  bThreadEnded = 0;
1063  spuMemC = (unsigned char *)spuMem;
1064  pMixIrq = 0;
1065  memset((void *)s_chan, 0, (MAXCHAN + 1) * sizeof(SPUCHAN));
1066  pSpuIrq = 0;
1067  //iSPUIRQWait = 0;
1068  lastch = -1;
1069
1070  //ReadConfigSPU();                                      // read user stuff
1071  SetupStreams();                                       // prepare streaming
1072
1073  return 0;
1074 }
1075
1076 // SPUOPEN: called by main emu after init
1077 long CALLBACK SPUopen(void)
1078 {
1079  if (bSPUIsOpen) return 0;                             // security for some stupid main emus
1080
1081  SetupSound();                                         // setup sound (before init!)
1082  SetupTimer();                                         // timer for feeding data
1083
1084  bSPUIsOpen = 1;
1085
1086  return PSE_SPU_ERR_SUCCESS;
1087 }
1088
1089 // SPUCLOSE: called before shutdown
1090 long CALLBACK SPUclose(void)
1091 {
1092  if (!bSPUIsOpen) return 0;                            // some security
1093
1094  bSPUIsOpen = 0;                                       // no more open
1095
1096  RemoveTimer();                                        // no more feeding
1097  RemoveSound();                                        // no more sound handling
1098
1099  return 0;
1100 }
1101
1102 // SPUSHUTDOWN: called by main emu on final exit
1103 long CALLBACK SPUshutdown(void)
1104 {
1105  SPUclose();
1106  RemoveStreams();                                      // no more streaming
1107
1108  return 0;
1109 }
1110
1111 // SPUTEST: we don't test, we are always fine ;)
1112 long CALLBACK SPUtest(void)
1113 {
1114  return 0;
1115 }
1116
1117 // SPUCONFIGURE: call config dialog
1118 long CALLBACK SPUconfigure(void)
1119 {
1120 #ifdef _MACOSX
1121  DoConfiguration();
1122 #else
1123 // StartCfgTool("CFG");
1124 #endif
1125  return 0;
1126 }
1127
1128 // SPUABOUT: show about window
1129 void CALLBACK SPUabout(void)
1130 {
1131 #ifdef _MACOSX
1132  DoAbout();
1133 #else
1134 // StartCfgTool("ABOUT");
1135 #endif
1136 }
1137
1138 // SETUP CALLBACKS
1139 // this functions will be called once, 
1140 // passes a callback that should be called on SPU-IRQ/cdda volume change
1141 void CALLBACK SPUregisterCallback(void (CALLBACK *callback)(void))
1142 {
1143  irqCallback = callback;
1144 }
1145
1146 void CALLBACK SPUregisterCDDAVolume(void (CALLBACK *CDDAVcallback)(unsigned short,unsigned short))
1147 {
1148  cddavCallback = CDDAVcallback;
1149 }
1150
1151 // COMMON PLUGIN INFO FUNCS
1152 /*
1153 char * CALLBACK PSEgetLibName(void)
1154 {
1155  return _(libraryName);
1156 }
1157
1158 unsigned long CALLBACK PSEgetLibType(void)
1159 {
1160  return  PSE_LT_SPU;
1161 }
1162
1163 unsigned long CALLBACK PSEgetLibVersion(void)
1164 {
1165  return (1 << 16) | (6 << 8);
1166 }
1167
1168 char * SPUgetLibInfos(void)
1169 {
1170  return _(libraryInfo);
1171 }
1172 */
1173
1174 // debug
1175 void spu_get_debug_info(int *chans_out, int *run_chans, int *fmod_chans_out, int *noise_chans_out)
1176 {
1177  int ch = 0, fmod_chans = 0, noise_chans = 0, irq_chans = 0;
1178
1179  for(;ch<MAXCHAN;ch++)
1180  {
1181   if (!(dwChannelOn & (1<<ch)))
1182    continue;
1183   if (s_chan[ch].bFMod == 2)
1184    fmod_chans |= 1 << ch;
1185   if (s_chan[ch].bNoise)
1186    noise_chans |= 1 << ch;
1187   if((spuCtrl&CTRL_IRQ) && s_chan[ch].pCurr <= pSpuIrq && s_chan[ch].pLoop <= pSpuIrq)
1188    irq_chans |= 1 << ch;
1189  }
1190
1191  *chans_out = dwChannelOn;
1192  *run_chans = ~dwChannelOn & ~dwChannelDead & irq_chans;
1193  *fmod_chans_out = fmod_chans;
1194  *noise_chans_out = noise_chans;
1195 }
1196
1197 // vim:shiftwidth=1:expandtab