⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mplayer.c

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 C
📖 第 1 页 / 共 5 页
字号:
			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 + -