102 lines
3.4 KiB
C#
102 lines
3.4 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
|
|
namespace BizHawk.Emulation.Sound
|
|
{
|
|
public sealed partial class YM2612 : ISoundProvider
|
|
{
|
|
public readonly Channel[] Channels;
|
|
|
|
int frameStartClock;
|
|
int frameEndClock;
|
|
|
|
public YM2612()
|
|
{
|
|
Channels = new Channel[6];
|
|
Channels[0] = new Channel();
|
|
Channels[1] = new Channel();
|
|
Channels[2] = new Channel();
|
|
Channels[3] = new Channel();
|
|
Channels[4] = new Channel();
|
|
Channels[5] = new Channel();
|
|
|
|
InitTimers();
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
throw new Exception("something is resetting the ym2612");
|
|
}
|
|
|
|
public void BeginFrame(int clock)
|
|
{
|
|
frameStartClock = clock;
|
|
while (commands.Count > 0)
|
|
{
|
|
var cmd = commands.Dequeue();
|
|
WriteCommand(cmd);
|
|
}
|
|
}
|
|
|
|
public void EndFrame(int clock)
|
|
{
|
|
frameEndClock = clock;
|
|
}
|
|
|
|
public void DiscardSamples() { }
|
|
public int MaxVolume { get; set; }
|
|
|
|
public void GetSamples(short[] samples)
|
|
{
|
|
int elapsedCycles = frameEndClock - frameStartClock;
|
|
int start = 0;
|
|
while (commands.Count > 0)
|
|
{
|
|
var cmd = commands.Dequeue();
|
|
int pos = ((cmd.Clock * samples.Length) / elapsedCycles) & ~1;
|
|
GetSamplesImmediate(samples, start, pos - start);
|
|
start = pos;
|
|
WriteCommand(cmd);
|
|
}
|
|
GetSamplesImmediate(samples, start, samples.Length - start);
|
|
}
|
|
|
|
void GetSamplesImmediate(short[] samples, int pos, int length)
|
|
{
|
|
int channelVolume = MaxVolume / 6;
|
|
|
|
for (int i=0; i<length/2; i++)
|
|
{
|
|
// TODO: channels 1-5
|
|
// TODO, non-DAC
|
|
|
|
if (DacEnable)
|
|
{
|
|
short dacValue = (short)(((DacValue-80) * channelVolume) / 80);
|
|
if (Channels[5].LeftOutput) samples[pos] += dacValue;
|
|
if (Channels[5].RightOutput) samples[pos + 1] += dacValue;
|
|
}
|
|
pos += 2;
|
|
}
|
|
|
|
}
|
|
|
|
// Pg 8 major post w/ info on clock rates, envelope generator, loudness
|
|
// Note: part about EG clock is wrong, see pg 12. :|
|
|
// pg 27 contains further sets of corrections to previous pages. Jesus. Including data on SSG-EG.
|
|
// pg 32 contains some details about the LFO
|
|
// pg 33 paul jensens contains frequency conversion. gmaniac corrected.
|
|
// pg 33 blargg comments on DAC size - depends on if I WANT to emulate the inaccuracies of the DAC or a hypotheticaly perfect YM2612. more on DAC on page 37 - contradicting blargg.
|
|
|
|
/*
|
|
Chilly Willy wrote:
|
|
Hmm - does the FM channel still update even if it is set to PCM?
|
|
|
|
Yes, it does. FM Channel 6 and Reg $2A are independent of each other. "DAC mode" (Reg $2B) only chose output of one of them. If it is in "FM Mode" it outputs Channel 6 output. If it is in "DAC Mode", it outputs value stored in Reg $2A and normalized to scale of DAC (-512 to + 512). Normalization formula is
|
|
(v - $80) * 4
|
|
where v = ($2A).
|
|
|
|
I tested in on HW.
|
|
*/
|
|
}
|
|
} |