Skip to content

Instantly share code, notes, and snippets.

@iamgreaser
Created September 6, 2011 23:12
Show Gist options
  • Save iamgreaser/1199267 to your computer and use it in GitHub Desktop.
Save iamgreaser/1199267 to your computer and use it in GitHub Desktop.
How not to make a mixer (.it player component I've since polished up)
void do_channel(struct fatmodule *mod, int idx, SLONG *buf)
{
SWORD v = 0;
int pan;
int mch = (mod->chn[idx].master == -1 ? idx : mod->chn[idx].master);
if(!mod->chn[idx].tperiod)
mod->chn[idx].tperiod = mod->chn[idx].period;
if(mod->chn[idx].tperiod && mod->smpdata[mod->chn[idx].sample].b != NULL)
{
v = (
mod->smplist[mod->chn[idx].sample].flags & 0x02
? mod->smpdata[mod->chn[idx].sample].w[mod->chn[idx].pos]
: mod->smpdata[mod->chn[idx].sample].b[mod->chn[idx].pos] << 8
);
if(mod->chn[idx].tvol == 0xFF)
mod->chn[idx].tvol = mod->chn[idx].rvol;
if(mod->chn[idx].flags & FC_MIXME)
if(
mod->chn[idx].tvol
&& mod->smplist[mod->chn[idx].sample].gv
&& !(mod->impm.chanpan[mch] & 0x80)
)
{
v = (v * mod->chn[idx].tvol * mod->smplist[mod->chn[idx].sample].gv) / (64 * 64);
v = (v * mod->impm.chanvol[mch]) / 64;
pan = mod->chn[idx].pan;
if(mod->impm.flags & 0x0004)
{
if(mod->inslist[mod->chn[idx].cinstr-1].env[0].flg & 0x01)
v = (v * mod->chn[idx].ey[0]) / 64;
if(mod->inslist[mod->chn[idx].cinstr-1].env[1].flg & 0x01)
pan = ((pan - 32) * mod->chn[idx].ey[1]) / 64 + 32;
v = (v * mod->inslist[mod->chn[idx].cinstr-1].gv) / 128;
v = (v * mod->chn[idx].nfc) / 1024;
}
//if(mod->chn[idx].master != -1)
// printf("%02X %04X\n", idx, (UWORD)v);
//printf("%04X\n", (UWORD)v);
if(v)
{
if(mod->impm.chanpan[mch] == 100 || pan == 100)
{
buf[0] += v;
buf[1] -= v;
} else if(pan < 32) {
buf[0] += (v * pan) >> 5;
buf[1] += v;
} else {
buf[0] += v;
buf[1] += (v * (64 - pan)) >> 5;
}
}
}
if(mod->chn[idx].flags & FC_REVERSE)
{
mod->chn[idx].subpos -= mod->chn[idx].tperiod;
while(mod->chn[idx].subpos < 0)
{
mod->chn[idx].pos--;
mod->chn[idx].subpos += mod->bfreq;
}
} else {
mod->chn[idx].subpos += mod->chn[idx].tperiod;
/*while(mod->chn[idx].subpos >= mod->bfreq)
{
mod->chn[idx].pos++;
mod->chn[idx].subpos -= mod->bfreq;
}*/
mod->chn[idx].pos += mod->chn[idx].subpos / mod->bfreq;
mod->chn[idx].subpos %= mod->bfreq;
}
//printf("pos %08X/%08X\n", mod->chn[idx].pos, mod->chn[idx].subpos);
if(mod->chn[idx].flags & FC_DOLOOP)
{
if(mod->chn[idx].pos >= mod->chn[idx].lpend && !(mod->chn[idx].flags & FC_REVERSE))
{
if(mod->chn[idx].flags & FC_BIDI)
{
mod->chn[idx].pos = mod->chn[idx].lpend-1;
mod->chn[idx].flags |= FC_REVERSE;
//printf("<==\n");
} else {
mod->chn[idx].pos = mod->chn[idx].lpbeg;
}
mod->chn[idx].subpos = 0;
} else if(mod->chn[idx].pos <= mod->chn[idx].lpbeg
&& (mod->chn[idx].flags & FC_REVERSE)) {
if(mod->chn[idx].flags & FC_BIDI)
{
mod->chn[idx].pos = mod->chn[idx].lpbeg+1;
mod->chn[idx].flags &= ~FC_REVERSE;
//printf("==>\n");
} else {
while(mod->chn[idx].pos > mod->chn[idx].lpend)
mod->chn[idx].pos -= mod->chn[idx].lpend-mod->chn[idx].lpbeg;
//mod->chn[idx].pos = mod->chn[idx].lpend-1;
}
//mod->chn[idx].subpos = 0;
}
}
if(mod->chn[idx].pos >= mod->smplist[mod->chn[idx].sample].len)
{
//mod->chn[idx].period = 0;
//printf("\e[1mbuh %i\e[0m\n",idx);
mod->chn[idx].flags &= ~(FC_PLAYING|FC_MIXME);
}
}
}
// * SNIP *
int len = (bfreq*5)/(mod->tempo*2);
SLONG mixbuf[2];
//printf("S/T %03i/%03i\n", mod->speed, mod->tempo);
for(i = 0; i < len; i++)
{
wbuf[i*2+1] = wbuf[i*2] = 0;
mixbuf[0] = mixbuf[1] = 0;
for(j = 0; j < 256; j++)
{
if(mod->chn[j].flags & FC_PLAYING)
do_channel(mod, j, &mixbuf[0]);
}
mixbuf[0] = (mixbuf[0] * mod->impm.mv) >> 7;
mixbuf[1] = (mixbuf[1] * mod->impm.mv) >> 7;
mixbuf[0] = (mixbuf[0] * mod->impm.gv) >> 7;
mixbuf[1] = (mixbuf[1] * mod->impm.gv) >> 7;
mixbuf[0] -= mixbuf_offs[0];
mixbuf[1] -= mixbuf_offs[1];
if(mixbuf[0] > 0x7FFF)
{
mixbuf_offs[0] += mixbuf[0]-0x7FFF;
mixbuf[0] = 0x7FFF;
}
if(mixbuf[1] > 0x7FFF)
{
mixbuf_offs[1] += mixbuf[1]-0x7FFF;
mixbuf[1] = 0x7FFF;
}
if(mixbuf[0] < -0x7FFF)
{
mixbuf_offs[0] += mixbuf[0]+0x7FFF;
mixbuf[0] = -0x7FFF;
}
if(mixbuf[1] < -0x7FFF)
{
mixbuf_offs[1] += mixbuf[1]+0x7FFF;
mixbuf[1] = -0x7FFF;
}
if(mixbuf_offs[0] < 0)
{
mixbuf_offs[0] = -((-mixbuf_offs[0]*7)>>3);
} else {
mixbuf_offs[0] = (mixbuf_offs[0]*7)>>3;
}
if(mixbuf_offs[1] < 0)
{
mixbuf_offs[1] = -((-mixbuf_offs[1]*7)>>3);
} else {
mixbuf_offs[1] = (mixbuf_offs[1]*7)>>3;
}
wbuf[i*2] = (SWORD)mixbuf[0];
wbuf[i*2+1] = (SWORD)mixbuf[1];
}
mod->tick++;
if(mod->tick >= mod->speed)
mod->tick = -1;
write(dsp, &wbuf[0], channels*2*len);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment