89 lines
2.0 KiB
C#
89 lines
2.0 KiB
C#
namespace StoicGoose.Core.Sound
|
|
{
|
|
/* Channel 4, supports noise */
|
|
public sealed class SoundChannel4
|
|
{
|
|
const int counterReload = 2048;
|
|
|
|
readonly static byte[] noiseLfsrTaps = { 14, 10, 13, 4, 8, 6, 9, 11 };
|
|
|
|
ushort counter;
|
|
byte pointer;
|
|
|
|
public byte OutputLeft { get; set; }
|
|
public byte OutputRight { get; set; }
|
|
|
|
readonly WaveTableReadDelegate waveTableReadDelegate;
|
|
|
|
/* REG_SND_CH4_PITCH */
|
|
public ushort Pitch { get; set; }
|
|
/* REG_SND_CH4_VOL */
|
|
public byte VolumeLeft { get; set; }
|
|
public byte VolumeRight { get; set; }
|
|
/* REG_SND_CTRL */
|
|
public bool IsEnabled { get; set; }
|
|
public bool IsNoiseEnabled { get; set; }
|
|
|
|
/* REG_SND_NOISE */
|
|
public byte NoiseMode { get; set; }
|
|
public bool NoiseReset { get; set; }
|
|
public bool NoiseEnable { get; set; }
|
|
/* REG_SND_RANDOM */
|
|
public ushort NoiseLfsr { get; set; }
|
|
|
|
public SoundChannel4(WaveTableReadDelegate waveTableRead) => waveTableReadDelegate = waveTableRead;
|
|
|
|
public void Reset()
|
|
{
|
|
counter = counterReload;
|
|
pointer = 0;
|
|
OutputLeft = OutputRight = 0;
|
|
|
|
Pitch = 0;
|
|
VolumeLeft = VolumeRight = 0;
|
|
IsEnabled = false;
|
|
|
|
IsNoiseEnabled = false;
|
|
|
|
NoiseMode = 0;
|
|
NoiseReset = NoiseEnable = false;
|
|
NoiseLfsr = 0;
|
|
}
|
|
|
|
public void Step()
|
|
{
|
|
counter--;
|
|
if (counter == Pitch)
|
|
{
|
|
if (NoiseEnable)
|
|
{
|
|
var tap = noiseLfsrTaps[NoiseMode];
|
|
var noise = (1 ^ (NoiseLfsr >> 7) ^ (NoiseLfsr >> tap)) & 0b1;
|
|
NoiseLfsr = (ushort)(((NoiseLfsr << 1) | noise) & 0x7FFF);
|
|
}
|
|
|
|
var data = IsNoiseEnabled ? ((NoiseLfsr & 0b1) * 0x0F) : waveTableReadDelegate((ushort)(pointer >> 1));
|
|
if (!IsNoiseEnabled)
|
|
{
|
|
if ((pointer & 0b1) == 0b1) data >>= 4;
|
|
data &= 0x0F;
|
|
}
|
|
|
|
OutputLeft = (byte)(data * VolumeLeft);
|
|
OutputRight = (byte)(data * VolumeRight);
|
|
|
|
if (NoiseReset)
|
|
{
|
|
NoiseLfsr = 0;
|
|
OutputLeft = OutputRight = 0;
|
|
NoiseReset = false;
|
|
}
|
|
|
|
pointer++;
|
|
pointer &= 0b11111;
|
|
counter = counterReload;
|
|
}
|
|
}
|
|
}
|
|
}
|