static void I_SDLUpdateSound(void *userdata, Uint8 *stream, int len)
{
   // Mix current sound data.
   // Data, from raw sound, for right and left.
   Uint8  sample;
   Sint32 dl;
   Sint32 dr;
   
   // Pointers in audio stream, left, right, end.
   Sint16 *leftout, *rightout, *leftend;
   
   // haleyjd: channel pointer for speed++
   channel_info_t *chan;
         
   // Determine end, for left channel only
   //  (right channel is implicit).
   leftend = leftout + len / STEP;

   // Love thy L2 cache - made this a loop.
   // Now more channels could be set at compile time
   //  as well. Thus loop those channels.
   for(chan = channelinfo; chan != &channelinfo[MAX_CHANNELS]; ++chan)
   {
      // fast rejection before semaphore lock
      if(!chan->data || chan->stopChannel)
         continue;
         
      // try to acquire semaphore, but do not block; if the main thread is using
      // this channel we'll just skip it for now - safer and faster.
      if(SDL_SemTryWait(chan->semaphore) != 0)
         continue;
      
      // Left and right channel
      //  are in audio stream, alternating.
      leftout  = (Sint16 *)stream;
      rightout = leftout + 1;
      
      // lost before semaphore acquired? (very unlikely, but must check for safety)
      // BTW, don't move this up or you'll chew major CPU whenever this does happen.
      if(!chan->data)
      {
         SDL_SemPost(chan->semaphore);
         continue;
      }
      
      // Mix sounds into the mixing buffer.
      // Loop over step*SAMPLECOUNT,
      //  that is 512 values for two channels.
      while(leftout != leftend)
      {
         // Get the raw data from the channel. 
         // Sounds are now prefiltered.
         sample = *(chan->data);

         // Reset left/right value. 
         // Add left and right part
         //  for this channel (sound)
         //  to the current data.
         // Adjust volume accordingly.
         dl = (Sint32)(*leftout)  + chan->leftvol_lookup[sample];
         dr = (Sint32)(*rightout) + chan->rightvol_lookup[sample];
                  
         // Clamp to range. Left hardware channel.
         if(dl > SHRT_MAX)
            *leftout = SHRT_MAX;
         else if(dl < SHRT_MIN)
            *leftout = SHRT_MIN;
         else
            *leftout = (Sint16)dl;
            
         // Same for right hardware channel.
         if(dr > SHRT_MAX)
            *rightout = SHRT_MAX;
         else if(dr < SHRT_MIN)
            *rightout = SHRT_MIN;
         else
            *rightout = (Sint16)dr;

         // Increment current pointers in stream
         leftout  += STEP;
         rightout += STEP;
         
         // Increment index
         chan->stepremainder += chan->step;
         
         // MSB is next sample
         chan->data += chan->stepremainder >> 16;
         
         // Limit to LSB
         chan->stepremainder &= 0xffff;
         
         // Check whether we are done
         if(chan->data >= chan->enddata)
         {
            if(chan->loop && 
               !(paused || (menuactive && !demoplayback && !netgame)))
            {
               // haleyjd 06/03/06: restart a looping sample if not paused
               chan->dta = chan->startdata;
               chan->stepremainder = 0;
            }
            else
            {
               // flag the channel to be stopped by the main thread ASAP
               chan->stopChannel = true;
               break;
            }
         }
      }
      
      // release semaphore and move on to the next channel
      SDL_SemPost(chan->semaphore);
   }
}