public IntSubArray(IntSubArray subarray, int offset = 0) { this.buffer = subarray.buffer; this.offset = subarray.offset + offset; }
static int OPLOpenTable() { int s, t; double rate; int i, j; double pom; /* allocate dynamic tables */ TL_TABLE = new IntSubArray(TL_MAX * 2); SIN_TABLE = new IntSubArray[SIN_ENT * 4]; AMS_TABLE = new IntSubArray(AMS_ENT * 2); VIB_TABLE = new IntSubArray(VIB_ENT * 2); /* make total level table */ for (t = 0; t < EG_ENT - 1; t++) { rate = ((1 << TL_BITS) - 1) / Math.Pow(10, EG_STEP * t / 20); /* dB . voltage */ TL_TABLE[t] = (int)rate; TL_TABLE[TL_MAX + t] = -TL_TABLE[t]; /* Log(LOG_INF,"TotalLevel(%3d) = %x\n",t,TL_TABLE[t]);*/ } /* fill volume off area */ for (t = EG_ENT - 1; t < TL_MAX; t++) { TL_TABLE[t] = TL_TABLE[TL_MAX + t] = 0; } /* make sinwave table (total level offet) */ /* degree 0 = degree 180 = off */ SIN_TABLE[0] = SIN_TABLE[SIN_ENT / 2] = new IntSubArray(TL_TABLE, EG_ENT - 1); for (s = 1; s <= SIN_ENT / 4; s++) { pom = Math.Sin(2 * Math.PI * s / SIN_ENT); /* sin */ pom = 20 * Math.Log10(1 / pom); /* decibel */ j = (int)(pom / EG_STEP); /* TL_TABLE steps */ /* degree 0 - 90 , degree 180 - 90 : plus section */ SIN_TABLE[s] = SIN_TABLE[SIN_ENT / 2 - s] = new IntSubArray(TL_TABLE, j); /* degree 180 - 270 , degree 360 - 270 : minus section */ SIN_TABLE[SIN_ENT / 2 + s] = SIN_TABLE[SIN_ENT - s] = new IntSubArray(TL_TABLE, TL_MAX + j); /* Log(LOG_INF,"sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP);*/ } for (s = 0; s < SIN_ENT; s++) { SIN_TABLE[SIN_ENT * 1 + s] = s < (SIN_ENT / 2) ? SIN_TABLE[s] : new IntSubArray(TL_TABLE, EG_ENT); SIN_TABLE[SIN_ENT * 2 + s] = SIN_TABLE[s % (SIN_ENT / 2)]; SIN_TABLE[SIN_ENT * 3 + s] = ((s / (SIN_ENT / 4)) & 1) != 0 ? new IntSubArray(TL_TABLE, EG_ENT) : SIN_TABLE[SIN_ENT * 2 + s]; } /* envelope counter . envelope output table */ for (i = 0; i < EG_ENT; i++) { /* ATTACK curve */ pom = Math.Pow(((double)(EG_ENT - 1 - i) / EG_ENT), 8) * EG_ENT; /* if( pom >= EG_ENT ) pom = EG_ENT-1; */ ENV_CURVE[i] = (int)pom; /* DECAY ,RELEASE curve */ ENV_CURVE[(EG_DST >> ENV_BITS) + i] = i; } /* off */ ENV_CURVE[EG_OFF >> ENV_BITS] = EG_ENT - 1; /* make LFO ams table */ for (i = 0; i < AMS_ENT; i++) { pom = (1.0 + Math.Sin(2 * Math.PI * i / AMS_ENT)) / 2; /* sin */ AMS_TABLE[i] = (int)((1.0 / EG_STEP) * pom); /* 1dB */ AMS_TABLE[AMS_ENT + i] = (int)((4.8 / EG_STEP) * pom); /* 4.8dB */ } /* make LFO vibrate table */ for (i = 0; i < VIB_ENT; i++) { /* 100cent = 1seminote = 6% ?? */ pom = (double)VIB_RATE * 0.06 * Math.Sin(2 * Math.PI * i / VIB_ENT); /* +-100sect step */ VIB_TABLE[i] = (int)(VIB_RATE + (pom * 0.07)); /* +- 7cent */ VIB_TABLE[VIB_ENT + i] = (int)(VIB_RATE + (pom * 0.14)); /* +-14cent */ /* Log(LOG_INF,"vib %d=%d\n",i,VIB_TABLE[VIB_ENT+i]); */ } return 1; }
public static void YM3812UpdateOne(FM_OPL OPL, _ShortPtr buffer, int length) { int i; int data; _ShortPtr buf = buffer; uint amsCnt = (uint)OPL.amsCnt; uint vibCnt = (uint)OPL.vibCnt; byte rythm = (byte)(OPL.rythm & 0x20); OPL_CH CH; int R_CH; if ((object)OPL != cur_chip) { cur_chip = OPL; /* channel pointers */ S_CH = OPL.P_CH; E_CH = 9;// 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 != 0 ? 6 : E_CH; for (i = 0; i < length; i++) { /* channel A channel B channel C */ /* LFO */ ams = ams_table[(int)((amsCnt += (uint)amsIncr) >> AMS_SHIFT)]; vib = vib_table[(int)((vibCnt += (uint)vibIncr) >> VIB_SHIFT)]; outd[0] = 0; /* FM part */ for (int k = 0; k != R_CH; k++) { CH = S_CH[k]; //for(CH=S_CH ; CH < R_CH ; CH++) OPL_CALC_CH(CH); } /* Rythn part */ if (rythm != 0) OPL_CALC_RH(S_CH); /* limit check */ data = Limit(outd[0], OPL_MAXOUT, OPL_MINOUT); /* store to sound buffer */ buf.write16(i, (ushort)(data >> OPL_OUTSB)); } OPL.amsCnt = (int)amsCnt; OPL.vibCnt = (int)vibCnt; }
static void OPMInitTable(int num) { YM2151 OPM = (FMOPM[num]); int i; double pom; double rate; if (FMOPM[num].ST.rate != 0) rate = (double)(1 << FREQ_BITS) / (3579545.0 / FMOPM[num].ST.clock * FMOPM[num].ST.rate); else rate = 1; for (i = 0; i < 8 * 12 * 64 + 950; i++) { /* This calculation type was used from the Jarek's YM2151 emulator */ pom = 6.875 * Math.Pow(2, ((i + 4 * 64) * 1.5625 / 1200.0)); /*13.75Hz is note A 12semitones below A-0, so D#0 is 4 semitones above then*/ /*calculate phase increment for above precounted Hertz value*/ OPM.KC_TABLE[i] = (uint)(pom * rate); /*Log(LOG_WAR,"OPM KC %d = %x\n",i,OPM.KC_TABLE[i]);*/ } /* make time tables */ init_timetables(OPM.ST, OPM_DTTABLE, OPM_ARRATE, OPM_DRRATE); #if FM_LFO_SUPPORT /* LFO wave table */ for (i = 0; i < LFO_ENT; i++) { OPM.LFO_wave[i] = LFO_RATE * i / LFO_ENT / 127; OPM.LFO_wave[LFO_ENT + i] = (i < LFO_ENT / 2 ? 0 : LFO_RATE) / 127; OPM.LFO_wave[LFO_ENT * 2 + i] = LFO_RATE * (i < LFO_ENT / 2 ? i : LFO_ENT - i) / (LFO_ENT / 2) / 127; OPM.LFO_wave[LFO_ENT * 3 + i] = LFO_RATE * (Mame.rand() & 0xff) / 256 / 127; } #endif /* NOISE wave table */ for (i = 0; i < SIN_ENT; i++) { int sign = (Mame.rand() & 1) != 0 ? TL_MAX : 0; int lev = Mame.rand() & 0x1ff; //pom = lev ? 20*log10(0x200/lev) : 0; /* decibel */ //NOISE_TABLE[i] = &TL_TABLE[sign + (int)(pom / EG_STEP)]; /* TL_TABLE steps */ NOISE_TABLE[i] = new IntSubArray(TL_TABLE, sign + lev * EG_ENT / 0x200); /* TL_TABLE steps */ } }
static void OPLCloseTable() { TL_TABLE = null; SIN_TABLE = null; AMS_TABLE = null; VIB_TABLE = null; }
/* set sustain rate */ static void set_sr(FM_SLOT SLOT, int v, IntSubArray dr_table) { SLOT.SR = (v &= 0x1f) != 0 ? new IntSubArray(dr_table, v << 1) : new IntSubArray(RATE_0); SLOT.evss = SLOT.SR[SLOT.ksr]; if (SLOT.eg_next == FM_EG_SR) SLOT.evs = SLOT.evss; }
/* set release rate */ static void set_sl_rr(FM_SLOT SLOT, int v, IntSubArray dr_table) { SLOT.SL = SL_TABLE[(v >> 4)]; SLOT.RR = new IntSubArray(dr_table, ((v & 0x0f) << 2) | 2); SLOT.evsr = SLOT.RR[SLOT.ksr]; if (SLOT.eg_next == FM_EG_Release) SLOT.evs = SLOT.evsr; }
static void setup_connection(FM_CH CH) { IntSubArray carrier = new IntSubArray(out_ch,CH.PAN); /* NONE,LEFT,RIGHT or CENTER */ switch (CH.ALGO) { case 0: /* PG---S1---S2---S3---S4---OUT */ CH.connect1 = new IntSubArray(pg_in2); CH.connect2 = new IntSubArray(pg_in3); CH.connect3 = new IntSubArray(pg_in4); break; case 1: /* PG---S1-+-S3---S4---OUT */ /* PG---S2-+ */ CH.connect1 = new IntSubArray(pg_in3); CH.connect2 = new IntSubArray(pg_in3); CH.connect3 = new IntSubArray(pg_in4); break; case 2: /* PG---S1------+-S4---OUT */ /* PG---S2---S3-+ */ CH.connect1 = new IntSubArray(pg_in4); CH.connect2 = new IntSubArray(pg_in3); CH.connect3 = new IntSubArray(pg_in4); break; case 3: /* PG---S1---S2-+-S4---OUT */ /* PG---S3------+ */ CH.connect1 = new IntSubArray(pg_in2); CH.connect2 = new IntSubArray(pg_in4); CH.connect3 = new IntSubArray(pg_in4); break; case 4: /* PG---S1---S2-+--OUT */ /* PG---S3---S4-+ */ CH.connect1 = new IntSubArray(pg_in2); CH.connect2 = new IntSubArray(carrier); CH.connect3 = new IntSubArray(pg_in4); break; case 5: /* +-S2-+ */ /* PG---S1-+-S3-+-OUT */ /* +-S4-+ */ CH.connect1 = null; /* special case */ CH.connect2 = new IntSubArray(carrier); CH.connect3 = new IntSubArray(carrier); break; case 6: /* PG---S1---S2-+ */ /* PG--------S3-+-OUT */ /* PG--------S4-+ */ CH.connect1 = new IntSubArray(pg_in2); CH.connect2 = new IntSubArray(carrier); CH.connect3 = new IntSubArray(carrier); break; case 7: /* PG---S1-+ */ /* PG---S2-+-OUT */ /* PG---S3-+ */ /* PG---S4-+ */ CH.connect1 = new IntSubArray(carrier); CH.connect2 = new IntSubArray(carrier); CH.connect3 = new IntSubArray(carrier); break; } CH.connect4 = carrier; }
/* set attack rate & key scale */ static void set_ar_ksr(FM_CH CH, FM_SLOT SLOT, int v, IntSubArray ar_table) { SLOT.KSR = (byte)(3 - (v >> 6)); SLOT.AR = (v &= 0x1f) != 0 ? new IntSubArray(ar_table, v << 1) : new IntSubArray(RATE_0); SLOT.evsa = SLOT.AR[SLOT.ksr]; if (SLOT.eg_next == FM_EG_AR) SLOT.evs = SLOT.evsa; CH.SLOT[SLOT1].Incr = unchecked((uint)-1); }
static int FMInitTable() { int s, t; double rate; int i, j; double pom; /* allocate total level table plus+minus section */ TL_TABLE = new int[2 * TL_MAX]; /* make total level table */ for (t = 0; t < TL_MAX; t++) { if (t >= PG_CUT_OFF) rate = 0; /* under cut off area */ else rate = ((1 << TL_BITS) - 1) / Math.Pow(10, EG_STEP * t / 20); /* dB . voltage */ TL_TABLE[t] = (int)rate; TL_TABLE[TL_MAX + t] = -TL_TABLE[t]; /* Log(LOG_INF,"TotalLevel(%3d) = %x\n",t,TL_TABLE[t]);*/ } /* make sinwave table (total level offet) */ for (s = 1; s <= SIN_ENT / 4; s++) { pom = Math.Sin(2.0 * Math.PI * s / SIN_ENT); /* sin */ pom = 20 * Math.Log10(1 / pom); /* . decibel */ j = (int)(pom / EG_STEP); /* TL_TABLE steps */ /* cut off check */ if (j > PG_CUT_OFF) j = PG_CUT_OFF; /* degree 0 - 90 , degree 180 - 90 : plus section */ SIN_TABLE[s] = SIN_TABLE[SIN_ENT / 2 - s] = new IntSubArray(TL_TABLE, j); /* degree 180 - 270 , degree 360 - 270 : minus section */ SIN_TABLE[SIN_ENT / 2 + s] = SIN_TABLE[SIN_ENT - s] = new IntSubArray(TL_TABLE, TL_MAX + j); /* Log(LOG_INF,"sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP); */ } /* degree 0 = degree 180 = off */ SIN_TABLE[0] = SIN_TABLE[SIN_ENT / 2] = new IntSubArray(TL_TABLE, PG_CUT_OFF); /* envelope counter . envelope output table */ for (i = 0; i < EG_ENT; i++) { /* ATTACK curve */ /* !!!!! preliminary !!!!! */ pom = Math.Pow(((double)(EG_ENT - 1 - i) / EG_ENT), 8) * EG_ENT; /* if( pom >= EG_ENT ) pom = EG_ENT-1; */ ENV_CURVE[i] = (int)pom; /* DECAY ,RELEASE curve */ ENV_CURVE[(EG_DST >> ENV_BITS) + i] = i; #if FM_SEG_SUPPORT /* DECAY UPSIDE (SSG ENV) */ ENV_CURVE[(EG_UST>>ENV_BITS)+i]= EG_ENT-1-i; #endif } /* off */ ENV_CURVE[EG_OFF >> ENV_BITS] = EG_ENT - 1; /* decay to reattack envelope converttable */ j = EG_ENT - 1; for (i = 0; i < EG_ENT; i++) { while (j != 0 && (ENV_CURVE[j] < i)) j--; DRAR_TABLE[i] = j << ENV_BITS; /* Log(LOG_INF,"DR %06X = %06X,AR=%06X\n",i,DRAR_TABLE[i],ENV_CURVE[DRAR_TABLE[i]>>ENV_BITS] ); */ } return 1; }
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 } }
static void set_algorythm(OPL_CH CH) { IntSubArray carrier = new IntSubArray(outd); CH.connect1 = CH.CON != 0 ? carrier : new IntSubArray(feedback2); CH.connect2 = carrier; }
static int palette_start() { int num; game_palette = new byte[3 * Machine.drv.total_colors]; palette_map = new ushort[Machine.drv.total_colors]; if (Machine.drv.color_table_len != 0) { Machine.game_colortable = new ushort[(int)Machine.drv.color_table_len]; Machine.remapped_colortable = new ushort[Machine.drv.color_table_len];// new UShortSubArray((int)Machine.drv.color_table_len); } else { Machine.game_colortable = null; Machine.remapped_colortable = null; } if (Machine.color_depth == 16 || (Machine.gamedrv.flags & GAME_REQUIRES_16BIT) != 0) { if (Machine.color_depth == 8 || Machine.drv.total_colors > 65532) use_16bit = STATIC_16BIT; else use_16bit = PALETTIZED_16BIT; } else use_16bit = NO_16BIT; switch (use_16bit) { case NO_16BIT: if ((Machine.drv.video_attributes & VIDEO_MODIFIES_PALETTE) != 0) total_shrinked_pens = DYNAMIC_MAX_PENS; else total_shrinked_pens = STATIC_MAX_PENS; break; case STATIC_16BIT: total_shrinked_pens = 32768; break; case PALETTIZED_16BIT: total_shrinked_pens = (int)(Machine.drv.total_colors + RESERVED_PENS); break; } shrinked_pens = new ushort[total_shrinked_pens]; shrinked_palette = new byte[3 * total_shrinked_pens]; Machine.pens = new ushort[Machine.drv.total_colors]; if ((Machine.drv.video_attributes & VIDEO_MODIFIES_PALETTE) != 0) { /* if the palette changes dynamically, */ /* we'll need the usage arrays to help in shrinking. */ palette_used_colors = new _BytePtr(((int)((1 + 1 + 1 + 3 + 1) * Machine.drv.total_colors * sizeof(byte)))); pen_visiblecount = new IntSubArray((int)(2 * Machine.drv.total_colors)); if (palette_used_colors == null || pen_visiblecount == null) { palette_stop(); return 1; } old_used_colors = new _BytePtr(palette_used_colors, (int)Machine.drv.total_colors * sizeof(byte)); just_remapped = new _BytePtr(old_used_colors, (int)Machine.drv.total_colors * sizeof(byte)); new_palette = new _BytePtr(just_remapped, (int)Machine.drv.total_colors * sizeof(byte)); palette_dirty = new _BytePtr(new_palette, 3 * (int)Machine.drv.total_colors * sizeof(byte)); memset(palette_used_colors, PALETTE_COLOR_USED, (int)Machine.drv.total_colors * sizeof(byte)); memset(old_used_colors, PALETTE_COLOR_UNUSED, (int)Machine.drv.total_colors * sizeof(byte)); memset(palette_dirty, 0, (int)(Machine.drv.total_colors * sizeof(byte))); pen_cachedcount = new IntSubArray(pen_visiblecount, (int)Machine.drv.total_colors); for (int i = 0; i < Machine.drv.total_colors; i++) { pen_visiblecount[i] = 0; pen_cachedcount[i] = 0; } } else palette_used_colors = old_used_colors = just_remapped = new_palette = palette_dirty = null; if (Machine.color_depth == 8) num = 256; else num = 65536; palette_shadow_table = new UShortSubArray(2 * num); if (palette_shadow_table == null) { palette_stop(); return 1; } palette_highlight_table = new UShortSubArray(palette_shadow_table, num); for (int i = 0; i < num; i++) { palette_shadow_table[i] = (ushort)i; palette_highlight_table[i] = (ushort)i; } if ((Machine.drv.color_table_len != 0 && (Machine.game_colortable == null || Machine.remapped_colortable == null)) || game_palette == null || palette_map == null || shrinked_pens == null || shrinked_palette == null || Machine.pens == null) { palette_stop(); return 1; } return 0; }
static void palette_stop() { //free(palette_used_colors); palette_used_colors = old_used_colors = just_remapped = new_palette = palette_dirty = null; //free(pen_visiblecount); pen_visiblecount = null; //free(game_palette); game_palette = null; //free(palette_map); palette_map = null; //free(Machine.game_colortable); Machine.game_colortable = null; //free(Machine.remapped_colortable); Machine.remapped_colortable = null; // free(shrinked_pens); shrinked_pens = null; // free(shrinked_palette); shrinked_palette = null; //free(Machine.pens); Machine.pens = null; //free(palette_shadow_table); palette_shadow_table = null; }