📄 mplayer.c
字号:
{
DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/2));
return 0;
}
static int DoMEDEffectF2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
DoEEffects(tick, flags, a, mod, channel, 0xd0|(mod->sngspd/2));
return 0;
}
static int DoMEDEffectF3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/3));
return 0;
}
/*========== Oktalyzer effects */
static int DoOktArp(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat, dat2;
dat2 = UniGetByte(); /* arpeggio style */
dat = UniGetByte();
if (!tick) {
if (!dat && (flags & UF_ARPMEM))
dat=a->arpmem;
else
a->arpmem=dat;
}
if (a->main.period)
DoArpeggio(tick, flags, a, dat2);
return 0;
}
/*========== General player functions */
static int DoNothing(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UniSkipOpcode();
return 0;
}
typedef int (*effect_func) (UWORD, UWORD, MP_CONTROL *, MODULE *, SWORD);
static effect_func effects[UNI_LAST] = {
DoNothing, /* 0 */
DoNothing, /* UNI_NOTE */
DoNothing, /* UNI_INSTRUMENT */
DoPTEffect0, /* UNI_PTEFFECT0 */
DoPTEffect1, /* UNI_PTEFFECT1 */
DoPTEffect2, /* UNI_PTEFFECT2 */
DoPTEffect3, /* UNI_PTEFFECT3 */
DoPTEffect4, /* UNI_PTEFFECT4 */
DoPTEffect5, /* UNI_PTEFFECT5 */
DoPTEffect6, /* UNI_PTEFFECT6 */
DoPTEffect7, /* UNI_PTEFFECT7 */
DoPTEffect8, /* UNI_PTEFFECT8 */
DoPTEffect9, /* UNI_PTEFFECT9 */
DoPTEffectA, /* UNI_PTEFFECTA */
DoPTEffectB, /* UNI_PTEFFECTB */
DoPTEffectC, /* UNI_PTEFFECTC */
DoPTEffectD, /* UNI_PTEFFECTD */
DoPTEffectE, /* UNI_PTEFFECTE */
DoPTEffectF, /* UNI_PTEFFECTF */
DoS3MEffectA, /* UNI_S3MEFFECTA */
DoS3MEffectD, /* UNI_S3MEFFECTD */
DoS3MEffectE, /* UNI_S3MEFFECTE */
DoS3MEffectF, /* UNI_S3MEFFECTF */
DoS3MEffectI, /* UNI_S3MEFFECTI */
DoS3MEffectQ, /* UNI_S3MEFFECTQ */
DoS3MEffectR, /* UNI_S3MEFFECTR */
DoS3MEffectT, /* UNI_S3MEFFECTT */
DoS3MEffectU, /* UNI_S3MEFFECTU */
DoKeyOff, /* UNI_KEYOFF */
DoKeyFade, /* UNI_KEYFADE */
DoVolEffects, /* UNI_VOLEFFECTS */
DoPTEffect4, /* UNI_XMEFFECT4 */
DoXMEffect6, /* UNI_XMEFFECT6 */
DoXMEffectA, /* UNI_XMEFFECTA */
DoXMEffectE1, /* UNI_XMEFFECTE1 */
DoXMEffectE2, /* UNI_XMEFFECTE2 */
DoXMEffectEA, /* UNI_XMEFFECTEA */
DoXMEffectEB, /* UNI_XMEFFECTEB */
DoXMEffectG, /* UNI_XMEFFECTG */
DoXMEffectH, /* UNI_XMEFFECTH */
DoXMEffectL, /* UNI_XMEFFECTL */
DoXMEffectP, /* UNI_XMEFFECTP */
DoXMEffectX1, /* UNI_XMEFFECTX1 */
DoXMEffectX2, /* UNI_XMEFFECTX2 */
DoITEffectG, /* UNI_ITEFFECTG */
DoITEffectH, /* UNI_ITEFFECTH */
DoITEffectI, /* UNI_ITEFFECTI */
DoITEffectM, /* UNI_ITEFFECTM */
DoITEffectN, /* UNI_ITEFFECTN */
DoITEffectP, /* UNI_ITEFFECTP */
DoITEffectT, /* UNI_ITEFFECTT */
DoITEffectU, /* UNI_ITEFFECTU */
DoITEffectW, /* UNI_ITEFFECTW */
DoITEffectY, /* UNI_ITEFFECTY */
DoNothing, /* UNI_ITEFFECTZ */
DoITEffectS0, /* UNI_ITEFFECTS0 */
DoULTEffect9, /* UNI_ULTEFFECT9 */
DoMEDSpeed, /* UNI_MEDSPEED */
DoMEDEffectF1, /* UNI_MEDEFFECTF1 */
DoMEDEffectF2, /* UNI_MEDEFFECTF2 */
DoMEDEffectF3, /* UNI_MEDEFFECTF3 */
DoOktArp, /* UNI_OKTARP */
};
static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a)
{
UWORD tick = mod->vbtick;
UWORD flags = mod->flags;
UBYTE c;
int explicitslides = 0;
effect_func f;
while((c=UniGetByte())) {
f = effects[c];
if (f != DoNothing)
a->sliding = 0;
explicitslides |= f(tick, flags, a, mod, channel);
}
return explicitslides;
}
static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat)
{
int t;
MP_VOICE *aout;
dat&=0xf;
aout=(a->slave)?a->slave:NULL;
switch (dat) {
case 0x0: /* past note cut */
for (t=0;t<md_sngchn;t++)
if (mod->voice[t].master==a)
mod->voice[t].main.fadevol=0;
break;
case 0x1: /* past note off */
for (t=0;t<md_sngchn;t++)
if (mod->voice[t].master==a) {
mod->voice[t].main.keyoff|=KEY_OFF;
if ((!(mod->voice[t].venv.flg & EF_ON))||
(mod->voice[t].venv.flg & EF_LOOP))
mod->voice[t].main.keyoff=KEY_KILL;
}
break;
case 0x2: /* past note fade */
for (t=0;t<md_sngchn;t++)
if (mod->voice[t].master==a)
mod->voice[t].main.keyoff|=KEY_FADE;
break;
case 0x3: /* set NNA note cut */
a->main.nna=(a->main.nna&~NNA_MASK)|NNA_CUT;
break;
case 0x4: /* set NNA note continue */
a->main.nna=(a->main.nna&~NNA_MASK)|NNA_CONTINUE;
break;
case 0x5: /* set NNA note off */
a->main.nna=(a->main.nna&~NNA_MASK)|NNA_OFF;
break;
case 0x6: /* set NNA note fade */
a->main.nna=(a->main.nna&~NNA_MASK)|NNA_FADE;
break;
case 0x7: /* disable volume envelope */
if (aout)
aout->main.volflg&=~EF_ON;
break;
case 0x8: /* enable volume envelope */
if (aout)
aout->main.volflg|=EF_ON;
break;
case 0x9: /* disable panning envelope */
if (aout)
aout->main.panflg&=~EF_ON;
break;
case 0xa: /* enable panning envelope */
if (aout)
aout->main.panflg|=EF_ON;
break;
case 0xb: /* disable pitch envelope */
if (aout)
aout->main.pitflg&=~EF_ON;
break;
case 0xc: /* enable pitch envelope */
if (aout)
aout->main.pitflg|=EF_ON;
break;
}
}
void pt_UpdateVoices(MODULE *mod, int max_volume)
{
SWORD envpan,envvol,envpit,channel;
UWORD playperiod;
SLONG vibval,vibdpt;
ULONG tmpvol;
MP_VOICE *aout;
INSTRUMENT *i;
SAMPLE *s;
mod->totalchn=mod->realchn=0;
for (channel=0;channel<md_sngchn;channel++) {
aout=&mod->voice[channel];
i=aout->main.i;
s=aout->main.s;
if (!s || !s->length) continue;
if (aout->main.period<40)
aout->main.period=40;
else if (aout->main.period>50000)
aout->main.period=50000;
if ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_KEYOFF)) {
Voice_Play_internal(channel,s,(aout->main.start==-1)?
((s->flags&SF_UST_LOOP)?s->loopstart:0):aout->main.start);
aout->main.fadevol=32768;
aout->aswppos=0;
}
envvol = 256;
envpan = PAN_CENTER;
envpit = 32;
if (i && ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_ENV))) {
if (aout->main.volflg & EF_ON)
envvol = StartEnvelope(&aout->venv,aout->main.volflg,
i->volpts,i->volsusbeg,i->volsusend,
i->volbeg,i->volend,i->volenv,aout->main.keyoff);
if (aout->main.panflg & EF_ON)
envpan = StartEnvelope(&aout->penv,aout->main.panflg,
i->panpts,i->pansusbeg,i->pansusend,
i->panbeg,i->panend,i->panenv,aout->main.keyoff);
if (aout->main.pitflg & EF_ON)
envpit = StartEnvelope(&aout->cenv,aout->main.pitflg,
i->pitpts,i->pitsusbeg,i->pitsusend,
i->pitbeg,i->pitend,i->pitenv,aout->main.keyoff);
if (aout->cenv.flg & EF_ON)
aout->masterperiod=GetPeriod(mod->flags,
(UWORD)aout->main.note<<1, aout->master->speed);
} else {
if (aout->main.volflg & EF_ON)
envvol = ProcessEnvelope(aout,&aout->venv,256);
if (aout->main.panflg & EF_ON)
envpan = ProcessEnvelope(aout,&aout->penv,PAN_CENTER);
if (aout->main.pitflg & EF_ON)
envpit = ProcessEnvelope(aout,&aout->cenv,32);
}
if (aout->main.kick == KICK_NOTE) {
aout->main.kick_flag = 1;
}
aout->main.kick=KICK_ABSENT;
tmpvol = aout->main.fadevol; /* max 32768 */
tmpvol *= aout->main.chanvol; /* * max 64 */
tmpvol *= aout->main.outvolume; /* * max 256 */
tmpvol /= (256 * 64); /* tmpvol is max 32768 again */
aout->totalvol = tmpvol >> 2; /* used to determine samplevolume */
tmpvol *= envvol; /* * max 256 */
tmpvol *= mod->volume; /* * max 128 */
tmpvol /= (128 * 256 * 128);
/* fade out */
if (mod->sngpos>=mod->numpos)
tmpvol=0;
else
tmpvol=(tmpvol*max_volume)/128;
if ((aout->masterchn!=-1)&& mod->control[aout->masterchn].muted)
Voice_SetVolume_internal(channel,0);
else {
Voice_SetVolume_internal(channel,tmpvol);
if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
mod->realchn++;
mod->totalchn++;
}
if (aout->main.panning==PAN_SURROUND)
Voice_SetPanning_internal(channel,PAN_SURROUND);
else
if ((mod->panflag)&&(aout->penv.flg & EF_ON))
Voice_SetPanning_internal(channel,
DoPan(envpan,aout->main.panning));
else
Voice_SetPanning_internal(channel,aout->main.panning);
if (aout->main.period && s->vibdepth)
switch (s->vibtype) {
case 0:
vibval=avibtab[s->avibpos&127];
if (aout->avibpos & 0x80) vibval=-vibval;
break;
case 1:
vibval=64;
if (aout->avibpos & 0x80) vibval=-vibval;
break;
case 2:
vibval=63-(((aout->avibpos+128)&255)>>1);
break;
default:
vibval=(((aout->avibpos+128)&255)>>1)-64;
break;
}
else
vibval=0;
if (s->vibflags & AV_IT) {
if ((aout->aswppos>>8)<s->vibdepth) {
aout->aswppos += s->vibsweep;
vibdpt=aout->aswppos;
} else
vibdpt=s->vibdepth<<8;
vibval=(vibval*vibdpt)>>16;
if (aout->mflag) {
if (!(mod->flags&UF_LINEAR)) vibval>>=1;
aout->main.period-=vibval;
}
} else {
/* do XM style auto-vibrato */
if (!(aout->main.keyoff & KEY_OFF)) {
if (aout->aswppos<s->vibsweep) {
vibdpt=(aout->aswppos*s->vibdepth)/s->vibsweep;
aout->aswppos++;
} else
vibdpt=s->vibdepth;
} else {
/* keyoff -> depth becomes 0 if final depth wasn't reached or
stays at final level if depth WAS reached */
if (aout->aswppos>=s->vibsweep)
vibdpt=s->vibdepth;
else
vibdpt=0;
}
vibval=(vibval*vibdpt)>>8;
aout->main.period-=vibval;
}
/* update vibrato position */
aout->avibpos=(aout->avibpos+s->vibrate)&0xff;
/* process pitch envelope */
playperiod=aout->main.period;
if ((aout->main.pitflg&EF_ON)&&(envpit!=32)) {
long p1;
envpit-=32;
if ((aout->main.note<<1)+envpit<=0) envpit=-(aout->main.note<<1);
p1=GetPeriod(mod->flags, ((UWORD)aout->main.note<<1)+envpit,
aout->master->speed)-aout->masterperiod;
if (p1>0) {
if ((UWORD)(playperiod+p1)<=playperiod) {
p1=0;
aout->main.keyoff|=KEY_OFF;
}
} else if (p1<0) {
if ((UWORD)(playperiod+p1)>=playperiod) {
p1=0;
aout->main.keyoff|=KEY_OFF;
}
}
playperiod+=p1;
}
if (!aout->main.fadevol) { /* check for a dead note (fadevol=0) */
Voice_Stop_internal(channel);
mod->totalchn--;
if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
mod->realchn--;
} else {
Voice_SetFrequency_internal(channel,
getfrequency(mod->flags,playperiod));
/* if keyfade, start substracting fadeoutspeed from fadevol: */
if ((i)&&(aout->main.keyoff&KEY_FADE)) {
if (aout->main.fadevol>=i->volfade)
aout->main.fadevol-=i->volfade;
else
aout->main.fadevol=0;
}
}
md_bpm=mod->bpm+mod->relspd;
if (md_bpm<32)
md_bpm=32;
else if ((!(mod->flags&UF_HIGHBPM)) && md_bpm>255)
md_bpm=255;
}
}
/* Handles new notes or instruments */
void pt_Notes(MODULE *mod)
{
SWORD channel;
MP_CONTROL *a;
UBYTE c,inst;
int tr,funky; /* funky is set to indicate note or instrument change */
for (channel=0;channel<mod->numchn;channel++) {
a=&mod->control[channel];
if (mod->sngpos>=mod->numpos) {
tr=mod->numtrk;
mod->numrow=0;
} else {
tr=mod->patterns[(mod->positions[mod->sngpos]*mod->numchn)+channel];
mod->numrow=mod->pattrows[mod->positions[mod->sngpos]];
}
a->row=(tr<mod->numtrk)?UniFindRow(mod->tracks[tr],mod->patpos):NULL;
a->newsamp=0;
if (!mod->vbtick) a->main.notedelay=0;
if (!a->row) continue;
UniSetRow(a->row);
funky=0;
while((c=UniGetByte()))
switch (c) {
case UNI_NOTE:
funky|=1;
a->oldnote=a->anote,a->anote=UniGetByte();
a->main.kick =KICK_NOTE;
a->main.start=-1;
a->sliding=0;
/* retrig tremolo and vibrato waves ? */
if (!(a->wavecontrol & 0x80)) a->trmpos=0;
if (!(a->wavecontrol & 0x08)) a->vibpos=0;
if (!a->panbwave) a->panbpos=0;
break;
case UNI_INSTRUMENT:
inst=UniGetByte();
if (inst>=mod->numins) break; /* safety valve */
funky|=2;
a->main.i=(mod->flags & UF_INST)?&mod->instruments[inst]:NULL;
a->retrig=0;
a->s3mtremor=0;
a->ultoffset=0;
a->main.sample=inst;
break;
default:
UniSkipOpcode();
break;
}
if (funky) {
INSTRUMENT *i;
SAMPLE *s;
if ((i=a->main.i)) {
if (i->samplenumber[a->anote] >= mod->numsmp) continue;
s=&mod->samples[i->samplenumber[a->anote]];
a->main.note=i->samplenote[a->anote];
} else {
a->main.note=a->anote;
s=&mod->samples[a->main.sample];
}
if (a->main.s!=s) {
a->main.s=s;
a->newsamp=a->main.period;
}
/* channel or instrument determined panning ? */
a->main.panning=mod->panning[channel];
if (s->flags & SF_OWNPAN)
a->main.panning=s->panning;
else if ((i)&&(i->flags & IF_OWNPAN))
a->main.panning=i->panning;
a->main.handle=s->handle;
a->speed=s->speed;
if (i) {
if ((mod->panflag)&&(i->flags & IF_PITCHPAN)
&&(a->main.panning!=PAN_SURROUND)){
a->main.panning+=
((a->anote-i->pitpancenter)*i->pitpansep)/8;
if (a->main.panning<PAN_LEFT)
a->main.panning=PAN_LEFT;
else if (a->main.panning>PAN_RIGHT)
a->main.panning=PAN_RIGHT;
}
a->main.pitflg=i->pitflg;
a->main.volflg=i->volflg;
a->main.panflg=i->panflg;
a->main.nna=i->nnatype;
a->dca=i->dca;
a->dct=i->dct;
} else {
a->main.pitflg=a->main.volflg=a->main.panflg=0;
a->main.nna=a->dca=0;
a->dct=DCT_OFF;
}
if (funky&2) /* instrument change */ {
/* IT random volume variations: 0:8 bit fixed, and one bit for
sign. */
a->volume=a->tmpvolume=s->volume;
if ((s)&&(i)) {
if (i->rvolvar) {
a->volume=a->tmpvolume=s->volume+
((s->volume*((SLONG)i->rvolvar*(SLONG)getrandom(512)
))/25600);
if (a->volume<0)
a->volume=a->tmpvolume=0;
else if (a->volume>64)
a->volume=a->tmpvolume=64;
}
if ((mod->panflag)&&(a->m
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -