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