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

📄 fmopl.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	{		/* PG */		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);		else          SLOT->Cnt += SLOT->Incr;		/* connectoion */		if(CH->FB)		{			int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB;			CH->op1_out[1] = CH->op1_out[0];			*CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1);		}		else		{			*CH->connect1 += OP_OUT(SLOT,env_out,0);		}	}else	{		CH->op1_out[1] = CH->op1_out[0];		CH->op1_out[0] = 0;	}	/* SLOT 2 */	SLOT = &CH->SLOT[SLOT2];	env_out=OPL_CALC_SLOT(SLOT);	if( env_out < EG_ENT-1 )	{		/* PG */		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);		else          SLOT->Cnt += SLOT->Incr;		/* connectoion */		outd[0] += OP_OUT(SLOT,env_out, feedback2);	}}/* ---------- calcrate rythm block ---------- */#define WHITE_NOISE_db 6.0INLINE void OPL_CALC_RH( OPL_CH *CH ){	UINT32 env_tam,env_sd,env_top,env_hh;	int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP);	INT32 tone8;	OPL_SLOT *SLOT;	int env_out;	/* BD : same as FM serial mode and output level is large */	feedback2 = 0;	/* SLOT 1 */	SLOT = &CH[6].SLOT[SLOT1];	env_out=OPL_CALC_SLOT(SLOT);	if( env_out < EG_ENT-1 )	{		/* PG */		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);		else          SLOT->Cnt += SLOT->Incr;		/* connectoion */		if(CH[6].FB)		{			int feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB;			CH[6].op1_out[1] = CH[6].op1_out[0];			feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1);		}		else		{			feedback2 = OP_OUT(SLOT,env_out,0);		}	}else	{		feedback2 = 0;		CH[6].op1_out[1] = CH[6].op1_out[0];		CH[6].op1_out[0] = 0;	}	/* SLOT 2 */	SLOT = &CH[6].SLOT[SLOT2];	env_out=OPL_CALC_SLOT(SLOT);	if( env_out < EG_ENT-1 )	{		/* PG */		if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);		else          SLOT->Cnt += SLOT->Incr;		/* connectoion */		outd[0] += OP_OUT(SLOT,env_out, feedback2)*2;	}	// SD  (17) = mul14[fnum7] + white noise	// TAM (15) = mul15[fnum8]	// TOP (18) = fnum6(mul18[fnum8]+whitenoise)	// HH  (14) = fnum7(mul18[fnum8]+whitenoise) + white noise	env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise;	env_tam=OPL_CALC_SLOT(SLOT8_1);	env_top=OPL_CALC_SLOT(SLOT8_2);	env_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise;	/* PG */	if(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE);	else             SLOT7_1->Cnt += 2*SLOT7_1->Incr;	if(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE);	else             SLOT7_2->Cnt += (CH[7].fc*8);	if(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE);	else             SLOT8_1->Cnt += SLOT8_1->Incr;	if(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE);	else             SLOT8_2->Cnt += (CH[8].fc*48);	tone8 = OP_OUT(SLOT8_2,whitenoise,0 );	/* SD */	if( env_sd < EG_ENT-1 )		outd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8;	/* TAM */	if( env_tam < EG_ENT-1 )		outd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2;	/* TOP-CY */	if( env_top < EG_ENT-1 )		outd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2;	/* HH */	if( env_hh  < EG_ENT-1 )		outd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2;}/* ----------- initialize time tabls ----------- */static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE ){	int i;	double rate;	/* make attack rate & decay rate tables */	for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;	for (i = 4;i <= 60;i++){		rate  = OPL->freqbase;						/* frequency rate */		if( i < 60 ) rate *= 1.0+(i&3)*0.25;		/* b0-1 : x1 , x1.25 , x1.5 , x1.75 */		rate *= 1<<((i>>2)-1);						/* b2-5 : shift bit */		rate *= (double)(EG_ENT<<ENV_BITS);		OPL->AR_TABLE[i] = rate / ARRATE;		OPL->DR_TABLE[i] = rate / DRRATE;	}	for (i = 60;i < 76;i++)	{		OPL->AR_TABLE[i] = EG_AED-1;		OPL->DR_TABLE[i] = OPL->DR_TABLE[60];	}#if 0	for (i = 0;i < 64 ;i++){	/* make for overflow area */		LOG(LOG_WAR,("rate %2d , ar %f ms , dr %f ms \n",i,			((double)(EG_ENT<<ENV_BITS) / OPL->AR_TABLE[i]) * (1000.0 / OPL->rate),			((double)(EG_ENT<<ENV_BITS) / OPL->DR_TABLE[i]) * (1000.0 / OPL->rate) ));	}#endif}/* ---------- generic table initialize ---------- */static int OPLOpenTable( void ){	int s,t;	double rate;	int i,j;	double pom;	/* allocate dynamic tables */	if( (TL_TABLE = malloc(TL_MAX*2*sizeof(INT32))) == NULL)		return 0;	if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL)	{		free(TL_TABLE);		return 0;	}	if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL)	{		free(TL_TABLE);		free(SIN_TABLE);		return 0;	}	if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(INT32))) == NULL)	{		free(TL_TABLE);		free(SIN_TABLE);		free(AMS_TABLE);		return 0;	}	/* make total level table */	for (t = 0;t < EG_ENT-1 ;t++){		rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20);	/* dB -> voltage */		TL_TABLE[       t] =  (int)rate;		TL_TABLE[TL_MAX+t] = -TL_TABLE[t];/*		LOG(LOG_INF,("TotalLevel(%3d) = %x\n",t,TL_TABLE[t]));*/	}	/* fill volume off area */	for ( t = EG_ENT-1; t < TL_MAX ;t++){		TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0;	}	/* make sinwave table (total level offet) */	/* degree 0 = degree 180                   = off */	SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2]         = &TL_TABLE[EG_ENT-1];	for (s = 1;s <= SIN_ENT/4;s++){		pom = sin(2*PI*s/SIN_ENT); /* sin     */		pom = 20*log10(1/pom);	   /* decibel */		j = pom / EG_STEP;         /* TL_TABLE steps */        /* degree 0   -  90    , degree 180 -  90 : plus section */		SIN_TABLE[          s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j];        /* degree 180 - 270    , degree 360 - 270 : minus section */		SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT  -s] = &TL_TABLE[TL_MAX+j];/*		LOG(LOG_INF,("sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP));*/	}	for (s = 0;s < SIN_ENT;s++)	{		SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];		SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)];		SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s];	}	/* envelope counter -> envelope output table */	for (i=0; i<EG_ENT; i++)	{		/* ATTACK curve */		pom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT;		/* if( pom >= EG_ENT ) pom = EG_ENT-1; */		ENV_CURVE[i] = (int)pom;		/* DECAY ,RELEASE curve */		ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i;	}	/* off */	ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;	/* make LFO ams table */	for (i=0; i<AMS_ENT; i++)	{		pom = (1.0+sin(2*PI*i/AMS_ENT))/2; /* sin */		AMS_TABLE[i]         = (1.0/EG_STEP)*pom; /* 1dB   */		AMS_TABLE[AMS_ENT+i] = (4.8/EG_STEP)*pom; /* 4.8dB */	}	/* make LFO vibrate table */	for (i=0; i<VIB_ENT; i++)	{		/* 100cent = 1seminote = 6% ?? */		pom = (double)VIB_RATE*0.06*sin(2*PI*i/VIB_ENT); /* +-100sect step */		VIB_TABLE[i]         = VIB_RATE + (pom*0.07); /* +- 7cent */		VIB_TABLE[VIB_ENT+i] = VIB_RATE + (pom*0.14); /* +-14cent */		/* LOG(LOG_INF,("vib %d=%d\n",i,VIB_TABLE[VIB_ENT+i])); */	}	return 1;}static void OPLCloseTable( void ){	free(TL_TABLE);	free(SIN_TABLE);	free(AMS_TABLE);	free(VIB_TABLE);}/* CSM Key Controll */INLINE void CSMKeyControll(OPL_CH *CH){	OPL_SLOT *slot1 = &CH->SLOT[SLOT1];	OPL_SLOT *slot2 = &CH->SLOT[SLOT2];	/* all key off */	OPL_KEYOFF(slot1);	OPL_KEYOFF(slot2);	/* total level latch */	slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);	slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);	/* key on */	CH->op1_out[0] = CH->op1_out[1] = 0;	OPL_KEYON(slot1);	OPL_KEYON(slot2);}/* ---------- opl initialize ---------- */static void OPL_initalize(FM_OPL *OPL){	int fn;	/* frequency base */	OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72  : 0;	/* Timer base time */	OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );	/* make time tables */	init_timetables( OPL , OPL_ARRATE , OPL_DRRATE );	/* make fnumber -> increment counter table */	for( fn=0 ; fn < 1024 ; fn++ )	{		OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2;	}	/* LFO freq.table */	OPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<<AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0;	OPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<<VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0;}/* ---------- write a OPL registers ---------- */static void OPLWriteReg(FM_OPL *OPL, int r, int v){	OPL_CH *CH;	int slot;	int block_fnum;	switch(r&0xe0)	{	case 0x00: /* 00-1f:controll */		switch(r&0x1f)		{		case 0x01:			/* wave selector enable */			if(OPL->type&OPL_TYPE_WAVESEL)			{				OPL->wavesel = v&0x20;				if(!OPL->wavesel)				{					/* preset compatible mode */					int c;					for(c=0;c<OPL->max_ch;c++)					{						OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];						OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];					}				}			}			return;		case 0x02:	/* Timer 1 */			OPL->T[0] = (256-v)*4;			break;		case 0x03:	/* Timer 2 */			OPL->T[1] = (256-v)*16;			return;		case 0x04:	/* IRQ clear / mask and Timer enable */			if(v&0x80)			{	/* IRQ flag clear */				OPL_STATUS_RESET(OPL,0x7f);			}			else			{	/* set IRQ mask ,timer enable*/				UINT8 st1 = v&1;				UINT8 st2 = (v>>1)&1;				/* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */				OPL_STATUS_RESET(OPL,v&0x78);				OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01);				/* timer 2 */				if(OPL->st[1] != st2)				{					double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0;					OPL->st[1] = st2;					if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval);				}				/* timer 1 */				if(OPL->st[0] != st1)				{					double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0;					OPL->st[0] = st1;					if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval);				}			}			return;#if BUILD_Y8950		case 0x06:		/* Key Board OUT */			if(OPL->type&OPL_TYPE_KEYBOARD)			{				if(OPL->keyboardhandler_w)					OPL->keyboardhandler_w(OPL->keyboard_param,v);				else					LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n"));			}			return;		case 0x07:	/* DELTA-T controll : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */			if(OPL->type&OPL_TYPE_ADPCM)				YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);			return;		case 0x08:	/* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */			OPL->mode = v;			v&=0x1f;	/* for DELTA-T unit */		case 0x09:		/* START ADD */		case 0x0a:		case 0x0b:		/* STOP ADD  */		case 0x0c:		case 0x0d:		/* PRESCALE   */		case 0x0e:		case 0x0f:		/* ADPCM data */		case 0x10: 		/* DELTA-N    */		case 0x11: 		/* DELTA-N    */		case 0x12: 		/* EG-CTRL    */			if(OPL->type&OPL_TYPE_ADPCM)				YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);			return;#if 0		case 0x15:		/* DAC data    */		case 0x16:		case 0x17:		/* SHIFT    */			return;		case 0x18:		/* I/O CTRL (Direction) */			if(OPL->type&OPL_TYPE_IO)				OPL->portDirection = v&0x0f;			return;		case 0x19:		/* I/O DATA */			if(OPL->type&OPL_TYPE_IO)			{				OPL->portLatch = v;				if(OPL->porthandler_w)					OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);			}			return;		case 0x1a:		/* PCM data */			return;#endif#endif		}		break;	case 0x20:	/* am,vib,ksr,eg type,mul */		slot = slot_array[r&0x1f];		if(slot == -1) return;		set_mul(OPL,slot,v);		return;	case 0x40:		slot = slot_array[r&0x1f];		if(slot == -1) return;		set_ksl_tl(OPL,slot,v);		return;	case 0x60:		slot = slot_array[r&0x1f];		if(slot == -1) return;		set_ar_dr(OPL,slot,v);		return;	case 0x80:		slot = slot_array[r&0x1f];		if(slot == -1) return;		set_sl_rr(OPL,slot,v);		return;	case 0xa0:		switch(r)		{		case 0xbd:			/* amsep,vibdep,r,bd,sd,tom,tc,hh */			{			UINT8 rkey = OPL->rythm^v;			OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];			OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];			OPL->rythm  = v&0x3f;			if(OPL->rythm&0x20)			{#if 0				usrintf_showmessage("OPL Rythm mode select");#endif				/* BD key on/off */				if(rkey&0x10)				{					if(v&0x10)					{						OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;						OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);						OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);					}					else					{						OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);						OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);					}				}				/* SD key on/off */				if(rkey&0x08)				{					if(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);					else       OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);				}/* TAM key on/off */				if(rkey&0x04)				{					if(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);					else       OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);

⌨️ 快捷键说明

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