"Fossies" - the Fresh Open Source Software Archive

Member "audacious-plugins-3.10.1/src/psf/peops2/spu.cc" (26 Dec 2018, 34659 Bytes) of package /linux/misc/audacious-plugins-3.10.1.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "spu.cc" see the Fossies "Dox" file reference documentation.

    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 
    9 /***************************************************************************
   10  *                                                                         *
   11  *   This program is free software; you can redistribute it and/or modify  *
   12  *   it under the terms of the GNU General Public License as published by  *
   13  *   the Free Software Foundation; either version 2 of the License, or     *
   14  *   (at your option) any later version. See also the license.txt file for *
   15  *   additional informations.                                              *
   16  *                                                                         *
   17  ***************************************************************************/
   18 
   19 //*************************************************************************//
   20 // History of changes:
   21 //
   22 // 2005/08/29 - Pete
   23 // - changed to 48Khz output
   24 //
   25 // 2004/12/25 - Pete
   26 // - inc'd version for pcsx2-0.7
   27 //
   28 // 2004/04/18 - Pete
   29 // - changed all kind of things in the plugin
   30 //
   31 // 2004/04/04 - Pete
   32 // - changed plugin to emulate PS2 spu
   33 //
   34 // 2003/04/07 - Eric
   35 // - adjusted cubic interpolation algorithm
   36 //
   37 // 2003/03/16 - Eric
   38 // - added cubic interpolation
   39 //
   40 // 2003/03/01 - linuzappz
   41 // - libraryName changes using ALSA
   42 //
   43 // 2003/02/28 - Pete
   44 // - added option for type of interpolation
   45 // - adjusted spu irqs again (Thousant Arms, Valkyrie Profile)
   46 // - added MONO support for MSWindows DirectSound
   47 //
   48 // 2003/02/20 - kode54
   49 // - amended interpolation code, goto GOON could skip initialization of gpos and cause segfault
   50 //
   51 // 2003/02/19 - kode54
   52 // - moved SPU IRQ handler and changed sample flag processing
   53 //
   54 // 2003/02/18 - kode54
   55 // - moved ADSR calculation outside of the sample decode loop, somehow I doubt that
   56 //   ADSR timing is relative to the frequency at which a sample is played... I guess
   57 //   this remains to be seen, and I don't know whether ADSR is applied to noise channels...
   58 //
   59 // 2003/02/09 - kode54
   60 // - one-shot samples now process the end block before stopping
   61 // - in light of removing fmod hack, now processing ADSR on frequency channel as well
   62 //
   63 // 2003/02/08 - kode54
   64 // - replaced easy interpolation with gaussian
   65 // - removed fmod averaging hack
   66 // - changed .sinc to be updated from .iRawPitch, no idea why it wasn't done this way already (<- Pete: because I sometimes fail to see the obvious, haharhar :)
   67 //
   68 // 2003/02/08 - linuzappz
   69 // - small bugfix for one usleep that was 1 instead of 1000
   70 // - added iDisStereo for no stereo (Linux)
   71 //
   72 // 2003/01/22 - Pete
   73 // - added easy interpolation & small noise adjustments
   74 //
   75 // 2003/01/19 - Pete
   76 // - added Neill's reverb
   77 //
   78 // 2003/01/12 - Pete
   79 // - added recording window handlers
   80 //
   81 // 2003/01/06 - Pete
   82 // - added Neill's ADSR timings
   83 //
   84 // 2002/12/28 - Pete
   85 // - adjusted spu irq handling, fmod handling and loop handling
   86 //
   87 // 2002/08/14 - Pete
   88 // - added extra reverb
   89 //
   90 // 2002/06/08 - linuzappz
   91 // - SPUupdate changed for SPUasync
   92 //
   93 // 2002/05/15 - Pete
   94 // - generic cleanup for the Peops release
   95 //
   96 //*************************************************************************//
   97 
   98 #include "stdafx.h"
   99 
  100 #define _IN_SPU
  101 
  102 #include "../peops2/externals.h"
  103 #include "../peops2/regs.h"
  104 #include "../peops2/dma.h"
  105 
  106 ////////////////////////////////////////////////////////////////////////
  107 // globals
  108 ////////////////////////////////////////////////////////////////////////
  109 
  110 // psx buffer / addresses
  111 
  112 unsigned short  regArea[32*1024];
  113 unsigned short  spuMem[1*1024*1024];
  114 unsigned char * spuMemC;
  115 unsigned char * pSpuIrq[2];
  116 unsigned char * pSpuBuffer;
  117 
  118 // user settings
  119 
  120 int             iUseXA=0;
  121 int             iXAPitch=1;
  122 int             iUseTimer=2;
  123 int             iSPUIRQWait=1;
  124 int             iDebugMode=0;
  125 int             iRecordMode=0;
  126 int             iUseReverb=1;
  127 int             iUseInterpolation=2;
  128 
  129 // MAIN infos struct for each channel
  130 
  131 SPUCHAN         s_chan[MAXCHAN+1];                     // channel + 1 infos (1 is security for fmod handling)
  132 REVERBInfo      rvb[2];
  133 
  134 unsigned long   dwNoiseVal=1;                          // global noise generator
  135 
  136 unsigned short  spuCtrl2[2];                           // some vars to store psx reg infos
  137 unsigned short  spuStat2[2];
  138 unsigned long   spuIrq2[2];
  139 unsigned long   spuAddr2[2];                           // address into spu mem
  140 unsigned long   spuRvbAddr2[2];
  141 unsigned long   spuRvbAEnd2[2];
  142 int             bEndThread=0;                          // thread handlers
  143 int             bThreadEnded=0;
  144 int             bSpuInit=0;
  145 int             bSPUIsOpen=0;
  146 
  147 unsigned long dwNewChannel2[2];                        // flags for faster testing, if new channel starts
  148 unsigned long dwEndChannel2[2];
  149 
  150 // UNUSED IN PS2 YET
  151 void (CALLBACK *irqCallback)(void)=0;                  // func of main emu, called on spu irq
  152 void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0;
  153 
  154 // certain globals (were local before, but with the new timeproc I need em global)
  155 
  156 const int f[5][2] = {   {    0,  0  },
  157                         {   60,  0  },
  158                         {  115, -52 },
  159                         {   98, -55 },
  160                         {  122, -60 } };
  161 int SSumR[NSSIZE];
  162 int SSumL[NSSIZE];
  163 int iCycle=0;
  164 short * pS;
  165 
  166 static int lastch=-1;      // last channel processed on spu irq in timer mode
  167 static int iSecureStart=0; // secure start counter
  168 
  169 ////////////////////////////////////////////////////////////////////////
  170 // CODE AREA
  171 ////////////////////////////////////////////////////////////////////////
  172 
  173 // dirty inline func includes
  174 
  175 #include "reverb.cc"
  176 #include "adsr.cc"
  177 
  178 ////////////////////////////////////////////////////////////////////////
  179 // helpers for simple interpolation
  180 
  181 //
  182 // easy interpolation on upsampling, no special filter, just "Pete's common sense" tm
  183 //
  184 // instead of having n equal sample values in a row like:
  185 //       ____
  186 //           |____
  187 //
  188 // we compare the current delta change with the next delta change.
  189 //
  190 // if curr_delta is positive,
  191 //
  192 //  - and next delta is smaller (or changing direction):
  193 //         \.
  194 //          -__
  195 //
  196 //  - and next delta significant (at least twice) bigger:
  197 //         --_
  198 //            \.
  199 //
  200 //  - and next delta is nearly same:
  201 //          \.
  202 //           \.
  203 //
  204 //
  205 // if curr_delta is negative,
  206 //
  207 //  - and next delta is smaller (or changing direction):
  208 //          _--
  209 //         /
  210 //
  211 //  - and next delta significant (at least twice) bigger:
  212 //            /
  213 //         __-
  214 //
  215 //  - and next delta is nearly same:
  216 //           /
  217 //          /
  218 //
  219 
  220 
  221 static inline void InterpolateUp(int ch)
  222 {
  223  if(s_chan[ch].SB[32]==1)                              // flag == 1? calc step and set flag... and don't change the value in this pass
  224   {
  225    const int id1=s_chan[ch].SB[30]-s_chan[ch].SB[29];  // curr delta to next val
  226    const int id2=s_chan[ch].SB[31]-s_chan[ch].SB[30];  // and next delta to next-next val :)
  227 
  228    s_chan[ch].SB[32]=0;
  229 
  230    if(id1>0)                                           // curr delta positive
  231     {
  232      if(id2<id1)
  233       {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;}
  234      else
  235      if(id2<(id1<<1))
  236       s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L;
  237      else
  238       s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L;
  239     }
  240    else                                                // curr delta negative
  241     {
  242      if(id2>id1)
  243       {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;}
  244      else
  245      if(id2>(id1<<1))
  246       s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L;
  247      else
  248       s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L;
  249     }
  250   }
  251  else
  252  if(s_chan[ch].SB[32]==2)                              // flag 1: calc step and set flag... and don't change the value in this pass
  253   {
  254    s_chan[ch].SB[32]=0;
  255 
  256    s_chan[ch].SB[28]=(s_chan[ch].SB[28]*s_chan[ch].sinc)/0x20000L;
  257    if(s_chan[ch].sinc<=0x8000)
  258         s_chan[ch].SB[29]=s_chan[ch].SB[30]-(s_chan[ch].SB[28]*((0x10000/s_chan[ch].sinc)-1));
  259    else s_chan[ch].SB[29]+=s_chan[ch].SB[28];
  260   }
  261  else                                                  // no flags? add bigger val (if possible), calc smaller step, set flag1
  262   s_chan[ch].SB[29]+=s_chan[ch].SB[28];
  263 }
  264 
  265 //
  266 // even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm
  267 //
  268 
  269 static inline void InterpolateDown(int ch)
  270 {
  271  if(s_chan[ch].sinc>=0x20000L)                                 // we would skip at least one val?
  272   {
  273    s_chan[ch].SB[29]+=(s_chan[ch].SB[30]-s_chan[ch].SB[29])/2; // add easy weight
  274    if(s_chan[ch].sinc>=0x30000L)                               // we would skip even more vals?
  275     s_chan[ch].SB[29]+=(s_chan[ch].SB[31]-s_chan[ch].SB[30])/2;// add additional next weight
  276   }
  277 }
  278 
  279 ////////////////////////////////////////////////////////////////////////
  280 // helpers for gauss interpolation
  281 
  282 #define gval0 (((short*)(&s_chan[ch].SB[29]))[gpos])
  283 #define gval(x) (((short*)(&s_chan[ch].SB[29]))[(gpos+x)&3])
  284 
  285 #include "gauss_i.h"
  286 
  287 ////////////////////////////////////////////////////////////////////////
  288 
  289 //#include "xa.c"
  290 
  291 ////////////////////////////////////////////////////////////////////////
  292 // START SOUND... called by main thread to setup a new sound on a channel
  293 ////////////////////////////////////////////////////////////////////////
  294 
  295 static inline void StartSound(int ch)
  296 {
  297  dwNewChannel2[ch/24]&=~(1<<(ch%24));                  // clear new channel bit
  298  dwEndChannel2[ch/24]&=~(1<<(ch%24));                  // clear end channel bit
  299 
  300  StartADSR(ch);
  301  StartREVERB(ch);
  302 
  303  s_chan[ch].pCurr=s_chan[ch].pStart;                   // set sample start
  304 
  305  s_chan[ch].s_1=0;                                     // init mixing vars
  306  s_chan[ch].s_2=0;
  307  s_chan[ch].iSBPos=28;
  308 
  309  s_chan[ch].bNew=0;                                    // init channel flags
  310  s_chan[ch].bStop=0;
  311  s_chan[ch].bOn=1;
  312 
  313  s_chan[ch].SB[29]=0;                                  // init our interpolation helpers
  314  s_chan[ch].SB[30]=0;
  315 
  316  if(iUseInterpolation>=2)                              // gauss interpolation?
  317       {s_chan[ch].spos=0x30000L;s_chan[ch].SB[28]=0;}  // -> start with more decoding
  318  else {s_chan[ch].spos=0x10000L;s_chan[ch].SB[31]=0;}  // -> no/simple interpolation starts with one 44100 decoding
  319 }
  320 
  321 ////////////////////////////////////////////////////////////////////////
  322 // MAIN SPU FUNCTION
  323 // here is the main job handler... thread, timer or direct func call
  324 // basically the whole sound processing is done in this fat func!
  325 ////////////////////////////////////////////////////////////////////////
  326 
  327 static u32 sampcount;
  328 static u32 decaybegin;
  329 static u32 decayend;
  330 
  331 static u32 seektime;
  332 int psf2_seek(u32 t)
  333 {
  334  seektime=t*441/10;
  335  if(seektime>=sampcount) return(1);
  336  return(0);
  337 }
  338 
  339 // Counting to 65536 results in full volume offage.
  340 void setlength2(s32 stop, s32 fade)
  341 {
  342  if(stop==~0)
  343  {
  344   decaybegin=~0;
  345  }
  346  else
  347  {
  348   stop=(stop*441)/10;
  349   fade=(fade*441)/10;
  350 
  351   decaybegin=stop;
  352   decayend=stop+fade;
  353  }
  354 }
  355 // 5 ms waiting phase, if buffer is full and no new sound has to get started
  356 // .. can be made smaller (smallest val: 1 ms), but bigger waits give
  357 // better performance
  358 
  359 #define PAUSE_W 5
  360 #define PAUSE_L 5000
  361 
  362 ////////////////////////////////////////////////////////////////////////
  363 
  364 int iSpuAsyncWait=0;
  365 
  366 static void *MAINThread(void (*update)(const void *, int))
  367 {
  368  int s_1,s_2,fa;
  369  unsigned char * start;unsigned int nSample;
  370  int ch,predict_nr,shift_factor,flags,d,d2,s;
  371  int gpos,bIRQReturn=0;
  372 
  373 // while(!bEndThread)                                    // until we are shutting down
  374   {
  375    //--------------------------------------------------//
  376    // ok, at the beginning we are looking if there is
  377    // enuff free place in the dsound/oss buffer to
  378    // fill in new data, or if there is a new channel to start.
  379    // if not, we wait (thread) or return (timer/spuasync)
  380    // until enuff free place is available/a new channel gets
  381    // started
  382 
  383    if(dwNewChannel2[0] || dwNewChannel2[1])            // new channel should start immedately?
  384     {                                                  // (at least one bit 0 ... MAXCHANNEL is set?)
  385      iSecureStart++;                                   // -> set iSecure
  386      if(iSecureStart>5) iSecureStart=0;                //    (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance)
  387     }
  388    else iSecureStart=0;                                // 0: no new channel should start
  389 
  390 /* if (!iSecureStart)
  391     {
  392      iSecureStart=0;                                   // reset secure
  393      return;
  394     }*/
  395 
  396 #if 0
  397    while(!iSecureStart && !bEndThread) // &&               // no new start? no thread end?
  398 //         (SoundGetBytesBuffered()>TESTSIZE))           // and still enuff data in sound buffer?
  399     {
  400      iSecureStart=0;                                   // reset secure
  401 
  402      if(iUseTimer) return 0;                           // linux no-thread mode? bye
  403 
  404      if(dwNewChannel2[0] || dwNewChannel2[1])
  405       iSecureStart=1;                                  // if a new channel kicks in (or, of course, sound buffer runs low), we will leave the loop
  406     }
  407 #endif
  408 
  409    //--------------------------------------------------// continue from irq handling in timer mode?
  410 
  411    if(lastch>=0)                                       // will be -1 if no continue is pending
  412     {
  413      ch=lastch; lastch=-1;                  // -> setup all kind of vars to continue
  414      goto GOON;                                        // -> directly jump to the continue point
  415     }
  416 
  417    //--------------------------------------------------//
  418    //- main channel loop                              -//
  419    //--------------------------------------------------//
  420     {
  421      for(ch=0;ch<MAXCHAN;ch++)                         // loop em all... we will collect 1 ms of sound of each playing channel
  422       {
  423        if(s_chan[ch].bNew) StartSound(ch);             // start new sound
  424        if(!s_chan[ch].bOn) continue;                   // channel not playing? next
  425 
  426        if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq)   // new psx frequency?
  427         {
  428          s_chan[ch].iUsedFreq=s_chan[ch].iActFreq;     // -> take it and calc steps
  429          s_chan[ch].sinc=s_chan[ch].iRawPitch<<4;
  430          if(!s_chan[ch].sinc) s_chan[ch].sinc=1;
  431          if(iUseInterpolation==1) s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag
  432         }
  433 //       ns=0;
  434 //       while(ns<NSSIZE)                                // loop until 1 ms of data is reached
  435         {
  436          while(s_chan[ch].spos>=0x10000L)
  437           {
  438            if(s_chan[ch].iSBPos==28)                   // 28 reached?
  439             {
  440              start=s_chan[ch].pCurr;                   // set up the current pos
  441 
  442              if (start == (unsigned char*)-1)          // special "stop" sign
  443               {
  444                s_chan[ch].bOn=0;                       // -> turn everything off
  445                s_chan[ch].ADSRX.lVolume=0;
  446                s_chan[ch].ADSRX.EnvelopeVol=0;
  447                goto ENDX;                              // -> and done for this channel
  448               }
  449 
  450              s_chan[ch].iSBPos=0;
  451 
  452              //////////////////////////////////////////// spu irq handler here? mmm... do it later
  453 
  454              s_1=s_chan[ch].s_1;
  455              s_2=s_chan[ch].s_2;
  456 
  457              predict_nr=(int)*start;start++;
  458              shift_factor=predict_nr&0xf;
  459              predict_nr >>= 4;
  460              flags=(int)*start;start++;
  461 
  462              // -------------------------------------- //
  463 
  464              for (nSample=0;nSample<28;start++)
  465               {
  466                d=(int)*start;
  467                s=((d&0xf)<<12);
  468                if(s&0x8000) s|=0xffff0000;
  469 
  470                fa=(s >> shift_factor);
  471                fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
  472                s_2=s_1;s_1=fa;
  473                s=((d & 0xf0) << 8);
  474 
  475                s_chan[ch].SB[nSample++]=fa;
  476 
  477                if(s&0x8000) s|=0xffff0000;
  478                fa=(s>>shift_factor);
  479                fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
  480                s_2=s_1;s_1=fa;
  481 
  482                s_chan[ch].SB[nSample++]=fa;
  483               }
  484 
  485              //////////////////////////////////////////// irq check
  486 
  487              if(spuCtrl2[ch/24]&0x40)                  // some irq active?
  488               {
  489                if((pSpuIrq[ch/24] >  start-16 &&       // irq address reached?
  490                    pSpuIrq[ch/24] <= start) ||
  491                   ((flags&1) &&                        // special: irq on looping addr, when stop/loop flag is set
  492                    (pSpuIrq[ch/24] >  s_chan[ch].pLoop-16 &&
  493                     pSpuIrq[ch/24] <= s_chan[ch].pLoop)))
  494                 {
  495                  s_chan[ch].iIrqDone=1;                // -> debug flag
  496 
  497                  if(irqCallback) irqCallback();        // -> call main emu (not supported in SPU2 right now)
  498                  else
  499                   {
  500                    if(ch<24) InterruptDMA4();            // -> let's see what is happening if we call our irqs instead ;)
  501                    else      InterruptDMA7();
  502                   }
  503 
  504                  if(iSPUIRQWait)                       // -> option: wait after irq for main emu
  505                   {
  506                    iSpuAsyncWait=1;
  507                    bIRQReturn=1;
  508                   }
  509                 }
  510               }
  511 
  512              //////////////////////////////////////////// flag handler
  513 
  514              if((flags&4) && (!s_chan[ch].bIgnoreLoop))
  515               s_chan[ch].pLoop=start-16;               // loop adress
  516 
  517              if(flags&1)                               // 1: stop/loop
  518               {
  519                dwEndChannel2[ch/24]|=(1<<(ch%24));
  520 
  521                // We play this block out first...
  522                //if(!(flags&2)|| s_chan[ch].pLoop==nullptr)
  523                                                        // 1+2: do loop... otherwise: stop
  524                if(flags!=3 || s_chan[ch].pLoop==nullptr)  // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example)
  525                 {                                      // and checking if pLoop is set avoids crashes, yeah
  526                  start = (unsigned char*)-1;
  527                 }
  528                else
  529                 {
  530                  start = s_chan[ch].pLoop;
  531                 }
  532               }
  533 
  534              s_chan[ch].pCurr=start;                   // store values for next cycle
  535              s_chan[ch].s_1=s_1;
  536              s_chan[ch].s_2=s_2;
  537 
  538              ////////////////////////////////////////////
  539 
  540              if(bIRQReturn)                            // special return for "spu irq - wait for cpu action"
  541               {
  542                bIRQReturn=0;
  543                 {
  544                  lastch=ch;
  545 //                 lastns=ns;   // changemeback
  546 
  547                  return nullptr;
  548                 }
  549               }
  550 
  551              ////////////////////////////////////////////
  552 
  553 GOON: ;
  554 
  555             }
  556 
  557            fa=s_chan[ch].SB[s_chan[ch].iSBPos++];      // get sample data
  558 
  559 //           if((spuCtrl2[ch/24]&0x4000)==0) fa=0;       // muted?
  560 //           else                                        // else adjust
  561             {
  562              if(fa>32767L)  fa=32767L;
  563              if(fa<-32767L) fa=-32767L;
  564             }
  565 
  566            if(iUseInterpolation>=2)                    // gauss/cubic interpolation
  567             {
  568              gpos = s_chan[ch].SB[28];
  569              gval0 = fa;
  570              gpos = (gpos+1) & 3;
  571              s_chan[ch].SB[28] = gpos;
  572             }
  573            else
  574            if(iUseInterpolation==1)                    // simple interpolation
  575             {
  576              s_chan[ch].SB[28] = 0;
  577              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'
  578              s_chan[ch].SB[30] = s_chan[ch].SB[31];
  579              s_chan[ch].SB[31] = fa;
  580              s_chan[ch].SB[32] = 1;                    // -> flag: calc new interolation
  581             }
  582            else s_chan[ch].SB[29]=fa;                  // no interpolation
  583 
  584            s_chan[ch].spos -= 0x10000L;
  585           }
  586 
  587          ////////////////////////////////////////////////
  588          // noise handler... just produces some noise data
  589          // surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used...
  590          // and sometimes the noise will be used as fmod modulation... pfff
  591 
  592          if(s_chan[ch].bNoise)
  593           {
  594            if((dwNoiseVal<<=1)&0x80000000L)
  595             {
  596              dwNoiseVal^=0x0040001L;
  597              fa=((dwNoiseVal>>2)&0x7fff);
  598              fa=-fa;
  599             }
  600            else fa=(dwNoiseVal>>2)&0x7fff;
  601 
  602            // mmm... depending on the noise freq we allow bigger/smaller changes to the previous val
  603            fa=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl2[ch/24]&0x3f00)>>9))+1));
  604            if(fa>32767L)  fa=32767L;
  605            if(fa<-32767L) fa=-32767L;
  606            s_chan[ch].iOldNoise=fa;
  607 
  608            if(iUseInterpolation<2)                     // no gauss/cubic interpolation?
  609             s_chan[ch].SB[29] = fa;                    // -> store noise val in "current sample" slot
  610           }                                            //----------------------------------------
  611          else                                          // NO NOISE (NORMAL SAMPLE DATA) HERE
  612           {//------------------------------------------//
  613            if(iUseInterpolation==3)                    // cubic interpolation
  614             {
  615              long xd;
  616              xd = ((s_chan[ch].spos) >> 1)+1;
  617              gpos = s_chan[ch].SB[28];
  618 
  619              fa  = gval(3) - 3*gval(2) + 3*gval(1) - gval0;
  620              fa *= (xd - (2<<15)) / 6;
  621              fa >>= 15;
  622              fa += gval(2) - gval(1) - gval(1) + gval0;
  623              fa *= (xd - (1<<15)) >> 1;
  624              fa >>= 15;
  625              fa += gval(1) - gval0;
  626              fa *= xd;
  627              fa >>= 15;
  628              fa = fa + gval0;
  629             }
  630            //------------------------------------------//
  631            else
  632            if(iUseInterpolation==2)                    // gauss interpolation
  633             {
  634              int vl, vr;
  635              vl = (s_chan[ch].spos >> 6) & ~3;
  636              gpos = s_chan[ch].SB[28];
  637              vr=(gauss[vl]*gval0)&~2047;
  638              vr+=(gauss[vl+1]*gval(1))&~2047;
  639              vr+=(gauss[vl+2]*gval(2))&~2047;
  640              vr+=(gauss[vl+3]*gval(3))&~2047;
  641              fa = vr>>11;
  642 /*
  643              vr=(gauss[vl]*gval0)>>9;
  644              vr+=(gauss[vl+1]*gval(1))>>9;
  645              vr+=(gauss[vl+2]*gval(2))>>9;
  646              vr+=(gauss[vl+3]*gval(3))>>9;
  647              fa = vr>>2;
  648 */
  649             }
  650            //------------------------------------------//
  651            else
  652            if(iUseInterpolation==1)                    // simple interpolation
  653             {
  654              if(s_chan[ch].sinc<0x10000L)              // -> upsampling?
  655                   InterpolateUp(ch);                   // --> interpolate up
  656              else InterpolateDown(ch);                 // --> else down
  657              fa=s_chan[ch].SB[29];
  658             }
  659            //------------------------------------------//
  660            else fa=s_chan[ch].SB[29];                  // no interpolation
  661           }
  662 
  663          s_chan[ch].sval = (MixADSR(ch) * fa) / 1023;  // add adsr
  664 
  665          if(s_chan[ch].bFMod==2)                       // fmod freq channel
  666           {
  667            int NP=s_chan[ch+1].iRawPitch;
  668            double intr;
  669 
  670            NP=((32768L+s_chan[ch].sval)*NP)/32768L;    // mmm... I still need to adjust that to 1/48 khz... we will wait for the first game/demo using it to decide how to do it :)
  671 
  672            if(NP>0x3fff) NP=0x3fff;
  673            if(NP<0x1)    NP=0x1;
  674 
  675            intr = (double)48000.0f / (double)44100.0f * (double)NP;
  676            NP = (uint32_t)intr;
  677 
  678            NP=(44100L*NP)/(4096L);                     // calc frequency
  679 
  680            s_chan[ch+1].iActFreq=NP;
  681            s_chan[ch+1].iUsedFreq=NP;
  682            s_chan[ch+1].sinc=(((NP/10)<<16)/4410);
  683            if(!s_chan[ch+1].sinc) s_chan[ch+1].sinc=1;
  684            if(iUseInterpolation==1)                    // freq change in sipmle interpolation mode
  685             s_chan[ch+1].SB[32]=1;
  686 
  687 // mmmm... set up freq decoding positions?
  688 //           s_chan[ch+1].iSBPos=28;
  689 //           s_chan[ch+1].spos=0x10000L;
  690           }
  691          else
  692           {
  693            //////////////////////////////////////////////
  694            // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff)
  695 
  696            if(s_chan[ch].iMute)
  697             s_chan[ch].sval=0;                         // debug mute
  698            else
  699             {
  700              if(s_chan[ch].bVolumeL)
  701               SSumL[0]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000L;
  702              if(s_chan[ch].bVolumeR)
  703               SSumR[0]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000L;
  704             }
  705 
  706            //////////////////////////////////////////////
  707            // now let us store sound data for reverb
  708 
  709            if(s_chan[ch].bRVBActive) StoreREVERB(ch,0);
  710           }
  711 
  712          ////////////////////////////////////////////////
  713          // ok, go on until 1 ms data of this channel is collected
  714 
  715          s_chan[ch].spos += s_chan[ch].sinc;
  716 
  717         }
  718 ENDX:   ;
  719       }
  720     }
  721 
  722   //---------------------------------------------------//
  723   //- here we have another 1 ms of sound data
  724   //---------------------------------------------------//
  725 
  726   ///////////////////////////////////////////////////////
  727   // mix all channels (including reverb) into one buffer
  728 
  729     SSumL[0]+=MixREVERBLeft(0,0);
  730     SSumL[0]+=MixREVERBLeft(0,1);
  731     SSumR[0]+=MixREVERBRight(0);
  732     SSumR[0]+=MixREVERBRight(1);
  733 
  734     d=SSumL[0];SSumL[0]=0;
  735     d2=SSumR[0];SSumR[0]=0;
  736 
  737     if(d<-32767) d=-32767;
  738     if(d>32767) d=32767;
  739     if(d2<-32767) d2=-32767;
  740     if(d2>32767) d2=32767;
  741 
  742     if(sampcount>=decaybegin)
  743      {
  744       s32 dmul;
  745       if(decaybegin!=~0) // Is anyone REALLY going to be playing a song
  746                          // for 13 hours?
  747        {
  748         if(sampcount>=decayend)
  749          {
  750           update(nullptr, 0);
  751           return(0);
  752          }
  753 
  754         dmul=256-(256*(sampcount-decaybegin)/(decayend-decaybegin));
  755         d=(d*dmul)>>8;
  756         d2=(d2*dmul)>>8;
  757        }
  758      }
  759     sampcount++;
  760 
  761     *pS++=d;
  762     *pS++=d2;
  763 
  764     InitREVERB();
  765 
  766   //////////////////////////////////////////////////////
  767   // feed the sound
  768   // wanna have around 1/60 sec (16.666 ms) updates
  769   if(seektime != 0 && sampcount < seektime)
  770    {
  771     pS=(short *)pSpuBuffer;
  772    }
  773   else if((((u8*)pS)-((u8*)pSpuBuffer)) == (735*4))
  774    {
  775     short *pSilenceIter = (short *)pSpuBuffer;
  776     int iSilenceCount = 0;
  777 
  778     for(; pSilenceIter < pS; pSilenceIter++)
  779      {
  780       if(*pSilenceIter == 0)
  781        iSilenceCount++;
  782 
  783       if(iSilenceCount > 20)
  784        break;
  785      }
  786 
  787     if(iSilenceCount < 20)
  788      update((u8*)pSpuBuffer,(u8*)pS-(u8*)pSpuBuffer);
  789 
  790     pS=(short *)pSpuBuffer;
  791    }
  792  }
  793 
  794  // end of big main loop...
  795 
  796  bThreadEnded=1;
  797 
  798  return 0;
  799 }
  800 
  801 ////////////////////////////////////////////////////////////////////////
  802 ////////////////////////////////////////////////////////////////////////
  803 ////////////////////////////////////////////////////////////////////////
  804 
  805 ////////////////////////////////////////////////////////////////////////
  806 // SPU ASYNC... even newer epsxe func
  807 //  1 time every 'cycle' cycles... harhar
  808 ////////////////////////////////////////////////////////////////////////
  809 
  810 EXPORT_GCC void CALLBACK SPU2async(void (*update)(const void *, int))
  811 {
  812  if(iSpuAsyncWait)
  813   {
  814    iSpuAsyncWait++;
  815    if(iSpuAsyncWait<=64) return;
  816    iSpuAsyncWait=0;
  817   }
  818  MAINThread(update);                                      // -> linux high-compat mode
  819 }
  820 
  821 ////////////////////////////////////////////////////////////////////////
  822 // INIT/EXIT STUFF
  823 ////////////////////////////////////////////////////////////////////////
  824 
  825 ////////////////////////////////////////////////////////////////////////
  826 // SPUINIT: this func will be called first by the main emu
  827 ////////////////////////////////////////////////////////////////////////
  828 
  829 
  830 EXPORT_GCC long CALLBACK SPU2init(void)
  831 {
  832  spuMemC=(unsigned char *)spuMem;                      // just small setup
  833  memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN));
  834  memset(rvb,0,2*sizeof(REVERBInfo));
  835 
  836  sampcount = 0;
  837  seektime = 0;
  838 
  839  InitADSR();
  840 
  841  return 0;
  842 }
  843 
  844 ////////////////////////////////////////////////////////////////////////
  845 // SETUPTIMER: init of certain buffers and threads/timers
  846 ////////////////////////////////////////////////////////////////////////
  847 
  848 static void SetupTimer(void)
  849 {
  850  memset(SSumR,0,NSSIZE*sizeof(int));                   // init some mixing buffers
  851  memset(SSumL,0,NSSIZE*sizeof(int));
  852  pS=(short *)pSpuBuffer;                               // setup soundbuffer pointer
  853 
  854  bEndThread=0;                                         // init thread vars
  855  bThreadEnded=0;
  856  bSpuInit=1;                                           // flag: we are inited
  857 }
  858 
  859 ////////////////////////////////////////////////////////////////////////
  860 // REMOVETIMER: kill threads/timers
  861 ////////////////////////////////////////////////////////////////////////
  862 
  863 static void RemoveTimer(void)
  864 {
  865  bEndThread=1;                                         // raise flag to end thread
  866  bThreadEnded=0;                                       // no more spu is running
  867  bSpuInit=0;
  868 }
  869 
  870 ////////////////////////////////////////////////////////////////////////
  871 // SETUPSTREAMS: init most of the spu buffers
  872 ////////////////////////////////////////////////////////////////////////
  873 
  874 static void SetupStreams(void)
  875 {
  876  int i;
  877 
  878  pSpuBuffer=(unsigned char *)malloc(32768);            // alloc mixing buffer
  879 
  880  i=NSSIZE*2;
  881 
  882  sRVBStart[0] = (int *)malloc(i*4);                    // alloc reverb buffer
  883  memset(sRVBStart[0],0,i*4);
  884  sRVBEnd[0]  = sRVBStart[0] + i;
  885  sRVBPlay[0] = sRVBStart[0];
  886  sRVBStart[1] = (int *)malloc(i*4);                    // alloc reverb buffer
  887  memset(sRVBStart[1],0,i*4);
  888  sRVBEnd[1]  = sRVBStart[1] + i;
  889  sRVBPlay[1] = sRVBStart[1];
  890 
  891  for(i=0;i<MAXCHAN;i++)                                // loop sound channels
  892   {
  893 // we don't use mutex sync... not needed, would only
  894 // slow us down:
  895 //   s_chan[i].hMutex=CreateMutex(nullptr,false,nullptr);
  896    s_chan[i].ADSRX.SustainLevel = 1024;                // -> init sustain
  897    s_chan[i].iMute=0;
  898    s_chan[i].iIrqDone=0;
  899    s_chan[i].pLoop=spuMemC;
  900    s_chan[i].pStart=spuMemC;
  901    s_chan[i].pCurr=spuMemC;
  902   }
  903 }
  904 
  905 ////////////////////////////////////////////////////////////////////////
  906 // REMOVESTREAMS: free most buffer
  907 ////////////////////////////////////////////////////////////////////////
  908 
  909 static void RemoveStreams(void)
  910 {
  911  free(pSpuBuffer);                                     // free mixing buffer
  912  pSpuBuffer=nullptr;
  913  free(sRVBStart[0]);                                   // free reverb buffer
  914  sRVBStart[0]=0;
  915  free(sRVBStart[1]);                                   // free reverb buffer
  916  sRVBStart[1]=0;
  917 
  918 /*
  919  int i;
  920  for(i=0;i<MAXCHAN;i++)
  921   {
  922    WaitForSingleObject(s_chan[i].hMutex,2000);
  923    ReleaseMutex(s_chan[i].hMutex);
  924    if(s_chan[i].hMutex)
  925     {CloseHandle(s_chan[i].hMutex);s_chan[i].hMutex=0;}
  926   }
  927 */
  928 }
  929 
  930 
  931 ////////////////////////////////////////////////////////////////////////
  932 // SPUOPEN: called by main emu after init
  933 ////////////////////////////////////////////////////////////////////////
  934 
  935 EXPORT_GCC long CALLBACK SPU2open(void *pDsp)
  936 {
  937  if(bSPUIsOpen) return 0;                              // security for some stupid main emus
  938 
  939  iUseXA=0;                                             // just small setup
  940  bEndThread=0;
  941  bThreadEnded=0;
  942  spuMemC=(unsigned char *)spuMem;
  943  memset((void *)s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN));
  944  pSpuIrq[0]=0;
  945  pSpuIrq[1]=0;
  946  iSPUIRQWait=1;
  947  dwNewChannel2[0]=0;
  948  dwNewChannel2[1]=0;
  949  dwEndChannel2[0]=0;
  950  dwEndChannel2[1]=0;
  951  spuCtrl2[0]=0;
  952  spuCtrl2[1]=0;
  953  spuStat2[0]=0;
  954  spuStat2[1]=0;
  955  spuIrq2[0]=0;
  956  spuIrq2[1]=0;
  957  spuAddr2[0]=0xffffffff;
  958  spuAddr2[1]=0xffffffff;
  959  spuRvbAddr2[0]=0;
  960  spuRvbAddr2[1]=0;
  961  spuRvbAEnd2[0]=0;
  962  spuRvbAEnd2[1]=0;
  963 
  964 // ReadConfig();                                         // read user stuff
  965 
  966 // SetupSound();                                         // setup midas (before init!)
  967 
  968  SetupStreams();                                       // prepare streaming
  969 
  970  SetupTimer();                                         // timer for feeding data
  971 
  972  bSPUIsOpen=1;
  973 
  974  return 0;
  975 }
  976 
  977 ////////////////////////////////////////////////////////////////////////
  978 
  979 ////////////////////////////////////////////////////////////////////////
  980 // SPUCLOSE: called before shutdown
  981 ////////////////////////////////////////////////////////////////////////
  982 
  983 EXPORT_GCC void CALLBACK SPU2close(void)
  984 {
  985  if(!bSPUIsOpen) return;                               // some security
  986 
  987  bSPUIsOpen=0;                                         // no more open
  988 
  989  RemoveTimer();                                        // no more feeding
  990 
  991 // RemoveSound();                                        // no more sound handling
  992 
  993  RemoveStreams();                                      // no more streaming
  994 }
  995 
  996 ////////////////////////////////////////////////////////////////////////
  997 // SPUSHUTDOWN: called by main emu on final exit
  998 ////////////////////////////////////////////////////////////////////////
  999 
 1000 EXPORT_GCC void CALLBACK SPU2shutdown(void)
 1001 {
 1002  return;
 1003 }
 1004 
 1005 ////////////////////////////////////////////////////////////////////////
 1006 // SPUTEST: we don't test, we are always fine ;)
 1007 ////////////////////////////////////////////////////////////////////////
 1008 
 1009 EXPORT_GCC long CALLBACK SPU2test(void)
 1010 {
 1011  return 0;
 1012 }
 1013 
 1014 ////////////////////////////////////////////////////////////////////////
 1015 // SETUP CALLBACKS
 1016 // this functions will be called once,
 1017 // passes a callback that should be called on SPU-IRQ/cdda volume change
 1018 ////////////////////////////////////////////////////////////////////////
 1019 
 1020 // not used yet
 1021 EXPORT_GCC void CALLBACK SPU2irqCallback(void (CALLBACK *callback)(void))
 1022 {
 1023  irqCallback = callback;
 1024 }
 1025 
 1026 // not used yet
 1027 EXPORT_GCC void CALLBACK SPU2registerCallback(void (CALLBACK *callback)(void))
 1028 {
 1029  irqCallback = callback;
 1030 }
 1031 
 1032 // not used yet
 1033 EXPORT_GCC void CALLBACK SPU2registerCDDAVolume(void (CALLBACK *CDDAVcallback)(unsigned short,unsigned short))
 1034 {
 1035  cddavCallback = CDDAVcallback;
 1036 }