📄 mplayer.c
字号:
UBYTE q; UWORD temp=0; q=(a->vibpos>>2)&0x1f; switch (a->wavecontrol&3) { case 0: /* sine */ temp=VibratoTable[q]; break; case 1: /* square wave */ temp=255; break; case 2: /* ramp down */ q<<=3; if (a->vibpos<0) q=255-q; temp=q; break; case 3: /* random */ temp=getrandom(256); break; } temp*=a->vibdepth; temp>>=8; temp<<=2; if (a->vibpos>=0) a->period=a->tmpperiod+temp; else a->period=a->tmpperiod-temp; a->vibpos+=a->vibspd;}static void DoITFineVibrato(void){ UBYTE q; UWORD temp=0; q=(a->vibpos>>2)&0x1f; switch (a->wavecontrol&3) { case 0: /* sine */ temp=VibratoTable[q]; break; case 1: /* square wave */ temp=255; break; case 2: /* ramp down */ q<<=3; if (a->vibpos<0) q=255-q; temp=q; break; case 3: /* random */ temp=getrandom(256); break; } temp*=a->vibdepth; temp>>=8; if (a->vibpos>=0) a->period=a->tmpperiod+temp; else a->period=a->tmpperiod-temp; a->vibpos+=a->vibspd;}static void DoITTremor(UBYTE inf){ UBYTE on,off; if (inf) a->s3mtronof=inf; else { inf=a->s3mtronof; if (!inf) return; } if (!pf->vbtick) return; on=(inf>>4); off=(inf&0xf); a->s3mtremor%=(on+off); a->volume=(a->s3mtremor<on)?a->tmpvolume:0; a->s3mtremor++;}static void DoITPanbrello(void){ UBYTE q; SLONG temp=0; q=a->panbpos; switch (a->panbwave) { case 0: /* sine */ temp=PanbrelloTable[q]; break; case 1: /* square wave */ temp=(q<0x80)?64:0; break; case 2: /* ramp down */ q<<=3; temp=q; break; case 3: /* random */ if (a->panbpos>=a->panbspd) { a->panbpos=0; temp=getrandom(256); } } temp*=a->panbdepth; temp=(temp/8)+pf->panning[mp_channel]; a->panning=(temp<PAN_LEFT)?PAN_LEFT:(temp>PAN_RIGHT?PAN_RIGHT:temp); a->panbpos+=a->panbspd;}static void DoITToneSlide(void){ /* if we don't come from another note, ignore the slide and play the note as is */ if (!a->oldnote) return; if (pf->vbtick) { int dist; /* We have to slide a->period towards a->wantedperiod, compute the difference between those two values */ dist=a->period-a->wantedperiod; /* if they are equal or if portamentospeed is too big... */ if ((!dist)||((a->portspeed<<2)>abs(dist))) /* ... make tmpperiod equal tperiod */ a->tmpperiod=a->period=a->wantedperiod; else if (dist>0) { a->tmpperiod-=a->portspeed<<2; a->period-=a->portspeed<<2; /* dist>0 slide up */ } else { a->tmpperiod+=a->portspeed<<2; a->period+=a->portspeed<<2; /* dist<0 slide down */ } } else a->tmpperiod=a->period;}static void DoNNAEffects(UBYTE dat);/* Impulse/Scream Tracker Sxx effects. All Sxx effects share the same memory space. */static void DoSSEffects(UBYTE dat){ UBYTE inf,c; inf=dat&0xf; c=dat>>4; if (!dat) { c=a->sseffect; inf=a->ssdata; } else { a->sseffect=c; a->ssdata=inf; } switch (c) { case SS_GLISSANDO: /* S1x set glissando voice */ DoEEffects(0x30|inf); break; case SS_FINETUNE: /* S2x set finetune */ DoEEffects(0x50|inf); break; case SS_VIBWAVE: /* S3x set vibrato waveform */ DoEEffects(0x40|inf); break; case SS_TREMWAVE: /* S4x set tremolo waveform */ DoEEffects(0x70|inf); break; case SS_PANWAVE: /* S5x panbrello */ a->panbwave=inf; break; case SS_FRAMEDELAY: /* S6x delay x number of frames (patdly) */ DoEEffects(0xe0|inf); break; case SS_S7EFFECTS: /* S7x instrument / NNA commands */ DoNNAEffects(inf); break; case SS_PANNING: /* S8x set panning position */ DoEEffects(0x80 | inf); break; case SS_SURROUND: /* S9x set surround Sound */ if (pf->panflag) a->panning=pf->panning[mp_channel]=PAN_SURROUND; break; case SS_HIOFFSET: /* SAy set high order sample offset yxx00h */ if (!pf->vbtick) { a->hioffset=inf<<16; a->start=a->hioffset|a->soffset; if ((a->s)&&(a->start>a->s->length)) a->start=a->s->flags&(SF_LOOP|SF_BIDI)?a->s->loopstart:a->s->length; } break; case SS_PATLOOP: /* SBx pattern loop */ DoEEffects(0x60|inf); break; case SS_NOTECUT: /* SCx notecut */ DoEEffects(0xC0|inf); break; case SS_NOTEDELAY: /* SDx notedelay */ DoEEffects(0xD0|inf); break; case SS_PATDELAY: /* SEx patterndelay */ DoEEffects(0xE0|inf); break; }}/* Impulse Tracker Volume/Pan Column effects. All volume/pan column effects share the same memory space. */static void DoVolEffects(UBYTE c){ UBYTE inf=UniGetByte(); if ((!c)&&(!inf)) { c=a->voleffect; inf=a->voldata; } else { a->voleffect=c; a->voldata=inf; } if (c) switch (c) { case VOL_VOLUME: if (pf->vbtick) break; if (inf>64) inf=64; a->tmpvolume=inf; break; case VOL_PANNING: if (pf->panflag) a->panning=/*pf->panning[mp_channel]=*/inf; break; case VOL_VOLSLIDE: DoS3MVolSlide(inf); break; case VOL_PITCHSLIDEDN: if (a->period) DoS3MSlideDn(inf); break; case VOL_PITCHSLIDEUP: if (a->period) DoS3MSlideUp(inf); break; case VOL_PORTAMENTO: if (inf) a->slidespeed=inf; if (a->period) { if ((!pf->vbtick)||(a->newsamp)){ a->kick=KICK_NOTE; a->start=-1; } else a->kick=(a->kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT; DoITToneSlide(); a->ownper=1; } break; case VOL_VIBRATO: if (!pf->vbtick) { if (inf&0x0f) a->vibdepth=inf&0xf; if (inf&0xf0) a->vibspd=(inf&0xf0)>>2; } if (a->period) { DoITVibrato(); a->ownper=1; } break; }}/*========== UltraTracker effects */static void DoULTSampleOffset(void){ UWORD offset=UniGetWord(); if (offset) a->ultoffset=offset; a->start=a->ultoffset<<2; if ((a->s)&&(a->start>a->s->length)) a->start=a->s->flags&(SF_LOOP|SF_BIDI)?a->s->loopstart:a->s->length;}/*========== OctaMED effects */static void DoMEDSpeed(void){ UWORD speed=UniGetWord(); pf->bpm=speed;}/*========== General player functions */static void pt_playeffects(void){ UBYTE dat,c; while((c=UniGetByte())) { int oldsliding=a->sliding; a->sliding=0; switch (c) { case UNI_NOTE: case UNI_INSTRUMENT: a->sliding=oldsliding; UniSkipOpcode(c); break; case UNI_PTEFFECT0: dat=UniGetByte(); if (!pf->vbtick) { if ((!dat)&&(pf->flags&UF_ARPMEM)) dat=a->arpmem; a->arpmem=dat; } if (a->period) DoArpeggio(a->arpmem); break; case UNI_PTEFFECT1: dat=UniGetByte(); if ((!pf->vbtick)&&(dat)) a->slidespeed=(UWORD)dat<<2; if (a->period) if (pf->vbtick) a->tmpperiod-=a->slidespeed; break; case UNI_PTEFFECT2: dat=UniGetByte(); if ((!pf->vbtick)&&(dat)) a->slidespeed=(UWORD)dat<<2; if (a->period) if (pf->vbtick) a->tmpperiod+=a->slidespeed; break; case UNI_PTEFFECT3: dat=UniGetByte(); if ((!pf->vbtick)&&(dat)) a->portspeed=(UWORD)dat<<2; if (a->period) { if (!a->fadevol) a->kick=(a->kick==KICK_NOTE)?KICK_NOTE:KICK_KEYOFF; else a->kick=(a->kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT; DoToneSlide(); a->ownper=1; } break; case UNI_PTEFFECT4: case UNI_XMEFFECT4: dat=UniGetByte(); if (!pf->vbtick) { if (dat&0x0f) a->vibdepth=dat&0xf; if (dat&0xf0) a->vibspd=(dat&0xf0)>>2; } else if (a->period) { DoVibrato(); a->ownper=1; } break; case UNI_PTEFFECT5: dat=UniGetByte(); if (a->period) { if (!a->fadevol) a->kick=(a->kick==KICK_NOTE)?KICK_NOTE:KICK_KEYOFF; else a->kick=(a->kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT; DoToneSlide(); a->ownper=1; } DoVolSlide(dat); break; case UNI_PTEFFECT6: dat=UniGetByte(); if ((a->period)&&(pf->vbtick)) { DoVibrato(); a->ownper=1; } DoVolSlide(dat); break; case UNI_PTEFFECT7: dat=UniGetByte(); if (!pf->vbtick) { if (dat&0x0f) a->trmdepth=dat&0xf; if (dat&0xf0) a->trmspd=(dat&0xf0)>>2; } if (a->period) { DoTremolo(); a->ownvol=1; } break; case UNI_PTEFFECT8: dat=UniGetByte(); if (pf->panflag) a->panning=pf->panning[mp_channel]=dat; break; case UNI_PTEFFECT9: dat=UniGetByte(); if (!pf->vbtick) { if (dat) a->soffset=(UWORD)dat<<8; a->start=a->hioffset|a->soffset; if ((a->s)&&(a->start>a->s->length)) a->start=a->s->flags&(SF_LOOP|SF_BIDI)?a->s->loopstart:a->s->length; } break; case UNI_PTEFFECTA: DoVolSlide(UniGetByte()); break; case UNI_PTEFFECTB: dat=UniGetByte(); if ((pf->vbtick)||(pf->patdly2)) break; /* Vincent Voois uses a nasty trick in "Universal Bolero" */ if (dat==pf->sngpos && pf->patbrk==pf->patpos) break; if ((!pf->loop)&&(!pf->patbrk)&&((dat<pf->sngpos)|| ((pf->sngpos==pf->numpos-1)&&(!pf->patbrk))|| ((dat==pf->sngpos)&&(pf->flags&UF_NOWRAP)))) { /* if we don't loop, better not to skip the end of the pattern, after all... so: pf->patbrk=0; */ pf->posjmp=3; } else { /* if we were fading, adjust... */ if (pf->sngpos==(pf->numpos-1)) pf->volume=pf->initvolume>128?128:pf->initvolume; pf->sngpos=dat; pf->posjmp=2; pf->patpos=0; } break; case UNI_PTEFFECTC: dat=UniGetByte(); if (pf->vbtick) break; if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */ else if (dat>64) dat=64; a->tmpvolume=dat; break; case UNI_PTEFFECTD: dat=UniGetByte(); if ((pf->vbtick)||(pf->patdly2)) break; if ((pf->positions[pf->sngpos]!=255)&& (dat>pf->pattrows[pf->positions[pf->sngpos]])) dat=pf->pattrows[pf->positions[pf->sngpos]]; pf->patbrk=dat; if (!pf->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 ((pf->sngpos==pf->numpos-1)&&(dat)&&((pf->loop)|| (pf->positions[pf->sngpos]==(pf->numpat-1) && !(pf->flags&UF_NOWRAP)))) { pf->sngpos=0; pf->posjmp=2; } else pf->posjmp=3; } break; case UNI_PTEFFECTE: DoEEffects(UniGetByte()); break; case UNI_PTEFFECTF: dat=UniGetByte(); if (pf->vbtick||pf->patdly2) break; if (pf->extspd&&(dat>=0x20)) pf->bpm=dat; else if (dat) { pf->sngspd=(dat>32)?32:dat; pf->vbtick=0; } break; case UNI_S3MEFFECTA: DoS3MSpeed(UniGetByte()); break; case UNI_S3MEFFECTD: DoS3MVolSlide(UniGetByte()); break; case UNI_S3MEFFECTE: dat=UniGetByte(); if (a->period) DoS3MSlideDn(dat); break; case UNI_S3MEFFECTF: dat=UniGetByte(); if (a->period) DoS3MSlideUp(dat); break; case UNI_S3MEFFECTI: DoS3MTremor(UniGetByte()); a->ownvol=1; break; case UNI_S3MEFFECTQ: dat=UniGetByte(); if (a->period) DoS3MRetrig(dat); break; case UNI_S3MEFFECTR: dat=UniGetByte(); if (!pf->vbtick) { if (dat&0x0f) a->trmdepth=dat&0xf; if (dat&0xf0) a->trmspd=(dat&0xf0)>>2; } DoS3MTremolo(); a->ownvol=1; break; case UNI_S3MEFFECTT: DoS3MTempo(UniGetByte()); break; case UNI_S3MEFFECTU: dat=UniGetByte(); if (!pf->vbtick) { if (dat&0x0f) a->vibdepth=dat&0xf; if (dat&0xf0) a->vibspd=(dat&0xf0)>>2; } else if (a->period) { DoS3MFineVibrato(); a->ownper=1; } break; case UNI_KEYOFF: a->keyoff|=KEY_OFF; if ((!(a->volflg&EF_ON))||(a->volflg&EF_LOOP)) a->keyoff=KEY_KILL; break; case UNI_KEYFADE: dat=UniGetByte(); if ((pf->vbtick>=dat)||(pf->vbtick==pf->sngspd-1)) { a->keyoff=KEY_KILL; if (!(a->volflg&EF_ON)) a->fadevol=0; } break; case UNI_VOLEFFECTS: DoVolEffects(UniGetByte()); break; case UNI_XMEFFECTA: DoXMVolSlide(UniGetByte()); break; case UNI_XMEFFECTE1: /* XM fineslide up */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -