1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
//Simple macros for checking samples!
//Precalcs handling!
#define C_SAMPLEPOS(channel) (soundchannels[channel].sound.position)
#define C_BUFFERSIZE(channel) (soundchannels[channel].sound.numsamples)
//Use precalculated sample positions!
#define C_SAMPLERATE(channel,position) (convert_samplerate[soundchannels[(channel)].samplerate][(position)])
#define C_GETSAMPLEPOS(channel,rchannel,time) (samplepos[soundchannels[(channel)].stereo][(((word)time)<<1)|(rchannel)])
#define C_STEREO(channel) (soundchannels[channel].stereo)
#define C_VOLUMEPERCENT(channel) (soundchannels[channel].volume_percent)
#define C_SAMPLE(channel,samplepos) (soundchannels[channel].sound.samples[samplepos])
OPTINLINE void mixchannels(sample_stereo_t *res) //Mixes the channels with each other at a specific time!
{
//Process multichannel!
const float SHORTY = 1/USHRT_MAX; //Simple for easy multiplication of division!
float result_l, result_r; //The result!
float multi_l, multi_r; //Multiplication of all channels!
uint_32 n, relsample; //Current channel and relative sample!
word channelsleft; //Reversed of above!
//Channel specific data
float volume,sample_l, sample_r;
if (__HW_DISABLED) return; //Abort?
//First, initialise our variables!
channelsleft = soundchannels_used; //Ammount of channels left!
if (!channelsleft)
{
res->l = res->r = 0.0f; //Nothin to process!
return; //Done!
}
//Result and active counters!
result_l = result_r = 0.0f; //Init to standard sum!
multi_l = multi_r = 1.0f; //Init to standard factor!
n = 0; //Current channel number counter and active channel counter!
//Now process all channels!
for (;;) //Process all channels!
{
if (soundchannels[n].soundhandler) //Active?
{
if (soundchannels[n].samplerate && memprotect(soundchannels[n].sound.samples,soundchannels[n].sound.length,"SW_Samples") && samplepos[soundchannels[n].stereo] && convert_samplerate[soundchannels[n].samplerate]) //Allocated all neccesary channel data?
{
relsample = C_SAMPLERATE(n,C_SAMPLEPOS(n)); //Get the sample rate!
while (relsample>=C_BUFFERSIZE(n)) //Expired, we've reached the end of the buffer (sample overflow)?
{
#ifdef DEBUG_SOUNDSPEED
dolog("Sound","Buffering %i @ %i/%i samples; extra data: %p",n,C_SAMPLEPOS(n),C_BUFFERSIZE(n),soundchannels[n].extradata);
#endif
//Buffer and update buffer position!
soundchannels[n].soundhandler(soundchannels[n].sound.samples,C_BUFFERSIZE(n),soundchannels[n].extradata); /* Request next sample for this channel, also give our channel extra information! */
C_SAMPLEPOS(n) -= C_BUFFERSIZE(n); //Reset position in the next frame!
relsample = C_SAMPLERATE(n,C_SAMPLEPOS(n)); //Get the sample rate for the new buffer!
}
//Now process the buffered sound itself!
volume = C_VOLUMEPERCENT(n); //Retrieve the current volume!
sample_l = C_SAMPLE(n,C_GETSAMPLEPOS(n,0,relsample))*volume; //The composed sample, based on the relative position!
sample_r = C_SAMPLE(n,C_GETSAMPLEPOS(n,1,relsample))*volume; //The composed sample, based on the relative position!
++C_SAMPLEPOS(n); //Next position on each channel!
//Next, add the data to the mixer!
result_l += sample_l; //Mix the channels equally together based on volume!
multi_l *= sample_l; //Multi based on volume!
result_r += sample_r; //See above!
multi_r *= sample_r; //See above!
}
}
if (!--channelsleft) break; //Stop searching if nothing left!
++n; //Next channel!
}
//Final calculations!
multi_l *= SHORTY; //Set the limit!
multi_r *= SHORTY; //Set the limit!
result_l -= multi_l; //Final step in mixing: all channels equally!
result_r -= multi_r; //Final step in mixing: all channels equally!
//Now we have: (a+...)-((a*...)/MAXVAL), where MAXVAL is 256,65536 etc. depending on the type.
res->l = result_l; //Left channel!
res->r = result_r; //Right channel!
}
|