📄 mplayer.c
字号:
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->main.panning!=PAN_SURROUND)) { a->main.panning+=((a->main.panning*((SLONG)i->rpanvar* (SLONG)getrandom(512)))/25600); if (a->main.panning<PAN_LEFT) a->main.panning=PAN_LEFT; else if (a->main.panning>PAN_RIGHT) a->main.panning=PAN_RIGHT; } } } a->wantedperiod=a->tmpperiod= GetPeriod(mod->flags, (UWORD)a->main.note<<1,a->speed); a->main.keyoff=KEY_KICK; } }}/* Handles effects */void pt_EffectsPass1(MODULE *mod){ SWORD channel; MP_CONTROL *a; MP_VOICE *aout; int explicitslides; for (channel=0;channel<mod->numchn;channel++) { a=&mod->control[channel]; if ((aout=a->slave)) { a->main.fadevol=aout->main.fadevol; a->main.period=aout->main.period; if (a->main.kick==KICK_KEYOFF) a->main.keyoff=aout->main.keyoff; } if (!a->row) continue; UniSetRow(a->row); a->ownper=a->ownvol=0; explicitslides = pt_playeffects(mod, channel, a); /* continue volume slide if necessary for XM and IT */ if (mod->flags&UF_BGSLIDES) { if (!explicitslides && a->sliding) DoS3MVolSlide(mod->vbtick, mod->flags, a, 0); else if (a->tmpvolume) a->sliding = explicitslides; } if (!a->ownper) a->main.period=a->tmpperiod; if (!a->ownvol) a->volume=a->tmpvolume; if (a->main.s) { if (a->main.i) a->main.outvolume= (a->volume*a->main.s->globvol*a->main.i->globvol)>>10; else a->main.outvolume=(a->volume*a->main.s->globvol)>>4; if (a->main.outvolume>256) a->main.outvolume=256; else if (a->main.outvolume<0) a->main.outvolume=0; } }}/* NNA management */void pt_NNA(MODULE *mod){ SWORD channel; MP_CONTROL *a; for (channel=0;channel<mod->numchn;channel++) { a=&mod->control[channel]; if (a->main.kick==KICK_NOTE) { BOOL kill=0; if (a->slave) { MP_VOICE *aout; aout=a->slave; if (aout->main.nna & NNA_MASK) { /* Make sure the old MP_VOICE channel knows it has no master now ! */ a->slave=NULL; /* assume the channel is taken by NNA */ aout->mflag=0; switch (aout->main.nna) { case NNA_CONTINUE: /* continue note, do nothing */ break; case NNA_OFF: /* note off */ aout->main.keyoff|=KEY_OFF; if ((!(aout->main.volflg & EF_ON))|| (aout->main.volflg & EF_LOOP)) aout->main.keyoff=KEY_KILL; break; case NNA_FADE: aout->main.keyoff |= KEY_FADE; break; } } } if (a->dct!=DCT_OFF) { int t; for (t=0;t<md_sngchn;t++) if ((!Voice_Stopped_internal(t))&& (mod->voice[t].masterchn==channel)&& (a->main.sample==
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -