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 / virtch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-07  |  21.3 KB  |  844 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: virtch.c,v 1.19 1998/12/07 06:00:54 miod Exp $
  22.  
  23.   Sample mixing routines, using a 32 bits mixing buffer.
  24.  
  25. ==============================================================================*/
  26.  
  27. /*
  28.  
  29.   Optional features include:
  30.     (a) 4-step reverb (for 16 bit output only)
  31.     (b) Interpolation of sample data during mixing
  32.     (c) Dolby Surround Sound
  33.     (d) Optimized assembly mixers for the Intel platform
  34.     (e) Optional high-speed or high-quality modes
  35. */
  36.  
  37. #ifdef HAVE_CONFIG_H
  38. #include "config.h"
  39. #endif
  40.  
  41. #include <mikmod_internals.h>
  42.  
  43. #include <stddef.h>
  44. #include <string.h>
  45.  
  46. #define __FAST_REVERB__
  47.  
  48. /*
  49.    Constant definitions
  50.    ====================
  51.  
  52.       BITSHIFT
  53.         Controls the maximum volume of the sound output.  All data is shifted
  54.         right by BITSHIFT after being mixed. Higher values result in quieter
  55.         sound and less chance of distortion.
  56.  
  57.     REVERBERATION
  58.         Controls the duration of the reverb. Larger values represent a shorter
  59.         reverb loop. Smaller values extend the reverb but can result in more of
  60.         an echo-ish sound.
  61.  
  62. */
  63.  
  64. #define BITSHIFT        9
  65. #define REVERBERATION    110000L
  66.  
  67. #define FRACBITS 11
  68. #define FRACMASK ((1L<<FRACBITS)-1L)
  69.  
  70. #define TICKLSIZE 8192
  71. #define TICKWSIZE (TICKLSIZE<<1)
  72. #define TICKBSIZE (TICKWSIZE<<1)
  73.  
  74. #ifndef MIN
  75. #define MIN(a,b) (((a)<(b)) ? (a) : (b))
  76. #endif
  77.  
  78. typedef struct VINFO {
  79.     UBYTE kick;      /* =1 -> sample has to be restarted */
  80.     UBYTE active;    /* =1 -> sample is playing */
  81.     UWORD flags;     /* 16/8 bits looping/one-shot */
  82.     SWORD handle;    /* identifies the sample */
  83.     ULONG start;     /* start index */
  84.     ULONG size;      /* samplesize */
  85.     ULONG reppos;    /* loop start */
  86.     ULONG repend;    /* loop end */
  87.     ULONG frq;       /* current frequency */
  88.     int   vol;       /* current volume */
  89.     int   pan;       /* current panning position */
  90.     SLONG current;   /* current index in the sample */
  91.     SLONG increment; /* fixed-point increment value */
  92. } VINFO;
  93.  
  94. static    SWORD **Samples;
  95. static    SLONG lvolsel,rvolsel; /* Volume Selectors for 16 bit mixers. */
  96.  
  97. static    VINFO *vinf=NULL,*vnf;
  98. static    long tickleft,samplesthatfit,vc_memory=0;
  99. static    int vc_softchn;
  100. static    SLONG idxsize,idxlpos,idxlend;
  101. static    SLONG *vc_tickbuf=NULL;
  102. static    UWORD vc_mode;
  103.  
  104. /* Reverb control variables */
  105.  
  106. static    int RVc1, RVc2, RVc3, RVc4;
  107. #ifndef __FAST_REVERB__
  108. static    int RVc5, RVc6, RVc7, RVc8;
  109. #endif
  110. static    ULONG RVRindex;
  111.  
  112. /* For Mono or Left Channel */
  113. static    SLONG *RVbufL1=NULL,*RVbufL2=NULL,*RVbufL3=NULL,*RVbufL4=NULL;
  114. #ifndef __FAST_REVERB__
  115. static    SLONG *RVbufL5=NULL,*RVbufL6=NULL,*RVbufL7=NULL,*RVbufL8=NULL;
  116. #endif
  117.  
  118. /* For Stereo only (Right Channel) */
  119. static    SLONG *RVbufR1=NULL,*RVbufR2=NULL,*RVbufR3=NULL,*RVbufR4=NULL;
  120. #ifndef __FAST_REVERB__
  121. static    SLONG *RVbufR5=NULL,*RVbufR6=NULL,*RVbufR7=NULL,*RVbufR8=NULL;
  122. #endif
  123.  
  124. /*========== 16 bit sample mixers */
  125.  
  126. static SLONG MixMonoNormal(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
  127. {
  128.     SWORD sample;
  129.  
  130.     while(todo--) {
  131.         sample = srce[index >> FRACBITS];
  132.         index += increment;
  133.  
  134.         *dest++ += lvolsel * sample;
  135.     }
  136.     return index;
  137. }
  138.  
  139. static SLONG MixStereoNormal(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
  140. {
  141.     SWORD sample;
  142.  
  143.     while(todo--) {
  144.         sample=srce[index >> FRACBITS];
  145.         index += increment;
  146.  
  147.         *dest++ += lvolsel * sample;
  148.         *dest++ += rvolsel * sample;
  149.     }
  150.     return index;
  151. }
  152.  
  153. static SLONG MixSurroundNormal(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
  154. {
  155.     SWORD sample;
  156.  
  157.     while(todo--) {
  158.         sample = srce[index >> FRACBITS];
  159.         index += increment;
  160.  
  161.         if(lvolsel>=rvolsel) {
  162.             *dest++ += lvolsel*sample;
  163.             *dest++ -= lvolsel*sample;
  164.         } else {
  165.             *dest++ -= rvolsel*sample;
  166.             *dest++ += rvolsel*sample;
  167.         }
  168.     }
  169.     return index;
  170. }
  171.  
  172. static SLONG MixMonoInterp(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
  173. {
  174.     SLONG sample;
  175.  
  176.     while(todo--) {
  177.         sample=((srce[index>>FRACBITS]*((FRACMASK+1L)-(index&FRACMASK))) +
  178.                 (srce[(index>>FRACBITS)+1]*(index&FRACMASK))) >> FRACBITS;
  179.         index += increment;
  180.  
  181.         *dest++ += lvolsel * sample;
  182.     }
  183.     return index;
  184. }
  185.  
  186. static SLONG MixStereoInterp(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
  187. {
  188.     SLONG sample;
  189.  
  190.     while(todo--) {
  191.         sample=((srce[index>>FRACBITS]*((FRACMASK+1L)-(index&FRACMASK))) +
  192.                 (srce[(index>>FRACBITS)+1]*(index&FRACMASK))) >> FRACBITS;
  193.         index += increment;
  194.  
  195.         *dest++ += lvolsel * sample;
  196.         *dest++ += rvolsel * sample;
  197.     }
  198.     return index;
  199. }
  200.  
  201. static SLONG MixSurroundInterp(SWORD* srce,SLONG* dest,SLONG index,SLONG increment,SLONG todo)
  202. {
  203.     SLONG sample;
  204.  
  205.     while(todo--) {
  206.         sample=((srce[index>>FRACBITS]*((FRACMASK+1L)-(index&FRACMASK))) +
  207.                 (srce[(index>>FRACBITS)+1]*(index&FRACMASK))) >> FRACBITS;
  208.         index += increment;
  209.  
  210.         if(lvolsel>=rvolsel) {
  211.             *dest++ += lvolsel*sample;
  212.             *dest++ -= lvolsel*sample;
  213.         } else {
  214.             *dest++ -= rvolsel*sample;
  215.             *dest++ += rvolsel*sample;
  216.         }
  217.     }
  218.     return index;
  219. }
  220.  
  221. static void (*MixReverb)(SLONG* srce,SLONG count);
  222.  
  223. /* Reverb macros */
  224. #define COMPUTE_LOC(n) loc##n = RVRindex % RVc##n
  225. #define COMPUTE_LECHO(n) RVbufL##n [loc##n ]=speedup+((ReverbPct*RVbufL##n [loc##n ])>>7)
  226. #define COMPUTE_RECHO(n) RVbufR##n [loc##n ]=speedup+((ReverbPct*RVbufR##n [loc##n ])>>7)
  227.  
  228. static void MixReverb_Normal(SLONG* srce,SLONG count)
  229. {
  230.     unsigned int speedup;
  231.     int ReverbPct;
  232.     unsigned int loc1,loc2,loc3,loc4;
  233. #ifndef __FAST_REVERB__
  234.     unsigned int loc5,loc6,loc7,loc8;
  235.  
  236.     ReverbPct=58+(md_reverb*4);
  237. #else
  238.     ReverbPct=89+(md_reverb*2);
  239. #endif
  240.  
  241.     COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
  242. #ifndef __FAST_REVERB__
  243.     COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
  244. #endif
  245.  
  246.     while(count--) {
  247.         /* Compute the left channel echo buffers */
  248.         speedup = *srce >> 3;
  249.  
  250.         COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4);
  251. #ifndef __FAST_REVERB__
  252.         COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8);
  253. #endif
  254.  
  255.         /* Prepare to compute actual finalized data */
  256.         RVRindex++;
  257.  
  258.         COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
  259. #ifndef __FAST_REVERB__
  260.         COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
  261. #endif
  262.  
  263.         /* left channel */
  264. #ifdef __FAST_REVERB__
  265.         *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4];
  266. #else
  267.         *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+
  268.                   RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8];
  269. #endif
  270.     }
  271. }
  272.  
  273. static void MixReverb_Stereo(SLONG* srce,SLONG count)
  274. {
  275.     unsigned int speedup;
  276.     int          ReverbPct;
  277.     unsigned int loc1, loc2, loc3, loc4;
  278. #ifndef __FAST_REVERB__
  279.     unsigned int loc5, loc6, loc7, loc8;
  280.  
  281.     ReverbPct = 63 + (md_reverb*4);
  282. #else
  283.     ReverbPct = 92 + (md_reverb*2);
  284. #endif
  285.  
  286.     COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
  287. #ifndef __FAST_REVERB__
  288.     COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
  289. #endif
  290.  
  291.     while(count--) {
  292.         /* Compute the left channel echo buffers */
  293.         speedup = *srce >> 3;
  294.  
  295.         COMPUTE_LECHO(1); COMPUTE_LECHO(2); COMPUTE_LECHO(3); COMPUTE_LECHO(4);
  296. #ifndef __FAST_REVERB__
  297.         COMPUTE_LECHO(5); COMPUTE_LECHO(6); COMPUTE_LECHO(7); COMPUTE_LECHO(8);
  298. #endif
  299.  
  300.         /* Compute the right channel echo buffers */
  301.         speedup = srce[1] >> 3;
  302.  
  303.         COMPUTE_RECHO(1); COMPUTE_RECHO(2); COMPUTE_RECHO(3); COMPUTE_RECHO(4);
  304. #ifndef __FAST_REVERB__
  305.         COMPUTE_RECHO(5); COMPUTE_RECHO(6); COMPUTE_RECHO(7); COMPUTE_RECHO(8);
  306. #endif
  307.  
  308.         /* Prepare to compute actual finalized data */
  309.         RVRindex++;
  310.  
  311.         COMPUTE_LOC(1); COMPUTE_LOC(2); COMPUTE_LOC(3); COMPUTE_LOC(4);
  312. #ifndef __FAST_REVERB__
  313.         COMPUTE_LOC(5); COMPUTE_LOC(6); COMPUTE_LOC(7); COMPUTE_LOC(8);
  314. #endif
  315.  
  316. #ifdef __FAST_REVERB__
  317.         /* left channel then right channel */
  318.         *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4];
  319.         *srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4];
  320. #else
  321.         /* left channel then right channel */
  322.         *srce++ +=RVbufL1[loc1]-RVbufL2[loc2]+RVbufL3[loc3]-RVbufL4[loc4]+
  323.                   RVbufL5[loc5]-RVbufL6[loc6]+RVbufL7[loc7]-RVbufL8[loc8];
  324.  
  325.         *srce++ +=RVbufR1[loc1]-RVbufR2[loc2]+RVbufR3[loc3]-RVbufR4[loc4]+
  326.                   RVbufR5[loc5]-RVbufR6[loc6]+RVbufR7[loc7]-RVbufR8[loc8];
  327. #endif
  328.     }
  329. }
  330.  
  331. /* Mixing macros */
  332. #define EXTRACT_SAMPLE(var,size) var=*srce++>>(BITSHIFT+16-size)
  333. #define CHECK_SAMPLE(var,bound) var=(var>=bound)?bound-1:(var<-bound)?-bound:var
  334. #define PUT_SAMPLE(var) *dste++=var
  335.  
  336. static void Mix32To16(SWORD* dste,SLONG* srce,ULONG count)
  337. {
  338.     SLONG x1,x2,x3,x4;
  339.     int    remain;
  340.  
  341.     remain=count&3;
  342.     for(count>>=2;count;count--) {
  343.         EXTRACT_SAMPLE(x1,16); EXTRACT_SAMPLE(x2,16);
  344.         EXTRACT_SAMPLE(x3,16); EXTRACT_SAMPLE(x4,16);
  345.  
  346.         CHECK_SAMPLE(x1,32768); CHECK_SAMPLE(x2,32768);
  347.         CHECK_SAMPLE(x3,32768); CHECK_SAMPLE(x4,32768);
  348.  
  349.         PUT_SAMPLE(x1); PUT_SAMPLE(x2); PUT_SAMPLE(x3); PUT_SAMPLE(x4);
  350.     }
  351.     while(remain--) {
  352.         EXTRACT_SAMPLE(x1,16);
  353.         CHECK_SAMPLE(x1,32768);
  354.         PUT_SAMPLE(x1);
  355.     }
  356. }
  357.  
  358. static void Mix32To8(SBYTE* dste,SLONG* srce,ULONG count)
  359. {
  360.     SWORD x1,x2,x3,x4;
  361.     int    remain;
  362.  
  363.     remain=count&3;
  364.     for(count>>=2;count;count--) {
  365.         EXTRACT_SAMPLE(x1,8); EXTRACT_SAMPLE(x2,8);
  366.         EXTRACT_SAMPLE(x3,8); EXTRACT_SAMPLE(x4,8);
  367.  
  368.         CHECK_SAMPLE(x1,128); CHECK_SAMPLE(x2,128);
  369.         CHECK_SAMPLE(x3,128); CHECK_SAMPLE(x4,128);
  370.  
  371.         PUT_SAMPLE(x1+128); PUT_SAMPLE(x2+128);
  372.         PUT_SAMPLE(x3+128); PUT_SAMPLE(x4+128);
  373.     }
  374.     while(remain--) {
  375.         EXTRACT_SAMPLE(x1,8);
  376.         CHECK_SAMPLE(x1,128);
  377.         PUT_SAMPLE(x1+128);
  378.     }
  379. }
  380.  
  381. static ULONG samples2bytes(ULONG samples)
  382. {
  383.     if(vc_mode & DMODE_16BITS) samples<<=1;
  384.     if(vc_mode & DMODE_STEREO) samples<<=1;
  385.     return samples;
  386. }
  387.  
  388. static ULONG bytes2samples(ULONG bytes)
  389. {
  390.     if(vc_mode & DMODE_16BITS) bytes>>=1;
  391.     if(vc_mode & DMODE_STEREO) bytes>>=1;
  392.     return bytes;
  393. }
  394.  
  395. static void AddChannel(SLONG* ptr,SLONG todo)
  396. {
  397.     SLONG end,done;
  398.     SWORD *s;
  399.  
  400.     if(!(s=Samples[vnf->handle])) {
  401.         vnf->current = vnf->active  = 0;
  402.         return;
  403.     }
  404.  
  405.     /* update the 'current' index so the sample loops, or stops playing if it
  406.        reached the end of the sample */
  407.     while(todo>0) {
  408.         if(vnf->flags & SF_REVERSE) {
  409.             /* The sample is playing in reverse */
  410.             if((vnf->flags&SF_LOOP)&&(vnf->current<idxlpos)) {
  411.                 /* the sample is looping and has reached the loopstart index */
  412.                 if(vnf->flags & SF_BIDI) {
  413.                     /* sample is doing bidirectional loops, so 'bounce' the
  414.                        current index against the idxlpos */
  415.                     vnf->current = idxlpos+(idxlpos-vnf->current);
  416.                     vnf->flags &= ~SF_REVERSE;
  417.                     vnf->increment = -vnf->increment;
  418.                 } else
  419.                     /* normal backwards looping, so set the current position to
  420.                        loopend index */
  421.                     vnf->current=idxlend-(idxlpos-vnf->current);
  422.             } else {
  423.                 /* the sample is not looping, so check if it reached index 0 */
  424.                 if(vnf->current < 0) {
  425.                     /* playing index reached 0, so stop playing this sample */
  426.                     vnf->current = vnf->active  = 0;
  427.                     break;
  428.                 }
  429.             }
  430.         } else {
  431.             /* The sample is playing forward */
  432.             if((vnf->flags & SF_LOOP) && (vnf->current > idxlend)) {
  433.                 /* the sample is looping, check the loopend index */
  434.                 if(vnf->flags & SF_BIDI) {
  435.                     /* sample is doing bidirectional loops, so 'bounce' the
  436.                        current index against the idxlend */
  437.                     vnf->flags |= SF_REVERSE;
  438.                     vnf->increment = -vnf->increment;
  439.                     vnf->current = idxlend-(vnf->current-idxlend);
  440.                 } else
  441.                     /* normal backwards looping, so set the current position
  442.                        to loopend index */
  443.                     vnf->current=idxlpos+(vnf->current-idxlend);
  444.             } else {
  445.                 /* sample is not looping, so check if it reached the last
  446.                    position */
  447.                 if(vnf->current > idxsize) {
  448.                     /* yes, so stop playing this sample */
  449.                     vnf->current = vnf->active  = 0;
  450.                     break;
  451.                 }
  452.             }
  453.         }
  454.  
  455.         end=(vnf->flags&SF_REVERSE)?(vnf->flags&SF_LOOP)?idxlpos:0:
  456.              (vnf->flags&SF_LOOP)?idxlend:idxsize;
  457.  
  458.         /* if the sampled is not blocked... */
  459.         if (vnf->increment)
  460.             done=MIN((end-vnf->current)/vnf->increment+1,todo);
  461.         else
  462.             done=0;
  463.  
  464.         if(!done) {
  465.             vnf->active = 0;
  466.             break;
  467.         }
  468.  
  469.         if(vnf->vol) {
  470.             if((md_mode & DMODE_INTERP)) {
  471.                 if(vc_mode & DMODE_STEREO)
  472.                     if((vnf->pan == PAN_SURROUND) && (vc_mode & DMODE_SURROUND))
  473.                         vnf->current = MixSurroundInterp(s,ptr,vnf->current,vnf->increment,done);
  474.                     else
  475.                         vnf->current = MixStereoInterp(s,ptr,vnf->current,vnf->increment,done);
  476.                 else
  477.                     vnf->current = MixMonoInterp(s,ptr,vnf->current,vnf->increment,done);
  478.             } else if(vc_mode & DMODE_STEREO)
  479.                 if((vnf->pan == PAN_SURROUND) && (vc_mode & DMODE_SURROUND))
  480.                     vnf->current = MixSurroundNormal(s,ptr,vnf->current,vnf->increment,done);
  481.                 else
  482.                     vnf->current = MixStereoNormal(s,ptr,vnf->current,vnf->increment,done);
  483.             else
  484.                 vnf->current = MixMonoNormal(s,ptr,vnf->current,vnf->increment, done);
  485.         } else {
  486.             /* update sample position */
  487.             vnf->current+=vnf->increment*done;
  488.         }
  489.  
  490.         todo-=done;
  491.         ptr +=(vc_mode & DMODE_STEREO)?(done<<1):done;
  492.     }
  493. }
  494.  
  495. static void VC_WriteSamples(SBYTE* buf,ULONG todo)
  496. {
  497.     int left,portion=0,count;
  498.     SBYTE  *buffer;
  499.     int t, pan, vol;
  500.  
  501.     while(todo) {
  502.         if(!tickleft) {
  503.             if(vc_mode & DMODE_SOFT_MUSIC) md_player();
  504.             tickleft=(md_mixfreq*125L)/(md_bpm*50L);
  505.         }
  506.         left = MIN(tickleft, todo);
  507.         buffer    = buf;
  508.         tickleft -= left;
  509.         todo     -= left;
  510.         buf += samples2bytes(left);
  511.  
  512.         while(left) {
  513.             portion = MIN(left, samplesthatfit);
  514.             count   = (vc_mode & DMODE_STEREO)?(portion<<1):portion;
  515.             memset(vc_tickbuf, 0, count<<2);
  516.             for(t=0;t<vc_softchn;t++) {
  517.                 vnf = &vinf[t];
  518.  
  519.                 if(vnf->kick) {
  520.                     vnf->current=vnf->start<<FRACBITS;
  521.                     vnf->kick   =0;
  522.                     vnf->active =1;
  523.                 }
  524.  
  525.                 if(!vnf->frq) vnf->active = 0;
  526.  
  527.                 if(vnf->active) {
  528.                     vnf->increment=(vnf->frq<<FRACBITS)/md_mixfreq;
  529.                     if(vnf->flags&SF_REVERSE) vnf->increment=-vnf->increment;
  530.                     vol = vnf->vol;  pan = vnf->pan;
  531.  
  532.                     if(vc_mode & DMODE_STEREO) {
  533.                         if(pan != PAN_SURROUND) {
  534.                             lvolsel = (vol * (PAN_RIGHT-pan)) >> 8;
  535.                             rvolsel = (vol * pan) >> 8;
  536.                         } else
  537.                             lvolsel = rvolsel = vol/2;
  538.                     } else
  539.                         lvolsel = vol;
  540.  
  541.                     idxsize = (vnf->size)? (vnf->size << FRACBITS)-1 : 0;
  542.                     idxlend = (vnf->repend)? (vnf->repend << FRACBITS)-1 : 0;
  543.                     idxlpos = vnf->reppos << FRACBITS;
  544.                     AddChannel(vc_tickbuf, portion);
  545.                 }
  546.             }
  547.  
  548.             if(md_reverb) {
  549.                 if(md_reverb>15) md_reverb=15;
  550.                 MixReverb(vc_tickbuf, portion);
  551.             }
  552.  
  553.             if(vc_mode & DMODE_16BITS)
  554.                 Mix32To16((SWORD*) buffer, vc_tickbuf, count);
  555.             else
  556.                 Mix32To8((SBYTE*) buffer, vc_tickbuf, count);
  557.  
  558.             buffer += samples2bytes(portion);
  559.             left   -= portion;
  560.         }
  561.     }
  562. }
  563.  
  564. /* Fill the buffer with 'todo' bytes of silence (it depends on the mixing mode
  565.    how the buffer is filled) */
  566. void VC_SilenceBytes(SBYTE* buf,ULONG todo)
  567. {
  568.     /* clear the buffer to zero (16 bits signed ) or 0x80 (8 bits unsigned) */
  569.     if(vc_mode & DMODE_16BITS)
  570.         memset(buf,0,todo);
  571.     else
  572.         memset(buf,0x80,todo);
  573. }
  574.  
  575. /* Writes 'todo' mixed SBYTES (!!) to 'buf'. It returns the number of SBYTES
  576.    actually written to 'buf' (which is rounded to number of samples that fit
  577.    into 'todo' bytes). */
  578. ULONG VC_WriteBytes(SBYTE* buf,ULONG todo)
  579. {
  580.     if(!vc_softchn) {
  581.         VC_SilenceBytes(buf,todo);
  582.         return todo;
  583.     }
  584.  
  585.     todo = bytes2samples(todo);
  586.     VC_WriteSamples(buf,todo);
  587.  
  588.     return samples2bytes(todo);
  589. }
  590.  
  591. BOOL VC_Init(void)
  592. {
  593.     if(!(Samples=(SWORD**)_mm_calloc(MAXSAMPLEHANDLES,sizeof(SWORD*)))) {
  594.         _mm_errno = MMERR_INITIALIZING_MIXER;
  595.         return 1;
  596.     }
  597.     if(!vc_tickbuf)
  598.         if(!(vc_tickbuf=(SLONG*)_mm_malloc((TICKLSIZE+32)*sizeof(SLONG)))) {
  599.             _mm_errno = MMERR_INITIALIZING_MIXER;
  600.             return 1;
  601.         }
  602.  
  603.     MixReverb=(md_mode&DMODE_STEREO)?MixReverb_Stereo:MixReverb_Normal;
  604.     vc_mode = md_mode;
  605.     return 0;
  606. }
  607.  
  608. void VC_Exit(void)
  609. {
  610.     if(vc_tickbuf) free(vc_tickbuf);
  611.     if(vinf) free(vinf);
  612.     if(Samples) free(Samples);
  613.  
  614.     vc_tickbuf = NULL;
  615.     vinf = NULL;
  616.     Samples = NULL;
  617. }
  618.  
  619. BOOL VC_PlayStart(void)
  620. {
  621.     samplesthatfit=TICKLSIZE;
  622.     if(vc_mode & DMODE_STEREO) samplesthatfit >>= 1;
  623.     tickleft = 0;
  624.  
  625.     RVc1 = (5000L * md_mixfreq) / REVERBERATION;
  626.     RVc2 = (5078L * md_mixfreq) / REVERBERATION;
  627.     RVc3 = (5313L * md_mixfreq) / REVERBERATION;
  628.     RVc4 = (5703L * md_mixfreq) / REVERBERATION;
  629. #ifndef __FAST_REVERB__
  630.     RVc5 = (6250L * md_mixfreq) / REVERBERATION;
  631.     RVc6 = (6953L * md_mixfreq) / REVERBERATION;
  632.     RVc7 = (7813L * md_mixfreq) / REVERBERATION;
  633.     RVc8 = (8828L * md_mixfreq) / REVERBERATION;
  634. #endif
  635.  
  636.     if(!(RVbufL1=(SLONG*)_mm_calloc((RVc1+1),sizeof(SLONG)))) return 1;
  637.     if(!(RVbufL2=(SLONG*)_mm_calloc((RVc2+1),sizeof(SLONG)))) return 1;
  638.     if(!(RVbufL3=(SLONG*)_mm_calloc((RVc3+1),sizeof(SLONG)))) return 1;
  639.     if(!(RVbufL4=(SLONG*)_mm_calloc((RVc4+1),sizeof(SLONG)))) return 1;
  640. #ifndef __FAST_REVERB__
  641.     if(!(RVbufL5=(SLONG*)_mm_calloc((RVc5+1),sizeof(SLONG)))) return 1;
  642.     if(!(RVbufL6=(SLONG*)_mm_calloc((RVc6+1),sizeof(SLONG)))) return 1;
  643.     if(!(RVbufL7=(SLONG*)_mm_calloc((RVc7+1),sizeof(SLONG)))) return 1;
  644.     if(!(RVbufL8=(SLONG*)_mm_calloc((RVc8+1),sizeof(SLONG)))) return 1;
  645. #endif
  646.  
  647.     if(!(RVbufR1=(SLONG*)_mm_calloc((RVc1+1),sizeof(SLONG)))) return 1;
  648.     if(!(RVbufR2=(SLONG*)_mm_calloc((RVc2+1),sizeof(SLONG)))) return 1;
  649.     if(!(RVbufR3=(SLONG*)_mm_calloc((RVc3+1),sizeof(SLONG)))) return 1;
  650.     if(!(RVbufR4=(SLONG*)_mm_calloc((RVc4+1),sizeof(SLONG)))) return 1;
  651. #ifndef __FAST_REVERB__
  652.     if(!(RVbufR5=(SLONG*)_mm_calloc((RVc5+1),sizeof(SLONG)))) return 1;
  653.     if(!(RVbufR6=(SLONG*)_mm_calloc((RVc6+1),sizeof(SLONG)))) return 1;
  654.     if(!(RVbufR7=(SLONG*)_mm_calloc((RVc7+1),sizeof(SLONG)))) return 1;
  655.     if(!(RVbufR8=(SLONG*)_mm_calloc((RVc8+1),sizeof(SLONG)))) return 1;
  656. #endif
  657.  
  658.     RVRindex = 0;
  659.     return 0;
  660. }
  661.  
  662. void VC_PlayStop(void)
  663. {
  664.     if(RVbufL1) free(RVbufL1);
  665.     if(RVbufL2) free(RVbufL2);
  666.     if(RVbufL3) free(RVbufL3);
  667.     if(RVbufL4) free(RVbufL4);
  668.     RVbufL1 = RVbufL2 = RVbufL3 = RVbufL4 = NULL;
  669. #ifndef __FAST_REVERB__
  670.     if(RVbufL5) free(RVbufL5);
  671.     if(RVbufL6) free(RVbufL6);
  672.     if(RVbufL7) free(RVbufL7);
  673.     if(RVbufL8) free(RVbufL8);
  674.     RVbufL5 = RVbufL6 = RVbufL7 = RVbufL8 = NULL;
  675. #endif
  676.     if(RVbufR1) free(RVbufR1);
  677.     if(RVbufR2) free(RVbufR2);
  678.     if(RVbufR3) free(RVbufR3);
  679.     if(RVbufR4) free(RVbufR4);
  680.     RVbufR1 = RVbufR2 = RVbufR3 = RVbufR4 = NULL;
  681. #ifndef __FAST_REVERB__
  682.     if(RVbufR5) free(RVbufR5);
  683.     if(RVbufR6) free(RVbufR6);
  684.     if(RVbufR7) free(RVbufR7);
  685.     if(RVbufR8) free(RVbufR8);
  686.     RVbufR5 = RVbufR6 = RVbufR7 = RVbufR8 = NULL;
  687. #endif
  688. }
  689.  
  690. BOOL VC_SetNumVoices(void)
  691. {
  692.     int t;
  693.  
  694.     if(!(vc_softchn=md_softchn)) return 0;
  695.  
  696.     if(vinf) free(vinf);
  697.     if(!(vinf= _mm_calloc(sizeof(VINFO),vc_softchn))) return 1;
  698.  
  699.     for(t=0;t<vc_softchn;t++) {
  700.         vinf[t].frq=10000;
  701.         vinf[t].pan=(t&1)?PAN_LEFT:PAN_RIGHT;
  702.     }
  703.  
  704.     return 0;
  705. }
  706.  
  707. void VC_VoiceSetVolume(UBYTE voice,UWORD vol)
  708. {
  709.     vinf[voice].vol = vol;
  710. }
  711.  
  712. void VC_VoiceSetFrequency(UBYTE voice,ULONG frq)
  713. {
  714.     vinf[voice].frq = frq;
  715. }
  716.  
  717. void VC_VoiceSetPanning(UBYTE voice, ULONG pan)
  718. {
  719.     vinf[voice].pan = pan;
  720. }
  721.  
  722. void VC_VoicePlay(UBYTE voice,SWORD handle,ULONG start,ULONG size,ULONG reppos,ULONG repend,UWORD flags)
  723. {
  724.     vinf[voice].flags    = flags;
  725.     vinf[voice].handle   = handle;
  726.     vinf[voice].start    = start;
  727.     vinf[voice].size     = size;
  728.     vinf[voice].reppos   = reppos;
  729.     vinf[voice].repend   = repend;
  730.     vinf[voice].kick     = 1;
  731. }
  732.  
  733. void VC_VoiceStop(UBYTE voice)
  734. {
  735.     vinf[voice].active = 0;
  736. }  
  737.  
  738. BOOL VC_VoiceStopped(UBYTE voice)
  739. {
  740.     return(vinf[voice].active==0);
  741. }
  742.  
  743. SLONG VC_VoiceGetPosition(UBYTE voice)
  744. {
  745.     return(vinf[voice].current >> FRACBITS);
  746. }
  747.  
  748. /*========== External mixer interface */
  749.  
  750. void VC_SampleUnload(SWORD handle)
  751. {
  752.     if (handle<MAXSAMPLEHANDLES) {
  753.         if (Samples[handle])
  754.             free(Samples[handle]);
  755.         Samples[handle]=NULL;
  756.     }
  757. }
  758.  
  759. SWORD VC_SampleLoad(SAMPLOAD* sload,int type)
  760. {
  761.     SAMPLE *s = sload->sample;
  762.     int handle;
  763.     ULONG t, length,loopstart,loopend;
  764.  
  765.     if(type==MD_HARDWARE) return -1;
  766.  
  767.     /* Find empty slot to put sample address in */
  768.     for(handle=0;handle<MAXSAMPLEHANDLES;handle++)
  769.         if(!Samples[handle]) break;
  770.  
  771.     if(handle==MAXSAMPLEHANDLES) {
  772.         _mm_errno = MMERR_OUT_OF_HANDLES;
  773.         return -1;
  774.     }
  775.  
  776.     length    = s->length;
  777.     loopstart = s->loopstart;
  778.     loopend   = s->loopend;
  779.  
  780.     SL_SampleSigned(sload);
  781.  
  782.     SL_Sample8to16(sload);
  783.     if(!(Samples[handle]=(SWORD*)_mm_malloc((length+20)<<1))) {
  784.         _mm_errno = MMERR_SAMPLE_TOO_BIG;
  785.         return -1;
  786.     }
  787.  
  788.     /* read sample into buffer. */
  789.     if (SL_Load(Samples[handle],sload,length))
  790.         return -1;
  791.  
  792.     /* Unclick samples: */
  793.     if(s->flags & SF_LOOP) {
  794.         if(s->flags & SF_BIDI)
  795.             for(t=0;t<16;t++)
  796.                 Samples[handle][loopend+t]=Samples[handle][(loopend-t)-1];
  797.         else
  798.             for(t=0;t<16;t++)
  799.                 Samples[handle][loopend+t]=Samples[handle][t+loopstart];
  800.     } else
  801.         for(t=0;t<16;t++)
  802.             Samples[handle][t+length]=0;
  803.  
  804.     return handle;
  805. }
  806.  
  807. ULONG VC_SampleSpace(int type)
  808. {
  809.     return vc_memory;
  810. }
  811.  
  812. ULONG VC_SampleLength(int type,SAMPLE* s)
  813. {
  814.     return (s->length*((s->flags&SF_16BITS)?2:1))+16;
  815. }
  816.  
  817. ULONG VC_VoiceRealVolume(UBYTE voice)
  818. {
  819.     ULONG i,s,size;
  820.     int k,j;
  821.     SWORD *smp;
  822.     SLONG t;
  823.  
  824.     t = vinf[voice].current>>FRACBITS;
  825.     if(!vinf[voice].active) return 0;
  826.  
  827.     s = vinf[voice].handle;
  828.     size = vinf[voice].size;
  829.  
  830.     i=64; t-=64; k=0; j=0;
  831.     if(i>size) i = size;
  832.     if(t<0) t = 0;
  833.     if(t+i > size) t = size-i;
  834.  
  835.     i &= ~1;  /* make sure it's EVEN. */
  836.  
  837.     smp = &Samples[s][t];
  838.     for(;i;i--,smp++) {
  839.         if(k<*smp) k = *smp;
  840.         if(j>*smp) j = *smp;
  841.     }
  842.     return abs(k-j);
  843. }
  844.