engine/source/gamelib/soundmix.c
// Input: number of input samples to mix
number of input samples to mix
number of input samples to mix
static void mixaudio(unsigned int todo)
{
    static int i, chan, lvolume, rvolume, lmusic, rmusic;
    static unsigned int fp_pos, fp_period, fp_len, fp_playto;
    static int snum;
    static unsigned char *sptr8;
    static short *sptr16;
    if(musicchannel.active && !musicchannel.paused)
    {
        sptr16 = musicchannel.buf[musicchannel.playing_buffer];
        fp_playto = musicchannel.fp_playto[musicchannel.playing_buffer];
        fp_pos = musicchannel.fp_samplepos;
        fp_period = musicchannel.fp_period;
        lvolume = musicchannel.volume[0];
        rvolume = musicchannel.volume[1];
        for(i = 0; i < (int)todo;)
        {
            if(fp_pos >= fp_playto)
            {
                musicchannel.fp_playto[musicchannel.playing_buffer] = 0;
                musicchannel.playing_buffer++;
                musicchannel.playing_buffer %= MUSIC_NUM_BUFFERS;
                fp_pos = fp_pos - fp_playto;
                if(fp_pos < musicchannel.fp_playto[musicchannel.playing_buffer])
                {
                    sptr16 = musicchannel.buf[musicchannel.playing_buffer];
                    fp_playto = musicchannel.fp_playto[musicchannel.playing_buffer];
                }
                else
                {
                    musicchannel.fp_playto[musicchannel.playing_buffer] = 0;
                    fp_pos = 0;
                    musicchannel.active = 0;
                    break;
                }
            }
            lmusic = rmusic = sptr16[FIX_TO_INT(fp_pos)];
            lmusic = (lmusic * lvolume / MAXVOLUME);
            rmusic = (rmusic * rvolume / MAXVOLUME);
            mixbuf[i++] += lmusic;
            if(musicchannel.channels == SOUND_MONO)
            {
                mixbuf[i++] += rmusic;
            }
            fp_pos += fp_period;
        }
        musicchannel.fp_samplepos = fp_pos;
    }
    for(chan = 0; chan < max_channels; chan++)
    {
        if(vchannel[chan].active && !vchannel[chan].paused)
        {
            unsigned modlen;
            snum = vchannel[chan].samplenum;
            if(!soundcache[snum].sample.sampleptr)
            {
                vchannel[chan].active = 0;
                continue;
            }
            modlen = soundcache[snum].sample.soundlen;
            fp_len = INT_TO_FIX(soundcache[snum].sample.soundlen);
            fp_pos = vchannel[chan].fp_samplepos;
            fp_period = vchannel[chan].fp_period;
            lvolume = vchannel[chan].volume[0];
            rvolume = vchannel[chan].volume[1];
            if(fp_len < 1)
            {
                fp_len = 1;
            }
            if(modlen < 1)
            {
                modlen = 1;
            }
            if(soundcache[snum].sample.bits == 8)
            {
                sptr8 = soundcache[snum].sample.sampleptr;
                for(i = 0; i < (int)todo;)
                {
                    lmusic = rmusic = sptr8[FIX_TO_INT(fp_pos)];
                    mixbuf[i++] += ((lmusic << 8) * lvolume / MAXVOLUME) - 0x8000;
                    if(vchannel[chan].channels == SOUND_MONO)
                    {
                        mixbuf[i++] += ((rmusic << 8) * rvolume / MAXVOLUME) - 0x8000;
                    }
                    fp_pos += fp_period;
                    if(fp_pos >= fp_len)
                    {
                        fp_pos %= fp_len; 
                        if(vchannel[chan].active != CHANNEL_LOOPING)
                        {
                            vchannel[chan].active = 0;
                            break;
                        }
                    }
                }
            }
            else if(soundcache[snum].sample.bits == 16)
            {
                sptr16 = soundcache[snum].sample.sampleptr;
                for(i = 0; i < (int)todo;)
                {
                    lmusic = rmusic = (int)(short)SwapLSB16(sptr16[FIX_TO_INT(fp_pos)]);
                    mixbuf[i++] += (lmusic * lvolume / MAXVOLUME);
                    if(vchannel[chan].channels == SOUND_MONO)
                    {
                        mixbuf[i++] += (rmusic * rvolume / MAXVOLUME);
                    }
                    fp_pos += fp_period;
                    if(fp_pos >= fp_len)
                    {
                        fp_pos %= fp_len; 
                        if(vchannel[chan].active != CHANNEL_LOOPING)
                        {
                            vchannel[chan].active = 0;
                            break;
                        }
                    }
                }
            }
            vchannel[chan].fp_samplepos = fp_pos;
        }
    }
}
static void mixaudio ( unsigned int todo ) { static int i , chan , lvolume , rvolume , lmusic , rmusic ; static unsigned int fp_pos , fp_period , fp_len , fp_playto ; static int snum ; static unsigned char * sptr8 ; static short * sptr16 ; if ( musicchannel . active && ! musicchannel . paused ) { sptr16 = musicchannel . buf [ musicchannel . playing_buffer ] ; fp_playto = musicchannel . fp_playto [ musicchannel . playing_buffer ] ; fp_pos = musicchannel . fp_samplepos ; fp_period = musicchannel . fp_period ; lvolume = musicchannel . volume [ 0 ] ; rvolume = musicchannel . volume [ 1 ] ; for ( i = 0 ; i < ( int ) todo ; ) { if ( fp_pos >= fp_playto ) { musicchannel . fp_playto [ musicchannel . playing_buffer ] = 0 ; musicchannel . playing_buffer ++ ; musicchannel . playing_buffer %= MUSIC_NUM_BUFFERS ; fp_pos = fp_pos - fp_playto ; if ( fp_pos < musicchannel . fp_playto [ musicchannel . playing_buffer ] ) { sptr16 = musicchannel . buf [ musicchannel . playing_buffer ] ; fp_playto = musicchannel . fp_playto [ musicchannel . playing_buffer ] ; } else { musicchannel . fp_playto [ musicchannel . playing_buffer ] = 0 ; fp_pos = 0 ; musicchannel . active = 0 ; break ; } } lmusic = rmusic = sptr16 [ FIX_TO_INT ( fp_pos ) ] ; lmusic = ( lmusic * lvolume / MAXVOLUME ) ; rmusic = ( rmusic * rvolume / MAXVOLUME ) ; mixbuf [ i ++ ] += lmusic ; if ( musicchannel . channels == SOUND_MONO ) { mixbuf [ i ++ ] += rmusic ; } fp_pos += fp_period ; } musicchannel . fp_samplepos = fp_pos ; } for ( chan = 0 ; chan < max_channels ; chan ++ ) { if ( vchannel [ chan ] . active && ! vchannel [ chan ] . paused ) { unsigned modlen ; snum = vchannel [ chan ] . samplenum ; if ( ! soundcache [ snum ] . sample . sampleptr ) { vchannel [ chan ] . active = 0 ; continue ; } modlen = soundcache [ snum ] . sample . soundlen ; fp_len = INT_TO_FIX ( soundcache [ snum ] . sample . soundlen ) ; fp_pos = vchannel [ chan ] . fp_samplepos ; fp_period = vchannel [ chan ] . fp_period ; lvolume = vchannel [ chan ] . volume [ 0 ] ; rvolume = vchannel [ chan ] . volume [ 1 ] ; if ( fp_len < 1 ) { fp_len = 1 ; } if ( modlen < 1 ) { modlen = 1 ; } if ( soundcache [ snum ] . sample . bits == 8 ) { sptr8 = soundcache [ snum ] . sample . sampleptr ; for ( i = 0 ; i < ( int ) todo ; ) { lmusic = rmusic = sptr8 [ FIX_TO_INT ( fp_pos ) ] ; mixbuf [ i ++ ] += ( ( lmusic << 8 ) * lvolume / MAXVOLUME ) - 0x8000 ; if ( vchannel [ chan ] . channels == SOUND_MONO ) { mixbuf [ i ++ ] += ( ( rmusic << 8 ) * rvolume / MAXVOLUME ) - 0x8000 ; } fp_pos += fp_period ; if ( fp_pos >= fp_len ) { fp_pos %= fp_len ; if ( vchannel [ chan ] . active != CHANNEL_LOOPING ) { vchannel [ chan ] . active = 0 ; break ; } } } } else if ( soundcache [ snum ] . sample . bits == 16 ) { sptr16 = soundcache [ snum ] . sample . sampleptr ; for ( i = 0 ; i < ( int ) todo ; ) { lmusic = rmusic = ( int ) ( short ) SwapLSB16 ( sptr16 [ FIX_TO_INT ( fp_pos ) ] ) ; mixbuf [ i ++ ] += ( lmusic * lvolume / MAXVOLUME ) ; if ( vchannel [ chan ] . channels == SOUND_MONO ) { mixbuf [ i ++ ] += ( rmusic * rvolume / MAXVOLUME ) ; } fp_pos += fp_period ; if ( fp_pos >= fp_len ) { fp_pos %= fp_len ; if ( vchannel [ chan ] . active != CHANNEL_LOOPING ) { vchannel [ chan ] . active = 0 ; break ; } } } } vchannel [ chan ] . fp_samplepos = fp_pos ; } } }
Input: number of input samples to mix
Input : number of input samples to mix
// First mix the music, if playing // Mix it // Reached end of playable area, // switch buffers or stop // Done playing this one // Advance to next buffer // Correct position in next buffer // Anything to play? // Yeah, switch! // Nothing more to do // Also disable this buffer, just incase // End for // Mix a sample // Reached end of sample, stop or loop // = INT_TO_FIX(0); // Reached end of sample, stop or loop // = INT_TO_FIX(0);