home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 February / PCO_0299.ISO / filesbbs / linux / mikmod-3.000 / mikmod-3 / mikmod-3.1.2 / playercode / virtch2.c < prev   
Encoding:
C/C++ Source or Header  |  1998-12-07  |  25.6 KB  |  994 lines

  1. /*    MikMod sound library
  2.     (c) 1998 Miodrag Vallat and others - see file AUTHORS for complete list
  3.  
  4.     This library is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU Library General Public License as
  6.     published by the Free Software Foundation; either version 2 of
  7.     the License, or (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU Library General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU Library General Public
  15.     License along with this library; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /*==============================================================================
  20.  
  21.   $Id: virtch2.c,v 1.16 1998/12/07 06:00:55 miod Exp $
  22.  
  23.   High-quality sample mixing routines, using a 32 bits mixing buffer,
  24.   interpolation, and sample smoothing to improve sound quality and remove
  25.   clicks.
  26.  
  27. ==============================================================================*/
  28.  
  29. /*
  30.  
  31.   Future Additions:
  32.     Low-Pass filter to remove annoying staticy buzz.
  33.  
  34. */
  35.  
  36. #ifdef HAVE_CONFIG_H
  37. #include "config.h"
  38. #endif
  39.  
  40. #include <mikmod_internals.h>
  41.   
  42. #include <stddef.h>
  43. #include <string.h>
  44.  
  45. /*
  46.    Constant Definitions
  47.    ====================
  48.  
  49.     MAXVOL_FACTOR (was BITSHIFT in virtch.c)
  50.         Controls the maximum volume of the output data. All mixed data is
  51.         divided by this number after mixing, so larger numbers result in
  52.         quieter mixing.  Smaller numbers will increase the likliness of
  53.         distortion on loud modules.
  54.  
  55.     REVERBERATION
  56.         Larger numbers result in shorter reverb duration. Longer reverb
  57.         durations can cause unwanted static and make the reverb sound more
  58.         like a crappy echo.
  59.  
  60.     SAMPLING_SHIFT
  61.         Specified the shift multiplier which controls by how much the mixing
  62.         rate is multiplied while mixing.  Higher values can improve quality by
  63.         smoothing the sound and reducing pops and clicks. Note, this is a shift
  64.         value, so a value of 2 becomes a mixing-rate multiplier of 4, and a
  65.         value of 3 = 8, etc.
  66.  
  67.     FRACBITS
  68.         The number of bits per integer devoted to the fractional part of the
  69.         number. Generally, this number should not be changed for any reason.
  70.  
  71.     !!! IMPORTANT !!! All values below MUST ALWAYS be greater than 0
  72.  
  73. */
  74.  
  75. #define MAXVOL_FACTOR (1<<9)
  76. #define    REVERBERATION 11000L
  77.  
  78. #define SAMPLING_SHIFT 2
  79. #define SAMPLING_FACTOR (1UL<<SAMPLING_SHIFT)
  80.  
  81. #define    FRACBITS 28
  82. #define FRACMASK ((1UL<<FRACBITS)-1UL)
  83.  
  84. #define TICKLSIZE 8192
  85. #define TICKWSIZE (TICKLSIZE * 2)
  86. #define TICKBSIZE (TICKWSIZE * 2)
  87.  
  88. #define CLICK_SHIFT_BASE 6
  89. #define CLICK_SHIFT (CLICK_SHIFT_BASE * SAMPLING_SHIFT)
  90. #define CLICK_BUFFER (1L << CLICK_SHIFT)
  91.  
  92. #ifndef MIN
  93. #define MIN(a,b) (((a)<(b)) ? (a) : (b))
  94. #endif
  95.  
  96. #ifdef HAS_64BIT_INT
  97. typedef SLONGLONG FRACTYPE;
  98. #else
  99. #include <math.h>
  100. typedef double FRACTYPE;
  101. #endif
  102.  
  103. typedef struct VINFO {
  104.     UBYTE    kick;              /* =1 -> sample has to be restarted */
  105.     UBYTE    active;            /* =1 -> sample is playing */
  106.     UWORD    flags;             /* 16/8 bits looping/one-shot */
  107.     SWORD    handle;            /* identifies the sample */
  108.     ULONG    start;             /* start index */
  109.     ULONG    size;              /* samplesize */
  110.     ULONG    reppos;            /* loop start */
  111.     ULONG    repend;            /* loop end */
  112.     ULONG    frq;               /* current frequency */
  113.     int      vol;               /* current volume */
  114.     int      pan;               /* current panning position */
  115.  
  116.     int      click;
  117.     int      rampvol;
  118.     SLONG    lastvalL,lastvalR;
  119.     int      lvolsel,rvolsel;   /* Volume factor in range 0-255 */
  120.     int      oldlvol,oldrvol;
  121.  
  122.     FRACTYPE current;           /* current index in the sample */
  123.     FRACTYPE increment;         /* increment value */
  124. } VINFO;
  125.  
  126. static    SWORD **Samples;
  127. static    VINFO *vinf=NULL,*vnf;
  128. static    long tickleft,samplesthatfit,vc_memory=0;
  129. static    int vc_softchn;
  130. static    FRACTYPE idxsize,idxlpos,idxlend;
  131. static    SLONG *vc_tickbuf=NULL;
  132. static    UWORD vc_mode;
  133.  
  134. /* Reverb control variables */
  135.  
  136. static    int RVc1, RVc2, RVc3, RVc4, RVc5, RVc6, RVc7, RVc8;
  137. static    ULONG RVRindex;
  138.  
  139. /* For Mono or Left Channel */
  140. static    SLONG *RVbufL1=NULL,*RVbufL2=NULL,*RVbufL3=NULL,*RVbufL4=NULL,
  141.               *RVbufL5=NULL,*RVbufL6=NULL,*RVbufL7=NULL,*RVbufL8=NULL;
  142.  
  143. /* For Stereo only (Right Channel) */
  144. static    SLONG *RVbufR1=NULL,*RVbufR2=NULL,*RVbufR3=NULL,*RVbufR4=NULL,
  145.               *RVbufR5=NULL,*RVbufR6=NULL,*RVbufR7=NULL,*RVbufR8=NULL;
  146.  
  147. /*========== 64 bit/floating-point mixers */
  148.  
  149. static FRACTYPE MixMonoNormal(SWORD* srce,SLONG* dest,FRACTYPE index,FRACTYPE increment,SLONG todo)
  150. {
  151.     SWORD sample=0;
  152.     FRACTYPE i,f;
  153.  
  154.     while(todo--) {
  155. #ifdef HAS_64BIT_INT
  156.         i=index>>FRACBITS,f=index&FRACMASK;
  157.         sample=(SWORD)(((FRACTYPE)(srce[i]*(FRACMASK+1L-f)) +
  158.                        ((FRACTYPE)srce[i+1]*f)) >> FRACBITS);
  159. #else
  160.         f=modf(index,&i);
  161.         sample=(srce[(SLONG)i]*(1.0-f))+(srce[(SLONG)i+1]*f);
  162. #endif
  163.         index+=increment;
  164.  
  165.         if(vnf->rampvol) {
  166.             *dest++ += (long)(
  167.               ( ( (FRACTYPE)(vnf->oldlvol*vnf->rampvol) +
  168.                   (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) *
  169.                 (FRACTYPE)sample )
  170. #ifdef HAS_64BIT_INT
  171.               >> CLICK_SHIFT );
  172. #else
  173.               / CLICK_BUFFER );
  174. #endif
  175.             vnf->rampvol--;
  176.         } else
  177.           if(vnf->click) {
  178.             *dest++ += (long)(
  179.               ( ( ((FRACTYPE)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
  180.                   (FRACTYPE)sample ) +
  181.                 (vnf->lastvalL*vnf->click) )
  182. #ifdef HAS_64BIT_INT
  183.               >> CLICK_SHIFT );
  184. #else
  185.               / CLICK_BUFFER );
  186. #endif
  187.             vnf->click--;
  188.         } else
  189.             *dest++ +=vnf->lvolsel*sample;
  190.     }
  191.     vnf->lastvalL=vnf->lvolsel * sample;
  192.  
  193.     return index;
  194. }
  195.  
  196. static FRACTYPE MixStereoNormal(SWORD* srce,SLONG* dest,FRACTYPE index,FRACTYPE increment,ULONG todo)
  197. {
  198.     SWORD sample=0;
  199.     FRACTYPE i,f;
  200.  
  201.     while(todo--) {
  202. #ifdef HAS_64BIT_INT
  203.         i=index>>FRACBITS,f=index&FRACMASK;
  204.         sample=(SWORD)((((FRACTYPE)srce[i]*(FRACMASK+1L-f)) +
  205.                        ((FRACTYPE)srce[i+1] * f)) >> FRACBITS);
  206. #else
  207.         f=modf(index,&i);
  208.         sample=(srce[(SLONG)i]*(1.0-f))+(srce[(SLONG)i+1]*f);
  209. #endif
  210.         index += increment;
  211.  
  212.         if(vnf->rampvol) {
  213.             *dest++ += (long)(
  214.               ( ( ((FRACTYPE)vnf->oldlvol*vnf->rampvol) +
  215.                   (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol))
  216.                 ) * (FRACTYPE)sample )
  217. #ifdef HAS_64BIT_INT
  218.               >> CLICK_SHIFT );
  219. #else
  220.               / CLICK_BUFFER );
  221. #endif
  222.             *dest++ += (long)(
  223.               ( ( ((FRACTYPE)vnf->oldrvol*vnf->rampvol) +
  224.                   (vnf->rvolsel*(CLICK_BUFFER-vnf->rampvol))
  225.                 ) * (FRACTYPE)sample )
  226. #ifdef HAS_64BIT_INT
  227.               >> CLICK_SHIFT );
  228. #else
  229.               / CLICK_BUFFER );
  230. #endif
  231.             vnf->rampvol--;
  232.         } else
  233.           if(vnf->click) {
  234.             *dest++ += (long)(
  235.               ( ( (FRACTYPE)(vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
  236.                   (FRACTYPE)sample ) + (vnf->lastvalL * vnf->click) )
  237. #ifdef HAS_64BIT_INT
  238.                 >> CLICK_SHIFT );
  239. #else
  240.                 / CLICK_BUFFER );
  241. #endif
  242.             *dest++ += (long)(
  243.               ( ( ((FRACTYPE)vnf->rvolsel*(CLICK_BUFFER-vnf->click)) *
  244.                   (FRACTYPE)sample ) + (vnf->lastvalR * vnf->click) )
  245. #ifdef HAS_64BIT_INT
  246.                 >> CLICK_SHIFT );
  247. #else
  248.                 / CLICK_BUFFER );
  249. #endif
  250.             vnf->click--;
  251.         } else {
  252.             *dest++ +=vnf->lvolsel*sample;
  253.             *dest++ +=vnf->rvolsel*sample;
  254.         }
  255.     }
  256.     vnf->lastvalL=vnf->lvolsel*sample;
  257.     vnf->lastvalR=vnf->rvolsel*sample;
  258.  
  259.     return index;
  260. }
  261.  
  262. static FRACTYPE MixStereoSurround(SWORD* srce,SLONG* dest,FRACTYPE index,FRACTYPE increment,ULONG todo)
  263. {
  264.     SWORD sample=0;
  265.     long whoop;
  266.     FRACTYPE i, f;
  267.  
  268.     /*dest--;*/
  269.     while(todo--) {
  270. #ifdef HAS_64BIT_INT
  271.         i=index>>FRACBITS,f=index&FRACMASK;
  272.         sample=(SWORD)((((FRACTYPE)srce[i]*(FRACMASK+1L-f)) +
  273.                        ((FRACTYPE)srce[i+1]*f)) >> FRACBITS);
  274. #else
  275.         f=modf(index,&i);
  276.         sample=(srce[(SLONG)i]*(1.0-f))+(srce[(SLONG)i+1]*f);
  277. #endif
  278.         index+=increment;
  279.  
  280.         if(vnf->rampvol) {
  281.             whoop=(long)(
  282.               ( ( (FRACTYPE)(vnf->oldlvol*vnf->rampvol) +
  283.                   (vnf->lvolsel*(CLICK_BUFFER-vnf->rampvol)) ) *
  284.                 (FRACTYPE)sample)
  285. #ifdef HAS_64BIT_INT
  286.               >> CLICK_SHIFT );
  287. #else
  288.               / CLICK_BUFFER );
  289. #endif
  290.             *dest++ +=whoop;
  291.             *dest++ -=whoop;
  292.             vnf->rampvol--;
  293.         } else
  294.           if(vnf->click) {
  295.             whoop = (long)(
  296.               ( ( ((FRACTYPE)vnf->lvolsel*(CLICK_BUFFER-vnf->click)) *
  297.                   (FRACTYPE)sample) +
  298.                 (vnf->lastvalL * vnf->click) )
  299. #ifdef HAS_64BIT_INT
  300.               >> CLICK_SHIFT );
  301. #else
  302.               / CLICK_BUFFER );
  303. #endif
  304.             *dest++ +=whoop;
  305.             *dest++ -=whoop;
  306.             vnf->click--;
  307.         } else {
  308.             *dest++ +=vnf->lvolsel*sample;
  309.             *dest++ -=vnf->lvolsel*sample;
  310.         }
  311.     }
  312.     vnf->lastvalL=vnf->lvolsel*sample;
  313.     vnf->lastvalR=vnf->lvolsel*sample;
  314.  
  315.     return index;
  316. }
  317.  
  318. static    void(*Mix32to16)(SWORD* dste,SLONG* srce,SLONG count);
  319. static    void(*Mix32to8)(SBYTE* dste,SLONG* srce,SLONG count);
  320. static    void(*MixReverb)(SLONG* srce,SLONG count);
  321.  
  322. /* Reverb macros */
  323. #define COMPUTE_LOC(n) loc##n = RVRindex % RVc##n
  324. #define COMPUTE_LECHO(n) RVbufL##n [loc##n ]=speedup+((ReverbPct*RVbufL##n [loc##n ])>>7)
  325. #define COMPUTE_RECHO(n) RVbufR##n [loc##n ]=speedup+((ReverbPct*RVbufR##n [loc##n ])>>7)
  326.  
  327. static void MixReverb_Normal(SLONG* srce,SLONG count)
  328. {
  329.     SLONG speedup;
  330.     int ReverbPct;
  331.     unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8;
  332.  
  333.     ReverbPct=58+(md_reverb*4);
  334.  
  335.     COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
  336.     COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
  337.  
  338.     while(count--) {
  339.         /* Compute the left channel echo buffers */
  340.         speedup = *srce >> 3;
  341.  
  342.         COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4);
  343.         COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8);
  344.  
  345.         /* Prepare to compute actual finalized data */
  346.         RVRindex++;
  347.  
  348.         COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
  349.         COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
  350.  
  351.         /* left channel */
  352.         *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+
  353.                   RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8];
  354.     }
  355. }
  356.  
  357. static void MixReverb_Stereo(SLONG *srce, SLONG count)
  358. {
  359.     SLONG speedup;
  360.     int ReverbPct;
  361.     unsigned int loc1,loc2,loc3,loc4,loc5,loc6,loc7,loc8;
  362.  
  363.     ReverbPct=58+(md_reverb*4);
  364.  
  365.     COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
  366.     COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
  367.  
  368.     while(count--) {
  369.         /* Compute the left channel echo buffers */
  370.         speedup = *srce >> 3;
  371.  
  372.         COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4);
  373.         COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8);
  374.  
  375.         /* Compute the right channel echo buffers */
  376.         speedup = srce[1] >> 3;
  377.  
  378.         COMPUTE_RECHO(1); COMPUTE_RECHO(2); COMPUTE_RECHO(3); COMPUTE_RECHO(4);
  379.         COMPUTE_RECHO(5); COMPUTE_RECHO(6); COMPUTE_RECHO(7); COMPUTE_RECHO(8);
  380.  
  381.         /* Prepare to compute actual finalized data */
  382.         RVRindex++;
  383.  
  384.         COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
  385.         COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
  386.  
  387.         /* left channel */
  388.         *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+ 
  389.                   RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8];
  390.  
  391.         /* right channel */
  392.         *srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4]+
  393.                   RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8];
  394.     }
  395. }
  396.  
  397. /* Mixing macros */
  398. #define EXTRACT_SAMPLE(var,attenuation) var=*srce++/(MAXVOL_FACTOR*attenuation)
  399. #define CHECK_SAMPLE(var,bound) var=(var>=bound)?bound-1:(var<-bound)?-bound:var
  400.  
  401. static void Mix32To16_Normal(SWORD* dste,SLONG* srce,SLONG count)
  402. {
  403.     SLONG x1,x2,tmpx;
  404.     int i;
  405.  
  406.     for(count/=SAMPLING_FACTOR;count;count--) {
  407.         tmpx=0;
  408.  
  409.         for(i=SAMPLING_FACTOR/2;i;i--) {
  410.             EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1);
  411.  
  412.             CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768);
  413.  
  414.             tmpx+=x1+x2;
  415.         }
  416.         *dste++ =tmpx/SAMPLING_FACTOR;
  417.     }
  418. }
  419.  
  420. static void Mix32To16_Stereo(SWORD* dste,SLONG* srce,SLONG count)
  421. {
  422.     SLONG x1,x2,x3,x4,tmpx,tmpy;
  423.     int i;
  424.  
  425.     for(count/=SAMPLING_FACTOR;count;count--) {
  426.         tmpx=tmpy=0;
  427.  
  428.         for(i=SAMPLING_FACTOR/2;i;i--) {
  429.             EXTRACT_SAMPLE(x1,1); EXTRACT_SAMPLE(x2,1);
  430.             EXTRACT_SAMPLE(x3,1); EXTRACT_SAMPLE(x4,1);
  431.  
  432.             CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768);
  433.             CHECK_SAMPLE(x3,32768); CHECK_SAMPLE(x4,32768);
  434.  
  435.             tmpx+=x1+x3;
  436.             tmpy+=x2+x4;
  437.         }
  438.         *dste++ =tmpx/SAMPLING_FACTOR;
  439.         *dste++ =tmpy/SAMPLING_FACTOR;
  440.     }
  441. }
  442.  
  443. static void Mix32To8_Normal(SBYTE* dste,SLONG* srce,SLONG count)
  444. {
  445.     int x1,x2,tmpx;
  446.     int i;
  447.  
  448.     for(count/=SAMPLING_FACTOR;count;count--) {
  449.         tmpx = 0;
  450.  
  451.         for(i=SAMPLING_FACTOR/2;i;i--) {
  452.             EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256);
  453.  
  454.             CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128);
  455.  
  456.             tmpx+=x1+x2;
  457.         }
  458.         *dste++ =(tmpx/SAMPLING_FACTOR)+128;
  459.     }
  460. }
  461.  
  462. static void Mix32To8_Stereo(SBYTE* dste,SLONG* srce,SLONG count)
  463. {
  464.     int x1,x2,x3,x4,tmpx,tmpy;
  465.     int i;
  466.  
  467.     for(count/=SAMPLING_FACTOR;count;count--) {
  468.         tmpx=tmpy=0;
  469.  
  470.         for(i=SAMPLING_FACTOR/2;i;i--) {
  471.             EXTRACT_SAMPLE(x1,256); EXTRACT_SAMPLE(x2,256);
  472.             EXTRACT_SAMPLE(x3,256); EXTRACT_SAMPLE(x4,256);
  473.  
  474.             CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128);
  475.             CHECK_SAMPLE(x3,128); CHECK_SAMPLE(x4,128);
  476.  
  477.             tmpx+=x1+x3;
  478.             tmpy+=x2+x4;
  479.         }
  480.         *dste++ =(tmpx/SAMPLING_FACTOR)+128;        
  481.         *dste++ =(tmpy/SAMPLING_FACTOR)+128;        
  482.     }
  483. }
  484.  
  485. static ULONG samples2bytes(ULONG samples)
  486. {
  487.     if(vc_mode & DMODE_16BITS) samples <<= 1;
  488.     if(vc_mode & DMODE_STEREO) samples <<= 1;
  489.     return samples;
  490. }
  491.  
  492. static ULONG bytes2samples(ULONG bytes)
  493. {
  494.     if(vc_mode & DMODE_16BITS) bytes >>= 1;
  495.     if(vc_mode & DMODE_STEREO) bytes >>= 1;
  496.     return bytes;
  497. }
  498.  
  499. static void AddChannel(SLONG* ptr,SLONG todo)
  500. {
  501.     FRACTYPE end;
  502.     SLONG done;
  503.     SWORD *s;
  504.  
  505.     if(!(s=Samples[vnf->handle])) {
  506.         vnf->current = vnf->active  = 0;
  507.         vnf->lastvalL = vnf->lastvalR = 0;
  508.         return;
  509.     }
  510.  
  511.     /* update the 'current' index so the sample loops, or stops playing if it
  512.        reached the end of the sample */
  513.     while(todo>0) {
  514.         if(vnf->flags & SF_REVERSE) {
  515.             /* The sample is playing in reverse */
  516.             if((vnf->flags&SF_LOOP)&&(vnf->current<idxlpos)) {
  517.                 /* the sample is looping and has reached the loopstart index */
  518.                 if(vnf->flags & SF_BIDI) {
  519.                     /* sample is doing bidirectional loops, so 'bounce' the
  520.                        current index against the idxlpos */
  521.                     vnf->current = idxlpos+(idxlpos-vnf->current);
  522.                     vnf->flags &= ~SF_REVERSE;
  523.                     vnf->increment  = -vnf->increment;
  524.                 } else
  525.                     /* normal backwards looping, so set the current position to
  526.                        loopend index */
  527.                     vnf->current=idxlend-(idxlpos-vnf->current);
  528.             } else {
  529.                 /* the sample is not looping, so check if it reached index 0 */
  530.                 if(vnf->current < 0) {
  531.                     /* playing index reached 0, so stop playing this sample */
  532.                     vnf->current = vnf->active  = 0;
  533.                     break;
  534.                 }
  535.             }
  536.         } else {
  537.             /* The sample is playing forward */
  538.             if((vnf->flags & SF_LOOP) && (vnf->current > idxlend)) {
  539.                 /* the sample is looping, check the loopend index */
  540.                 if(vnf->flags & SF_BIDI) {
  541.                     /* sample is doing bidirectional loops, so 'bounce' the
  542.                        current index against the idxlend */
  543.                     vnf->flags |= SF_REVERSE;
  544.                     vnf->increment = -vnf->increment;
  545.                     vnf->current = idxlend-(vnf->current-idxlend);
  546.                 } else
  547.                     /* normal backwards looping, so set the current position
  548.                        to loopend index */
  549.                     vnf->current=idxlpos+(vnf->current-idxlend);
  550.             } else {
  551.                 /* sample is not looping, so check if it reached the last
  552.                    position */
  553.                 if(vnf->current > idxsize) {
  554.                     /* yes, so stop playing this sample */
  555.                     vnf->current = vnf->active  = 0;
  556.                     break;
  557.                 }
  558.             }
  559.         }
  560.  
  561.         end=(FRACTYPE)(vnf->flags&SF_REVERSE)?(vnf->flags&SF_LOOP)?idxlpos:0:
  562.              (vnf->flags&SF_LOOP)?idxlend:idxsize;
  563.  
  564.         /* if the sample is not blocked... */
  565.         if (vnf->increment)
  566.             done=MIN((end-vnf->current)/vnf->increment+1,todo);
  567.         else
  568.             done=0;
  569.  
  570.         if(!done) {
  571.             vnf->active = 0;
  572.             break;
  573.         }
  574.  
  575.         if(vnf->vol || vnf->rampvol) {
  576.             if(vc_mode & DMODE_STEREO)
  577.                 if((vnf->pan == PAN_SURROUND) && (vc_mode & DMODE_SURROUND))
  578.                     vnf->current = MixStereoSurround(s,ptr,vnf->current,vnf->increment,done);
  579.                 else
  580.                     vnf->current = MixStereoNormal(s,ptr,vnf->current,vnf->increment,done);
  581.             else
  582.                 vnf->current = MixMonoNormal(s,ptr,vnf->current,vnf->increment,done);
  583.         } else  {
  584.             vnf->lastvalL = vnf->lastvalR = 0;
  585.             /* update sample position */
  586.             vnf->current+=vnf->increment*done;
  587.         }
  588.  
  589.         todo -= done;
  590.         ptr +=(vc_mode & DMODE_STEREO)?(done<<1):done;
  591.     }
  592. }
  593.  
  594. static void VC_WriteSamples(SBYTE* buf,ULONG todo)
  595. {
  596.     int left,portion=0;
  597.     SBYTE *buffer;
  598.     int t,pan,vol;
  599.  
  600.     todo*=SAMPLING_FACTOR;
  601.  
  602.     while(todo) {
  603.         if(!tickleft) {
  604.             if(vc_mode & DMODE_SOFT_MUSIC) md_player();
  605.             tickleft=(md_mixfreq*125L*SAMPLING_FACTOR)/(md_bpm*50L);
  606.             tickleft&=~(SAMPLING_FACTOR-1);
  607.         }
  608.         left = MIN(tickleft, todo);
  609.         buffer    = buf;
  610.         tickleft -= left;
  611.         todo     -= left;
  612.         buf += samples2bytes(left)/SAMPLING_FACTOR;
  613.  
  614.         while(left) {
  615.             portion = MIN(left, samplesthatfit);
  616.             memset(vc_tickbuf,0,portion<<((vc_mode&DMODE_STEREO)?3:2));
  617.             for(t=0;t<vc_softchn;t++) {
  618.                 vnf = &vinf[t];
  619.  
  620.                 if(vnf->kick) {
  621.                     vnf->current=(FRACTYPE)(vnf->start)
  622. #ifdef HAS_64BIT_INT
  623.                                  <<FRACBITS
  624. #endif
  625.                                  ;
  626.                     vnf->kick    = 0;
  627.                     vnf->active  = 1;
  628.                     vnf->click   = CLICK_BUFFER;
  629.                     vnf->rampvol = 0;
  630.                 }
  631.  
  632.                 if(!vnf->frq) vnf->active = 0;
  633.  
  634.                 if(vnf->active) {
  635.                     vnf->increment=((FRACTYPE)(vnf->frq)
  636. #ifdef HAS_64BIT_INT
  637.                                     <<(FRACBITS-SAMPLING_SHIFT))
  638. #else
  639.                                     /(1<<SAMPLING_SHIFT))
  640. #endif
  641.                                    /(FRACTYPE)md_mixfreq;
  642.                     if(vnf->flags&SF_REVERSE) vnf->increment=-vnf->increment;
  643.                     vol = vnf->vol;  pan = vnf->pan;
  644.  
  645.                     if(vc_mode & DMODE_STEREO) {
  646.                         if(pan!=PAN_SURROUND) {
  647.                             vnf->oldlvol=vnf->lvolsel;vnf->oldrvol=vnf->rvolsel;
  648.                             vnf->lvolsel=(vol*(PAN_RIGHT-pan))>>8;
  649.                             vnf->rvolsel=(vol*pan)>>8;
  650.                         } else {
  651.                             vnf->oldlvol=vnf->lvolsel;vnf->oldrvol=vnf->rvolsel;
  652.                             vnf->lvolsel=vnf->rvolsel=(vol * 256L) / 480;
  653.                         }
  654.                     } else {
  655.                         vnf->oldlvol = vnf->lvolsel;
  656.                         vnf->lvolsel = vol;
  657.                     }
  658.  
  659. #ifdef HAS_64BIT_INT
  660.                     idxsize=(vnf->size)?((FRACTYPE)(vnf->size)<<FRACBITS)-1:0;
  661.                     idxlend=(vnf->repend)?((FRACTYPE)(vnf->repend)<<FRACBITS)-1:0;
  662.                     idxlpos=(FRACTYPE)(vnf->reppos)<<FRACBITS;
  663. #else
  664.                     idxsize=(FRACTYPE)(vnf->size);
  665.                     idxlend=(FRACTYPE)(vnf->repend);
  666.                     idxlpos=(FRACTYPE)(vnf->reppos);
  667. #endif
  668.                     AddChannel(vc_tickbuf,portion);
  669.                 }
  670.             }
  671.  
  672.             if(md_reverb) {
  673.                 if(md_reverb>15) md_reverb=15;
  674.                 MixReverb(vc_tickbuf,portion);
  675.             }
  676.  
  677.             if(vc_mode & DMODE_16BITS)
  678.                 Mix32to16((SWORD*)buffer,vc_tickbuf,portion);
  679.             else
  680.                 Mix32to8((SBYTE*)buffer,vc_tickbuf,portion);
  681.  
  682.             buffer += samples2bytes(portion) / SAMPLING_FACTOR;
  683.             left   -= portion;
  684.         }
  685.     }
  686. }
  687.  
  688. /* Fill the buffer with 'todo' bytes of silence (it depends on the mixing mode
  689.    how the buffer is filled) */
  690. void VC_SilenceBytes(SBYTE* buf,ULONG todo)
  691. {
  692.     /* clear the buffer to zero (16 bits signed) or 0x80 (8 bits unsigned) */
  693.     if(vc_mode & DMODE_16BITS)
  694.         memset(buf,0,todo);
  695.     else
  696.         memset(buf,0x80,todo);
  697. }
  698.  
  699. /* Writes 'todo' mixed SBYTES (!!) to 'buf'. It returns the number of SBYTES
  700.    actually written to 'buf' (which is rounded to number of samples that fit
  701.    into 'todo' bytes). */
  702. ULONG VC_WriteBytes(SBYTE* buf,ULONG todo)
  703. {
  704.     if(!vc_softchn) {
  705.         VC_SilenceBytes(buf,todo);
  706.         return todo;
  707.     }
  708.  
  709.     todo = bytes2samples(todo);
  710.     VC_WriteSamples(buf,todo);
  711.  
  712.     return samples2bytes(todo);
  713. }
  714.  
  715. BOOL VC_Init(void)
  716. {
  717.     if(!(Samples=(SWORD**)_mm_calloc(MAXSAMPLEHANDLES,sizeof(SWORD*)))) {
  718.         _mm_errno = MMERR_INITIALIZING_MIXER;
  719.         return 1;
  720.     }
  721.     if(!vc_tickbuf)
  722.         if(!(vc_tickbuf=(SLONG*)_mm_malloc((TICKLSIZE+32)*sizeof(SLONG)))) {
  723.             _mm_errno = MMERR_INITIALIZING_MIXER;
  724.             return 1;
  725.         }
  726.  
  727.     if(md_mode & DMODE_STEREO) {
  728.         Mix32to16  = Mix32To16_Stereo;
  729.         Mix32to8   = Mix32To8_Stereo;
  730.         MixReverb  = MixReverb_Stereo;
  731.     } else {
  732.         Mix32to16  = Mix32To16_Normal;
  733.         Mix32to8   = Mix32To8_Normal;
  734.         MixReverb  = MixReverb_Normal;
  735.     }
  736.     md_mode |= DMODE_INTERP;
  737.     vc_mode = md_mode;
  738.     return 0;
  739. }
  740.  
  741. void VC_Exit(void)
  742. {
  743.     if(vc_tickbuf) free(vc_tickbuf);
  744.     if(vinf) free(vinf);
  745.     if(Samples) free(Samples);
  746.  
  747.     vc_tickbuf = NULL;
  748.     vinf = NULL;
  749.     Samples = NULL;
  750. }
  751.  
  752. BOOL VC_PlayStart(void)
  753. {
  754.     md_mode|=DMODE_INTERP;
  755.  
  756.     samplesthatfit = TICKLSIZE;
  757.     if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1;
  758.     tickleft = 0;
  759.  
  760. #ifndef HAS_64BIT_INT
  761.     RVc1 = (SLONG)(500.0    * md_mixfreq) / REVERBERATION;
  762.     RVc2 = (SLONG)(507.8125 * md_mixfreq) / REVERBERATION;
  763.     RVc3 = (SLONG)(531.25   * md_mixfreq) / REVERBERATION;
  764.     RVc4 = (SLONG)(570.3125 * md_mixfreq) / REVERBERATION;
  765.     RVc5 = (SLONG)(625.0    * md_mixfreq) / REVERBERATION;
  766.     RVc6 = (SLONG)(695.3125 * md_mixfreq) / REVERBERATION;
  767.     RVc7 = (SLONG)(781.25   * md_mixfreq) / REVERBERATION;
  768.     RVc8 = (SLONG)(882.8125 * md_mixfreq) / REVERBERATION;
  769. #else
  770.     RVc1 = (5000L * md_mixfreq) / (REVERBERATION * 10);
  771.     RVc2 = (5078L * md_mixfreq) / (REVERBERATION * 10);
  772.     RVc3 = (5313L * md_mixfreq) / (REVERBERATION * 10);
  773.     RVc4 = (5703L * md_mixfreq) / (REVERBERATION * 10);
  774.     RVc5 = (6250L * md_mixfreq) / (REVERBERATION * 10);
  775.     RVc6 = (6953L * md_mixfreq) / (REVERBERATION * 10);
  776.     RVc7 = (7813L * md_mixfreq) / (REVERBERATION * 10);
  777.     RVc8 = (8828L * md_mixfreq) / (REVERBERATION * 10);
  778. #endif
  779.  
  780.     if(!(RVbufL1=(SLONG*)_mm_calloc((RVc1+1),sizeof(SLONG)))) return 1;
  781.     if(!(RVbufL2=(SLONG*)_mm_calloc((RVc2+1),sizeof(SLONG)))) return 1;
  782.     if(!(RVbufL3=(SLONG*)_mm_calloc((RVc3+1),sizeof(SLONG)))) return 1;
  783.     if(!(RVbufL4=(SLONG*)_mm_calloc((RVc4+1),sizeof(SLONG)))) return 1;
  784.     if(!(RVbufL5=(SLONG*)_mm_calloc((RVc5+1),sizeof(SLONG)))) return 1;
  785.     if(!(RVbufL6=(SLONG*)_mm_calloc((RVc6+1),sizeof(SLONG)))) return 1;
  786.     if(!(RVbufL7=(SLONG*)_mm_calloc((RVc7+1),sizeof(SLONG)))) return 1;
  787.     if(!(RVbufL8=(SLONG*)_mm_calloc((RVc8+1),sizeof(SLONG)))) return 1;
  788.  
  789.     if(!(RVbufR1=(SLONG*)_mm_calloc((RVc1+1),sizeof(SLONG)))) return 1;
  790.     if(!(RVbufR2=(SLONG*)_mm_calloc((RVc2+1),sizeof(SLONG)))) return 1;
  791.     if(!(RVbufR3=(SLONG*)_mm_calloc((RVc3+1),sizeof(SLONG)))) return 1;
  792.     if(!(RVbufR4=(SLONG*)_mm_calloc((RVc4+1),sizeof(SLONG)))) return 1;
  793.     if(!(RVbufR5=(SLONG*)_mm_calloc((RVc5+1),sizeof(SLONG)))) return 1;
  794.     if(!(RVbufR6=(SLONG*)_mm_calloc((RVc6+1),sizeof(SLONG)))) return 1;
  795.     if(!(RVbufR7=(SLONG*)_mm_calloc((RVc7+1),sizeof(SLONG)))) return 1;
  796.     if(!(RVbufR8=(SLONG*)_mm_calloc((RVc8+1),sizeof(SLONG)))) return 1;
  797.  
  798.     RVRindex = 0;
  799.     return 0;
  800. }
  801.  
  802. void VC_PlayStop(void)
  803. {
  804.     if(RVbufL1) free(RVbufL1);
  805.     if(RVbufL2) free(RVbufL2);
  806.     if(RVbufL3) free(RVbufL3);
  807.     if(RVbufL4) free(RVbufL4);
  808.     if(RVbufL5) free(RVbufL5);
  809.     if(RVbufL6) free(RVbufL6);
  810.     if(RVbufL7) free(RVbufL7);
  811.     if(RVbufL8) free(RVbufL8);
  812.     if(RVbufR1) free(RVbufR1);
  813.     if(RVbufR2) free(RVbufR2);
  814.     if(RVbufR3) free(RVbufR3);
  815.     if(RVbufR4) free(RVbufR4);
  816.     if(RVbufR5) free(RVbufR5);
  817.     if(RVbufR6) free(RVbufR6);
  818.     if(RVbufR7) free(RVbufR7);
  819.     if(RVbufR8) free(RVbufR8);
  820.  
  821.     RVbufL1=RVbufL2=RVbufL3=RVbufL4=RVbufL5=RVbufL6=RVbufL7=RVbufL8=NULL;
  822.     RVbufR1=RVbufR2=RVbufR3=RVbufR4=RVbufR5=RVbufR6=RVbufR7=RVbufR8=NULL;
  823. }
  824.  
  825. BOOL VC_SetNumVoices(void)
  826. {
  827.     int t;
  828.  
  829.     md_mode|=DMODE_INTERP;
  830.  
  831.     if(!(vc_softchn=md_softchn)) return 0;
  832.  
  833.     if(vinf) free(vinf);
  834.     if(!(vinf=_mm_calloc(sizeof(VINFO),vc_softchn))) return 1;
  835.  
  836.     for(t=0;t<vc_softchn;t++) {
  837.         vinf[t].frq=10000;
  838.         vinf[t].pan=(t&1)?PAN_LEFT:PAN_RIGHT;
  839.     }
  840.  
  841.     return 0;
  842. }
  843.  
  844. void VC_VoiceSetVolume(UBYTE voice,UWORD vol)
  845. {    
  846.     /* protect against clicks if volume variation is too high */
  847.     if(abs((int)vinf[voice].vol-(int)vol)>32)
  848.         vinf[voice].rampvol=CLICK_BUFFER;
  849.     vinf[voice].vol=vol;
  850. }
  851.  
  852. void VC_VoiceSetFrequency(UBYTE voice,ULONG frq)
  853. {
  854.     vinf[voice].frq=frq;
  855. }
  856.  
  857. void VC_VoiceSetPanning(UBYTE voice,ULONG pan)
  858. {
  859.     /* protect against clicks if panning variation is too high */
  860.     if(abs((int)vinf[voice].pan-(int)pan)>48)
  861.         vinf[voice].rampvol=CLICK_BUFFER;
  862.     vinf[voice].pan=pan;
  863. }
  864.  
  865. void VC_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags)
  866. {
  867.     vinf[voice].flags    = flags;
  868.     vinf[voice].handle   = handle;
  869.     vinf[voice].start    = start;
  870.     vinf[voice].size     = size;
  871.     vinf[voice].reppos   = reppos;
  872.     vinf[voice].repend   = repend;
  873.     vinf[voice].kick     = 1;
  874. }
  875.  
  876. void VC_VoiceStop(UBYTE voice)
  877. {
  878.     vinf[voice].active = 0;
  879. }  
  880.  
  881. BOOL VC_VoiceStopped(UBYTE voice)
  882. {
  883.     return(vinf[voice].active==0);
  884. }
  885.  
  886. SLONG VC_VoiceGetPosition(UBYTE voice)
  887. {
  888. #ifdef HAS_64BIT_INT
  889.     return(vinf[voice].current>>FRACBITS);
  890. #else
  891.     return((SLONG)vinf[voice].current);
  892. #endif
  893. }
  894.  
  895. /*========== External mixer interface */
  896.  
  897. void VC_SampleUnload(SWORD handle)
  898. {
  899.     if (handle<MAXSAMPLEHANDLES) {
  900.         if (Samples[handle])
  901.             free(Samples[handle]);
  902.         Samples[handle]=NULL;
  903.     }
  904. }
  905.  
  906. SWORD VC_SampleLoad(SAMPLOAD* sload,int type)
  907. {
  908.     SAMPLE *s=sload->sample;
  909.     int handle;
  910.     ULONG t, length,loopstart,loopend;
  911.  
  912.     if(type==MD_HARDWARE) return -1;
  913.  
  914.     /* Find empty slot to put sample address in */
  915.     for(handle=0;handle<MAXSAMPLEHANDLES;handle++)
  916.         if(!Samples[handle]) break;
  917.  
  918.     if(handle==MAXSAMPLEHANDLES) {
  919.         _mm_errno = MMERR_OUT_OF_HANDLES;
  920.         return -1;
  921.     }
  922.  
  923.     length    = s->length;
  924.     loopstart = s->loopstart;
  925.     loopend   = s->loopend;
  926.  
  927.     SL_SampleSigned(sload);
  928.  
  929.     SL_Sample8to16(sload);
  930.     if(!(Samples[handle]=(SWORD*)_mm_malloc((length+20)<<1))) {
  931.         _mm_errno = MMERR_SAMPLE_TOO_BIG;
  932.         return -1;
  933.     }
  934.  
  935.     if (SL_Load(Samples[handle],sload,length))
  936.         return -1;
  937.  
  938.     /* Unclick samples: */
  939.     if(s->flags & SF_LOOP) {
  940.         if(s->flags & SF_BIDI)
  941.             for(t=0;t<16;t++)
  942.                 Samples[handle][loopend+t]=Samples[handle][(loopend-t)-1];
  943.         else
  944.             for(t=0;t<16;t++)
  945.                 Samples[handle][loopend+t]=Samples[handle][t+loopstart];
  946.     } else
  947.         for(t=0;t<16;t++)
  948.             Samples[handle][t+length]=0;
  949.  
  950.     return handle;
  951. }
  952.  
  953. ULONG VC_SampleSpace(int type)
  954. {
  955.     return vc_memory;
  956. }
  957.  
  958. ULONG VC_SampleLength(int type,SAMPLE* s)
  959. {
  960.     return (s->length*((s->flags&SF_16BITS)?2:1))+16;
  961. }
  962.  
  963. ULONG VC_VoiceRealVolume(UBYTE voice)
  964. {
  965.     ULONG i,s,size;
  966.     int k,j;
  967.     SWORD *smp;
  968.     SLONG t;
  969.  
  970. #ifdef HAS_64BIT_INT
  971.     t = vinf[voice].current>>FRACBITS;
  972. #else
  973.     t = (vinf[voice].current)/(1L<<FRACBITS);
  974. #endif
  975.     if(!vinf[voice].active) return 0;
  976.  
  977.     s = vinf[voice].handle;
  978.     size = vinf[voice].size;
  979.  
  980.     i=64; t-=64; k=0; j=0;
  981.     if(i>size) i = size;
  982.     if(t<0) t = 0;
  983.     if(t+i > size) t = size-i;
  984.  
  985.     i &= ~1;  /* make sure it's EVEN. */
  986.  
  987.     smp = &Samples[s][t];
  988.     for(;i;i--,smp++) {
  989.         if(k<*smp) k = *smp;
  990.         if(j>*smp) j = *smp;
  991.     }
  992.     return abs(k-j);
  993. }
  994.