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