📄 emu2413.c
字号:
UPDATE_TLL(S);\
UPDATE_RKS(S);\
UPDATE_WF(S); \
UPDATE_EG(S) /* EG should be last */
/* Force Refresh (When external program changes some parameters). */
void OPLL_forceRefresh(OPLL *opll)
{
int i ;
if(opll==NULL) return ;
for(i=0; i<18 ;i++)
{
UPDATE_PG(opll->slot[i]) ;
UPDATE_RKS(opll->slot[i]) ;
UPDATE_TLL(opll->slot[i]) ;
UPDATE_WF(opll->slot[i]) ;
UPDATE_EG(opll->slot[i]) ;
}
}
/* Slot key on */
INLINE static void slotOn(OPLL_SLOT *slot)
{
slot->eg_mode = ATTACK ;
slot->phase = 0 ;
slot->eg_phase = 0 ;
}
/* Slot key off */
INLINE static void slotOff(OPLL_SLOT *slot)
{
if(slot->eg_mode == ATTACK)
slot->eg_phase = EXPAND_BITS(AR_ADJUST_TABLE[HIGHBITS(slot->eg_phase,EG_DP_BITS-EG_BITS)],EG_BITS,EG_DP_BITS) ;
slot->eg_mode = RELEASE ;
}
/* Channel key on */
INLINE static void keyOn(OPLL *opll, int i)
{
if(!opll->slot_on_flag[i*2]) slotOn(opll->MOD(i)) ;
if(!opll->slot_on_flag[i*2+1]) slotOn(opll->CAR(i)) ;
opll->ch[i]->key_status = 1 ;
}
/* Channel key off */
INLINE static void keyOff(OPLL *opll, int i)
{
if(opll->slot_on_flag[i*2+1]) slotOff(opll->CAR(i)) ;
opll->ch[i]->key_status = 0 ;
}
INLINE static void keyOn_BD(OPLL *opll){ keyOn(opll,6) ; }
INLINE static void keyOn_SD(OPLL *opll){ if(!opll->slot_on_flag[SLOT_SD]) slotOn(opll->CAR(7)) ; }
INLINE static void keyOn_TOM(OPLL *opll){ if(!opll->slot_on_flag[SLOT_TOM]) slotOn(opll->MOD(8)) ; }
INLINE static void keyOn_HH(OPLL *opll){ if(!opll->slot_on_flag[SLOT_HH]) slotOn(opll->MOD(7)) ; }
INLINE static void keyOn_CYM(OPLL *opll){ if(!opll->slot_on_flag[SLOT_CYM]) slotOn(opll->CAR(8)) ; }
/* Drum key off */
INLINE static void keyOff_BD(OPLL *opll){ keyOff(opll,6) ; }
INLINE static void keyOff_SD(OPLL *opll){ if(opll->slot_on_flag[SLOT_SD]) slotOff(opll->CAR(7)) ; }
INLINE static void keyOff_TOM(OPLL *opll){ if(opll->slot_on_flag[SLOT_TOM]) slotOff(opll->MOD(8)) ; }
INLINE static void keyOff_HH(OPLL *opll){ if(opll->slot_on_flag[SLOT_HH]) slotOff(opll->MOD(7)) ; }
INLINE static void keyOff_CYM(OPLL *opll){ if(opll->slot_on_flag[SLOT_CYM]) slotOff(opll->CAR(8)) ; }
/* Change a voice */
INLINE static void setPatch(OPLL *opll, int i, int num)
{
opll->ch[i]->patch_number = num ;
opll->MOD(i)->patch = opll->patch[num*2+0] ;
opll->CAR(i)->patch = opll->patch[num*2+1] ;
}
/* Change a rythm voice */
INLINE static void setSlotPatch(OPLL_SLOT *slot, OPLL_PATCH *patch)
{
slot->patch = patch ;
}
/* Set sustine parameter */
INLINE static void setSustine(OPLL *opll, int c, int sustine)
{
opll->CAR(c)->sustine = sustine ;
if(opll->MOD(c)->type) opll->MOD(c)->sustine = sustine ;
}
/* Volume : 6bit ( Volume register << 2 ) */
INLINE static void setVolume(OPLL *opll, int c, int volume)
{
opll->CAR(c)->volume = volume ;
}
INLINE static void setSlotVolume(OPLL_SLOT *slot, int volume)
{
slot->volume = volume ;
}
/* Set F-Number ( fnum : 9bit ) */
INLINE static void setFnumber(OPLL *opll, int c, int fnum)
{
opll->CAR(c)->fnum = fnum ;
opll->MOD(c)->fnum = fnum ;
}
/* Set Block data (block : 3bit ) */
INLINE static void setBlock(OPLL *opll, int c, int block)
{
opll->CAR(c)->block = block ;
opll->MOD(c)->block = block ;
}
/* Change Rythm Mode */
INLINE static void setRythmMode(OPLL *opll, int mode)
{
opll->rythm_mode = mode ;
if(mode)
{
opll->ch[6]->patch_number = 16 ;
opll->ch[7]->patch_number = 17 ;
opll->ch[8]->patch_number = 18 ;
setSlotPatch(opll->slot[SLOT_BD1], opll->patch[16*2+0]) ;
setSlotPatch(opll->slot[SLOT_BD2], opll->patch[16*2+1]) ;
setSlotPatch(opll->slot[SLOT_HH], opll->patch[17*2+0]) ;
setSlotPatch(opll->slot[SLOT_SD], opll->patch[17*2+1]) ;
opll->slot[SLOT_HH]->type = 1 ;
setSlotPatch(opll->slot[SLOT_TOM], opll->patch[18*2+0]) ;
setSlotPatch(opll->slot[SLOT_CYM], opll->patch[18*2+1]) ;
opll->slot[SLOT_TOM]->type = 1 ;
}
else
{
setPatch(opll, 6, opll->reg[0x36]>>4) ;
setPatch(opll, 7, opll->reg[0x37]>>4) ;
opll->slot[SLOT_HH]->type = 0 ;
setPatch(opll, 8, opll->reg[0x38]>>4) ;
opll->slot[SLOT_TOM]->type = 0 ;
}
if(!opll->slot_on_flag[SLOT_BD1])
opll->slot[SLOT_BD1]->eg_mode = FINISH ;
if(!opll->slot_on_flag[SLOT_BD2])
opll->slot[SLOT_BD2]->eg_mode = FINISH ;
if(!opll->slot_on_flag[SLOT_HH])
opll->slot[SLOT_HH]->eg_mode = FINISH ;
if(!opll->slot_on_flag[SLOT_SD])
opll->slot[SLOT_SD]->eg_mode = FINISH ;
if(!opll->slot_on_flag[SLOT_TOM])
opll->slot[SLOT_TOM]->eg_mode = FINISH ;
if(!opll->slot_on_flag[SLOT_CYM])
opll->slot[SLOT_CYM]->eg_mode = FINISH ;
}
void OPLL_copyPatch(OPLL *opll, int num, OPLL_PATCH *patch)
{
memcpy(opll->patch[num],patch,sizeof(OPLL_PATCH)) ;
}
/***********************************************************
Initializing
***********************************************************/
static void OPLL_SLOT_reset(OPLL_SLOT *slot)
{
slot->sintbl = waveform[0] ;
slot->phase = 0 ;
slot->dphase = 0 ;
slot->output[0] = 0 ;
slot->output[1] = 0 ;
slot->feedback = 0 ;
slot->eg_mode = SETTLE ;
slot->eg_phase = EG_DP_WIDTH ;
slot->eg_dphase = 0 ;
slot->rks = 0 ;
slot->tll = 0 ;
slot->sustine = 0 ;
slot->fnum = 0 ;
slot->block = 0 ;
slot->volume = 0 ;
slot->pgout = 0 ;
slot->egout = 0 ;
slot->patch = &null_patch ;
}
static OPLL_SLOT *OPLL_SLOT_new(void)
{
OPLL_SLOT *slot ;
slot = malloc(sizeof(OPLL_SLOT)) ;
if(slot == NULL) return NULL ;
return slot ;
}
static void OPLL_SLOT_delete(OPLL_SLOT *slot)
{
free(slot) ;
}
static void OPLL_CH_reset(OPLL_CH *ch)
{
if(ch->mod!=NULL) OPLL_SLOT_reset(ch->mod) ;
if(ch->car!=NULL) OPLL_SLOT_reset(ch->car) ;
ch->key_status = 0 ;
}
static OPLL_CH *OPLL_CH_new(void)
{
OPLL_CH *ch ;
OPLL_SLOT *mod, *car ;
mod = OPLL_SLOT_new() ;
if(mod == NULL) return NULL ;
car = OPLL_SLOT_new() ;
if(car == NULL)
{
OPLL_SLOT_delete(mod) ;
return NULL ;
}
ch = malloc(sizeof(OPLL_CH)) ;
if(ch == NULL)
{
OPLL_SLOT_delete(mod) ;
OPLL_SLOT_delete(car) ;
return NULL ;
}
mod->type = 0 ;
car->type = 1 ;
ch->mod = mod ;
ch->car = car ;
return ch ;
}
static void OPLL_CH_delete(OPLL_CH *ch)
{
OPLL_SLOT_delete(ch->mod) ;
OPLL_SLOT_delete(ch->car) ;
free(ch) ;
}
OPLL *OPLL_new(void)
{
OPLL *opll ;
OPLL_CH *ch[9] ;
OPLL_PATCH *patch[19*2] ;
int i, j ;
for( i = 0 ; i < 19*2 ; i++ )
{
patch[i] = calloc(sizeof(OPLL_PATCH),1) ;
if(patch[i] == NULL)
{
for ( j = i ; i > 0 ; i++ ) free(patch[j-1]) ;
return NULL ;
}
}
for( i = 0 ; i < 9 ; i++ )
{
ch[i] = OPLL_CH_new() ;
if(ch[i]==NULL)
{
for ( j = i ; i > 0 ; i++ ) OPLL_CH_delete(ch[j-1]) ;
for ( j = 0 ; j < 19*2 ; j++ ) free(patch[j]) ;
return NULL ;
}
}
opll = malloc(sizeof(OPLL)) ;
if(opll == NULL) return NULL ;
for ( i = 0 ; i < 19*2 ; i++ )
opll->patch[i] = patch[i] ;
for ( i = 0 ; i <9 ; i++)
{
opll->ch[i] = ch[i] ;
opll->slot[i*2+0] = opll->ch[i]->mod ;
opll->slot[i*2+1] = opll->ch[i]->car ;
}
for ( i = 0 ; i < 18 ; i++) {
opll->slot[i]->plfo_am = &opll->lfo_am ; opll->slot[i]->plfo_pm = &opll->lfo_pm ; }
opll->mask = 0 ;
OPLL_reset(opll) ; OPLL_reset_patch(opll,0) ;
opll->masterVolume = 32 ;
return opll ;
}
void OPLL_delete(OPLL *opll)
{
int i ;
for ( i = 0 ; i < 9 ; i++ )
OPLL_CH_delete(opll->ch[i]) ;
for ( i = 0 ; i < 19*2 ; i++ )
free(opll->patch[i]) ;
free(opll) ;
}
/* Reset patch datas by system default. */
void OPLL_reset_patch(OPLL *opll, int type)
{
int i ;
for ( i = 0 ; i < 19*2 ; i++ )
OPLL_copyPatch(opll, i, &default_patch[type%OPLL_TONE_NUM][i]) ;
}
/* Reset whole of OPLL except patch datas. */
void OPLL_reset(OPLL *opll)
{
int i ;
if(!opll) return ;
opll->adr = 0 ;
opll->output[0] = 0 ;
opll->output[1] = 0 ;
opll->pm_phase = 0 ;
opll->am_phase = 0 ;
opll->noise_seed =0xffff ;
opll->noiseA = 0 ;
opll->noiseB = 0 ;
opll->noiseA_phase = 0 ;
opll->noiseB_phase = 0 ;
opll->noiseA_dphase = 0 ;
opll->noiseB_dphase = 0 ;
opll->noiseA_idx = 0 ;
opll->noiseB_idx = 0 ;
for(i = 0; i < 9 ; i++)
{
OPLL_CH_reset(opll->ch[i]) ;
setPatch(opll,i,0) ;
}
for ( i = 0 ; i < 0x40 ; i++ ) OPLL_writeReg(opll, i, 0) ;
}
void OPLL_setClock(uint32 c, uint32 r)
{
clk = c ;
rate = r ;
makeDphaseTable() ;
makeDphaseARTable() ;
makeDphaseDRTable() ;
pm_dphase = (uint32)rate_adjust(PM_SPEED * PM_DP_WIDTH / (clk/72) ) ;
am_dphase = (uint32)rate_adjust(AM_SPEED * AM_DP_WIDTH / (clk/72) ) ;
}
void OPLL_init(uint32 c, uint32 r)
{
makePmTable() ;
makeAmTable() ;
makeDB2LinTable() ;
makeAdjustTable() ;
makeTllTable() ;
makeRksTable() ;
makeSinTable() ;
makeDefaultPatch() ;
OPLL_setClock(c,r) ;
}
void OPLL_close(void)
{
}
/*********************************************************
Generate wave data
*********************************************************/
/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 2PI). */
#if ( SLOT_AMP_BITS - PG_BITS ) > 0
#define wave2_2pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS ))
#else
#define wave2_2pi(e) ( (e) << ( PG_BITS - SLOT_AMP_BITS ))
#endif
/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 4PI). */
#if ( SLOT_AMP_BITS - PG_BITS - 1 ) == 0
#define wave2_4pi(e) (e)
#elif ( SLOT_AMP_BITS - PG_BITS - 1 ) > 0
#define wave2_4pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 1 ))
#else
#define wave2_4pi(e) ( (e) << ( 1 + PG_BITS - SLOT_AMP_BITS ))
#endif
/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 8PI). */
#if ( SLOT_AMP_BITS - PG_BITS - 2 ) == 0
#define wave2_8pi(e) (e)
#elif ( SLOT_AMP_BITS - PG_BITS - 2 ) > 0
#define wave2_8pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 2 ))
#else
#define wave2_8pi(e) ( (e) << ( 2 + PG_BITS - SLOT_AMP_BITS ))
#endif
/* 16bit rand */
INLINE static uint32 mrand(uint32 seed)
{
return ((seed>>15)^((seed>>12)&1)) | ((seed<<1)&0xffff) ;
}
INLINE static uint32 DEC(uint32 db)
{
if(db<DB_MUTE+DB_MUTE)
{
return Min(db+DB_POS(0.375*2),DB_MUTE-1) ;
}
else
{
return Min(db+DB_POS(0.375*2),DB_MUTE+DB_MUTE+DB_MUTE-1) ;
}
}
/* Update Noise unit */
INLINE static void update_noise(OPLL *opll)
{
opll->noise_seed = mrand(opll->noise_seed) ;
opll->whitenoise = opll->noise_seed & 1 ;
opll->noiseA_phase = (opll->noiseA_phase + opll->noiseA_dphase) ;
opll->noiseB_phase = (opll->noiseB_phase + opll->noiseB_dphase) ;
if(opll->noiseA_phase<(1<<11))
{
if(opll->noiseA_phase>16) opll->noiseA = DB_MUTE - 1 ;
}
else
{
opll->noiseA_phase &= (1<<11)-1 ;
opll->noiseA_idx = (opll->noiseA_idx+1)&63 ;
opll->noiseA = noiseAtable[opll->noiseA_idx] ;
}
if(opll->noiseB_phase<(1<<12))
{
if(opll->noiseB_phase>16) opll->noiseB = DB_MUTE - 1 ;
}
else
{
opll->noiseB_phase &= (1<<12)-1 ;
opll->noiseB_idx = (opll->noiseB_idx+1)&7 ;
opll->noiseB = noiseBtable[opll->noiseB_idx] ;
}
}
/* Update AM, PM unit */
INLINE static void update_ampm(OPLL *opll)
{
opll->pm_phase = (opll->pm_phase + pm_dphase)&(PM_DP_WIDTH - 1) ;
opll->am_phase = (opll->am_phase + am_dphase)&(AM_DP_WIDTH - 1) ;
opll->lfo_am = amtable[HIGHBITS(opll->am_phase, AM_DP_BITS - AM_PG_BITS)] ;
opll->lfo_pm = pmtable[HIGHBITS(opll->pm_phase, PM_DP_BITS - PM_PG_BITS)] ;
}
/* PG */
INLINE static uint32 calc_phase(OPLL_SLOT *slot)
{
if(slot->patch->PM)
slot->phase += (slot->dphase * (*(slot->plfo_pm))) >> PM_AMP_BITS ;
else
slot->phase += slot->dphase ;
slot->phase &= (DP_WIDTH - 1) ;
return HIGHBITS(slot->phase, DP_BASE_BITS) ;
}
/* EG */
INLINE static uint32 calc_envelope(OPLL_SLOT *slot)
{
#define S2E(x) (SL2EG((int)(x/SL_STEP))<<(EG_DP_BITS-EG_BITS))
static uint32 SL[16] = {
S2E( 0), S2E( 3), S2E( 6), S2E( 9), S2E(12), S2E(15), S2E(18), S2E(21),
S2E(24), S2E(27), S2E(30), S2E(33), S2E(36), S2E(39), S2E(42), S2E(48)
} ;
uint32 egout ;
switch(slot->eg_mode)
{
case ATTACK:
slot->eg_phase += slot->eg_dphase ;
if(EG_DP_WIDTH & slot->eg_phase)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -