📄 fmopl.c.bak
字号:
}
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]);
}
/* TOP-CY key on/off */
if(rkey&0x02)
{
if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
}
/* HH key on/off */
if(rkey&0x01)
{
if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
}
}
}
return;
}
/* keyon,block,fnum */
if( (r&0x0f) > 8) return;
CH = &OPL->P_CH[r&0x0f];
if(!(r&0x10))
{ /* a0-a8 */
block_fnum = (CH->block_fnum&0x1f00) | v;
}
else
{ /* b0-b8 */
int keyon = (v>>5)&1;
block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
if(CH->keyon != keyon)
{
if( (CH->keyon=keyon) )
{
CH->op1_out[0] = CH->op1_out[1] = 0;
OPL_KEYON(&CH->SLOT[SLOT1]);
OPL_KEYON(&CH->SLOT[SLOT2]);
}
else
{
OPL_KEYOFF(&CH->SLOT[SLOT1]);
OPL_KEYOFF(&CH->SLOT[SLOT2]);
}
}
}
/* update */
if(CH->block_fnum != block_fnum)
{
int blockRv = 7-(block_fnum>>10);
int fnum = block_fnum&0x3ff;
CH->block_fnum = block_fnum;
CH->ksl_base = KSL_TABLE[block_fnum>>6];
CH->fc = OPL->FN_TABLE[fnum]>>blockRv;
CH->kcode = CH->block_fnum>>9;
if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1;
CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
}
return;
case 0xc0:
/* FB,C */
if( (r&0x0f) > 8) return;
CH = &OPL->P_CH[r&0x0f];
{
int feedback = (v>>1)&7;
CH->FB = feedback ? (8+1) - feedback : 0;
CH->CON = v&1;
set_algorythm(CH);
}
return;
case 0xe0: /* wave type */
slot = slot_array[r&0x1f];
if(slot == -1) return;
CH = &OPL->P_CH[slot/2];
if(OPL->wavesel)
{
/* Log(LOG_INF,"OPL SLOT %d wave select %d\n",slot,v&3); */
CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT];
}
return;
}
}
/* lock/unlock for common table */
static int OPL_LockTable(void)
{
num_lock++;
if(num_lock>1) return 0;
/* first time */
cur_chip = NULL;
/* allocate total level table (128kb space) */
if( !OPLOpenTable() )
{
num_lock--;
return -1;
}
return 0;
}
static void OPL_UnLockTable(void)
{
if(num_lock) num_lock--;
if(num_lock) return;
/* last time */
cur_chip = NULL;
OPLCloseTable();
}
#if (BUILD_YM3812 || BUILD_YM3526)
/*******************************************************************************/
/* YM3812 local section */
/*******************************************************************************/
/* ---------- update one of chip ----------- */
void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
{
int i;
int data;
FMSAMPLE *buf = buffer;
UINT32 amsCnt = OPL->amsCnt;
UINT32 vibCnt = OPL->vibCnt;
UINT8 rythm = OPL->rythm&0x20;
OPL_CH *CH,*R_CH;
if( (void *)OPL != cur_chip ){
cur_chip = (void *)OPL;
/* channel pointers */
S_CH = OPL->P_CH;
E_CH = &S_CH[9];
/* rythm slot */
SLOT7_1 = &S_CH[7].SLOT[SLOT1];
SLOT7_2 = &S_CH[7].SLOT[SLOT2];
SLOT8_1 = &S_CH[8].SLOT[SLOT1];
SLOT8_2 = &S_CH[8].SLOT[SLOT2];
/* LFO state */
amsIncr = OPL->amsIncr;
vibIncr = OPL->vibIncr;
ams_table = OPL->ams_table;
vib_table = OPL->vib_table;
}
R_CH = rythm ? &S_CH[6] : E_CH;
for( i=0; i < length ; i++ )
{
/* channel A channel B channel C */
/* LFO */
ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
outd[0] = 0;
/* FM part */
for(CH=S_CH ; CH < R_CH ; CH++)
OPL_CALC_CH(CH);
/* Rythn part */
if(rythm)
OPL_CALC_RH(S_CH);
/* limit check */
data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
/* store to sound buffer */
buf[i] = data >> OPL_OUTSB;
}
OPL->amsCnt = amsCnt;
OPL->vibCnt = vibCnt;
}
#endif /* (BUILD_YM3812 || BUILD_YM3526) */
#if BUILD_Y8950
void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
{
int i;
int data;
FMSAMPLE *buf = buffer;
UINT32 amsCnt = OPL->amsCnt;
UINT32 vibCnt = OPL->vibCnt;
UINT8 rythm = OPL->rythm&0x20;
OPL_CH *CH,*R_CH;
YM_DELTAT *DELTAT = OPL->deltat;
/* setup DELTA-T unit */
YM_DELTAT_DECODE_PRESET(DELTAT);
if( (void *)OPL != cur_chip ){
cur_chip = (void *)OPL;
/* channel pointers */
S_CH = OPL->P_CH;
E_CH = &S_CH[9];
/* rythm slot */
SLOT7_1 = &S_CH[7].SLOT[SLOT1];
SLOT7_2 = &S_CH[7].SLOT[SLOT2];
SLOT8_1 = &S_CH[8].SLOT[SLOT1];
SLOT8_2 = &S_CH[8].SLOT[SLOT2];
/* LFO state */
amsIncr = OPL->amsIncr;
vibIncr = OPL->vibIncr;
ams_table = OPL->ams_table;
vib_table = OPL->vib_table;
}
R_CH = rythm ? &S_CH[6] : E_CH;
for( i=0; i < length ; i++ )
{
/* channel A channel B channel C */
/* LFO */
ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
outd[0] = 0;
/* deltaT ADPCM */
if( DELTAT->flag )
YM_DELTAT_ADPCM_CALC(DELTAT);
/* FM part */
for(CH=S_CH ; CH < R_CH ; CH++)
OPL_CALC_CH(CH);
/* Rythn part */
if(rythm)
OPL_CALC_RH(S_CH);
/* limit check */
data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
/* store to sound buffer */
buf[i] = data >> OPL_OUTSB;
}
OPL->amsCnt = amsCnt;
OPL->vibCnt = vibCnt;
/* deltaT START flag */
if( !DELTAT->flag )
OPL->status &= 0xfe;
}
#endif
/* ---------- reset one of chip ---------- */
void OPLResetChip(FM_OPL *OPL)
{
int c,s;
int i;
/* reset chip */
OPL->mode = 0; /* normal mode */
OPL_STATUS_RESET(OPL,0x7f);
/* reset with register write */
OPLWriteReg(OPL,0x01,0); /* wabesel disable */
OPLWriteReg(OPL,0x02,0); /* Timer1 */
OPLWriteReg(OPL,0x03,0); /* Timer2 */
OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */
for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
/* reset OPerator paramater */
for( c = 0 ; c < OPL->max_ch ; c++ )
{
OPL_CH *CH = &OPL->P_CH[c];
/* OPL->P_CH[c].PAN = OPN_CENTER; */
for(s = 0 ; s < 2 ; s++ )
{
/* wave table */
CH->SLOT[s].wavetable = &SIN_TABLE[0];
/* CH->SLOT[s].evm = ENV_MOD_RR; */
CH->SLOT[s].evc = EG_OFF;
CH->SLOT[s].eve = EG_OFF+1;
CH->SLOT[s].evs = 0;
}
}
#if BUILD_Y8950
if(OPL->type&OPL_TYPE_ADPCM)
{
YM_DELTAT *DELTAT = OPL->deltat;
DELTAT->freqbase = OPL->freqbase;
DELTAT->output_pointer = outd;
DELTAT->portshift = 5;
DELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS;
YM_DELTAT_ADPCM_Reset(DELTAT,0);
}
#endif
}
/* ---------- Create one of vietual YM3812 ---------- */
/* 'rate' is sampling rate and 'bufsiz' is the size of the */
FM_OPL *OPLCreate(int type, int clock, int rate)
{
char *ptr;
FM_OPL *OPL;
int state_size;
int max_ch = 9; /* normaly 9 channels */
if( OPL_LockTable() ==-1) return NULL;
/* allocate OPL state space */
state_size = sizeof(FM_OPL);
state_size += sizeof(OPL_CH)*max_ch;
#if BUILD_Y8950
if(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);
#endif
/* allocate memory block */
ptr = malloc(state_size);
if(ptr==NULL) return NULL;
/* clear */
memset(ptr,0,state_size);
OPL = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);
OPL->P_CH = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;
#if BUILD_Y8950
if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT);
#endif
/* set channel state pointer */
OPL->type = type;
OPL->clock = clock;
OPL->rate = rate;
OPL->max_ch = max_ch;
/* init grobal tables */
OPL_initalize(OPL);
/* reset chip */
OPLResetChip(OPL);
return OPL;
}
/* ---------- Destroy one of vietual YM3812 ---------- */
void OPLDestroy(FM_OPL *OPL)
{
OPL_UnLockTable();
free(OPL);
}
/* ---------- Option handlers ---------- */
void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset)
{
OPL->TimerHandler = TimerHandler;
OPL->TimerParam = channelOffset;
}
void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param)
{
OPL->IRQHandler = IRQHandler;
OPL->IRQParam = param;
}
void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param)
{
OPL->UpdateHandler = UpdateHandler;
OPL->UpdateParam = param;
}
#if BUILD_Y8950
void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param)
{
OPL->porthandler_w = PortHandler_w;
OPL->porthandler_r = PortHandler_r;
OPL->port_param = param;
}
void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param)
{
OPL->keyboardhandler_w = KeyboardHandler_w;
OPL->keyboardhandler_r = KeyboardHandler_r;
OPL->keyboard_param = param;
}
#endif
/* ---------- YM3812 I/O interface ---------- */
int OPLWrite(FM_OPL *OPL,int a,int v)
{
if( !(a&1) )
{ /* address port */
OPL->address = v & 0xff;
}
else
{ /* data port */
if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
OPLWriteReg(OPL,OPL->address,v);
}
return OPL->status>>7;
}
unsigned char OPLRead(FM_OPL *OPL,int a)
{
if( !(a&1) )
{ /* status port */
return OPL->status & (OPL->statusmask|0x80);
}
/* data port */
switch(OPL->address)
{
case 0x05: /* KeyBoard IN */
if(OPL->type&OPL_TYPE_KEYBOARD)
{
if(OPL->keyboardhandler_r)
return OPL->keyboardhandler_r(OPL->keyboard_param);
else
Log(LOG_WAR,"OPL:read unmapped KEYBOARD port\n");
}
return 0;
#if 0
case 0x0f: /* ADPCM-DATA */
return 0;
#endif
case 0x19: /* I/O DATA */
if(OPL->type&OPL_TYPE_IO)
{
if(OPL->porthandler_r)
return OPL->porthandler_r(OPL->port_param);
else
Log(LOG_WAR,"OPL:read unmapped I/O port\n");
}
return 0;
case 0x1a: /* PCM-DATA */
return 0;
}
return 0;
}
int OPLTimerOver(FM_OPL *OPL,int c)
{
if( c )
{ /* Timer B */
OPL_STATUS_SET(OPL,0x20);
}
else
{ /* Timer A */
OPL_STATUS_SET(OPL,0x40);
/* CSM mode key,TL controll */
if( OPL->mode & 0x80 )
{ /* CSM mode total level latch and auto key on */
int ch;
if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
for(ch=0;ch<9;ch++)
CSMKeyControll( &OPL->P_CH[ch] );
}
}
/* reload timer */
if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase);
return OPL->status>>7;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -