static void TimerAOver(FM_ST ST) { /* status set if enabled */ if ((ST.mode & 0x04) != 0) FM_STATUS_SET(ST, 0x01); /* clear or reload the counter */ if (ST.timermodel == FM_TIMER_INTERVAL) { ST.TAC = (1024 - ST.TA); if (ST.Timer_Handler != null) ST.Timer_Handler(ST.index, 0, (int)ST.TAC, ST.TimerBase); } else ST.TAC = 0; }
/* Timer B Overflow */ static void TimerBOver(FM_ST ST) { /* status set if enabled */ if ((ST.mode & 0x08) != 0) FM_STATUS_SET(ST, 0x02); /* clear or reload the counter */ if (ST.timermodel == FM_TIMER_INTERVAL) { ST.TBC = (256 - ST.TB) << 4; if (ST.Timer_Handler != null) ST.Timer_Handler(ST.index, 1, (int)ST.TBC, ST.TimerBase); } else ST.TBC = 0; }
static void init_timetables(FM_ST ST, byte[] DTTABLE, int ARRATE, int DRRATE) { int i, d; double rate; /* DeTune table */ for (d = 0; d <= 3; d++) { for (i = 0; i <= 31; i++) { rate = (double)DTTABLE[d * 32 + i] * ST.freqbase * FREQ_RATE; ST.DT_TABLE[d][i] = (int)rate; ST.DT_TABLE[d + 4][i] = (int)-rate; } } /* make Attack & Decay tables */ for (i = 0; i < 4; i++) ST.AR_TABLE[i] = ST.DR_TABLE[i] = 0; for (i = 4; i < 64; i++) { rate = ST.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); ST.AR_TABLE[i] = (int)(rate / ARRATE); ST.DR_TABLE[i] = (int)(rate / DRRATE); } ST.AR_TABLE[62] = EG_AED - 1; ST.AR_TABLE[63] = EG_AED - 1; for (i = 64; i < 94; i++) { /* make for overflow area */ ST.AR_TABLE[i] = ST.AR_TABLE[63]; ST.DR_TABLE[i] = ST.DR_TABLE[63]; } #if false for (i = 0;i < 64 ;i++){ Log(LOG_WAR,"rate %2d , ar %f ms , dr %f ms \n",i, ((double)(EG_ENT<<ENV_BITS) / ST.AR_TABLE[i]) * (1000.0 / ST.rate), ((double)(EG_ENT<<ENV_BITS) / ST.DR_TABLE[i]) * (1000.0 / ST.rate) ); } #endif }
static void reset_channel(FM_ST ST, FM_CH[] CH, int chan) { int c, s; ST.mode = 0; /* normal mode */ FM_STATUS_RESET(ST, 0xff); ST.TA = 0; ST.TAC = 0; ST.TB = 0; ST.TBC = 0; for (c = 0; c < chan; c++) { CH[c] = new FM_CH(); CH[c].fc = 0; CH[c].PAN = OUTD_CENTER; for (s = 0; s < 4; s++) { CH[c].SLOT[s].SEG = 0; CH[c].SLOT[s].eg_next = FM_EG_Release; CH[c].SLOT[s].evc = EG_OFF; CH[c].SLOT[s].eve = EG_OFF + 1; CH[c].SLOT[s].evs = 0; } } }
/* set detune & multiple */ static void set_det_mul(FM_ST ST, FM_CH CH, FM_SLOT SLOT, int v) { SLOT.mul = (uint)MUL_TABLE[v & 0x0f]; SLOT.DT = ST.DT_TABLE[(v >> 4) & 7]; CH.SLOT[SLOT1].Incr = unchecked((uint)-1); }
static void FMSetMode(FM_ST ST, int n, int v) { /* b7 = CSM MODE */ /* b6 = 3 slot mode */ /* b5 = reset b */ /* b4 = reset a */ /* b3 = timer enable b */ /* b2 = timer enable a */ /* b1 = load b */ /* b0 = load a */ ST.mode = (uint)v; /* reset Timer b flag */ if ((v & 0x20) != 0) FM_STATUS_RESET(ST, 0x02); /* reset Timer a flag */ if ((v & 0x10) != 0) FM_STATUS_RESET(ST, 0x01); /* load b */ if ((v & 0x02) != 0) { if (ST.TBC == 0) { ST.TBC = (256 - ST.TB) << 4; /* External timer handler */ if (ST.Timer_Handler != null) ST.Timer_Handler(n, 1, (int)ST.TBC, ST.TimerBase); } } else if (ST.timermodel == FM_TIMER_INTERVAL) { /* stop interbval timer */ if (ST.TBC != 0) { ST.TBC = 0; if (ST.Timer_Handler != null) ST.Timer_Handler(n, 1, 0, ST.TimerBase); } } /* load a */ if ((v & 0x01) != 0) { if (ST.TAC == 0) { ST.TAC = (1024 - ST.TA); /* External timer handler */ if (ST.Timer_Handler != null) ST.Timer_Handler(n, 0, (int)ST.TAC, ST.TimerBase); } } else if (ST.timermodel == FM_TIMER_INTERVAL) { /* stop interbval timer */ if (ST.TAC != 0) { ST.TAC = 0; if (ST.Timer_Handler != null) ST.Timer_Handler(n, 0, 0, ST.TimerBase); } } }
static void FM_STATUS_RESET(FM_ST ST, int flag) { /* reset status flag */ ST.status &= (byte)~flag; if ((ST.irq) != 0 && (ST.status & ST.irqmask) == 0) { ST.irq = 0; /* callback user interrupt handler (IRQ is ON to OFF) */ if (ST.IRQ_Handler != null) ST.IRQ_Handler(ST.index, 0); } }
static void FM_IRQMASK_SET(FM_ST ST, int flag) { ST.irqmask = (byte)flag; /* IRQ handling check */ FM_STATUS_SET(ST, 0); FM_STATUS_RESET(ST, 0); }
static void FM_STATUS_SET(FM_ST ST, int flag) { /* set status flag */ ST.status |= (byte)flag; if ((ST.irq) == 0 && (ST.status & ST.irqmask) != 0) { ST.irq = 1; /* callback user interrupt handler (IRQ is OFF to ON) */ if (ST.IRQ_Handler != null) ST.IRQ_Handler(ST.index, 1); } }
public static void YM2203UpdateOne(int num, _ShortPtr buffer, int length) { YM2203 F2203 = (FM2203[num]); FM_OPN OPN = (FM2203[num].OPN); int i; FM_CH ch; _ShortPtr buf = new _ShortPtr(buffer); cur_chip = F2203; State = F2203.OPN.ST; cch[0] = F2203.CH[0]; cch[1] = F2203.CH[1]; cch[2] = F2203.CH[2]; #if FM_LFO_SUPPORT /* LFO */ lfo_amd = 0; lfo_pmd = 0; #endif /* frequency counter channel A */ CALC_FCOUNT(cch[0]); /* frequency counter channel B */ CALC_FCOUNT(cch[1]); /* frequency counter channel C */ if ((State.mode & 0xc0) != 0) { /* 3SLOT MODE */ if (cch[2].SLOT[SLOT1].Incr == unchecked((uint)-1)) { /* 3 slot mode */ CALC_FCSLOT(cch[2].SLOT[SLOT1], (int)OPN.SL3.fc[1], OPN.SL3.kcode[1]); CALC_FCSLOT(cch[2].SLOT[SLOT2], (int)OPN.SL3.fc[2], OPN.SL3.kcode[2]); CALC_FCSLOT(cch[2].SLOT[SLOT3], (int)OPN.SL3.fc[0], OPN.SL3.kcode[0]); CALC_FCSLOT(cch[2].SLOT[SLOT4], (int)cch[2].fc, cch[2].kcode); } } else CALC_FCOUNT(cch[2]); for (i = 0; i < length; i++) { /* channel A channel B channel C */ out_ch[OUTD_CENTER] = 0; /* calcrate FM */ //for( ch=cch[0] ; ch <= cch[2] ; ch++) for (int kk = 0; kk < 2; kk++) FM_CALC_CH(cch[kk]); /* limit check */ Limit(ref out_ch[OUTD_CENTER], FM_MAXOUT, FM_MINOUT); /* store to sound buffer */ buf.write16(i, (ushort)(out_ch[OUTD_CENTER] >> FM_OUTSB)); /* timer controll */ INTERNAL_TIMER_A(State, cch[2]); } INTERNAL_TIMER_B(State, length); }
static void INTERNAL_TIMER_B(FM_ST ST, int step) { }
/* external timer mode */ static void INTERNAL_TIMER_A(FM_ST ST, FM_CH CSM_CH) { }
public static void OPMUpdateOne(int num, _ShortPtr[] buffer, int length) { YM2151 OPM = (FMOPM[num]); int i; int amd, pmd; FM_CH ch; _ShortPtr bufL, bufR; /* set bufer */ bufL = buffer[0]; bufR = buffer[1]; if ((object)OPM != cur_chip) { cur_chip = OPM; State = OPM.ST; /* channel pointer */ cch[0] = OPM.CH[0]; cch[1] = OPM.CH[1]; cch[2] = OPM.CH[2]; cch[3] = OPM.CH[3]; cch[4] = OPM.CH[4]; cch[5] = OPM.CH[5]; cch[6] = OPM.CH[6]; cch[7] = OPM.CH[7]; /* ch7.op4 noise mode / step */ NoiseIncr = OPM.NoiseIncr; NoiseCnt = OPM.NoiseCnt; #if FM_LFO_SUPPORT /* LFO */ LFOCnt = OPM.LFOCnt; //LFOIncr = OPM.LFOIncr; if (LFOIncr == 0) { lfo_amd = 0; lfo_pmd = 0; } LFO_wave = OPM.wavetype; #endif } amd = OPM.amd; pmd = OPM.pmd; if (amd == 0 && pmd == 0) LFOIncr = 0; else LFOIncr = OPM.LFOIncr; OPM_CALC_FCOUNT(OPM, cch[0]); OPM_CALC_FCOUNT(OPM, cch[1]); OPM_CALC_FCOUNT(OPM, cch[2]); OPM_CALC_FCOUNT(OPM, cch[3]); OPM_CALC_FCOUNT(OPM, cch[4]); OPM_CALC_FCOUNT(OPM, cch[5]); OPM_CALC_FCOUNT(OPM, cch[6]); /* CSM check */ OPM_CALC_FCOUNT(OPM, cch[7]); for (i = 0; i < length; i++) { #if FM_LFO_SUPPORT /* LFO */ if (LFOIncr != 0) { int depth = LFO_wave[(int)((LFOCnt += LFOIncr) >> LFO_SHIFT)]; lfo_amd = (uint)(depth * amd); lfo_pmd = (depth - (LFO_RATE / 127 / 2)) * pmd; } #endif /* clear output acc. */ out_ch[OUTD_LEFT] = out_ch[OUTD_RIGHT] = out_ch[OUTD_CENTER] = 0; /* calcrate channel output */ //for(ch = cch[0] ; ch <= cch[6] ; ch++) for (int k = 0; k < 6; k++) { ch = cch[k]; FM_CALC_CH(ch); OPM_CALC_CH7(cch[7]); /* buffering */ //FM_BUFFERING_STEREO; #if FM_STEREO_MIX /* stereo mixing */ { /* get left & right output with clipping */ out_ch[OUTD_LEFT] += out_ch[OUTD_CENTER]; Limit( out_ch[OUTD_LEFT] , FM_MAXOUT, FM_MINOUT ); out_ch[OUTD_RIGHT] += out_ch[OUTD_CENTER]; Limit( out_ch[OUTD_RIGHT], FM_MAXOUT, FM_MINOUT ); /* buffering */ ((FMSAMPLE_MIX *)bufL)[i] = ((out_ch[OUTD_LEFT]>>FM_OUTSB)<<FM_OUTPUT_BIT)|(out_ch[OUTD_RIGHT]>>FM_OUTSB); } #else /* stereo separate */ { /* get left & right output with clipping */ out_ch[OUTD_LEFT] += out_ch[OUTD_CENTER]; Limit(ref out_ch[OUTD_LEFT], FM_MAXOUT, FM_MINOUT); out_ch[OUTD_RIGHT] += out_ch[OUTD_CENTER]; Limit(ref out_ch[OUTD_RIGHT], FM_MAXOUT, FM_MINOUT); /* buffering */ bufL.write16(i, (ushort)(out_ch[OUTD_LEFT] >> FM_OUTSB)); bufR.write16(i, (ushort)(out_ch[OUTD_RIGHT] >> FM_OUTSB)); } #endif /* timer A controll */ INTERNAL_TIMER_A(State, cch[7]); } INTERNAL_TIMER_B(State, length); OPM.NoiseCnt = NoiseCnt; #if FM_LFO_SUPPORT OPM.LFOCnt = LFOCnt; #endif } }