add metaspu V method, set NES to use it experimentally

This commit is contained in:
beirich 2011-08-14 01:42:54 +00:00
parent c7178543c7
commit cfccc65672
3 changed files with 135 additions and 2 deletions

View File

@ -922,7 +922,7 @@ namespace BizHawk.Emulation.Consoles.Nintendo
last_hwsamp = this_samp;
}
MetaspuSoundProvider metaspu = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_Z);
MetaspuSoundProvider metaspu = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
void ISoundProvider.GetSamples(short[] samples)
{

View File

@ -104,11 +104,17 @@ namespace BizHawk.DiscSystem
f = (byte) (lba - (m * 75 * 60) - (s * 75));
}
// converts MSF to LBA offset
public static int ConvertMSFtoLBA(byte m, byte s, byte f)
{
return f + (s*75) + (m*75*60);
}
// gets an identifying hash. hashes the first 512 sectors of
// the first data track on the disc.
public string GetHash()
{
byte[] buffer = new byte[512*2353];
byte[] buffer = new byte[512*2352];
foreach (var track in TOC.Sessions[0].Tracks)
{
if (track.TrackType == ETrackType.Audio)

View File

@ -40,6 +40,7 @@ namespace BizHawk.Emulation.Sound
ESynchMethod_N, //nitsuja's
ESynchMethod_Z, //zero's
//ESynchMethod_P, //PCSX2 spu2-x //ohno! not available yet in c#
ESynchMethod_V // vecna
};
public static class Metaspu
@ -52,6 +53,8 @@ namespace BizHawk.Emulation.Sound
return new ZeromusSynchronizer();
case ESynchMethod.ESynchMethod_N:
return new NitsujaSynchronizer();
case ESynchMethod.ESynchMethod_V:
return new VecnaSynchronizer();
default:
return new NitsujaSynchronizer();
}
@ -522,4 +525,128 @@ namespace BizHawk.Emulation.Sound
}; //NitsujaSynchronizer
class VecnaSynchronizer : ISynchronizingAudioBuffer
{
// vecna's attempt at a fully synchronous sound provider.
// It's similar in philosophy to my "BufferedAsync" provider, but BufferedAsync is not
// fully synchronous.
// Like BufferedAsync, it tries to make most frames 100% correct and just suck it up
// periodically and have a big bad-sounding mistake frame if it has to.
// It is significantly less ambitious and elaborate than the other methods.
// We'll see if it works better or not!
// It has a min and maximum amount of excess buffer to deal with minor overflows.
// When fastforwarding, it will discard samples above the maximum excess buffer.
// When underflowing, it will attempt to resample to a certain threshhold.
// If it underflows beyond that threshhold, it will give up and output silence.
// Since it has done this, it will go ahead and generate some excess silence in order
// to restock its excess buffer.
struct Sample
{
public short left, right;
public Sample(short l, short r)
{
left = l;
right = r;
}
}
private Queue<Sample> buffer;
private Sample[] resampleBuffer;
private const int SamplesInOneFrame = 735;
private const int MaxExcessSamples = 2048;
public VecnaSynchronizer()
{
buffer = new Queue<Sample>(2048);
resampleBuffer = new Sample[2730]; // 2048 * 1.25
// Give us a little buffer wiggle-room
for (int i=0; i<367; i++)
buffer.Enqueue(new Sample(0,0));
}
public void enqueue_samples(short[] buf, int samples_provided)
{
throw new Exception("bluh");
int samplesToEnqueue = samples_provided;
if (samples_provided + buffer.Count > MaxExcessSamples)
samplesToEnqueue = MaxExcessSamples - buffer.Count;
//for (int i = 0; i < samplesToEnqueue; i++)
//buffer.Enqueue(buf[i]);
Console.WriteLine("enqueue {0} samples, buffer at {1}/4096 max capacity, {2} excess samples",
samplesToEnqueue, buffer.Count, buffer.Count - SamplesInOneFrame);
}
public void enqueue_sample(short left, short right)
{
if (buffer.Count >= MaxExcessSamples - 1)
{
// if buffer is overfull, dequeue old samples to make room for new samples.
buffer.Dequeue();
}
buffer.Enqueue(new Sample(left, right));
}
public void clear()
{
Console.WriteLine("clear requested... but why! it makes me sad :'(");
buffer.Clear();
}
public int output_samples(short[] buf, int samples_requested)
{
if (samples_requested > buffer.Count)
{
// underflow!
if (buffer.Count > samples_requested * 3 / 4)
{
// if we're within 75% of target, then I guess we suck it up and resample.
// we sample in a goofy way, we could probably do it a bit smarter, if we cared more.
Console.WriteLine("REASONABLE UNDERFLOW, RESAMPLING.");
if (samples_requested > 2730)
throw new Exception("something rather bad has happened");
int samples_available = buffer.Count;
for (int i = 0; buffer.Count > 0; i++)
resampleBuffer[i] = buffer.Dequeue();
int index = 0;
for (int i = 0; i<samples_requested; i++)
{
Sample sample = resampleBuffer[i*samples_available/samples_requested];
buf[index++] = sample.left;
buf[index++] = sample.right;
}
} else {
// we're outside of a "reasonable" underflow. Give up and output silence.
Console.WriteLine("EXCESSIVE UNDERFLOW. GIVE UP AND MAKE A POP");
}
}
else
{
// normal operation
Console.WriteLine("samples in buffer {0}, requested {1}", buffer.Count, samples_requested);
int index = 0;
for (int i = 0; i < samples_requested && buffer.Count > 0; i++)
{
Sample sample = buffer.Dequeue();
buf[index++] = sample.left;
buf[index++] = sample.right;
}
}
return samples_requested;
}
}
}