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