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