using System; using VirtualNes.Core.Emu2413; namespace VirtualNes.Core { public class APU_VRC7 : APU_INTERFACE { OPLL VRC7_OPLL; byte address; public APU_VRC7() { Emu2413API.OPLL_init(3579545, 22050); // 仮のサンプリングレート VRC7_OPLL = Emu2413API.OPLL_new(); if (VRC7_OPLL != null) { Emu2413API.OPLL_reset(VRC7_OPLL); Emu2413API.OPLL_reset_patch(VRC7_OPLL, Emu2413API.OPLL_VRC7_TONE); VRC7_OPLL.masterVolume = 128; } // 仮設定 Reset(APU_CLOCK, 22050); } public override void Dispose() { if (VRC7_OPLL != null) { Emu2413API.OPLL_delete(VRC7_OPLL); VRC7_OPLL = null; // OPLL_close(); // 無くても良い(中身無し) } } public override void Reset(float fClock, int nRate) { if (VRC7_OPLL != null) { Emu2413API.OPLL_reset(VRC7_OPLL); Emu2413API.OPLL_reset_patch(VRC7_OPLL, Emu2413API.OPLL_VRC7_TONE); VRC7_OPLL.masterVolume = 128; } address = 0; Setup(fClock, nRate); } public override void Setup(float fClock, int nRate) { Emu2413API.OPLL_setClock((UInt32)(fClock * 2.0f), (UInt32)nRate); } public override void Write(ushort addr, byte data) { if (VRC7_OPLL != null) { if (addr == 0x9010) { address = data; } else if (addr == 0x9030) { Emu2413API.OPLL_writeReg(VRC7_OPLL, address, data); } } } public override int Process(int channel) { if (VRC7_OPLL != null) return Emu2413API.OPLL_calc(VRC7_OPLL); return 0; } float[] blkmul = { 0.5f, 1.0f, 2.0f, 4.0f, 8.0f, 16.0f, 32.0f, 64.0f }; public override int GetFreq(int channel) { if (VRC7_OPLL != null && channel < 8) { int fno = ((VRC7_OPLL.reg[0x20 + channel] & 0x01) << 8) + VRC7_OPLL.reg[0x10 + channel]; int blk = (VRC7_OPLL.reg[0x20 + channel] >> 1) & 0x07; if ((VRC7_OPLL.reg[0x20 + channel] & 0x10) != 0) { return (int)((256.0d * fno * blkmul[blk]) / ((1 << 18) / (3579545.0 / 72.0))); } } return 0; } public override uint GetSize() { return 0; } public override void SaveState(StateBuffer buffer) { //not impl } } }