home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / snd_mix.c.orig < prev    next >
Text File  |  2000-06-17  |  9KB  |  399 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of 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.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // snd_mix.c -- portable code to mix sounds for snd_dma.c
  21.  
  22. #include "quakedef.h"
  23.  
  24. #ifdef _WIN32
  25. #include "winquake.h"
  26. #else
  27. #define DWORD unsigned long
  28. #endif
  29.  
  30. #define PAINTBUFFER_SIZE  512
  31. portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
  32. int   snd_scaletable[32][256];
  33. int   *snd_p, snd_linear_count, snd_vol;
  34. short *snd_out;
  35.  
  36. void Snd_WriteLinearBlastStereo16 (void);
  37.  
  38. #if !id386
  39. void Snd_WriteLinearBlastStereo16 (void)
  40. {
  41.   int   i;
  42.   int   val;
  43.  
  44.   for (i=0 ; i<snd_linear_count ; i+=2)
  45.   {
  46.     val = (snd_p[i]*snd_vol)>>8;
  47.     if (val > 0x7fff)
  48.       snd_out[i] = 0x7fff;
  49.     else if (val < (short)0x8000)
  50.       snd_out[i] = (short)0x8000;
  51.     else
  52.       snd_out[i] = val;
  53.  
  54.     val = (snd_p[i+1]*snd_vol)>>8;
  55.     if (val > 0x7fff)
  56.       snd_out[i+1] = 0x7fff;
  57.     else if (val < (short)0x8000)
  58.       snd_out[i+1] = (short)0x8000;
  59.     else
  60.       snd_out[i+1] = val;
  61.   }
  62. }
  63. #endif
  64.  
  65. void S_TransferStereo16 (int endtime)
  66. {
  67.   int   lpos;
  68.   int   lpaintedtime;
  69.   DWORD *pbuf;
  70. #ifdef _WIN32
  71.   int   reps;
  72.   DWORD dwSize,dwSize2;
  73.   DWORD *pbuf2;
  74.   HRESULT hresult;
  75. #endif
  76.   
  77.   snd_vol = volume.value*256;
  78.  
  79.   snd_p = (int *) paintbuffer;
  80.   lpaintedtime = paintedtime;
  81.  
  82. #ifdef _WIN32
  83.   if (pDSBuf)
  84.   {
  85.     reps = 0;
  86.  
  87.     while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, 
  88.                      &pbuf2, &dwSize2, 0)) != DS_OK)
  89.     {
  90.       if (hresult != DSERR_BUFFERLOST)
  91.       {
  92.         Con_Printf ("S_TransferStereo16: DS::Lock Sound Buffer Failed\n");
  93.         S_Shutdown ();
  94.         S_Startup ();
  95.         return;
  96.       }
  97.  
  98.       if (++reps > 10000)
  99.       {
  100.         Con_Printf ("S_TransferStereo16: DS: couldn't restore buffer\n");
  101.         S_Shutdown ();
  102.         S_Startup ();
  103.         return;
  104.       }
  105.     }
  106.   }
  107.   else
  108. #endif
  109.   {
  110.     pbuf = (DWORD *)shm->buffer;
  111.   }
  112.  
  113.   while (lpaintedtime < endtime)
  114.   {
  115.   // handle recirculating buffer issues
  116.     lpos = lpaintedtime & ((shm->samples>>1)-1);
  117.  
  118.     snd_out = (short *) pbuf + (lpos<<1);
  119.  
  120.     snd_linear_count = (shm->samples>>1) - lpos;
  121.     if (lpaintedtime + snd_linear_count > endtime)
  122.       snd_linear_count = endtime - lpaintedtime;
  123.  
  124.     snd_linear_count <<= 1;
  125.  
  126.   // write a linear blast of samples
  127.     Snd_WriteLinearBlastStereo16 ();
  128.  
  129.     snd_p += snd_linear_count;
  130.     lpaintedtime += (snd_linear_count>>1);
  131.   }
  132.  
  133. #ifdef _WIN32
  134.   if (pDSBuf)
  135.     pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0);
  136. #endif
  137. }
  138.  
  139. void S_TransferPaintBuffer(int endtime)
  140. {
  141.   int   out_idx;
  142.   int   count;
  143.   int   out_mask;
  144.   int   *p;
  145.   int   step;
  146.   int   val;
  147.   int   snd_vol;
  148.   DWORD *pbuf;
  149. #ifdef _WIN32
  150.   int   reps;
  151.   DWORD dwSize,dwSize2;
  152.   DWORD *pbuf2;
  153.   HRESULT hresult;
  154. #endif
  155.  
  156.   if (shm->samplebits == 16 && shm->channels == 2)
  157.   {
  158.     S_TransferStereo16 (endtime);
  159.     return;
  160.   }
  161.   
  162.   p = (int *) paintbuffer;
  163.   count = (endtime - paintedtime) * shm->channels;
  164.   out_mask = shm->samples - 1; 
  165.   out_idx = paintedtime * shm->channels & out_mask;
  166.   step = 3 - shm->channels;
  167.   snd_vol = volume.value*256;
  168.  
  169. #ifdef _WIN32
  170.   if (pDSBuf)
  171.   {
  172.     reps = 0;
  173.  
  174.     while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &dwSize, 
  175.                      &pbuf2,&dwSize2, 0)) != DS_OK)
  176.     {
  177.       if (hresult != DSERR_BUFFERLOST)
  178.       {
  179.         Con_Printf ("S_TransferPaintBuffer: DS::Lock Sound Buffer Failed\n");
  180.         S_Shutdown ();
  181.         S_Startup ();
  182.         return;
  183.       }
  184.  
  185.       if (++reps > 10000)
  186.       {
  187.         Con_Printf ("S_TransferPaintBuffer: DS: couldn't restore buffer\n");
  188.         S_Shutdown ();
  189.         S_Startup ();
  190.         return;
  191.       }
  192.     }
  193.   }
  194.   else
  195. #endif
  196.   {
  197.     pbuf = (DWORD *)shm->buffer;
  198.   }
  199.  
  200.   if (shm->samplebits == 16)
  201.   {
  202.     short *out = (short *) pbuf;
  203.     while (count--)
  204.     {
  205.       val = (*p * snd_vol) >> 8;
  206.       p+= step;
  207.       if (val > 0x7fff)
  208.         val = 0x7fff;
  209.       else if (val < (short)0x8000)
  210.         val = (short)0x8000;
  211.       out[out_idx] = val;
  212.       out_idx = (out_idx + 1) & out_mask;
  213.     }
  214.   }
  215.   else if (shm->samplebits == 8)
  216.   {
  217.     unsigned char *out = (unsigned char *) pbuf;
  218.     while (count--)
  219.     {
  220.       val = (*p * snd_vol) >> 8;
  221.       p+= step;
  222.       if (val > 0x7fff)
  223.         val = 0x7fff;
  224.       else if (val < (short)0x8000)
  225.         val = (short)0x8000;
  226.       out[out_idx] = (val>>8) + 128;
  227.       out_idx = (out_idx + 1) & out_mask;
  228.     }
  229.   }
  230.  
  231. #ifdef _WIN32
  232.   if (pDSBuf) {
  233.     DWORD dwNewpos, dwWrite;
  234.     int il = paintedtime;
  235.     int ir = endtime - paintedtime;
  236.     
  237.     ir += il;
  238.  
  239.     pDSBuf->lpVtbl->Unlock(pDSBuf, pbuf, dwSize, NULL, 0);
  240.  
  241.     pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &dwNewpos, &dwWrite);
  242.  
  243. //    if ((dwNewpos >= il) && (dwNewpos <= ir))
  244. //      Con_Printf("%d-%d p %d c\n", il, ir, dwNewpos);
  245.   }
  246. #endif
  247. }
  248.  
  249.  
  250. /*
  251. ===============================================================================
  252.  
  253. CHANNEL MIXING
  254.  
  255. ===============================================================================
  256. */
  257.  
  258. void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int endtime);
  259. void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int endtime);
  260.  
  261. void S_PaintChannels(int endtime)
  262. {
  263.   int   i;
  264.   int   end;
  265.   channel_t *ch;
  266.   sfxcache_t  *sc;
  267.   int   ltime, count;
  268.  
  269.   while (paintedtime < endtime)
  270.   {
  271.   // if paintbuffer is smaller than DMA buffer
  272.     end = endtime;
  273.     if (endtime - paintedtime > PAINTBUFFER_SIZE)
  274.       end = paintedtime + PAINTBUFFER_SIZE;
  275.  
  276.   // clear the paint buffer
  277.     Q_memset(paintbuffer, 0, (end - paintedtime) * sizeof(portable_samplepair_t));
  278.  
  279.   // paint in the channels.
  280.     ch = channels;
  281.     for (i=0; i<total_channels ; i++, ch++)
  282.     {
  283.       if (!ch->sfx)
  284.         continue;
  285.       if (!ch->leftvol && !ch->rightvol)
  286.         continue;
  287.       sc = S_LoadSound (ch->sfx);
  288.       if (!sc)
  289.         continue;
  290.  
  291.       ltime = paintedtime;
  292.  
  293.       while (ltime < end)
  294.       { // paint up to end
  295.         if (ch->end < end)
  296.           count = ch->end - ltime;
  297.         else
  298.           count = end - ltime;
  299.  
  300.         if (count > 0)
  301.         { 
  302.           if (sc->width == 1)
  303.             SND_PaintChannelFrom8(ch, sc, count);
  304.           else
  305.             SND_PaintChannelFrom16(ch, sc, count);
  306.   
  307.           ltime += count;
  308.         }
  309.  
  310.       // if at end of loop, restart
  311.         if (ltime >= ch->end)
  312.         {
  313.           if (sc->loopstart >= 0)
  314.           {
  315.             ch->pos = sc->loopstart;
  316.             ch->end = ltime + sc->length - ch->pos;
  317.           }
  318.           else        
  319.           { // channel just stopped
  320.             ch->sfx = NULL;
  321.             break;
  322.           }
  323.         }
  324.       }
  325.                                 
  326.     }
  327.  
  328.   // transfer out according to DMA format
  329.     S_TransferPaintBuffer(end);
  330.     paintedtime = end;
  331.   }
  332. }
  333.  
  334. void SND_InitScaletable (void)
  335. {
  336.   int   i, j;
  337.   
  338.   for (i=0 ; i<32 ; i++)
  339.     for (j=0 ; j<256 ; j++)
  340.       snd_scaletable[i][j] = ((signed char)j) * i * 8;
  341. }
  342.  
  343.  
  344. #if !id386
  345.  
  346. void SND_PaintChannelFrom8 (channel_t *ch, sfxcache_t *sc, int count)
  347. {
  348.   int   data;
  349.   int   *lscale, *rscale;
  350.   unsigned char *sfx;
  351.   int   i;
  352.  
  353.   if (ch->leftvol > 255)
  354.     ch->leftvol = 255;
  355.   if (ch->rightvol > 255)
  356.     ch->rightvol = 255;
  357.     
  358.   lscale = snd_scaletable[ch->leftvol >> 3];
  359.   rscale = snd_scaletable[ch->rightvol >> 3];
  360.   sfx = (signed char *)sc->data + ch->pos;
  361.  
  362.   for (i=0 ; i<count ; i++)
  363.   {
  364.     data = sfx[i];
  365.     paintbuffer[i].left += lscale[data];
  366.     paintbuffer[i].right += rscale[data];
  367.   }
  368.   
  369.   ch->pos += count;
  370. }
  371.  
  372. #endif  // !id386
  373.  
  374.  
  375. void SND_PaintChannelFrom16 (channel_t *ch, sfxcache_t *sc, int count)
  376. {
  377.   int data;
  378.   int left, right;
  379.   int leftvol, rightvol;
  380.   signed short *sfx;
  381.   int i;
  382.  
  383.   leftvol = ch->leftvol;
  384.   rightvol = ch->rightvol;
  385.   sfx = (signed short *)sc->data + ch->pos;
  386.  
  387.   for (i=0 ; i<count ; i++)
  388.   {
  389.     data = sfx[i];
  390.     left = (data * leftvol) >> 8;
  391.     right = (data * rightvol) >> 8;
  392.     paintbuffer[i].left += left;
  393.     paintbuffer[i].right += right;
  394.   }
  395.  
  396.   ch->pos += count;
  397. }
  398.  
  399.