📄 mplayer.c
字号:
break;
case 5: /* okt arpeggio 5: N-x, N+y, N, and nothing at tick 0 */
if (!tick)
break;
switch (tick % 3) {
/* case 0: unchanged */
case 1:
note -= (a->arpmem >> 4);
break;
case 2:
note += (a->arpmem & 0xf);
break;
}
break;
}
a->main.period = GetPeriod(flags, (UWORD)note << 1, a->speed);
a->ownper = 1;
}
}
static int DoPTEffect0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat = UniGetByte();
if (!tick) {
if (!dat && (flags & UF_ARPMEM))
dat=a->arpmem;
else
a->arpmem=dat;
}
if (a->main.period)
DoArpeggio(tick, flags, a, 0);
return 0;
}
static int DoPTEffect1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat = UniGetByte();
if (!tick && dat)
a->slidespeed = (UWORD)dat << 2;
if (a->main.period)
if (tick)
a->tmpperiod -= a->slidespeed;
return 0;
}
static int DoPTEffect2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat = UniGetByte();
if (!tick && dat)
a->slidespeed = (UWORD)dat << 2;
if (a->main.period)
if (tick)
a->tmpperiod += a->slidespeed;
return 0;
}
static void DoToneSlide(UWORD tick, MP_CONTROL *a)
{
if (!a->main.fadevol)
a->main.kick = (a->main.kick == KICK_NOTE)? KICK_NOTE : KICK_KEYOFF;
else
a->main.kick = (a->main.kick == KICK_NOTE)? KICK_ENV : KICK_ABSENT;
if (tick != 0) {
int dist;
/* We have to slide a->main.period towards a->wantedperiod, so compute
the difference between those two values */
dist=a->main.period-a->wantedperiod;
/* if they are equal or if portamentospeed is too big ...*/
if (dist == 0 || a->portspeed > abs(dist))
/* ...make tmpperiod equal tperiod */
a->tmpperiod=a->main.period=a->wantedperiod;
else if (dist>0) {
a->tmpperiod-=a->portspeed;
a->main.period-=a->portspeed; /* dist>0, slide up */
} else {
a->tmpperiod+=a->portspeed;
a->main.period+=a->portspeed; /* dist<0, slide down */
}
} else
a->tmpperiod=a->main.period;
a->ownper = 1;
}
static int DoPTEffect3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat=UniGetByte();
if ((!tick)&&(dat)) a->portspeed=(UWORD)dat<<2;
if (a->main.period)
DoToneSlide(tick, a);
return 0;
}
static void DoVibrato(UWORD tick, MP_CONTROL *a)
{
UBYTE q;
UWORD temp = 0; /* silence warning */
if (!tick)
return;
q=(a->vibpos>>2)&0x1f;
switch (a->wavecontrol&3) {
case 0: /* sine */
temp=VibratoTable[q];
break;
case 1: /* ramp down */
q<<=3;
if (a->vibpos<0) q=255-q;
temp=q;
break;
case 2: /* square wave */
temp=255;
break;
case 3: /* random wave */
temp=getrandom(256);
break;
}
temp*=a->vibdepth;
temp>>=7;temp<<=2;
if (a->vibpos>=0)
a->main.period=a->tmpperiod+temp;
else
a->main.period=a->tmpperiod-temp;
a->ownper = 1;
if (tick != 0)
a->vibpos+=a->vibspd;
}
static int DoPTEffect4(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat=UniGetByte();
if (!tick) {
if (dat&0x0f) a->vibdepth=dat&0xf;
if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
}
if (a->main.period)
DoVibrato(tick, a);
return 0;
}
static void DoVolSlide(MP_CONTROL *a, UBYTE dat)
{
if (dat&0xf) {
a->tmpvolume-=(dat&0x0f);
if (a->tmpvolume<0)
a->tmpvolume=0;
} else {
a->tmpvolume+=(dat>>4);
if (a->tmpvolume>64)
a->tmpvolume=64;
}
}
static int DoPTEffect5(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat=UniGetByte();
if (a->main.period)
DoToneSlide(tick, a);
if (tick)
DoVolSlide(a, dat);
return 0;
}
/* DoPTEffect6 after DoPTEffectA */
static int DoPTEffect7(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
UBYTE q;
UWORD temp = 0; /* silence warning */
dat=UniGetByte();
if (!tick) {
if (dat&0x0f) a->trmdepth=dat&0xf;
if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
}
if (a->main.period) {
q=(a->trmpos>>2)&0x1f;
switch ((a->wavecontrol>>4)&3) {
case 0: /* sine */
temp=VibratoTable[q];
break;
case 1: /* ramp down */
q<<=3;
if (a->trmpos<0) q=255-q;
temp=q;
break;
case 2: /* square wave */
temp=255;
break;
case 3: /* random wave */
temp=getrandom(256);
break;
}
temp*=a->trmdepth;
temp>>=6;
if (a->trmpos>=0) {
a->volume=a->tmpvolume+temp;
if (a->volume>64) a->volume=64;
} else {
a->volume=a->tmpvolume-temp;
if (a->volume<0) a->volume=0;
}
a->ownvol = 1;
if (tick)
a->trmpos+=a->trmspd;
}
return 0;
}
static int DoPTEffect8(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat = UniGetByte();
if (mod->panflag)
a->main.panning = mod->panning[channel] = dat;
return 0;
}
static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat=UniGetByte();
if (!tick) {
if (dat) a->soffset=(UWORD)dat<<8;
a->main.start=a->hioffset|a->soffset;
if ((a->main.s)&&(a->main.start>a->main.s->length))
a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
a->main.s->loopstart:a->main.s->length;
}
return 0;
}
static int DoPTEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat=UniGetByte();
if (tick)
DoVolSlide(a, dat);
return 0;
}
static int DoPTEffect6(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
if (a->main.period)
DoVibrato(tick, a);
DoPTEffectA(tick, flags, a, mod, channel);
return 0;
}
static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat=UniGetByte();
if (tick || mod->patdly2)
return 0;
/* Vincent Voois uses a nasty trick in "Universal Bolero" */
if (dat == mod->sngpos && mod->patbrk == mod->patpos)
return 0;
if (!mod->loop && !mod->patbrk &&
(dat < mod->sngpos ||
(mod->sngpos == (mod->numpos - 1) && !mod->patbrk) ||
(dat == mod->sngpos && (flags & UF_NOWRAP))
)) {
/* if we don't loop, better not to skip the end of the
pattern, after all... so:
mod->patbrk=0; */
mod->posjmp=3;
} else {
/* if we were fading, adjust... */
if (mod->sngpos == (mod->numpos-1))
mod->volume=mod->initvolume>128?128:mod->initvolume;
mod->sngpos=dat;
mod->posjmp=2;
mod->patpos=0;
}
return 0;
}
static int DoPTEffectC(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat=UniGetByte();
if (tick) return 0;
if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */
else if (dat>64) dat=64;
a->tmpvolume=dat;
return 0;
}
static int DoPTEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat=UniGetByte();
if ((tick)||(mod->patdly2)) return 0;
if ((mod->positions[mod->sngpos]!=LAST_PATTERN)&&
(dat>mod->pattrows[mod->positions[mod->sngpos]]))
dat=mod->pattrows[mod->positions[mod->sngpos]];
mod->patbrk=dat;
if (!mod->posjmp) {
/* don't ask me to explain this code - it makes
backwards.s3m and children.xm (heretic's version) play
correctly, among others. Take that for granted, or write
the page of comments yourself... you might need some
aspirin - Miod */
if ((mod->sngpos==mod->numpos-1)&&(dat)&&((mod->loop)||
(mod->positions[mod->sngpos]==(mod->numpat-1)
&& !(flags&UF_NOWRAP)))) {
mod->sngpos=0;
mod->posjmp=2;
} else
mod->posjmp=3;
}
return 0;
}
static void DoEEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod,
SWORD channel, UBYTE dat)
{
UBYTE nib = dat & 0xf;
switch (dat>>4) {
case 0x0: /* hardware filter toggle, not supported */
break;
case 0x1: /* fineslide up */
if (a->main.period)
if (!tick)
a->tmpperiod-=(nib<<2);
break;
case 0x2: /* fineslide dn */
if (a->main.period)
if (!tick)
a->tmpperiod+=(nib<<2);
break;
case 0x3: /* glissando ctrl */
a->glissando=nib;
break;
case 0x4: /* set vibrato waveform */
a->wavecontrol&=0xf0;
a->wavecontrol|=nib;
break;
case 0x5: /* set finetune */
if (a->main.period) {
if (flags&UF_XMPERIODS)
a->speed=nib+128;
else
a->speed=finetune[nib];
a->tmpperiod=GetPeriod(flags, (UWORD)a->main.note<<1,a->speed);
}
break;
case 0x6: /* set patternloop */
if (tick)
break;
if (nib) { /* set reppos or repcnt ? */
/* set repcnt, so check if repcnt already is set, which means we
are already looping */
if (a->pat_repcnt)
a->pat_repcnt--; /* already looping, decrease counter */
else {
#if 0
/* this would make walker.xm, shipped with Xsoundtracker,
play correctly, but it's better to remain compatible
with FT2 */
if ((!(flags&UF_NOWRAP))||(a->pat_reppos!=POS_NONE))
#endif
a->pat_repcnt=nib; /* not yet looping, so set repcnt */
}
if (a->pat_repcnt) { /* jump to reppos if repcnt>0 */
if (a->pat_reppos==POS_NONE)
a->pat_reppos=mod->patpos-1;
if (a->pat_reppos==-1) {
mod->pat_repcrazy=1;
mod->patpos=0;
} else
mod->patpos=a->pat_reppos;
} else a->pat_reppos=POS_NONE;
} else
a->pat_reppos=mod->patpos-1; /* set reppos - can be (-1) */
break;
case 0x7: /* set tremolo waveform */
a->wavecontrol&=0x0f;
a->wavecontrol|=nib<<4;
break;
case 0x8: /* set panning */
if (mod->panflag) {
if (nib<=8) nib<<=4;
else nib*=17;
a->main.panning=mod->panning[channel]=nib;
}
break;
case 0x9: /* retrig note */
/* do not retrigger on tick 0, until we are emulating FT2 and effect
data is zero */
if (!tick && !((flags & UF_FT2QUIRKS) && (!nib)))
break;
/* only retrigger if data nibble > 0, or if tick 0 (FT2 compat) */
if (nib || !tick) {
if (!a->retrig) {
/* when retrig counter reaches 0, reset counter and restart
the sample */
if (a->main.period) a->main.kick=KICK_NOTE;
a->retrig=nib;
}
a->retrig--; /* countdown */
}
break;
case 0xa: /* fine volume slide up */
if (tick)
break;
a->tmpvolume+=nib;
if (a->tmpvolume>64) a->tmpvolume=64;
break;
case 0xb: /* fine volume slide dn */
if (tick)
break;
a->tmpvolume-=nib;
if (a->tmpvolume<0)a->tmpvolume=0;
break;
case 0xc: /* cut note */
/* When tick reaches the cut-note value, turn the volume to
zero (just like on the amiga) */
if (tick>=nib)
a->tmpvolume=0; /* just turn the volume down */
break;
case 0xd: /* note delay */
/* delay the start of the sample until tick==nib */
if (!tick)
a->main.notedelay=nib;
else if (a->main.notedelay)
a->main.notedelay--;
break;
case 0xe: /* pattern delay */
if (!tick)
if (!mod->patdly2)
mod->patdly=nib+1; /* only once, when tick=0 */
break;
case 0xf: /* invert loop, not supported */
break;
}
}
static int DoPTEffectE(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
DoEEffects(tick, flags, a, mod, channel, UniGetByte());
return 0;
}
static int DoPTEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE dat;
dat=UniGetByte();
if (tick||mod->patdly2) return 0;
if (mod->extspd&&(dat>=mod->bpmlimit))
mod->bpm=dat;
else
if (dat) {
mod->sngspd=(dat>=mod->bpmlimit)?mod->bpmlimit-1:dat;
mod->vbtick=0;
}
return 0;
}
/*========== Scream Tracker effects */
static int DoS3MEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
UBYTE speed;
speed = UniGetByte();
if (tick || mod->patdly2)
return 0;
if (speed > 128)
speed -= 128;
if (speed) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -