Swag up NullSound

This commit is contained in:
nattthebear 2016-12-11 14:07:12 -05:00
parent b465eaa470
commit eb72ff9053
4 changed files with 62 additions and 24 deletions

View File

@ -22,7 +22,7 @@ namespace BizHawk.Client.EmuHawk
// Sound refactor TODO: we could try set it here, but we want the client to be responsible for mode switching? There may be non-trivial complications with when to switch modes that we don't want this object worrying about
if (asyncSoundProvider.SyncMode != SyncSoundMode.Async)
{
throw new InvalidOperationException("Only sync mode is supported, set sync mode before passing in the sound provider");
throw new InvalidOperationException("Only async mode is supported, set async mode before passing in the sound provider");
}
if (!aset || !vset)

View File

@ -734,16 +734,7 @@ namespace BizHawk.Client.EmuHawk
_currentVideoProvider = NullVideo.Instance;
}
if (Global.Emulator.HasSoundProvider())
{
_currentSoundProvider = Global.Emulator.AsSoundProvider();
}
else
{
// Set the samples per frame based on VSync rate (which is 60 unless the core states otherwise)
// Use 44.1 khz because we like to do that
_currentSoundProvider = new NullSound((int)(44100 / Global.Emulator.CoreComm.VsyncRate));
}
_currentSoundProvider = Global.Emulator.AsSoundProviderOrDefault();
}
}

View File

@ -4,43 +4,76 @@ namespace BizHawk.Emulation.Common
{
public class NullSound : ISoundProvider
{
private readonly int _spf;
private readonly long _spfNumerator;
private readonly long _spfDenominator;
private long _remainder = 0;
private short[] _buff = new short[0];
public NullSound(int spf)
private NullSound()
{
_spf = spf;
SyncMode = SyncSoundMode.Sync;
}
/// <summary>
/// create a NullSound that provides an exact number of audio samples per call when in sync mode
/// </summary>
/// <param name="spf"></param>
public NullSound(int spf)
:this()
{
_spfNumerator = spf;
_spfDenominator = 1;
}
/// <summary>
/// create a NullSound that exactly matches a given framerate when in sync mode
/// </summary>
/// <param name="fpsNum"></param>
/// <param name="fpsDen"></param>
public NullSound(long fpsNum, long fpsDen)
{
_spfNumerator = fpsDen * 44100;
_spfDenominator = fpsNum;
}
public bool CanProvideAsync
{
get { return false; }
get { return true; }
}
public SyncSoundMode SyncMode
{
get { return SyncSoundMode.Sync; }
get;
private set;
}
public void GetSamplesSync(out short[] samples, out int nsamp)
{
short[] ret = new short[_spf * 2];
samples = ret;
nsamp = _spf;
if (SyncMode != SyncSoundMode.Sync)
throw new InvalidOperationException("Wrong sound mode");
int s = (int)((_spfNumerator + _remainder) / _spfDenominator);
_remainder = (_spfNumerator + _remainder) % _spfDenominator;
if (_buff.Length < s * 2)
_buff = new short[s * 2];
samples = _buff;
nsamp = s;
}
public void DiscardSamples() { }
public void SetSyncMode(SyncSoundMode mode)
{
if (mode == SyncSoundMode.Async)
{
throw new NotSupportedException("Async mode is not supported.");
}
SyncMode = mode;
}
public void GetSamplesAsync(short[] samples)
{
throw new InvalidOperationException("Async mode is not supported.");
if (SyncMode != SyncSoundMode.Async)
throw new InvalidOperationException("Wrong sound mode");
Array.Clear(samples, 0, samples.Length);
}
}
}

View File

@ -2,6 +2,7 @@
using System.Linq;
using System.Reflection;
using BizHawk.Common.ReflectionExtensions;
using System.Runtime.CompilerServices;
namespace BizHawk.Emulation.Common.IEmulatorExtensions
{
@ -48,6 +49,19 @@ namespace BizHawk.Emulation.Common.IEmulatorExtensions
return core.ServiceProvider.GetService<ISoundProvider>();
}
private static readonly ConditionalWeakTable<IEmulator, ISoundProvider> CachedNullSoundProviders = new ConditionalWeakTable<IEmulator, ISoundProvider>();
/// <summary>
/// returns the core's SoundProvider, or a suitable dummy provider
/// </summary>
public static ISoundProvider AsSoundProviderOrDefault(this IEmulator core)
{
var ret = core.ServiceProvider.GetService<ISoundProvider>();
if (ret == null)
ret = CachedNullSoundProviders.GetValue(core, e => new NullSound(e.CoreComm.VsyncNum, e.CoreComm.VsyncDen));
return ret;
}
public static bool HasMemoryDomains(this IEmulator core)
{
if (core == null)