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

📄 emu2413.c

📁 最好的任天堂模拟器
💻 C
📖 第 1 页 / 共 3 页
字号:
  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 + -