nes: FDS: use blargg's blip_buf. there are still problems with the audio channel though...
This commit is contained in:
parent
cb4288ada4
commit
34a6248606
|
@ -34,6 +34,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
bool vs_io = false;
|
||||
bool vs_coin1;
|
||||
bool vs_coin2;
|
||||
/// <summary>clock speed of the main cpu in hz</summary>
|
||||
public int cpuclockrate { get; private set; }
|
||||
|
||||
//irq state management
|
||||
public bool irq_apu { get { return _irq_apu; } set { _irq_apu = value; } }
|
||||
|
@ -84,7 +86,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
|
||||
public void GetSamples(short[] samples)
|
||||
{
|
||||
Console.WriteLine("Sync: {0}", nes.apu.dlist.Count);
|
||||
//Console.WriteLine("Sync: {0}", nes.apu.dlist.Count);
|
||||
int nsamp = samples.Length / 2;
|
||||
if (nsamp > blipbuffsize) // oh well.
|
||||
nsamp = blipbuffsize;
|
||||
|
@ -107,7 +109,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
{
|
||||
Console.WriteLine("ASync: {0}", nes.apu.dlist.Count);
|
||||
//Console.WriteLine("ASync: {0}", nes.apu.dlist.Count);
|
||||
foreach (var d in nes.apu.dlist)
|
||||
blip.AddDelta(d.time, d.value);
|
||||
nes.apu.dlist.Clear();
|
||||
|
@ -165,12 +167,9 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
ports[0] = new JoypadPortDevice(this, 0);
|
||||
ports[1] = new JoypadPortDevice(this, 1);
|
||||
|
||||
BoardSystemHardReset();
|
||||
|
||||
// don't replace the magicSoundProvider on reset, as it's not needed
|
||||
// if (magicSoundProvider != null) magicSoundProvider.Dispose();
|
||||
|
||||
|
||||
// set up region
|
||||
switch (cart.system)
|
||||
{
|
||||
|
@ -181,26 +180,23 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
ppu.region = PPU.Region.PAL;
|
||||
CoreOutputComm.VsyncNum = 50;
|
||||
CoreOutputComm.VsyncDen = 1;
|
||||
cpuclockrate = 1662607;
|
||||
cpu_sequence = cpu_sequence_PAL;
|
||||
if (magicSoundProvider == null)
|
||||
magicSoundProvider = new MagicSoundProvider(this, 1662607);
|
||||
break;
|
||||
case "NES-NTSC":
|
||||
case "Famicom":
|
||||
apu = new APU(this, apu, false);
|
||||
ppu.region = PPU.Region.NTSC;
|
||||
cpuclockrate = 1789773;
|
||||
cpu_sequence = cpu_sequence_NTSC;
|
||||
if (magicSoundProvider == null)
|
||||
magicSoundProvider = new MagicSoundProvider(this, 1789773);
|
||||
break;
|
||||
// there's no official name for these in bootgod, not sure what we should use
|
||||
//case "PC10"://TODO
|
||||
case "VS":
|
||||
apu = new APU(this, apu, false);
|
||||
ppu.region = PPU.Region.RGB;
|
||||
cpuclockrate = 1789773;
|
||||
cpu_sequence = cpu_sequence_NTSC;
|
||||
if (magicSoundProvider == null)
|
||||
magicSoundProvider = new MagicSoundProvider(this, 1789773);
|
||||
vs_io = true;
|
||||
break;
|
||||
// this is in bootgod, but not used at all
|
||||
|
@ -209,9 +205,8 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
ppu.region = PPU.Region.Dendy;
|
||||
CoreOutputComm.VsyncNum = 50;
|
||||
CoreOutputComm.VsyncDen = 1;
|
||||
cpuclockrate = 1773448;
|
||||
cpu_sequence = cpu_sequence_NTSC;
|
||||
if (magicSoundProvider == null)
|
||||
magicSoundProvider = new MagicSoundProvider(this, 1773448);
|
||||
break;
|
||||
case null:
|
||||
Console.WriteLine("Unknown NES system! Defaulting to NTSC.");
|
||||
|
@ -220,6 +215,10 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
Console.WriteLine("Unrecognized NES system \"{0}\"! Defaulting to NTSC.", cart.system);
|
||||
goto case "NES-NTSC";
|
||||
}
|
||||
if (magicSoundProvider == null)
|
||||
magicSoundProvider = new MagicSoundProvider(this, (uint)cpuclockrate);
|
||||
|
||||
BoardSystemHardReset();
|
||||
|
||||
//check fceux's PowerNES function for more information:
|
||||
//relevant games: Cybernoid; Minna no Taabou no Nakayoshi Daisakusen; Huang Di; and maybe mechanized attack
|
||||
|
|
|
@ -116,7 +116,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
Cart.board_type = "FAMICOM_DISK_SYSTEM";
|
||||
|
||||
diskdrive = new RamAdapter();
|
||||
audio = new FDSAudio();
|
||||
audio = new FDSAudio(NES.cpuclockrate);
|
||||
|
||||
InsertSide(0);
|
||||
// set mirroring??
|
||||
|
@ -386,5 +386,15 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
{
|
||||
audio.ApplyCustomAudio(samples);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
base.Dispose();
|
||||
if (audio != null)
|
||||
{
|
||||
audio.Dispose();
|
||||
audio = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ using System.Text;
|
|||
namespace BizHawk.Emulation.Consoles.Nintendo
|
||||
{
|
||||
// http://wiki.nesdev.com/w/index.php/FDS_audio
|
||||
public class FDSAudio
|
||||
public class FDSAudio : IDisposable
|
||||
{
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
|
@ -99,11 +99,25 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
|
||||
int latchedoutput;
|
||||
|
||||
/// <summary>
|
||||
/// enough room to hold roughly one frame of final output, 0-2047
|
||||
/// </summary>
|
||||
short[] samplebuff = new short[32768];
|
||||
int samplebuffpos = 0;
|
||||
public FDSAudio(int m2rate)
|
||||
{
|
||||
// minor hack: due to the way the initialization sequence goes, this might get called
|
||||
// with m2rate = 0. such an instance will never be asked for samples, though
|
||||
if (m2rate > 0)
|
||||
{
|
||||
blip = new Sound.Utilities.BlipBuffer(blipsize);
|
||||
blip.SetRates(m2rate, 44100);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (blip != null)
|
||||
{
|
||||
blip.Dispose();
|
||||
blip = null;
|
||||
}
|
||||
}
|
||||
|
||||
void CalcMod()
|
||||
{
|
||||
|
@ -134,7 +148,12 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
tmp *= waveramoutput;
|
||||
tmp *= mastervol_num;
|
||||
tmp /= mastervol_den;
|
||||
latchedoutput = tmp;
|
||||
|
||||
if (latchedoutput != tmp)
|
||||
{
|
||||
dlist.Add(new Delta(sampleclock, tmp - latchedoutput));
|
||||
latchedoutput = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -206,9 +225,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
CalcOut();
|
||||
}
|
||||
}
|
||||
samplebuff[samplebuffpos++] = (short)latchedoutput;
|
||||
// if for some reason ApplyCustomAudio() is not called, glitch up but don't crash
|
||||
samplebuffpos &= 32767;
|
||||
sampleclock++;
|
||||
}
|
||||
|
||||
public void WriteReg(int addr, byte value)
|
||||
|
@ -309,30 +326,54 @@ namespace BizHawk.Emulation.Consoles.Nintendo
|
|||
return ret;
|
||||
}
|
||||
|
||||
Sound.Utilities.DCFilter dc = Sound.Utilities.DCFilter.DetatchedMode(4096);
|
||||
Sound.Utilities.BlipBuffer blip;
|
||||
|
||||
struct Delta
|
||||
{
|
||||
public uint time;
|
||||
public int value;
|
||||
public Delta(uint time, int value)
|
||||
{
|
||||
this.time = time;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
List<Delta> dlist = new List<Delta>();
|
||||
|
||||
uint sampleclock = 0;
|
||||
const int blipsize = 4096;
|
||||
|
||||
short[] mixout = new short[blipsize];
|
||||
|
||||
public void ApplyCustomAudio(short[] samples)
|
||||
{
|
||||
for (int i = 0; i < samples.Length; i += 2)
|
||||
int nsamp = samples.Length / 2;
|
||||
if (nsamp > blipsize) // oh well.
|
||||
nsamp = blipsize;
|
||||
uint targetclock = (uint)blip.ClocksNeeded(nsamp);
|
||||
foreach (var d in dlist)
|
||||
{
|
||||
// worst imaginable resampling
|
||||
int pos = i * samplebuffpos / samples.Length;
|
||||
int samp = samplebuff[pos] * 6 - 12096;
|
||||
samp += samples[i];
|
||||
if (samp > 32767)
|
||||
samples[i] = 32767;
|
||||
else if (samp < -32768)
|
||||
samples[i] = -32768;
|
||||
else
|
||||
samples[i] = (short)samp;
|
||||
|
||||
// NES audio is mono, so this should be identical anyway
|
||||
samples[i + 1] = samples[i];
|
||||
// original deltas are in -2016..2016
|
||||
blip.AddDelta(d.time * targetclock / sampleclock, d.value * 6);
|
||||
}
|
||||
//Console.WriteLine("##{0}##", samplebuffpos);
|
||||
samplebuffpos = 0;
|
||||
//Console.WriteLine("sclock {0} tclock {1} ndelta {2}", sampleclock, targetclock, dlist.Count);
|
||||
dlist.Clear();
|
||||
blip.EndFrame(targetclock);
|
||||
sampleclock = 0;
|
||||
blip.ReadSamples(mixout, nsamp, false);
|
||||
|
||||
dc.PushThroughSamples(samples, samples.Length);
|
||||
for (int i = 0, j = 0; i < nsamp; i++, j += 2)
|
||||
{
|
||||
int s = mixout[i] + samples[j];
|
||||
if (s > 32767)
|
||||
samples[j] = 32767;
|
||||
else if (s <= -32768)
|
||||
samples[j] = -32768;
|
||||
else
|
||||
samples[j] = (short)s;
|
||||
// nes audio is mono, so we can ignore the original value of samples[j+1]
|
||||
samples[j + 1] = samples[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue