public static void OPL3_SlotGenerate(ref opl3_slot slot) { unsafe { slot._out = envelope_sin[slot.reg_wf]((ushort)(slot.pg_phase_out + *slot.mod), (ushort)(slot.eg_out)); } }
public static void OPL3_SlotWriteE0(ref opl3_slot slot, byte data) { slot.reg_wf = (byte)(data & 0x07); if (slot.chip.newm == 0x00) { slot.reg_wf &= 0x03; } }
public static void OPL3_SlotWrite80(ref opl3_slot slot, byte data) { slot.reg_sl = (byte)((data >> 4) & 0x0f); if (slot.reg_sl == 0x0f) { slot.reg_sl = 0x1f; } slot.reg_rr = (byte)(data & 0x0f); }
public static void OPL3_EnvelopeUpdateKSL(ref opl3_slot slot) { short ksl = (short)((kslrom[slot.channel.f_num >> 6] << 2) - ((0x08 - slot.channel.block) << 5)); if (ksl < 0) { ksl = 0; } slot.eg_ksl = (byte)ksl; }
public static void OPL3_SlotCalcFB(ref opl3_slot slot) { if (slot.channel.fb != 0x00) { slot.fbmod = (short)((slot.prout + slot._out) >> (0x09 - slot.channel.fb)); } else { slot.fbmod = 0; } slot.prout = slot._out; }
// // Slot // public static void OPL3_SlotWrite20(ref opl3_slot slot, byte data) { unsafe { if (((data >> 7) & 0x01) != 0) { //slot.trem = slot.chip.tremolo; slot.tremZero = false; } else { //slot.trem = (byte)slot.chip.zeromod; slot.tremZero = true; } slot.reg_vib = (byte)((data >> 6) & 0x01); slot.reg_type = (byte)((data >> 5) & 0x01); slot.reg_ksr = (byte)((data >> 4) & 0x01); slot.reg_mult = (byte)(data & 0x0f); } }
static void OPL3_SlotWrite60(ref opl3_slot slot, byte data) { slot.reg_ar = (byte)((data >> 4) & 0x0f); slot.reg_dr = (byte)(data & 0x0f); }
static void OPL3_SlotWrite40(ref opl3_slot slot, byte data) { slot.reg_ksl = (byte)((data >> 6) & 0x03); slot.reg_tl = (byte)(data & 0x3f); OPL3_EnvelopeUpdateKSL(ref slot); }
// // Phase Generator // public static void OPL3_PhaseGenerate(ref opl3_slot slot) { opl3_chip chip; ushort f_num; uint basefreq; byte rm_xor, n_bit; uint noise; ushort phase; chip = slot.chip; f_num = slot.channel.f_num; if (slot.reg_vib != 0) { sbyte range; byte vibpos; range = (sbyte)((f_num >> 7) & 7); vibpos = slot.chip.vibpos; if ((vibpos & 3) == 0) { range = 0; } else if ((vibpos & 1) != 0) { range >>= 1; } range >>= slot.chip.vibshift; if ((vibpos & 4) != 0) { range = (sbyte)-range; } f_num += (ushort)range; } basefreq = (uint)((f_num << slot.channel.block) >> 1); phase = (ushort)(slot.pg_phase >> 9); if (slot.pg_reset != 0) { slot.pg_phase = 0; } slot.pg_phase += (basefreq * mt[slot.reg_mult]) >> 1; // Rhythm mode noise = chip.noise; slot.pg_phase_out = phase; if (slot.slot_num == 13) // hh { chip.rm_hh_bit2 = (byte)((phase >> 2) & 1); chip.rm_hh_bit3 = (byte)((phase >> 3) & 1); chip.rm_hh_bit7 = (byte)((phase >> 7) & 1); chip.rm_hh_bit8 = (byte)((phase >> 8) & 1); } if (slot.slot_num == 17 && (chip.rhy & 0x20) != 0) // tc { chip.rm_tc_bit3 = (byte)((phase >> 3) & 1); chip.rm_tc_bit5 = (byte)((phase >> 5) & 1); } if ((chip.rhy & 0x20) != 0) { rm_xor = (byte)((chip.rm_hh_bit2 ^ chip.rm_hh_bit7) | (chip.rm_hh_bit3 ^ chip.rm_tc_bit5) | (chip.rm_tc_bit3 ^ chip.rm_tc_bit5)); switch (slot.slot_num) { case 13: // hh slot.pg_phase_out = (ushort)(rm_xor << 9); if ((rm_xor ^ (noise & 1)) != 0) { slot.pg_phase_out |= 0xd0; } else { slot.pg_phase_out |= 0x34; } break; case 16: // sd slot.pg_phase_out = (ushort)((chip.rm_hh_bit8 << 9) | ((chip.rm_hh_bit8 ^ (noise & 1)) << 8)); break; case 17: // tc slot.pg_phase_out = (ushort)((rm_xor << 9) | 0x80); break; default: break; } } n_bit = (byte)(((noise >> 14) ^ noise) & 0x01); chip.noise = (byte)((noise >> 1) | (n_bit << 22)); }
public static void OPL3_EnvelopeKeyOff(ref opl3_slot slot, EnvelopeKeyType type) { slot.key &= (byte)~type; }
static void OPL3_EnvelopeKeyOn(ref opl3_slot slot, EnvelopeKeyType type) { slot.key |= (byte)type; }
public static void OPL3_EnvelopeCalc(ref opl3_slot slot) { byte nonzero; byte rate; byte rate_hi; byte rate_lo; byte reg_rate = 0; byte ks; byte eg_shift, shift; ushort eg_rout; short eg_inc; byte eg_off; byte reset = 0; //unsafe //{ // slot.eg_out = (short)(slot.eg_rout + (slot.reg_tl << 2) + (slot.eg_ksl >> kslshift[slot.reg_ksl]) + *slot.trem); //} slot.eg_out = (short)(slot.eg_rout + (slot.reg_tl << 2) + (slot.eg_ksl >> kslshift[slot.reg_ksl]) + (slot.tremZero == false ? slot.chip.tremolo : 0)); if (slot.key != 0 && slot.eg_gen == envelope_gen_num.release) { reset = 1; reg_rate = slot.reg_ar; } else { switch (slot.eg_gen) { case envelope_gen_num.attack: reg_rate = slot.reg_ar; break; case envelope_gen_num.decay: reg_rate = slot.reg_dr; break; case envelope_gen_num.sustain: unsafe { if (slot.reg_type == 0) { reg_rate = slot.reg_rr; } } break; case envelope_gen_num.release: reg_rate = slot.reg_rr; break; } } slot.pg_reset = reset; ks = (byte)(slot.channel.ksv >> ((slot.reg_ksr ^ 1) << 1)); nonzero = (byte)((reg_rate != 0) ? 1 : 0); rate = (byte)(ks + (reg_rate << 2)); rate_hi = (byte)(rate >> 2); rate_lo = (byte)(rate & 0x03); if ((rate_hi & 0x10) != 0) { rate_hi = 0x0f; } eg_shift = (byte)(rate_hi + slot.chip.eg_add); shift = 0; if (nonzero != 0) { if (rate_hi < 12) { if (slot.chip.eg_state != 0) { switch (eg_shift) { case 12: shift = 1; break; case 13: shift = (byte)((rate_lo >> 1) & 0x01); break; case 14: shift = (byte)(rate_lo & 0x01); break; default: break; } } } else { shift = (byte)((rate_hi & 0x03) + eg_incstep[rate_lo][slot.chip.timer & 0x03]); if ((shift & 0x04) != 0) { shift = 0x03; } if (shift == 0) { shift = slot.chip.eg_state; } } } eg_rout = (ushort)slot.eg_rout; eg_inc = 0; eg_off = 0; // Instant attack if (reset != 0 && rate_hi == 0x0f) { eg_rout = 0x00; } // Envelope off if ((slot.eg_rout & 0x1f8) == 0x1f8) { eg_off = 1; } if (slot.eg_gen != envelope_gen_num.attack && reset == 0 && eg_off != 0) { eg_rout = 0x1ff; } switch (slot.eg_gen) { case envelope_gen_num.attack: if (slot.eg_rout == 0) { slot.eg_gen = envelope_gen_num.decay; } else if (slot.key != 0 && shift > 0 && rate_hi != 0x0f) { eg_inc = (short)(((~slot.eg_rout) << shift) >> 4); } break; case envelope_gen_num.decay: if ((slot.eg_rout >> 4) == slot.reg_sl) { slot.eg_gen = envelope_gen_num.sustain; } else if (eg_off == 0 && reset == 0 && shift > 0) { eg_inc = (short)(1 << (shift - 1)); } break; case envelope_gen_num.sustain: case envelope_gen_num.release: if (eg_off == 0 && reset == 0 && shift > 0) { eg_inc = (short)(1 << (shift - 1)); } break; } slot.eg_rout = (short)((eg_rout + eg_inc) & 0x1ff); // Key off if (reset != 0) { slot.eg_gen = envelope_gen_num.attack; } if (slot.key == 0) { slot.eg_gen = envelope_gen_num.release; } }