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