AxibugEmuOnline/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ApuEX/APU_VRC7.cs
ALIENJACK\alien 8952b842b1 APU补全中
2024-08-06 19:50:33 +08:00

97 lines
2.7 KiB
C#

using System;
using System.Net;
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 * (double)fno * blkmul[blk]) / ((double)(1 << 18) / (3579545.0 / 72.0)));
}
}
return 0;
}
}
}