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

📄 mplayer.c

📁 SDL_mixer 是一个基于 SDL 的混音器
💻 C
📖 第 1 页 / 共 5 页
字号:
			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 + -