111 lines
2.7 KiB
C#
111 lines
2.7 KiB
C#
using System;
|
|
using BizHawk.Emulation.Common;
|
|
|
|
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|
{
|
|
public partial class GambatteLink : ISoundProvider
|
|
{
|
|
public bool CanProvideAsync => false;
|
|
|
|
public void SetSyncMode(SyncSoundMode mode)
|
|
{
|
|
if (mode == SyncSoundMode.Async)
|
|
{
|
|
throw new NotSupportedException("Async mode is not supported.");
|
|
}
|
|
}
|
|
|
|
public SyncSoundMode SyncMode => SyncSoundMode.Sync;
|
|
|
|
public void GetSamplesSync(out short[] samples, out int nsamp)
|
|
{
|
|
nsamp = _sampleBufferContains;
|
|
samples = SampleBuffer;
|
|
}
|
|
|
|
public void GetSamplesAsync(short[] samples)
|
|
{
|
|
throw new InvalidOperationException("Async mode is not supported.");
|
|
}
|
|
|
|
public void DiscardSamples()
|
|
{
|
|
_sampleBufferContains = 0;
|
|
}
|
|
|
|
// i tried using the left and right buffers and then mixing them together... it was kind of a mess of code, and slow
|
|
private BlipBuffer _blipLeft;
|
|
private BlipBuffer _blipRight;
|
|
|
|
private readonly short[] LeftBuffer = new short[(35112 + 2064) * 2];
|
|
private readonly short[] RightBuffer = new short[(35112 + 2064) * 2];
|
|
|
|
private readonly short[] SampleBuffer = new short[1536];
|
|
private int _sampleBufferContains = 0;
|
|
|
|
private int _latchLeft;
|
|
private int _latchRight;
|
|
|
|
private unsafe void PrepSound()
|
|
{
|
|
fixed (short* sl = LeftBuffer, sr = RightBuffer)
|
|
{
|
|
for (uint i = 0; i < SampPerFrame * 2; i += 2)
|
|
{
|
|
int s = (sl[i] + sl[i + 1]) / 2;
|
|
if (s != _latchLeft)
|
|
{
|
|
_blipLeft.AddDelta(i, s - _latchLeft);
|
|
_latchLeft = s;
|
|
}
|
|
|
|
s = (sr[i] + sr[i + 1]) / 2;
|
|
if (s != _latchRight)
|
|
{
|
|
_blipRight.AddDelta(i, s - _latchRight);
|
|
_latchRight = s;
|
|
}
|
|
}
|
|
}
|
|
|
|
_blipLeft.EndFrame(SampPerFrame * 2);
|
|
_blipRight.EndFrame(SampPerFrame * 2);
|
|
int count = _blipLeft.SamplesAvailable();
|
|
if (count != _blipRight.SamplesAvailable())
|
|
{
|
|
throw new Exception("Sound problem?");
|
|
}
|
|
|
|
// calling blip.Clear() causes rounding fractions to be reset,
|
|
// and if only one channel is muted, in subsequent frames we can be off by a sample or two
|
|
// not a big deal, but we didn't account for it. so we actually complete the entire
|
|
// audio read and then stamp it out if muted.
|
|
_blipLeft.ReadSamplesLeft(SampleBuffer, count);
|
|
if (L.Muted)
|
|
{
|
|
fixed (short* p = SampleBuffer)
|
|
{
|
|
for (int i = 0; i < SampleBuffer.Length; i += 2)
|
|
{
|
|
p[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
_blipRight.ReadSamplesRight(SampleBuffer, count);
|
|
if (R.Muted)
|
|
{
|
|
fixed (short* p = SampleBuffer)
|
|
{
|
|
for (int i = 1; i < SampleBuffer.Length; i += 2)
|
|
{
|
|
p[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
_sampleBufferContains = count;
|
|
}
|
|
}
|
|
}
|