📄 mod.c
字号:
i->pansusend, i->panbeg, i->panend, i->panenv, aout->keyoff); StartEnvelope (&aout->cenv, aout->pitflg, i->pitpts, i->pitsusbeg, i->pitsusend, i->pitbeg, i->pitend, i->pitenv, aout->keyoff); if (aout->cenv.flg & EF_ON) aout->masterperiod = GetPeriod ((UWORD) aout->note << 1, aout->master->speed); } aout->kick = KICK_ABSENT; envvol = (!(aout->volflg & EF_ON)) ? 256 : ProcessEnvelope (&aout->venv, 256, aout->keyoff); envpan = (!(aout->panflg & EF_ON)) ? PAN_CENTER : ProcessEnvelope (&aout->penv, PAN_CENTER, aout->keyoff); envpit = (!(aout->pitflg & EF_ON)) ? 32 : ProcessEnvelope (&aout->cenv, 32, aout->keyoff); tmpvol = aout->fadevol; /* max 32768 */ tmpvol *= aout->chanvol; /* * max 64 */ tmpvol *= aout->volume; /* * max 256 */ tmpvol /= 16384L; /* tmpvol is max 32768 */ aout->totalvol = tmpvol >> 2; /* totalvolume used to determine samplevolume */ tmpvol *= envvol; /* * max 256 */ tmpvol *= mp.volume; /* * max 128 */ tmpvol /= 4194304UL; Voice_SetVolume (mp.channel, tmpvol); if ((tmpvol) && (aout->master) && (aout->master->slave == aout)) mp.realchn++; mp.totalchn++; if (aout->panning == PAN_SURROUND) Voice_SetPanning (mp.channel, PAN_SURROUND); else if (aout->penv.flg & EF_ON) Voice_SetPanning (mp.channel, DoPan (envpan, aout->panning)); else Voice_SetPanning (mp.channel, aout->panning); if (aout->period && s->vibdepth) switch (s->vibtype) { case 0: vibval = avibtab[aout->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 (!(pf->flags & UF_LINEAR)) vibval >>= 1; aout->period -= vibval; } } else { /* do XM style auto-vibrato */ if (!(aout->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->period -= vibval; } /* update vibrato position */ aout->avibpos = (aout->avibpos + s->vibrate) & 0xff; /* process pitch envelope */ playperiod = aout->period; if ((aout->pitflg & EF_ON) && (envpit != 32)) { long p1; envpit -= 32; if ((aout->note << 1) + envpit <= 0) envpit = -(aout->note << 1); p1 = GetPeriod (((UWORD) aout->note << 1) + envpit, aout->master->speed) - aout->masterperiod; if (p1 > 0) { if ((UWORD) (playperiod + p1) <= playperiod) { p1 = 0; aout->keyoff |= KEY_OFF; } } else if (p1 < 0) { if ((UWORD) (playperiod + p1) >= playperiod) { p1 = 0; aout->keyoff |= KEY_OFF; } } playperiod += p1; } if (!aout->fadevol) { /* check for a dead note (fadevol=0) */ mp.totalchn--; if ((tmpvol) && (aout->master) && (aout->master->slave == aout)) mp.realchn--; } else { Voice_SetPeriod (mp.channel, getAmigaPeriod (pf->flags, playperiod)); if (kick_voice) Voice_Play (mp.channel, s, (aout->start == -1) ? ((s->flags & SF_UST_LOOP) ? s->loopstart : 0) : aout->start); /* if keyfade, start substracting fadeoutspeed from fadevol: */ if ((i) && (aout->keyoff & KEY_FADE)) { if (aout->fadevol >= i->volfade) aout->fadevol -= i->volfade; else aout->fadevol = 0; } } if (mp.bpm != mp.newbpm || mp.sngspd != mp.oldsngspd) { mp.bpm = mp.newbpm; mp.oldsngspd = mp.sngspd; Voice_NewTempo(mp.bpm, mp.sngspd); } }}/* Handles new notes or instruments */static void pt_Notes (void){ UBYTE c, inst; int tr, funky; /* funky is set to indicate note or instrument change */ for (mp.channel = 0; mp.channel < pf->numchn; mp.channel++) { a = &mp.control[mp.channel]; if (mp.sngpos >= pf->numpos) { tr = pf->numtrk; mp.numrow = 0; } else { tr = pf->patterns[(pf->positions[mp.sngpos] * pf->numchn) + mp.channel]; mp.numrow = pf->pattrows[pf->positions[mp.sngpos]]; } a->row = (tr < pf->numtrk) ? UniFindRow (pf->tracks[tr], mp.patpos) : NULL; a->newsamp = 0; if (!mp.vbtick) a->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->kick = KICK_NOTE; a->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 >= pf->numins) break; /* safety valve */ funky |= 2; a->i = (pf->flags & UF_INST) ? &pf->instruments[inst] : NULL; a->retrig = 0; a->s3mtremor = 0; a->ultoffset = 0; a->sample = inst; break; default: UniSkipOpcode (c); break; } if (funky) { INSTRUMENT *i; SAMPLE *s; i = a->i; if (i) { if (i->samplenumber[a->anote] >= pf->numsmp) continue; s = &pf->samples[i->samplenumber[a->anote]]; a->note = i->samplenote[a->anote]; } else { a->note = a->anote; s = &pf->samples[a->sample]; } if (a->s != s) { a->s = s; a->newsamp = a->period; } /* channel or instrument determined panning ? */ a->panning = pf->panning[mp.channel]; if (s->flags & SF_OWNPAN) a->panning = s->panning; else if ((i) && (i->flags & IF_OWNPAN)) a->panning = i->panning; a->data = s->data; a->speed = s->speed; if (i) { if ((i->flags & IF_PITCHPAN) && (a->panning != PAN_SURROUND)) { a->panning += ((a->anote - i->pitpancenter) * i->pitpansep) / 8; if (a->panning < PAN_LEFT) a->panning = PAN_LEFT; else if (a->panning > PAN_RIGHT) a->panning = PAN_RIGHT; } a->pitflg = i->pitflg; a->volflg = i->volflg; a->panflg = i->panflg; a->nna = i->nnatype; a->dca = i->dca; a->dct = i->dct; } else { a->pitflg = 0; a->volflg = 0; a->panflg = 0; a->nna = 0; 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 ((a->panning != PAN_SURROUND)) { a->panning += ((a->panning * ((SLONG) i->rpanvar * (SLONG) getrandom (512))) / 25600); if (a->panning < PAN_LEFT) a->panning = PAN_LEFT; else if (a->panning > PAN_RIGHT) a->panning = PAN_RIGHT; } } } a->wantedperiod = a->tmpperiod = GetPeriod ((UWORD) a->note << 1, a->speed); a->keyoff = KEY_KICK; } }}/* Handles effects */static void pt_EffectsPass1 (void){ MP_VOICE *aout; for (mp.channel = 0; mp.channel < pf->numchn; mp.channel++) { a = &mp.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; mp.explicitslides = 0; pt_playeffects (); /* continue volume slide if necessary for XM and IT */ if (pf->flags & UF_BGSLIDES) { if (!mp.explicitslides && a->sliding) DoS3MVolSlide(0); else if (a->tmpvolume) a->sliding = mp.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 */static void pt_NNA (void){ for (mp.channel = 0; mp.channel < pf->numchn; mp.channel++) { a = &mp.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 < MOD_NUM_VOICES; t++) if ((!Voice_Stopped (t)) && (mp.voice[t].masterchn == mp.channel) && (a->sample == mp.voice[t].sample)) { k = 0; switch (a->dct) { case DCT_NOTE: if (a->note == mp.voice[t].note) k = 1; break; case DCT_SAMPLE: if (a->data == mp.voice[t].data) k = 1; break; case DCT_INST: k = 1; break; } if (k) switch (a->dca) { case DCA_CUT: mp.voice[t].fadevol = 0; break; case DCA_OFF: mp.voice[t].keyoff |= KEY_OFF; if ((!(mp.voice[t].volflg & EF_ON)) || (mp.voice[t].volflg & EF_LOOP)) mp.voice[t].keyoff = KEY_KILL; break; case DCA_FADE: mp.voice[t].keyoff |= KEY_FADE; break; } } } } /* if (a->kick==KICK_NOTE) */ }}/* Setup module and NNA voices */static void pt_SetupVoices (void){ MP_VOICE *aout; for (mp.channel = 0; mp.channel < pf->numchn; mp.channel++) { a = &mp.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 = &mp.voice[a->slavechn = newchn]; } } else a->slave = &mp.voice[a->slavechn = mp.channel]; /* assign parts of MP_VOICE only done for a KICK_NOTE */ if ((aout = a->slave)) { if (aout->mflag && aout->master) aout->master->slave = NULL; aout->master = a; a->slave = aout; aout->masterchn = mp.channel; aout->mflag = 1; } } else aout = a->slave; if (aout) { aout->i = a->i; aout->s = a->s; aout->sample = a->sample; aout->data = a->data; aout->period = a->period; aout->panning = a->panning; aout->chanvol = a->chanvol; aout->fadevol = a->fadevol; aout->kick = a->kick; 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 */static void pt_EffectsPass2 (void){ UBYTE c; for (mp.channel = 0; mp.channel < pf->numchn; mp.channel++) { a = &mp.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); }}static BOOL HandleTick (void){ if ((!pf) || (mp.sngpos >= pf->numpos)) return 0; if (++mp.vbtick >= mp.sngspd) { if (mp.pat_repcrazy) mp.pat_repcrazy = 0; /* play 2 times row 0 */ else mp.patpos++; mp.vbtick = 0; /* process pattern-delay. mp.patdly2 is the counter and mp.patdly is the command memory. */ if (mp.patdly) mp.patdly2 = mp.patdly, mp.pat
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -