📄 mplayer.c
字号:
a->wantedperiod=a->tmpperiod=GetPeriod((UWORD)a->note<<1,a->speed); a->keyoff=KEY_KICK; } }}/* Handles effects */void pt_EffectsPass1(void){ MP_VOICE *aout; for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) { a=&pf->control[mp_channel]; if ((aout=a->slave)) { a->fadevol=aout->fadevol; a->period=aout->period; if (a->kick==KICK_KEYOFF) a->keyoff=aout->keyoff; } if (!a->row) continue; UniSetRow(a->row); a->ownper=a->ownvol=0; explicitslides=0; pt_playeffects(); /* continue volume slide if necessary for XM and IT */ if (pf->flags&UF_BGSLIDES) { if (!explicitslides) switch (a->sliding) { case 1: DoS3MVolSlide(0); break; case 2: DoXMVolSlide(0); break; } else if (a->tmpvolume) a->sliding=explicitslides; } if (!a->ownper) a->period=a->tmpperiod; if (!a->ownvol) a->volume=a->tmpvolume; if (a->s) { if (a->i) a->outvolume=(a->volume*a->s->globvol*a->i->globvol)>>10; else a->outvolume=(a->volume*a->s->globvol)>>4; if (a->outvolume>256)a->volume=256; else if (a->outvolume<0) a->outvolume=0; } }}/* NNA management */void pt_NNA(void){ for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) { a=&pf->control[mp_channel]; if (a->kick==KICK_NOTE) { BOOL k=0; if (a->slave) { MP_VOICE *aout; aout=a->slave; if (aout->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->nna) { case NNA_CONTINUE: /* continue note, do nothing */ break; case NNA_OFF: /* note off */ aout->keyoff|=KEY_OFF; if ((!(aout->volflg & EF_ON))||(aout->volflg & EF_LOOP)) aout->keyoff=KEY_KILL; break; case NNA_FADE: aout->keyoff |= KEY_FADE; break; } } } if (a->dct!=DCT_OFF) { int t; for (t=0;t<md_sngchn;t++) if ((!Voice_Stopped_internal(t))&& (pf->voice[t].masterchn==mp_channel)&& (a->sample==pf->voice[t].sample)) { k=0; switch (a->dct) { case DCT_NOTE: if (a->note==pf->voice[t].note) k=1; break; case DCT_SAMPLE: if (a->handle==pf->voice[t].handle) k=1; break; case DCT_INST: k=1; break; } if (k) switch (a->dca) { case DCA_CUT: pf->voice[t].fadevol=0; break; case DCA_OFF: pf->voice[t].keyoff|=KEY_OFF; if ((!(pf->voice[t].volflg&EF_ON))|| (pf->voice[t].volflg&EF_LOOP)) pf->voice[t].keyoff=KEY_KILL; break; case DCA_FADE: pf->voice[t].keyoff|=KEY_FADE; break; } } } } /* if (a->kick==KICK_NOTE) */ }}/* Setup module and NNA voices */void pt_SetupVoices(void){ MP_VOICE *aout; for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) { a=&pf->control[mp_channel]; if (a->notedelay) continue; if (a->kick==KICK_NOTE) { /* if no channel was cut above, find an empty or quiet channel here */ if (pf->flags&UF_NNA) { if (!a->slave) { int newchn; if ((newchn=MP_FindEmptyChannel())!=-1) a->slave=&pf->voice[a->slavechn=newchn]; } } else a->slave=&pf->voice[a->slavechn=mp_channel]; /* assign parts of MP_VOICE only done for a KICK ! */ if ((aout=a->slave)) { if (aout->mflag && aout->master) aout->master->slave=NULL; a->slave=aout; aout->master=a; aout->masterchn=mp_channel; aout->mflag=1; } } else aout=a->slave; if (aout) { aout->kick=a->kick; aout->i=a->i; aout->s=a->s; aout->sample=a->sample; aout->handle=a->handle; aout->period=a->period; aout->panning=a->panning; aout->chanvol=a->chanvol; aout->fadevol=a->fadevol; aout->start=a->start; aout->volflg=a->volflg; aout->panflg=a->panflg; aout->pitflg=a->pitflg; aout->volume=a->outvolume; aout->keyoff=a->keyoff; aout->note=a->note; aout->nna=a->nna; } a->kick=KICK_ABSENT; }}/* second effect pass */void pt_EffectsPass2(void){ UBYTE c; for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) { a=&pf->control[mp_channel]; if (!a->row) continue; UniSetRow(a->row); while((c=UniGetByte())) if (c==UNI_ITEFFECTS0) { c=UniGetByte(); if ((c>>4)==SS_S7EFFECTS) DoNNAEffects(c&0xf); } else UniSkipOpcode(c); }}void Player_HandleTick(void){ int max_volume;#if 0 /* don't handle the very first ticks, this allows the other hardware to settle down so we don't loose any starting notes */ if (isfirst) { isfirst--; return; }#endif if ((!pf)||(pf->forbid)||(pf->sngpos>=pf->numpos)) return; /* update time counter (sngtime is in milliseconds (in fact 2^-10)) */ pf->sngremainder+=(1<<9)*5; /* thus 2.5*(1<<10), since fps=0.4xtempo */ pf->sngtime+=pf->sngremainder/pf->bpm; pf->sngremainder%=pf->bpm; if (++pf->vbtick>=pf->sngspd) { if (pf->pat_repcrazy) pf->pat_repcrazy=0; /* play 2 times row 0 */ else pf->patpos++; pf->vbtick=0; /* process pattern-delay. pf->patdly2 is the counter and pf->patdly is the command memory. */ if (pf->patdly) pf->patdly2=pf->patdly,pf->patdly=0; if (pf->patdly2) { /* patterndelay active */ if (--pf->patdly2) /* so turn back pf->patpos by 1 */ if (pf->patpos) pf->patpos--; } /* do we have to get a new patternpointer ? (when pf->patpos reaches the pattern size, or when a patternbreak is active) */ if (((pf->patpos>=pf->numrow)&&(pf->numrow>0))&&(!pf->posjmp)) pf->posjmp=3; if (pf->posjmp) { pf->patpos=pf->numrow?(pf->patbrk%pf->numrow):0; pf->pat_repcrazy=0; pf->sngpos+=(pf->posjmp-2); for (mp_channel=0;mp_channel<pf->numchn;mp_channel++) pf->control[mp_channel].pat_reppos=-1; pf->patbrk=pf->posjmp=0; /* handle the "---" (end of song) pattern since it can occur *inside* the module in .IT and .S3M */ if ((pf->sngpos>=pf->numpos)||(pf->positions[pf->sngpos]==255)) { if (!pf->wrap) return; if (!(pf->sngpos=pf->reppos)) { pf->volume=pf->initvolume>128?128:pf->initvolume; pf->sngspd=pf->initspeed?(pf->initspeed<32?pf->initspeed:32):6; pf->bpm=pf->inittempo<32?32:pf->inittempo; } } if (pf->sngpos<0) pf->sngpos=pf->numpos-1; } if (!pf->patdly2) pt_Notes(); } if (((pf->sngpos==pf->numpos-1)||(pf->positions[pf->sngpos+1]==255))&& (pf->fadeout)) max_volume=pf->numrow?((pf->numrow-pf->patpos)*128)/pf->numrow:0; else max_volume=128; pt_EffectsPass1(); if (pf->flags&UF_NNA) pt_NNA(); pt_SetupVoices(); pt_EffectsPass2(); /* now set up the actual hardware channel playback information */ pt_UpdateVoices(max_volume);}static void Player_Init_internal(MODULE* mf){ int t; for (t=0;t<mf->numchn;t++) { mf->control[t].chanvol=mf->chanvol[t]; mf->control[t].panning=mf->panning[t]; } mf->sngtime=0; mf->sngremainder=0; mf->pat_repcrazy=0; mf->sngpos=0; mf->sngspd=mf->initspeed?(mf->initspeed<32?mf->initspeed:32):6; mf->volume=mf->initvolume>128?128:mf->initvolume; mf->vbtick=mf->sngspd; mf->patdly=0; mf->patdly2=0; mf->bpm=mf->inittempo<32?32:mf->inittempo; mf->realchn=0; mf->patpos=0; mf->posjmp=2; /* make sure the player fetches the first note */ mf->numrow=-1; mf->patbrk=0;}BOOL Player_Init(MODULE* mf){ mf->extspd=1; mf->panflag=1; mf->wrap=0; mf->loop=1; mf->fadeout=0; mf->relspd=0; /* make sure the player doesn't start with garbage */ if (!(mf->control=(MP_CONTROL*)_mm_calloc(mf->numchn,sizeof(MP_CONTROL)))) return 1; if (!(mf->voice=(MP_VOICE*)_mm_calloc(md_sngchn,sizeof(MP_VOICE)))) return 1; Player_Init_internal(mf); return 0;}void Player_Exit_internal(MODULE* mf){ if (!mf) return; if (mf==pf) { Player_Stop_internal(); pf=NULL; } if (mf->control) free(mf->control); if (mf->voice) free(mf->voice); mf->control=NULL; mf->voice=NULL;}void Player_Exit(MODULE* mf){ MUTEX_LOCK(vars); Player_Exit_internal(mf); MUTEX_UNLOCK(vars);}void Player_SetVolume(SWORD volume){ MUTEX_LOCK(vars); if (pf) pf->volume=pf->initvolume=(volume<0)?0:(volume>128)?128:volume; MUTEX_UNLOCK(vars);}MODULE* Player_GetModule(void){ MODULE* result; MUTEX_LOCK(vars); result=pf; MUTEX_UNLOCK(vars); return result;}void Player_Start(MODULE *mf){ int t; if (!mf) return; if (!MikMod_Active()) MikMod_EnableOutput(); mf->forbid=0; MUTEX_LOCK(vars); if (pf!=mf) { /* new song is being started, so completely stop out the old one. */ if (pf) pf->forbid=1; for (t=0;t<md_sngchn;t++) Voice_Stop_internal(t); } pf=mf; MUTEX_UNLOCK(vars);}void Player_Stop_internal(void){ if (!md_sfxchn) MikMod_DisableOutput_internal(); if (pf) pf->forbid=1; pf=NULL;}void Player_Stop(void){ MUTEX_LOCK(vars); Player_Stop_internal(); MUTEX_UNLOCK(vars);}BOOL Player_Active(void){ BOOL result=0; MUTEX_LOCK(vars); if (pf) result=(!(pf->sngpos>=pf->numpos)); MUTEX_UNLOCK(vars); return result;}void Player_NextPosition(void){ MUTEX_LOCK(vars); if (pf) { int t; pf->forbid=1; pf->posjmp=3; pf->patbrk=0; pf->vbtick=pf->sngspd; for (t=0;t<md_sngchn;t++) { Voice_Stop_internal(t); pf->voice[t].i=NULL; pf->voice[t].s=NULL; } for (t=0;t<pf->numchn;t++) { pf->control[t].i=NULL; pf->control[t].s=NULL; } pf->forbid=0; } MUTEX_UNLOCK(vars);}void Player_PrevPosition(void){ MUTEX_LOCK(vars); if (pf) { int t; pf->forbid=1; pf->posjmp=1; pf->patbrk=0; pf->vbtick=pf->sngspd; for (t=0;t<md_sngchn;t++) { Voice_Stop_internal(t); pf->voice[t].i=NULL; pf->voice[t].s=NULL; } for (t=0;t<pf->numchn;t++) { pf->control[t].i=NULL; pf->control[t].s=NULL; } pf->forbid=0; } MUTEX_UNLOCK(vars);}void Player_SetPosition(UWORD pos){ MUTEX_LOCK(vars); if (pf) { int t; pf->forbid=1; if (pos>=pf->numpos) pos=pf->numpos; pf->posjmp=2; pf->patbrk=0; pf->sngpos=pos; pf->vbtick=pf->sngspd; for (t=0;t<md_sngchn;t++) { Voice_Stop_internal(t); pf->voice[t].i=NULL; pf->voice[t].s=NULL; } for (t=0;t<pf->numchn;t++) { pf->control[t].i=NULL; pf->control[t].s=NULL; } pf->forbid=0; if (!pos) Player_Init_internal(pf); } MUTEX_UNLOCK(vars);}static void Player_Unmute_internal(SLONG arg1,va_list ap){ SLONG t,arg2,arg3=0; if (pf) { switch (arg1) { case MUTE_INCLUSIVE: if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))|| (arg2>arg3)||(arg3>=pf->numchn)) return; for (;arg2<pf->numchn && arg2<=arg3;arg2++) pf->control[arg2].muted=0; break; case MUTE_EXCLUSIVE: if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))|| (arg2>arg3)||(arg3>=pf->numchn)) return; for (t=0;t<pf->numchn;t++) { if ((t>=arg2) && (t<=arg3)) continue; pf->control[t].muted=0; } break; default: if (arg1<pf->numchn) pf->control[arg1].muted=0; break; } }}void Player_Unmute(SLONG arg1, ...){ va_list args; va_start(args,arg1); MUTEX_LOCK(vars); Player_Unm
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -