89 lines
1.8 KiB
C#
89 lines
1.8 KiB
C#
namespace StoicGoose.Core.Sound
|
|
{
|
|
/* Channel 3, has optional sweep */
|
|
public sealed class SoundChannel3
|
|
{
|
|
const int counterReload = 2048;
|
|
const int sweepReload = 32 * 256;
|
|
|
|
ushort counter;
|
|
byte pointer;
|
|
|
|
public byte OutputLeft { get; set; }
|
|
public byte OutputRight { get; set; }
|
|
|
|
int sweepCounter;
|
|
int sweepCycles;
|
|
|
|
readonly WaveTableReadDelegate waveTableReadDelegate;
|
|
|
|
/* REG_SND_CH3_PITCH */
|
|
public ushort Pitch { get; set; }
|
|
/* REG_SND_CH3_VOL */
|
|
public byte VolumeLeft { get; set; }
|
|
public byte VolumeRight { get; set; }
|
|
/* REG_SND_CTRL */
|
|
public bool IsEnabled { get; set; }
|
|
public bool IsSweepEnabled { get; set; }
|
|
|
|
/* REG_SND_SWEEP_VALUE */
|
|
public sbyte SweepValue { get; set; }
|
|
/* REG_SND_SWEEP_TIME */
|
|
public byte SweepTime { get; set; }
|
|
|
|
public SoundChannel3(WaveTableReadDelegate waveTableRead) => waveTableReadDelegate = waveTableRead;
|
|
|
|
public void Reset()
|
|
{
|
|
counter = counterReload;
|
|
pointer = 0;
|
|
OutputLeft = OutputRight = 0;
|
|
|
|
Pitch = 0;
|
|
VolumeLeft = VolumeRight = 0;
|
|
IsEnabled = false;
|
|
|
|
IsSweepEnabled = false;
|
|
|
|
sweepCounter = 0;
|
|
sweepCycles = sweepReload;
|
|
|
|
SweepValue = 0;
|
|
SweepTime = 0;
|
|
}
|
|
|
|
public void Step()
|
|
{
|
|
if (IsSweepEnabled)
|
|
{
|
|
sweepCycles--;
|
|
if (sweepCycles == 0)
|
|
{
|
|
sweepCounter--;
|
|
if (sweepCounter <= 0)
|
|
{
|
|
sweepCounter = SweepTime;
|
|
Pitch = (ushort)(Pitch + SweepValue);
|
|
}
|
|
}
|
|
sweepCycles = sweepReload;
|
|
}
|
|
|
|
counter--;
|
|
if (counter == Pitch)
|
|
{
|
|
var data = waveTableReadDelegate((ushort)(pointer >> 1));
|
|
if ((pointer & 0b1) == 0b1) data >>= 4;
|
|
data &= 0x0F;
|
|
|
|
OutputLeft = (byte)(data * VolumeLeft);
|
|
OutputRight = (byte)(data * VolumeRight);
|
|
|
|
pointer++;
|
|
pointer &= 0b11111;
|
|
counter = counterReload;
|
|
}
|
|
}
|
|
}
|
|
}
|