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

📄 mplayer.c

📁 这是著名的TCPMP播放器在WINDWOWS,和WINCE下编译通过的源程序.笔者对其中的LIBMAD库做了针对ARM MPU的优化. 并增加了词幕功能.
💻 C
📖 第 1 页 / 共 5 页
字号:
{
	DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/2));

	return 0;
}

static int DoMEDEffectF2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
	DoEEffects(tick, flags, a, mod, channel, 0xd0|(mod->sngspd/2));

	return 0;
}

static int DoMEDEffectF3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
	DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/3));

	return 0;
}

/*========== Oktalyzer effects */

static int DoOktArp(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
	UBYTE dat, dat2;

	dat2 = UniGetByte();	/* arpeggio style */
	dat = UniGetByte();
	if (!tick) {
		if (!dat && (flags & UF_ARPMEM))
			dat=a->arpmem;
		else
			a->arpmem=dat;
	}
	if (a->main.period)
		DoArpeggio(tick, flags, a, dat2);

	return 0;
}

/*========== General player functions */

static int DoNothing(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
{
	UniSkipOpcode();

	return 0;
}

typedef int (*effect_func) (UWORD, UWORD, MP_CONTROL *, MODULE *, SWORD);

static effect_func effects[UNI_LAST] = {
		DoNothing,		/* 0 */
		DoNothing,		/* UNI_NOTE */
		DoNothing,		/* UNI_INSTRUMENT */
		DoPTEffect0,	/* UNI_PTEFFECT0 */
		DoPTEffect1,	/* UNI_PTEFFECT1 */
		DoPTEffect2,	/* UNI_PTEFFECT2 */
		DoPTEffect3,	/* UNI_PTEFFECT3 */
		DoPTEffect4,	/* UNI_PTEFFECT4 */
		DoPTEffect5,	/* UNI_PTEFFECT5 */
		DoPTEffect6,	/* UNI_PTEFFECT6 */
		DoPTEffect7,	/* UNI_PTEFFECT7 */
		DoPTEffect8,	/* UNI_PTEFFECT8 */
		DoPTEffect9,	/* UNI_PTEFFECT9 */
		DoPTEffectA,	/* UNI_PTEFFECTA */
		DoPTEffectB,	/* UNI_PTEFFECTB */
		DoPTEffectC,	/* UNI_PTEFFECTC */
		DoPTEffectD,	/* UNI_PTEFFECTD */
		DoPTEffectE,	/* UNI_PTEFFECTE */
		DoPTEffectF,	/* UNI_PTEFFECTF */
		DoS3MEffectA,	/* UNI_S3MEFFECTA */
		DoS3MEffectD,	/* UNI_S3MEFFECTD */
		DoS3MEffectE,	/* UNI_S3MEFFECTE */
		DoS3MEffectF,	/* UNI_S3MEFFECTF */
		DoS3MEffectI,	/* UNI_S3MEFFECTI */
		DoS3MEffectQ,	/* UNI_S3MEFFECTQ */
		DoS3MEffectR,	/* UNI_S3MEFFECTR */
		DoS3MEffectT,	/* UNI_S3MEFFECTT */
		DoS3MEffectU,	/* UNI_S3MEFFECTU */
		DoKeyOff,		/* UNI_KEYOFF */
		DoKeyFade,		/* UNI_KEYFADE */
		DoVolEffects,	/* UNI_VOLEFFECTS */
		DoPTEffect4,	/* UNI_XMEFFECT4 */
		DoXMEffect6,	/* UNI_XMEFFECT6 */
		DoXMEffectA,	/* UNI_XMEFFECTA */
		DoXMEffectE1,	/* UNI_XMEFFECTE1 */
		DoXMEffectE2,	/* UNI_XMEFFECTE2 */
		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->m

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -