📄 emu2413.c
字号:
egout = 0 ;
slot->eg_phase= 0 ;
slot->eg_mode = DECAY ;
UPDATE_EG(slot) ;
}
else
{
egout = AR_ADJUST_TABLE[HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS)] ;
}
break;
case DECAY:
slot->eg_phase += slot->eg_dphase ;
egout = HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS) ;
if(slot->eg_phase >= SL[slot->patch->SL])
{
if(slot->patch->EG)
{
slot->eg_phase = SL[slot->patch->SL] ;
slot->eg_mode = SUSHOLD ;
UPDATE_EG(slot) ;
}
else
{
slot->eg_phase = SL[slot->patch->SL] ;
slot->eg_mode = SUSTINE ;
UPDATE_EG(slot) ;
}
egout = HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS) ;
}
break;
case SUSHOLD:
egout = HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS) ;
if(slot->patch->EG == 0)
{
slot->eg_mode = SUSTINE ;
UPDATE_EG(slot) ;
}
break;
case SUSTINE:
case RELEASE:
slot->eg_phase += slot->eg_dphase ;
egout = HIGHBITS(slot->eg_phase, EG_DP_BITS - EG_BITS) ;
if(egout >= (1<<EG_BITS))
{
slot->eg_mode = FINISH ;
egout = (1<<EG_BITS) - 1 ;
}
break;
case FINISH:
egout = (1<<EG_BITS) - 1 ;
break ;
default:
egout = (1<<EG_BITS) - 1 ;
break;
}
if(slot->patch->AM) egout = EG2DB(egout+slot->tll) + *(slot->plfo_am) ;
else egout = EG2DB(egout+slot->tll) ;
if(egout >= DB_MUTE) egout = DB_MUTE-1;
return egout ;
}
INLINE static int32 calc_slot_car(OPLL_SLOT *slot, int32 fm)
{
slot->egout = calc_envelope(slot) ;
slot->pgout = calc_phase(slot) ;
if(slot->egout>=(DB_MUTE-1)) return 0 ;
return DB2LIN_TABLE[slot->sintbl[(slot->pgout+wave2_8pi(fm))&(PG_WIDTH-1)] + slot->egout] ;
}
INLINE static int32 calc_slot_mod(OPLL_SLOT *slot)
{
int32 fm ;
slot->output[1] = slot->output[0] ;
slot->egout = calc_envelope(slot) ;
slot->pgout = calc_phase(slot) ;
if(slot->egout>=(DB_MUTE-1))
{
slot->output[0] = 0 ;
}
else if(slot->patch->FB!=0)
{
fm = wave2_4pi(slot->feedback) >> (7 - slot->patch->FB) ;
slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+fm)&(PG_WIDTH-1)] + slot->egout] ;
}
else
{
slot->output[0] = DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout] ;
}
slot->feedback = (slot->output[1] + slot->output[0])>>1 ;
return slot->feedback ;
}
INLINE static int32 calc_slot_tom(OPLL_SLOT *slot)
{
slot->egout = calc_envelope(slot) ;
slot->pgout = calc_phase(slot) ;
if(slot->egout>=(DB_MUTE-1)) return 0 ;
return DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout] ;
}
/* calc SNARE slot */
INLINE static int32 calc_slot_snare(OPLL_SLOT *slot, uint32 whitenoise)
{
slot->egout = calc_envelope(slot) ;
slot->pgout = calc_phase(slot) ;
if(slot->egout>=(DB_MUTE-1)) return 0 ;
if(whitenoise)
return DB2LIN_TABLE[snaretable[slot->pgout] + slot->egout] + DB2LIN_TABLE[slot->egout + 6] ;
else
return DB2LIN_TABLE[snaretable[slot->pgout] + slot->egout] ;
}
INLINE static int32 calc_slot_cym(OPLL_SLOT *slot, int32 a, int32 b, int32 c)
{
slot->egout = calc_envelope(slot) ;
if(slot->egout>=(DB_MUTE-1)) return 0 ;
return DB2LIN_TABLE[slot->egout+a]
+ (( DB2LIN_TABLE[slot->egout+b] + DB2LIN_TABLE[slot->egout+c] ) >> 2 );
}
INLINE static int32 calc_slot_hat(OPLL_SLOT *slot, int32 a, int32 b, int32 c, uint32 whitenoise)
{
slot->egout = calc_envelope(slot) ;
if(slot->egout>=(DB_MUTE-1)) return 0 ;
if(whitenoise)
{
return DB2LIN_TABLE[slot->egout+a]
+ (( DB2LIN_TABLE[slot->egout+b] + DB2LIN_TABLE[slot->egout+c] ) >> 2 );
}
else
{
return 0 ;
}
}
int16 OPLL_calc(OPLL *opll)
{
int32 inst = 0 , perc = 0 , out = 0 ;
int32 rythmC = 0, rythmH = 0;
int i ;
update_ampm(opll) ;
update_noise(opll) ;
for(i = 0 ; i < 6 ; i++)
if(!(opll->mask&OPLL_MASK_CH(i))&&(opll->CAR(i)->eg_mode!=FINISH))
inst += calc_slot_car(opll->CAR(i),calc_slot_mod(opll->MOD(i))) ;
if(!opll->rythm_mode)
{
for(i = 6 ; i < 9 ; i++)
if(!(opll->mask&OPLL_MASK_CH(i))&&(opll->CAR(i)->eg_mode!=FINISH))
inst += calc_slot_car(opll->CAR(i),calc_slot_mod(opll->MOD(i))) ;
}
else
{
opll->MOD(7)->pgout = calc_phase(opll->MOD(7)) ;
opll->CAR(8)->pgout = calc_phase(opll->CAR(8)) ;
if(opll->MOD(7)->phase<256) rythmH = DB_NEG(12.0) ; else rythmH = DB_MUTE - 1 ;
if(opll->CAR(8)->phase<256) rythmC = DB_NEG(12.0) ; else rythmC = DB_MUTE - 1 ;
if(!(opll->mask&OPLL_MASK_BD)&&(opll->CAR(6)->eg_mode!=FINISH))
perc += calc_slot_car(opll->CAR(6),calc_slot_mod(opll->MOD(6))) ;
if(!(opll->mask&OPLL_MASK_HH)&&(opll->MOD(7)->eg_mode!=FINISH))
perc += calc_slot_hat(opll->MOD(7), opll->noiseA, opll->noiseB, rythmH, opll->whitenoise) ;
if(!(opll->mask&OPLL_MASK_SD)&&(opll->CAR(7)->eg_mode!=FINISH))
perc += calc_slot_snare(opll->CAR(7), opll->whitenoise) ;
if(!(opll->mask&OPLL_MASK_TOM)&&(opll->MOD(8)->eg_mode!=FINISH))
perc += calc_slot_tom(opll->MOD(8)) ;
if(!(opll->mask&OPLL_MASK_CYM)&&(opll->CAR(8)->eg_mode!=FINISH))
perc += calc_slot_cym(opll->CAR(8), opll->noiseA, opll->noiseB, rythmC) ;
}
#if SLOT_AMP_BITS > 8
inst = (inst >> (SLOT_AMP_BITS - 8)) ;
perc = (perc >> (SLOT_AMP_BITS - 9)) ;
#else
inst = (inst << (8 - SLOT_AMP_BITS)) ;
perc = (perc << (9 - SLOT_AMP_BITS)) ;
#endif
out = ((inst + perc) * opll->masterVolume ) >> 2 ;
if(out>32767) return 32767 ;
if(out<-32768) return -32768 ;
return (int16)out ;
}
uint32 OPLL_setMask(OPLL *opll, uint32 mask)
{
uint32 ret ;
if(opll)
{
ret = opll->mask ;
opll->mask = mask ;
return ret ;
}
else return 0 ;
}
uint32 OPLL_toggleMask(OPLL *opll, uint32 mask)
{
uint32 ret ;
if(opll)
{
ret = opll->mask ;
opll->mask ^= mask ;
return ret ;
}
else return 0 ;
}
/****************************************************
Interfaces
*****************************************************/
void OPLL_writeReg(OPLL *opll, uint32 reg, uint32 data){
int i,v,ch ;
data = data&0xff ;
reg = reg&0x3f ;
switch(reg)
{
case 0x00:
opll->patch[0]->AM = (data>>7)&1 ;
opll->patch[0]->PM = (data>>6)&1 ;
opll->patch[0]->EG = (data>>5)&1 ;
opll->patch[0]->KR = (data>>4)&1 ;
opll->patch[0]->ML = (data)&15 ;
for(i=0;i<9;i++)
{
if(opll->ch[i]->patch_number==0)
{
UPDATE_PG(opll->MOD(i)) ;
UPDATE_RKS(opll->MOD(i)) ;
UPDATE_EG(opll->MOD(i)) ;
}
}
break ;
case 0x01:
opll->patch[1]->AM = (data>>7)&1 ;
opll->patch[1]->PM = (data>>6)&1 ;
opll->patch[1]->EG = (data>>5)&1 ;
opll->patch[1]->KR = (data>>4)&1 ;
opll->patch[1]->ML = (data)&15 ;
for(i=0;i<9;i++)
{
if(opll->ch[i]->patch_number==0)
{
UPDATE_PG(opll->CAR(i)) ;
UPDATE_RKS(opll->CAR(i)) ;
UPDATE_EG(opll->CAR(i)) ;
}
}
break;
case 0x02:
opll->patch[0]->KL = (data>>6)&3 ;
opll->patch[0]->TL = (data)&63 ;
for(i=0;i<9;i++)
{
if(opll->ch[i]->patch_number==0)
{
UPDATE_TLL(opll->MOD(i)) ;
}
}
break ;
case 0x03:
opll->patch[1]->KL = (data>>6)&3 ;
opll->patch[1]->WF = (data>>4)&1 ;
opll->patch[0]->WF = (data>>3)&1 ;
opll->patch[0]->FB = (data)&7 ;
for(i=0;i<9;i++)
{
if(opll->ch[i]->patch_number==0)
{
UPDATE_WF(opll->MOD(i)) ;
UPDATE_WF(opll->CAR(i)) ;
}
}
break ;
case 0x04:
opll->patch[0]->AR = (data>>4)&15 ;
opll->patch[0]->DR = (data)&15 ;
for(i=0;i<9;i++)
{
if(opll->ch[i]->patch_number==0)
{
UPDATE_EG(opll->MOD(i)) ;
}
}
break ;
case 0x05:
opll->patch[1]->AR = (data>>4)&15 ;
opll->patch[1]->DR = (data)&15 ;
for(i=0;i<9;i++)
{
if(opll->ch[i]->patch_number==0)
{
UPDATE_EG(opll->CAR(i)) ;
}
}
break ;
case 0x06:
opll->patch[0]->SL = (data>>4)&15 ;
opll->patch[0]->RR = (data)&15 ;
for(i=0;i<9;i++)
{
if(opll->ch[i]->patch_number==0)
{
UPDATE_EG(opll->MOD(i)) ;
}
}
break ;
case 0x07:
opll->patch[1]->SL = (data>>4)&15 ;
opll->patch[1]->RR = (data)&15 ;
for(i=0;i<9;i++)
{
if(opll->ch[i]->patch_number==0)
{
UPDATE_EG(opll->CAR(i)) ;
}
}
break ;
case 0x0e:
if(opll->rythm_mode)
{
opll->slot_on_flag[SLOT_BD1] = (opll->reg[0x0e]&0x10) | (opll->reg[0x26]&0x10) ;
opll->slot_on_flag[SLOT_BD2] = (opll->reg[0x0e]&0x10) | (opll->reg[0x26]&0x10) ;
opll->slot_on_flag[SLOT_SD] = (opll->reg[0x0e]&0x08) | (opll->reg[0x27]&0x10) ;
opll->slot_on_flag[SLOT_HH] = (opll->reg[0x0e]&0x01) | (opll->reg[0x27]&0x10) ;
opll->slot_on_flag[SLOT_TOM] = (opll->reg[0x0e]&0x04) | (opll->reg[0x28]&0x10) ;
opll->slot_on_flag[SLOT_CYM] = (opll->reg[0x0e]&0x02) | (opll->reg[0x28]&0x10) ;
}
else
{
opll->slot_on_flag[SLOT_BD1] = (opll->reg[0x26]&0x10) ;
opll->slot_on_flag[SLOT_BD2] = (opll->reg[0x26]&0x10) ;
opll->slot_on_flag[SLOT_SD] = (opll->reg[0x27]&0x10) ;
opll->slot_on_flag[SLOT_HH] = (opll->reg[0x27]&0x10) ;
opll->slot_on_flag[SLOT_TOM] = (opll->reg[0x28]&0x10) ;
opll->slot_on_flag[SLOT_CYM] = (opll->reg[0x28]&0x10) ;
}
if(((data>>5)&1)^(opll->rythm_mode))
{
setRythmMode(opll,(data&32)>>5) ;
}
if(opll->rythm_mode)
{
if(data&0x10) keyOn_BD(opll) ; else keyOff_BD(opll) ;
if(data&0x8) keyOn_SD(opll) ; else keyOff_SD(opll) ;
if(data&0x4) keyOn_TOM(opll) ; else keyOff_TOM(opll) ;
if(data&0x2) keyOn_CYM(opll) ; else keyOff_CYM(opll) ;
if(data&0x1) keyOn_HH(opll) ; else keyOff_HH(opll) ;
}
UPDATE_ALL(opll->MOD(6)) ;
UPDATE_ALL(opll->CAR(6)) ;
UPDATE_ALL(opll->MOD(7)) ;
UPDATE_ALL(opll->CAR(7)) ;
UPDATE_ALL(opll->MOD(8)) ;
UPDATE_ALL(opll->CAR(8)) ;
break ;
case 0x0f:
break ;
case 0x10: case 0x11: case 0x12: case 0x13:
case 0x14: case 0x15: case 0x16: case 0x17:
case 0x18:
ch = reg-0x10 ;
setFnumber(opll, ch, data + ((opll->reg[0x20+ch]&1)<<8)) ;
UPDATE_ALL(opll->MOD(ch));
UPDATE_ALL(opll->CAR(ch));
switch(reg)
{
case 0x17:
opll->noiseA_dphase = (data + ((opll->reg[0x27]&1)<<8)) << ((opll->reg[0x27]>>1)&7) ;
break ;
case 0x18:
opll->noiseB_dphase = (data + ((opll->reg[0x28]&1)<<8)) << ((opll->reg[0x28]>>1)&7) ;
break;
default:
break ;
}
break ;
case 0x20: case 0x21: case 0x22: case 0x23:
case 0x24: case 0x25: case 0x26: case 0x27:
case 0x28:
ch = reg - 0x20 ;
setFnumber(opll, ch, ((data&1)<<8) + opll->reg[0x10+ch]) ;
setBlock(opll, ch, (data>>1)&7 ) ;
opll->slot_on_flag[ch*2] = opll->slot_on_flag[ch*2+1] = (opll->reg[reg])&0x10 ;
if(opll->rythm_mode)
{
switch(reg)
{
case 0x26:
opll->slot_on_flag[SLOT_BD1] |= (opll->reg[0x0e])&0x10 ;
opll->slot_on_flag[SLOT_BD2] |= (opll->reg[0x0e])&0x10 ;
break ;
case 0x27:
opll->noiseA_dphase = (((data&1)<<8) + opll->reg[0x17] ) << ((data>>1)&7) ;
opll->slot_on_flag[SLOT_SD] |= (opll->reg[0x0e])&0x08 ;
opll->slot_on_flag[SLOT_HH] |= (opll->reg[0x0e])&0x01 ;
break;
case 0x28:
opll->noiseB_dphase = (((data&1)<<8) + opll->reg[0x18] ) << ((data>>1)&7);
opll->slot_on_flag[SLOT_TOM] |= (opll->reg[0x0e])&0x04 ;
opll->slot_on_flag[SLOT_CYM] |= (opll->reg[0x0e])&0x02 ;
break ;
default:
break ;
}
}
if((opll->reg[reg]^data)&0x20) setSustine(opll, ch, (data>>5)&1) ;
if(data&0x10) keyOn(opll, ch) ; else keyOff(opll, ch) ;
UPDATE_ALL(opll->MOD(ch)) ;
UPDATE_ALL(opll->CAR(ch)) ;
break ;
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
case 0x35: case 0x36: case 0x37: case 0x38:
i = (data>>4)&15 ;
v = data&15 ;
if((opll->rythm_mode)&&(reg>=0x36))
{
switch(reg)
{
case 0x37 :
setSlotVolume(opll->MOD(7), i<<2) ;
break ;
case 0x38 :
setSlotVolume(opll->MOD(8), i<<2) ;
break ;
}
}
else
{
setPatch(opll, reg-0x30, i) ;
}
setVolume(opll, reg-0x30, v<<2) ;
UPDATE_ALL(opll->MOD(reg-0x30)) ;
UPDATE_ALL(opll->CAR(reg-0x30)) ;
break ;
default:
break ;
}
opll->reg[reg] = (unsigned char)data ;
}
void OPLL_writeIO(OPLL *opll, uint32 adr, uint32 val)
{
adr &= 0xff ;
if(adr == 0x7C) opll->adr = val ;
else if(adr == 0x7D) OPLL_writeReg(opll, opll->adr, val) ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -