Major sound provider refactor. Create a unified interface ISoundProvider, that is an IEmulator service and break it off of IEmulator. IAsyncSoundProvider was kept as a shim for now, for legacy cores that were inherintly async.
This commit is contained in:
parent
5ac6746fb9
commit
b73a500d6b
|
@ -17,8 +17,14 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
private long _soundRemainder; // audio timekeeping for video dumping
|
||||
|
||||
public void DumpAV(IVideoProvider v, IAsyncSoundProvider s, out short[] samples, out int samplesprovided)
|
||||
public void DumpAV(IVideoProvider v, ISoundProvider asyncSoundProvider, out short[] samples, out int samplesprovided)
|
||||
{
|
||||
// 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");
|
||||
}
|
||||
|
||||
if (!aset || !vset)
|
||||
throw new InvalidOperationException("Must set params first!");
|
||||
|
||||
|
@ -29,7 +35,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
_soundRemainder = nsampnum % fpsnum;
|
||||
|
||||
samples = new short[nsamp * channels];
|
||||
s.GetSamples(samples);
|
||||
asyncSoundProvider.GetSamplesAsync(samples);
|
||||
samplesprovided = (int)nsamp;
|
||||
|
||||
w.AddFrame(v);
|
||||
|
@ -73,10 +79,16 @@ namespace BizHawk.Client.EmuHawk
|
|||
}
|
||||
}
|
||||
|
||||
public void DumpAV(IVideoProvider v, ISyncSoundProvider s, out short[] samples, out int samplesprovided)
|
||||
public void DumpAV(IVideoProvider v, ISoundProvider syncSoundProvider, out short[] samples, out int samplesprovided)
|
||||
{
|
||||
// Sound refactor TODO: we could just 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 (syncSoundProvider.SyncMode != SyncSoundMode.Sync)
|
||||
{
|
||||
throw new InvalidOperationException("Only sync mode is supported, set sync mode before passing in the sound provider");
|
||||
}
|
||||
|
||||
VerifyParams();
|
||||
s.GetSamples(out samples, out samplesprovided);
|
||||
syncSoundProvider.GetSamplesSync(out samples, out samplesprovided);
|
||||
exaudio_num += samplesprovided * (long)fpsnum;
|
||||
|
||||
// todo: scan for duplicate frames (ie, video content exactly matches previous frame) and for them, skip the threshone step
|
||||
|
|
|
@ -733,11 +733,24 @@ 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IVideoProvider _currentVideoProvider = NullVideo.Instance;
|
||||
|
||||
private ISoundProvider _currentSoundProvider = new NullSound(44100 / 60); // Reasonable default until we have a core instance
|
||||
|
||||
protected override void OnActivated(EventArgs e)
|
||||
{
|
||||
base.OnActivated(e);
|
||||
|
@ -1345,7 +1358,10 @@ namespace BizHawk.Client.EmuHawk
|
|||
// AVI/WAV state
|
||||
private IVideoWriter _currAviWriter;
|
||||
private HashSet<int> _currAviWriterFrameList;
|
||||
private IAsyncSoundProvider _aviSoundInput;
|
||||
|
||||
// Sound refator TODO: we can enforce async mode here with a property that gets/sets this but does an async check
|
||||
private ISoundProvider _aviSoundInputAsync; // Note: This sound provider must be in async mode!
|
||||
|
||||
private MetaspuSoundProvider _dumpProxy; // an audio proxy used for dumping
|
||||
private bool _dumpaudiosync; // set true to for experimental AV dumping
|
||||
private int _avwriterResizew;
|
||||
|
@ -1620,8 +1636,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
}
|
||||
else
|
||||
{
|
||||
Emulator.EndAsyncSound();
|
||||
GlobalWin.Sound.SetSyncInputPin(Emulator.SyncSoundProvider);
|
||||
GlobalWin.Sound.SetSyncInputPin(_currentSoundProvider);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3096,13 +3111,14 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
if (_dumpaudiosync)
|
||||
{
|
||||
Emulator.EndAsyncSound();
|
||||
_currentSoundProvider.SetSyncMode(SyncSoundMode.Sync);
|
||||
}
|
||||
else
|
||||
{
|
||||
_aviSoundInput = !Emulator.StartAsyncSound()
|
||||
? new MetaspuAsync(Emulator.SyncSoundProvider, ESynchMethod.ESynchMethod_V)
|
||||
: Emulator.SoundProvider;
|
||||
_aviSoundInputAsync = _currentSoundProvider.CanProvideAsync
|
||||
? _currentSoundProvider
|
||||
: new MetaspuAsync(_currentSoundProvider, ESynchMethod.ESynchMethod_V);
|
||||
|
||||
}
|
||||
_dumpProxy = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
|
||||
RewireSound();
|
||||
|
@ -3123,7 +3139,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
AVIStatusLabel.Image = Properties.Resources.Blank;
|
||||
AVIStatusLabel.ToolTipText = string.Empty;
|
||||
AVIStatusLabel.Visible = false;
|
||||
_aviSoundInput = null;
|
||||
_aviSoundInputAsync = null;
|
||||
_dumpProxy = null; // return to normal sound output
|
||||
RewireSound();
|
||||
}
|
||||
|
@ -3144,7 +3160,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
AVIStatusLabel.Image = Properties.Resources.Blank;
|
||||
AVIStatusLabel.ToolTipText = string.Empty;
|
||||
AVIStatusLabel.Visible = false;
|
||||
_aviSoundInput = null;
|
||||
_aviSoundInputAsync = null;
|
||||
_dumpProxy = null; // return to normal sound output
|
||||
RewireSound();
|
||||
}
|
||||
|
@ -3226,11 +3242,11 @@ namespace BizHawk.Client.EmuHawk
|
|||
int nsamp;
|
||||
if (_dumpaudiosync)
|
||||
{
|
||||
(_currAviWriter as VideoStretcher).DumpAV(output, Emulator.SyncSoundProvider, out samp, out nsamp);
|
||||
(_currAviWriter as VideoStretcher).DumpAV(output, _currentSoundProvider, out samp, out nsamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
(_currAviWriter as AudioStretcher).DumpAV(output, _aviSoundInput, out samp, out nsamp);
|
||||
(_currAviWriter as AudioStretcher).DumpAV(output, _aviSoundInputAsync, out samp, out nsamp);
|
||||
}
|
||||
|
||||
if (disposableOutput != null)
|
||||
|
@ -3238,7 +3254,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
disposableOutput.Dispose();
|
||||
}
|
||||
|
||||
_dumpProxy.buffer.enqueue_samples(samp, nsamp);
|
||||
_dumpProxy.Buffer.enqueue_samples(samp, nsamp);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -15,8 +15,9 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
private bool _disposed;
|
||||
private ISoundOutput _soundOutput;
|
||||
private ISyncSoundProvider _syncSoundProvider;
|
||||
private IAsyncSoundProvider _asyncSoundProvider;
|
||||
|
||||
private ISoundProvider _soundProvider;
|
||||
|
||||
private SoundOutputProvider _outputProvider;
|
||||
private readonly BufferedAsync _semiSync = new BufferedAsync();
|
||||
|
||||
|
@ -61,16 +62,11 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
_outputProvider = new SoundOutputProvider();
|
||||
_outputProvider.MaxSamplesDeficit = _soundOutput.MaxSamplesDeficit;
|
||||
_outputProvider.BaseSoundProvider = _syncSoundProvider;
|
||||
_outputProvider.BaseSoundProvider = _soundProvider;
|
||||
|
||||
Global.SoundMaxBufferDeficitMs = (int)Math.Ceiling(SamplesToMilliseconds(_soundOutput.MaxSamplesDeficit));
|
||||
|
||||
IsStarted = true;
|
||||
|
||||
//ApplyVolumeSettings();
|
||||
|
||||
//LogUnderruns = true;
|
||||
//_outputProvider.LogDebug = true;
|
||||
}
|
||||
|
||||
public void StopSound()
|
||||
|
@ -86,46 +82,28 @@ namespace BizHawk.Client.EmuHawk
|
|||
IsStarted = false;
|
||||
}
|
||||
|
||||
//public void ApplyVolumeSettings()
|
||||
//{
|
||||
// if (!IsStarted) return;
|
||||
|
||||
// double volume = Global.Config.SoundVolume / 100.0;
|
||||
// if (volume < 0.0) volume = 0.0;
|
||||
// if (volume > 1.0) volume = 1.0;
|
||||
// _soundOutput.ApplyVolumeSettings(volume);
|
||||
//}
|
||||
|
||||
public void SetSyncInputPin(ISyncSoundProvider source)
|
||||
// Sound refactor TODO: combine these methods, and check the SyncMode for behavior
|
||||
public void SetSyncInputPin(ISoundProvider source)
|
||||
{
|
||||
if (_asyncSoundProvider != null)
|
||||
{
|
||||
_asyncSoundProvider.DiscardSamples();
|
||||
_asyncSoundProvider = null;
|
||||
}
|
||||
_semiSync.DiscardSamples();
|
||||
_semiSync.BaseSoundProvider = null;
|
||||
_syncSoundProvider = source;
|
||||
_semiSync.ClearSoundProvider();
|
||||
_soundProvider = source;
|
||||
if (_outputProvider != null)
|
||||
{
|
||||
_outputProvider.BaseSoundProvider = source;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetAsyncInputPin(IAsyncSoundProvider source)
|
||||
public void SetAsyncInputPin(ISoundProvider source)
|
||||
{
|
||||
if (_syncSoundProvider != null)
|
||||
{
|
||||
_syncSoundProvider.DiscardSamples();
|
||||
_syncSoundProvider = null;
|
||||
}
|
||||
if (_outputProvider != null)
|
||||
{
|
||||
_outputProvider.DiscardSamples();
|
||||
_outputProvider.BaseSoundProvider = null;
|
||||
}
|
||||
_asyncSoundProvider = source;
|
||||
_semiSync.BaseSoundProvider = source;
|
||||
|
||||
_soundProvider = source;
|
||||
_semiSync.SetAsyncSoundProvider(source);
|
||||
_semiSync.RecalculateMagic(Global.Emulator.CoreComm.VsyncRate);
|
||||
}
|
||||
|
||||
|
@ -169,8 +147,10 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
if (!Global.Config.SoundEnabled || !IsStarted || _disposed)
|
||||
{
|
||||
if (_asyncSoundProvider != null) _asyncSoundProvider.DiscardSamples();
|
||||
if (_syncSoundProvider != null) _syncSoundProvider.DiscardSamples();
|
||||
if (_soundProvider != null) _soundProvider.DiscardSamples();
|
||||
// Sound refactor TODO: delete me
|
||||
//if (_asyncSoundProvider != null) _asyncSoundProvider.DiscardSamples();
|
||||
//if (_syncSoundProvider != null) _syncSoundProvider.DiscardSamples();
|
||||
if (_outputProvider != null) _outputProvider.DiscardSamples();
|
||||
return;
|
||||
}
|
||||
|
@ -188,15 +168,18 @@ namespace BizHawk.Client.EmuHawk
|
|||
samples = new short[samplesNeeded * ChannelCount];
|
||||
samplesProvided = samplesNeeded;
|
||||
|
||||
if (_asyncSoundProvider != null) _asyncSoundProvider.DiscardSamples();
|
||||
if (_syncSoundProvider != null) _syncSoundProvider.DiscardSamples();
|
||||
if (_soundProvider != null) _soundProvider.DiscardSamples();
|
||||
// Sound refactor TODO: delete me
|
||||
//if (_asyncSoundProvider != null) _asyncSoundProvider.DiscardSamples();
|
||||
//if (_syncSoundProvider != null) _syncSoundProvider.DiscardSamples();
|
||||
if (_outputProvider != null) _outputProvider.DiscardSamples();
|
||||
}
|
||||
else if (_syncSoundProvider != null)
|
||||
else if ( _soundProvider.SyncMode == SyncSoundMode.Sync)
|
||||
//else if (_syncSoundProvider != null) // Sound refactor TODO: delete me
|
||||
{
|
||||
if (Global.Config.SoundThrottle)
|
||||
{
|
||||
_syncSoundProvider.GetSamples(out samples, out samplesProvided);
|
||||
_soundProvider.GetSamplesSync(out samples, out samplesProvided);
|
||||
|
||||
while (samplesNeeded < samplesProvided && !Global.DisableSecondaryThrottling)
|
||||
{
|
||||
|
@ -213,11 +196,12 @@ namespace BizHawk.Client.EmuHawk
|
|||
_outputProvider.GetSamples(samplesNeeded, out samples, out samplesProvided);
|
||||
}
|
||||
}
|
||||
else if (_asyncSoundProvider != null)
|
||||
else if (_soundProvider != null && _soundProvider.SyncMode == SyncSoundMode.Sync)
|
||||
//else if (_asyncSoundProvider != null) // Sound refactor TODO: delete me
|
||||
{
|
||||
samples = new short[samplesNeeded * ChannelCount];
|
||||
|
||||
_semiSync.GetSamples(samples);
|
||||
_semiSync.GetSamplesAsync(samples);
|
||||
|
||||
samplesProvided = samplesNeeded;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,21 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
public int MaxSamplesDeficit { get; set; }
|
||||
|
||||
public ISyncSoundProvider BaseSoundProvider { get; set; }
|
||||
// Sound Refactor TODO: is this sync mode check necessary?
|
||||
private ISoundProvider _baseSoundProvider;
|
||||
public ISoundProvider BaseSoundProvider
|
||||
{
|
||||
get { return _baseSoundProvider; }
|
||||
set
|
||||
{
|
||||
if (value != null && value.SyncMode != SyncSoundMode.Sync)
|
||||
{
|
||||
throw new InvalidOperationException("Sync mode is required");
|
||||
}
|
||||
|
||||
_baseSoundProvider = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
|
@ -164,7 +178,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
short[] samples;
|
||||
int count;
|
||||
|
||||
BaseSoundProvider.GetSamples(out samples, out count);
|
||||
BaseSoundProvider.GetSamplesSync(out samples, out count);
|
||||
|
||||
bool correctedEmptyFrame = false;
|
||||
if (count == 0)
|
||||
|
|
|
@ -180,8 +180,13 @@ namespace BizHawk.Client.EmuHawk
|
|||
int nsamp;
|
||||
short[] samp;
|
||||
emu.FrameAdvance(true, true);
|
||||
|
||||
// some cores really really really like it if you drain their audio every frame
|
||||
emu.SyncSoundProvider.GetSamples(out samp, out nsamp);
|
||||
if (emu.HasSoundProvider())
|
||||
{
|
||||
emu.AsSoundProvider().GetSamplesSync(out samp, out nsamp);
|
||||
}
|
||||
|
||||
current.Frames++;
|
||||
if (emu.CanPollInput() && emu.AsInputPollable().IsLagFrame)
|
||||
current.LaggedFrames++;
|
||||
|
|
|
@ -9,10 +9,11 @@ namespace BizHawk.Emulation.Common
|
|||
[CoreAttributes("NullHawk", "", false, true)]
|
||||
[ServiceNotApplicable(typeof(IStatable), typeof(ISaveRam), typeof(IDriveLight), typeof(ICodeDataLogger), typeof(IMemoryDomains),
|
||||
typeof(IDebuggable), typeof(IDisassemblable), typeof(IInputPollable), typeof(IRegionable), typeof(ITraceable))]
|
||||
public class NullEmulator : IEmulator, IVideoProvider, ISyncSoundProvider, IAsyncSoundProvider, ISettable<NullEmulator.NullEmulatorSettings, object>
|
||||
public class NullEmulator : IEmulator, IVideoProvider, ISoundProvider, ISettable<NullEmulator.NullEmulatorSettings, object>
|
||||
{
|
||||
public NullEmulator(CoreComm comm, object settings)
|
||||
{
|
||||
SyncMode = SyncSoundMode.Sync;
|
||||
ServiceProvider = new BasicServiceProvider(this);
|
||||
CoreComm = comm;
|
||||
_settings = (NullEmulatorSettings)settings ?? new NullEmulatorSettings();
|
||||
|
@ -34,10 +35,6 @@ namespace BizHawk.Emulation.Common
|
|||
private readonly int[] frameBuffer = new int[256 * 192];
|
||||
private readonly Random rand = new Random();
|
||||
public CoreComm CoreComm { get; private set; }
|
||||
public IAsyncSoundProvider SoundProvider { get { return this; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return true; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public void ResetCounters()
|
||||
{
|
||||
|
@ -94,8 +91,15 @@ namespace BizHawk.Emulation.Common
|
|||
|
||||
private short[] sampbuff = new short[735 * 2];
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
#region ISoundProvider
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
if (SyncMode != SyncSoundMode.Sync)
|
||||
{
|
||||
throw new InvalidOperationException("Attempt to call a Sync method in async mode");
|
||||
}
|
||||
|
||||
nsamp = 735;
|
||||
samples = sampbuff;
|
||||
if (!_settings.SnowyDisplay)
|
||||
|
@ -108,20 +112,33 @@ namespace BizHawk.Emulation.Common
|
|||
{
|
||||
}
|
||||
|
||||
public void GetSamples(short[] samples)
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
if (SyncMode != SyncSoundMode.Async)
|
||||
{
|
||||
throw new InvalidOperationException("Attempt to call an Async method in sync mode");
|
||||
}
|
||||
|
||||
if (!_settings.SnowyDisplay)
|
||||
return;
|
||||
if (xmas)
|
||||
pleg.Generate(samples);
|
||||
}
|
||||
|
||||
public int MaxVolume
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get;
|
||||
set;
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode { get; private set; }
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
SyncMode = mode;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private NullEmulatorSettings _settings;
|
||||
|
||||
public class NullEmulatorSettings
|
||||
|
|
|
@ -1,10 +1,46 @@
|
|||
namespace BizHawk.Emulation.Common
|
||||
{
|
||||
public class NullSound : IAsyncSoundProvider
|
||||
{
|
||||
public static readonly NullSound SilenceProvider = new NullSound();
|
||||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.Common
|
||||
{
|
||||
public class NullSound : ISoundProvider
|
||||
{
|
||||
private readonly int _spf;
|
||||
|
||||
public NullSound(int spf)
|
||||
{
|
||||
_spf = spf;
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
short[] ret = new short[_spf * 2];
|
||||
samples = ret;
|
||||
nsamp = _spf;
|
||||
}
|
||||
|
||||
public void GetSamples(short[] samples) { }
|
||||
public void DiscardSamples() { }
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,8 +123,8 @@
|
|||
<Compile Include="Interfaces\IInputCallbackSystem.cs" />
|
||||
<Compile Include="Interfaces\IMemoryCallbackSystem.cs" />
|
||||
<Compile Include="Interfaces\IEmulatorServiceProvider.cs" />
|
||||
<Compile Include="Interfaces\ISoundProvider.cs" />
|
||||
<Compile Include="Interfaces\ISyncSoundProvider.cs" />
|
||||
<Compile Include="Interfaces\Services\ISoundProvider.cs" />
|
||||
<Compile Include="Interfaces\IAsyncSoundProvider.cs" />
|
||||
<Compile Include="Interfaces\Services\ICodeDataLogger.cs" />
|
||||
<Compile Include="Interfaces\Services\IDebuggable.cs" />
|
||||
<Compile Include="Interfaces\Services\IDisassemblable.cs" />
|
||||
|
|
|
@ -33,6 +33,21 @@ namespace BizHawk.Emulation.Common.IEmulatorExtensions
|
|||
return core.ServiceProvider.GetService<IVideoProvider>();
|
||||
}
|
||||
|
||||
public static bool HasSoundProvider(this IEmulator core)
|
||||
{
|
||||
if (core == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return core.ServiceProvider.HasService<ISoundProvider>();
|
||||
}
|
||||
|
||||
public static ISoundProvider AsSoundProvider(this IEmulator core)
|
||||
{
|
||||
return core.ServiceProvider.GetService<ISoundProvider>();
|
||||
}
|
||||
|
||||
public static bool HasMemoryDomains(this IEmulator core)
|
||||
{
|
||||
if (core == null)
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
using System;
|
||||
|
||||
namespace BizHawk.Emulation.Common
|
||||
{
|
||||
public interface IAsyncSoundProvider
|
||||
{
|
||||
void GetSamples(short[] samples);
|
||||
void DiscardSamples();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TODO: this is a shim for now
|
||||
/// turns an IAsyncSoundPRovider into a full ISoundProvider
|
||||
/// This is used in cores that have an async only sound implementation
|
||||
/// better is impleemnt a sync sound option in those cores without the need for
|
||||
/// this class or an IAsyncSoundPRovider interface
|
||||
/// </summary>
|
||||
public class FakeSyncSound : ISoundProvider
|
||||
{
|
||||
private readonly IAsyncSoundProvider source;
|
||||
private readonly int spf;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="spf">number of sample pairs to request and provide on each GetSamples() call</param>
|
||||
public FakeSyncSound(IAsyncSoundProvider source, int spf)
|
||||
{
|
||||
this.source = source;
|
||||
this.spf = spf;
|
||||
SyncMode = SyncSoundMode.Sync;
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
if (SyncMode != SyncSoundMode.Sync)
|
||||
{
|
||||
throw new InvalidOperationException("Must be in sync mode to call a sync method");
|
||||
}
|
||||
|
||||
short[] ret = new short[spf * 2];
|
||||
source.GetSamples(ret);
|
||||
samples = ret;
|
||||
nsamp = spf;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
source.DiscardSamples();
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
if (SyncMode != SyncSoundMode.Async)
|
||||
{
|
||||
throw new InvalidOperationException("Must be in async mode to call an async method");
|
||||
}
|
||||
|
||||
source.GetSamples(samples);
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode { get; private set; }
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
SyncMode = mode;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,24 +12,6 @@ namespace BizHawk.Emulation.Common
|
|||
/// <returns></returns>
|
||||
IEmulatorServiceProvider ServiceProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sound provider for async operation. this is optional, and is only required after StartAsyncSound() is called and returns true
|
||||
/// </summary>
|
||||
IAsyncSoundProvider SoundProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// sound provider for sync operation. this is manditory
|
||||
/// </summary>
|
||||
ISyncSoundProvider SyncSoundProvider { get; }
|
||||
|
||||
/// <summary>start async operation. (on construct, sync operation is assumed).</summary>
|
||||
/// <returns>false if core doesn't support async sound; SyncSoundProvider will continue to be used in that case</returns>
|
||||
bool StartAsyncSound();
|
||||
/// <summary>
|
||||
/// end async operation, returning to sync operation. after this, all sound requests will go to the SyncSoundProvider
|
||||
/// </summary>
|
||||
void EndAsyncSound();
|
||||
|
||||
/// <summary>
|
||||
/// Defines all the possible inputs and types that the core can receive
|
||||
/// </summary>
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
namespace BizHawk.Emulation.Common
|
||||
{
|
||||
public interface IAsyncSoundProvider
|
||||
{
|
||||
void GetSamples(short[] samples);
|
||||
void DiscardSamples();
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
namespace BizHawk.Emulation.Common
|
||||
{
|
||||
public interface ISyncSoundProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="nsamp">number of sample PAIRS available</param>
|
||||
void GetSamples(out short[] samples, out int nsamp);
|
||||
|
||||
void DiscardSamples();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// wraps an ISyncSoundProvider around an ISoundProvider
|
||||
/// </summary>
|
||||
public class FakeSyncSound : ISyncSoundProvider
|
||||
{
|
||||
private readonly IAsyncSoundProvider source;
|
||||
private readonly int spf;
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <param name="spf">number of sample pairs to request and provide on each GetSamples() call</param>
|
||||
public FakeSyncSound(IAsyncSoundProvider source, int spf)
|
||||
{
|
||||
this.source = source;
|
||||
this.spf = spf;
|
||||
}
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
{
|
||||
short[] ret = new short[spf * 2];
|
||||
source.GetSamples(ret);
|
||||
samples = ret;
|
||||
nsamp = spf;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
source.DiscardSamples();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
namespace BizHawk.Emulation.Common
|
||||
{
|
||||
public enum SyncSoundMode { Sync, Async };
|
||||
|
||||
public interface ISoundProvider : IEmulatorService
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns true if a core can provide Async sound
|
||||
/// </summary>
|
||||
bool CanProvideAsync { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets sync or async sound mode,
|
||||
/// Sync should be the default mode if not set
|
||||
/// All implementations must provide sync
|
||||
/// If a core can not provide async sound and the mode is set to sync,
|
||||
/// an NotSupportedException should be thrown
|
||||
/// </summary>
|
||||
void SetSyncMode(SyncSoundMode mode);
|
||||
|
||||
/// <summary>
|
||||
/// Reports which mode the sound provider is currently in
|
||||
/// </summary>
|
||||
SyncSoundMode SyncMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Provides samples in syncmode
|
||||
/// If the core is not in sync mode, this should throw an InvalidOperationException
|
||||
/// </summary>
|
||||
void GetSamplesSync(out short[] samples, out int nsamp);
|
||||
|
||||
/// <summary>
|
||||
/// Provides samples in async mode
|
||||
/// If the core is not in async mode, this shoudl throw an InvalidOperationException
|
||||
/// </summary>
|
||||
/// <param name="samples"></param>
|
||||
void GetSamplesAsync(short[] samples);
|
||||
|
||||
/// <summary>
|
||||
/// Discards stuff, is there anything more to say here?
|
||||
/// </summary>
|
||||
void DiscardSamples();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BizHawk.Emulation.Common
|
||||
{
|
||||
|
@ -27,10 +28,24 @@ namespace BizHawk.Emulation.Common
|
|||
* TODO: For systems that _really_ don't need BufferedAsync (pce not turbocd, sms), make a way to signal
|
||||
* that and then bypass the BufferedAsync.
|
||||
*/
|
||||
|
||||
public sealed class BufferedAsync : IAsyncSoundProvider
|
||||
public sealed class BufferedAsync : ISoundProvider
|
||||
{
|
||||
public IAsyncSoundProvider BaseSoundProvider;
|
||||
private ISoundProvider _baseSoundProvider;
|
||||
|
||||
public void SetAsyncSoundProvider(ISoundProvider provider)
|
||||
{
|
||||
if (provider.SyncMode != SyncSoundMode.Async)
|
||||
{
|
||||
throw new InvalidOperationException("a sound provider in async mode is required");
|
||||
}
|
||||
|
||||
_baseSoundProvider = provider;
|
||||
}
|
||||
|
||||
public void ClearSoundProvider()
|
||||
{
|
||||
_baseSoundProvider = null;
|
||||
}
|
||||
|
||||
readonly Queue<short> buffer = new Queue<short>(4096);
|
||||
|
||||
|
@ -50,11 +65,11 @@ namespace BizHawk.Emulation.Common
|
|||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
if (BaseSoundProvider != null)
|
||||
BaseSoundProvider.DiscardSamples();
|
||||
if (_baseSoundProvider != null)
|
||||
_baseSoundProvider.DiscardSamples();
|
||||
}
|
||||
|
||||
public void GetSamples(short[] samples)
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
int samplesToGenerate = SamplesInOneFrame;
|
||||
if (buffer.Count > samples.Length + MaxExcessSamples)
|
||||
|
@ -66,7 +81,7 @@ namespace BizHawk.Emulation.Common
|
|||
|
||||
var mySamples = new short[samplesToGenerate];
|
||||
|
||||
BaseSoundProvider.GetSamples(mySamples);
|
||||
_baseSoundProvider.GetSamplesAsync(mySamples);
|
||||
|
||||
foreach (short s in mySamples)
|
||||
{
|
||||
|
@ -78,5 +93,28 @@ namespace BizHawk.Emulation.Common
|
|||
samples[i] = buffer.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Async; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode != SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,24 +5,18 @@ namespace BizHawk.Emulation.Common
|
|||
/// <summary>
|
||||
/// implements a DC block filter on top of an ISoundProvider. rather simple.
|
||||
/// </summary>
|
||||
sealed public class DCFilter : IAsyncSoundProvider, ISyncSoundProvider
|
||||
sealed public class DCFilter : ISoundProvider
|
||||
{
|
||||
/*
|
||||
* A note about accuracy:
|
||||
*
|
||||
* DCFilter can be added to the final output of any console, and this change will be faithful to the original hardware.
|
||||
* Analog output hardware ALWAYS has dc blocking caps.
|
||||
*/
|
||||
private ISoundProvider _soundProvider;
|
||||
|
||||
IAsyncSoundProvider input;
|
||||
ISyncSoundProvider syncinput;
|
||||
private int latchL = 0;
|
||||
private int latchR = 0;
|
||||
private int accumL = 0;
|
||||
private int accumR = 0;
|
||||
|
||||
int latchL = 0;
|
||||
int latchR = 0;
|
||||
int accumL = 0;
|
||||
int accumR = 0;
|
||||
private int depth;
|
||||
|
||||
static int DepthFromFilterwidth(int filterwidth)
|
||||
private static int DepthFromFilterwidth(int filterwidth)
|
||||
{
|
||||
int ret = -2;
|
||||
while (filterwidth > 0)
|
||||
|
@ -33,34 +27,34 @@ namespace BizHawk.Emulation.Common
|
|||
return ret;
|
||||
}
|
||||
|
||||
int depth;
|
||||
|
||||
public static DCFilter AsISoundProvider(IAsyncSoundProvider input, int filterwidth)
|
||||
public DCFilter(ISoundProvider input, int filterwidth)
|
||||
{
|
||||
if (input == null)
|
||||
throw new ArgumentNullException();
|
||||
return new DCFilter(input, null, filterwidth);
|
||||
}
|
||||
|
||||
public static DCFilter AsISyncSoundProvider(ISyncSoundProvider syncinput, int filterwidth)
|
||||
{
|
||||
if (syncinput == null)
|
||||
throw new ArgumentNullException();
|
||||
return new DCFilter(null, syncinput, filterwidth);
|
||||
}
|
||||
|
||||
public static DCFilter DetatchedMode(int filterwidth)
|
||||
if (filterwidth < 8 || filterwidth > 65536)
|
||||
{
|
||||
return new DCFilter(null, null, filterwidth);
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
DCFilter(IAsyncSoundProvider input, ISyncSoundProvider syncinput, int filterwidth)
|
||||
depth = DepthFromFilterwidth(filterwidth);
|
||||
|
||||
_soundProvider = input;
|
||||
}
|
||||
|
||||
// Detached mode
|
||||
public DCFilter(int filterwidth)
|
||||
{
|
||||
if (filterwidth < 8 || filterwidth > 65536)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
this.input = input;
|
||||
this.syncinput = syncinput;
|
||||
}
|
||||
|
||||
depth = DepthFromFilterwidth(filterwidth);
|
||||
|
||||
_soundProvider = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -104,31 +98,43 @@ namespace BizHawk.Emulation.Common
|
|||
}
|
||||
}
|
||||
|
||||
void IAsyncSoundProvider.GetSamples(short[] samples)
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
input.GetSamples(samples);
|
||||
_soundProvider.GetSamplesAsync(samples);
|
||||
PushThroughSamples(samples, samples.Length);
|
||||
}
|
||||
|
||||
void IAsyncSoundProvider.DiscardSamples()
|
||||
public void DiscardSamples()
|
||||
{
|
||||
input.DiscardSamples();
|
||||
_soundProvider.DiscardSamples();
|
||||
}
|
||||
|
||||
void ISyncSoundProvider.GetSamples(out short[] samples, out int nsamp)
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
short[] sampin;
|
||||
int nsampin;
|
||||
syncinput.GetSamples(out sampin, out nsampin);
|
||||
|
||||
_soundProvider.GetSamplesSync(out sampin, out nsampin);
|
||||
|
||||
short[] ret = new short[nsampin * 2];
|
||||
PushThroughSamples(sampin, ret, nsampin * 2);
|
||||
samples = ret;
|
||||
nsamp = nsampin;
|
||||
}
|
||||
|
||||
void ISyncSoundProvider.DiscardSamples()
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
syncinput.DiscardSamples();
|
||||
get { return _soundProvider.SyncMode; }
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return _soundProvider.CanProvideAsync; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
_soundProvider.SetSyncMode(mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,23 +4,26 @@ using System.Collections.Generic;
|
|||
namespace BizHawk.Emulation.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// uses Metaspu to have an ISyncSoundProvider input to a ISoundProvider
|
||||
/// uses Metaspu to provide async sound to an ISoundProvider that does not provide its own async implementation
|
||||
/// </summary>
|
||||
public class MetaspuAsync : IAsyncSoundProvider
|
||||
// Sound Refactor TODO: rename me to MetaspuAsyncSoundProvider
|
||||
public class MetaspuAsync : ISoundProvider
|
||||
{
|
||||
private readonly ISynchronizingAudioBuffer buffer;
|
||||
private readonly ISyncSoundProvider input;
|
||||
public MetaspuAsync(ISyncSoundProvider input, ESynchMethod method)
|
||||
private readonly ISoundProvider input;
|
||||
|
||||
public MetaspuAsync(ISoundProvider input, ESynchMethod method)
|
||||
{
|
||||
input.SetSyncMode(SyncSoundMode.Sync);
|
||||
buffer = Metaspu.metaspu_construct(method);
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public void GetSamples(short[] samples)
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
short[] sampin;
|
||||
int numsamp;
|
||||
input.GetSamples(out sampin, out numsamp);
|
||||
input.GetSamplesSync(out sampin, out numsamp);
|
||||
buffer.enqueue_samples(sampin, numsamp);
|
||||
buffer.output_samples(samples, samples.Length / 2);
|
||||
}
|
||||
|
@ -30,37 +33,86 @@ namespace BizHawk.Emulation.Common
|
|||
input.DiscardSamples();
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public class MetaspuSoundProvider : IAsyncSoundProvider
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Async; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode != SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Only Async mode is supported");
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
throw new InvalidOperationException("Sync mode not supported");
|
||||
}
|
||||
}
|
||||
|
||||
// An async sound provider
|
||||
// Sound refactor TODO: can this be combined with the other Metaspu?
|
||||
public class MetaspuSoundProvider : ISoundProvider
|
||||
{
|
||||
public ISynchronizingAudioBuffer buffer;
|
||||
public MetaspuSoundProvider(ESynchMethod method)
|
||||
{
|
||||
buffer = Metaspu.metaspu_construct(method);
|
||||
Buffer = Metaspu.metaspu_construct(method);
|
||||
}
|
||||
|
||||
public ISynchronizingAudioBuffer Buffer { get; set; }
|
||||
private readonly short[] pullBuffer = new short[1470];
|
||||
|
||||
public MetaspuSoundProvider()
|
||||
: this(ESynchMethod.ESynchMethod_V)
|
||||
{
|
||||
}
|
||||
|
||||
private readonly short[] pullBuffer = new short[1470];
|
||||
public void PullSamples(IAsyncSoundProvider source)
|
||||
{
|
||||
Array.Clear(pullBuffer, 0, 1470);
|
||||
source.GetSamples(pullBuffer);
|
||||
buffer.enqueue_samples(pullBuffer, 735);
|
||||
Buffer.enqueue_samples(pullBuffer, 735);
|
||||
}
|
||||
|
||||
public void GetSamples(short[] samples)
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
buffer.output_samples(samples, samples.Length / 2);
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Async; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode != SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Only Async mode is supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
throw new InvalidOperationException("Sync mode is not supported.");
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
Buffer.output_samples(samples, samples.Length / 2);
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
buffer.clear();
|
||||
Buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +156,6 @@ namespace BizHawk.Emulation.Common
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class ZeromusSynchronizer : ISynchronizingAudioBuffer
|
||||
{
|
||||
public ZeromusSynchronizer()
|
||||
|
|
|
@ -33,14 +33,18 @@ namespace BizHawk.Emulation.Common
|
|||
public void DiscardSamples()
|
||||
{
|
||||
foreach (var soundSource in SoundProviders)
|
||||
{
|
||||
soundSource.DiscardSamples();
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamples(short[] samples)
|
||||
{
|
||||
foreach (var soundSource in SoundProviders)
|
||||
{
|
||||
soundSource.GetSamples(samples);
|
||||
}
|
||||
}
|
||||
|
||||
// Splits the volume space equally between available sources.
|
||||
public void EqualizeVolumes()
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Common
|
|||
/// <summary>
|
||||
/// junk wrapper around LibSpeexDSP. quite inefficient. will be replaced
|
||||
/// </summary>
|
||||
public class SpeexResampler : IDisposable, ISyncSoundProvider
|
||||
public class SpeexResampler : IDisposable, ISoundProvider
|
||||
{
|
||||
static class LibSpeexDSP
|
||||
{
|
||||
|
@ -250,7 +250,6 @@ namespace BizHawk.Emulation.Common
|
|||
public static extern string speex_resampler_strerror(RESAMPLER_ERR err);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// opaque pointer to state
|
||||
/// </summary>
|
||||
|
@ -266,12 +265,12 @@ namespace BizHawk.Emulation.Common
|
|||
|
||||
private short[] outbuf;
|
||||
|
||||
// for ISyncSoundProvider
|
||||
// for sync
|
||||
private short[] outbuf2 = new short[16];
|
||||
private int outbuf2pos = 0;
|
||||
|
||||
// to accept an ISyncSoundProvder input
|
||||
private readonly ISyncSoundProvider input;
|
||||
private readonly ISoundProvider input;
|
||||
|
||||
/// <summary>
|
||||
/// in buffer position in samples (not sample pairs)
|
||||
|
@ -309,7 +308,7 @@ namespace BizHawk.Emulation.Common
|
|||
/// <param name="srateout">sampling rate out, rounded to nearest hz</param>
|
||||
/// <param name="drainer">function which accepts output as produced. if null, act as an ISyncSoundProvider</param>
|
||||
/// <param name="input">source to take input from when output is requested. if null, no autofetching</param>
|
||||
public SpeexResampler(int quality, uint rationum, uint ratioden, uint sratein, uint srateout, Action<short[], int> drainer = null, ISyncSoundProvider input = null)
|
||||
public SpeexResampler(int quality, uint rationum, uint ratioden, uint sratein, uint srateout, Action<short[], int> drainer = null, ISoundProvider input = null)
|
||||
{
|
||||
if (drainer != null && input != null)
|
||||
throw new ArgumentException("Can't autofetch without being an ISyncSoundProvider?");
|
||||
|
@ -417,13 +416,13 @@ namespace BizHawk.Emulation.Common
|
|||
outbuf2pos += nsamp * 2;
|
||||
}
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
if (input != null)
|
||||
{
|
||||
short[] sampin;
|
||||
int nsampin;
|
||||
input.GetSamples(out sampin, out nsampin);
|
||||
input.GetSamplesSync(out sampin, out nsampin);
|
||||
EnqueueSamples(sampin, nsampin);
|
||||
}
|
||||
Flush();
|
||||
|
@ -436,6 +435,29 @@ namespace BizHawk.Emulation.Common
|
|||
{
|
||||
outbuf2pos = 0;
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -160,9 +160,6 @@
|
|||
</Compile>
|
||||
<Compile Include="Calculator\TI83LinkPort.cs" />
|
||||
<Compile Include="Computers\AppleII\AppleII.cs" />
|
||||
<Compile Include="Computers\AppleII\AppleII.IAudioProvider.cs">
|
||||
<DependentUpon>AppleII.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Computers\AppleII\AppleII.IDebuggable.cs">
|
||||
<DependentUpon>AppleII.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -181,6 +178,9 @@
|
|||
<Compile Include="Computers\AppleII\AppleII.ISettable.cs">
|
||||
<DependentUpon>AppleII.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Computers\AppleII\AppleII.ISoundProvider.cs">
|
||||
<DependentUpon>AppleII.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Computers\AppleII\AppleII.IStatable.cs">
|
||||
<DependentUpon>AppleII.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -375,6 +375,9 @@
|
|||
<Compile Include="Consoles\Atari\lynx\Lynx.ISaveRam.cs">
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Atari\lynx\Lynx.ISoundProvider.cs">
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Atari\lynx\Lynx.IStatable.cs">
|
||||
<DependentUpon>Lynx.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -397,6 +400,9 @@
|
|||
<Compile Include="Consoles\Coleco\ColecoVision.IStatable.cs">
|
||||
<DependentUpon>ColecoVision.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Coleco\ColecoVision.ISoundProvider.cs">
|
||||
<DependentUpon>ColecoVision.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Coleco\Input.cs" />
|
||||
<Compile Include="Consoles\Coleco\MemoryMap.cs" />
|
||||
<Compile Include="Consoles\Coleco\TMS9918A.cs" />
|
||||
|
@ -439,6 +445,9 @@
|
|||
<Compile Include="Consoles\Nintendo\Gameboy\Gambatte.ISettable.cs">
|
||||
<DependentUpon>Gambatte.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\Gambatte.ISoundProvider.cs">
|
||||
<DependentUpon>Gambatte.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\Gameboy\Gambatte.IStatable.cs">
|
||||
<DependentUpon>Gambatte.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -514,6 +523,9 @@
|
|||
<Compile Include="Consoles\Nintendo\GBA\VBANext.ISettings.cs">
|
||||
<DependentUpon>VBANext.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\GBA\VBANext.ISoundProvider.cs">
|
||||
<DependentUpon>VBANext.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\GBA\VBANext.IStatable.cs">
|
||||
<DependentUpon>VBANext.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -871,6 +883,9 @@
|
|||
<Compile Include="Consoles\Nintendo\QuickNES\QuickNES.ISettable.cs">
|
||||
<DependentUpon>QuickNES.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\QuickNES\QuickNES.ISoundProvider.cs">
|
||||
<DependentUpon>QuickNES.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Nintendo\QuickNES\QuickNES.IStatable.cs">
|
||||
<DependentUpon>QuickNES.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -905,6 +920,9 @@
|
|||
<Compile Include="Consoles\Sega\Genesis\Genesis.Input.cs" />
|
||||
<Compile Include="Consoles\Sega\Genesis\Genesis.IO.cs" />
|
||||
<Compile Include="Consoles\Sega\Genesis\Native68000\Musashi.cs" />
|
||||
<Compile Include="Consoles\Sega\gpgx64\GPGX.ISoundProvider.cs">
|
||||
<DependentUpon>GPGX.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Sega\gpgx\GenDbgHlp.cs" />
|
||||
<Compile Include="Consoles\Sega\gpgx\GPGX.cs" />
|
||||
<Compile Include="Consoles\Sega\gpgx\GPGX.ICodeDataLogger.cs">
|
||||
|
@ -934,6 +952,9 @@
|
|||
<Compile Include="Consoles\Sega\gpgx\GPGX.ISettable.cs">
|
||||
<DependentUpon>GPGX.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Sega\gpgx\GPGX.ISoundProvider.cs">
|
||||
<DependentUpon>GPGX.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Sega\gpgx\GPGX.IStatable.cs">
|
||||
<DependentUpon>GPGX.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -1034,6 +1055,9 @@
|
|||
<Compile Include="Consoles\Sega\SMS\SMS.ISettable.cs">
|
||||
<DependentUpon>SMS.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Sega\SMS\SMS.ISoundProvider.cs">
|
||||
<DependentUpon>SMS.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\Sega\SMS\SMS.IStatable.cs">
|
||||
<DependentUpon>SMS.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -1077,6 +1101,9 @@
|
|||
<Compile Include="Consoles\WonderSwan\WonderSwan.ISettable.cs">
|
||||
<DependentUpon>WonderSwan.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\WonderSwan\WonderSwan.ISoundProvider.cs">
|
||||
<DependentUpon>WonderSwan.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Consoles\WonderSwan\WonderSwan.IStatable.cs">
|
||||
<DependentUpon>WonderSwan.cs</DependentUpon>
|
||||
</Compile>
|
||||
|
|
|
@ -6,23 +6,6 @@ namespace BizHawk.Emulation.Cores.Calculators
|
|||
{
|
||||
public IEmulatorServiceProvider ServiceProvider { get; private set; }
|
||||
|
||||
public IAsyncSoundProvider SoundProvider
|
||||
{
|
||||
get { return NullSound.SilenceProvider; }
|
||||
}
|
||||
|
||||
public ISyncSoundProvider SyncSoundProvider
|
||||
{
|
||||
get { return new FakeSyncSound(NullSound.SilenceProvider, 735); }
|
||||
}
|
||||
|
||||
public bool StartAsyncSound()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public ControllerDefinition ControllerDefinition
|
||||
{
|
||||
get { return TI83Controller; }
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Components.Z80;
|
||||
|
@ -19,7 +14,7 @@ namespace BizHawk.Emulation.Cores.Calculators
|
|||
isPorted: false,
|
||||
isReleased: true
|
||||
)]
|
||||
[ServiceNotApplicable(typeof(ISaveRam), typeof(IRegionable), typeof(IDriveLight))]
|
||||
[ServiceNotApplicable(typeof(ISoundProvider), typeof(ISaveRam), typeof(IRegionable), typeof(IDriveLight))]
|
||||
public partial class TI83 : IEmulator, IVideoProvider, IStatable, IDebuggable, IInputPollable, ISettable<TI83.TI83Settings, object>
|
||||
{
|
||||
[CoreConstructor("TI83")]
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Computers.AppleII
|
||||
{
|
||||
partial class AppleII : ISyncSoundProvider
|
||||
{
|
||||
void ISyncSoundProvider.GetSamples(out short[] samples, out int nsamp)
|
||||
{
|
||||
_machine.Speaker.AudioService.GetSamples(out samples, out nsamp);
|
||||
}
|
||||
|
||||
void ISyncSoundProvider.DiscardSamples()
|
||||
{
|
||||
_machine.Speaker.AudioService.Clear();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,27 +6,6 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
|
|||
{
|
||||
public IEmulatorServiceProvider ServiceProvider { get; private set; }
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public IAsyncSoundProvider SoundProvider
|
||||
{
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public ISyncSoundProvider SyncSoundProvider
|
||||
{
|
||||
get { return this; }
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public bool StartAsyncSound()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
[FeatureNotImplemented]
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public ControllerDefinition ControllerDefinition
|
||||
{
|
||||
get { return AppleIIController; }
|
||||
|
@ -36,9 +15,15 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
|
|||
|
||||
public int Frame { get; set; }
|
||||
|
||||
public string SystemId { get { return "AppleII"; } }
|
||||
public string SystemId
|
||||
{
|
||||
get { return "AppleII"; }
|
||||
}
|
||||
|
||||
public bool DeterministicEmulation { get { return true; } }
|
||||
public bool DeterministicEmulation
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public void FrameAdvance(bool render, bool rendersound)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Computers.AppleII
|
||||
{
|
||||
public partial class AppleII : ISoundProvider
|
||||
{
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
_machine.Speaker.AudioService.GetSamples(out samples, out nsamp);
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
_machine.Speaker.AudioService.Clear();
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ namespace BizHawk.Emulation.Cores.Computers.AppleII
|
|||
isReleased: true
|
||||
)]
|
||||
[ServiceNotApplicable(typeof(ISaveRam), typeof(IRegionable))]
|
||||
public partial class AppleII : IEmulator, IDriveLight
|
||||
public partial class AppleII : IEmulator, ISoundProvider, IVideoProvider, IStatable, IDriveLight
|
||||
{
|
||||
public AppleII(CoreComm comm, IEnumerable<GameInfo> gameInfoSet, IEnumerable<byte[]> romSet, Settings settings)
|
||||
: this(comm, gameInfoSet.First(), romSet.First(), settings)
|
||||
|
|
|
@ -83,8 +83,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
|||
|
||||
if (_board.Sid != null)
|
||||
{
|
||||
SyncSoundProvider = DCFilter.AsISyncSoundProvider(_board.Sid, 512);
|
||||
_soundProvider = new DCFilter(_board.Sid, 512);
|
||||
((BasicServiceProvider)ServiceProvider).Register<ISoundProvider>(_soundProvider);
|
||||
}
|
||||
|
||||
DeterministicEmulation = true;
|
||||
|
||||
((BasicServiceProvider) ServiceProvider).Register<IVideoProvider>(_board.Vic);
|
||||
|
@ -136,12 +138,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
|||
public bool DeterministicEmulation { get; set; }
|
||||
[SaveState.SaveWithName("Frame")]
|
||||
public int Frame { get; set; }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
[SaveState.DoNotSave]
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
[SaveState.DoNotSave]
|
||||
public ISyncSoundProvider SyncSoundProvider { get; private set; }
|
||||
|
||||
[SaveState.DoNotSave]
|
||||
public ControllerDefinition ControllerDefinition { get { return C64ControllerDefinition; } }
|
||||
[SaveState.DoNotSave]
|
||||
|
@ -169,6 +166,13 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
|||
|
||||
#endregion
|
||||
|
||||
#region ISoundProvider
|
||||
|
||||
[SaveState.DoNotSave]
|
||||
public ISoundProvider _soundProvider { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
private void DoCycle()
|
||||
{
|
||||
if (_frameCycles == 0) {
|
||||
|
|
|
@ -1,17 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
||||
{
|
||||
public sealed partial class Sid : IAsyncSoundProvider, ISyncSoundProvider
|
||||
public sealed partial class Sid : ISoundProvider
|
||||
{
|
||||
public int MaxVolume
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return short.MaxValue; }
|
||||
set { }
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode != SyncSoundMode.Sync)
|
||||
{
|
||||
throw new InvalidOperationException("Only Sync mode is supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new NotSupportedException("Async is not available");
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
|
@ -19,7 +33,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
_outputBufferIndex = 0;
|
||||
}
|
||||
|
||||
public void GetSamples(short[] samples)
|
||||
// Expose this as GetSamplesAsync to support async sound
|
||||
// There's not need to do this though unless this core wants to handle async in its own way (the client can handle these situations if not available from the core)
|
||||
private void GetSamples(short[] samples)
|
||||
{
|
||||
Flush();
|
||||
var length = Math.Min(samples.Length, _outputBufferIndex);
|
||||
|
@ -30,7 +46,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.MOS
|
|||
_outputBufferIndex = 0;
|
||||
}
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
Flush();
|
||||
samples = _outputBuffer;
|
||||
|
|
|
@ -310,11 +310,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
_pal = DetectPal(_game, Rom);
|
||||
}
|
||||
|
||||
_tia = new TIA(this, _pal, Settings.SECAMColors);
|
||||
// dcfilter coefficent is from real observed hardware behavior: a latched "1" will fully decay by ~170 or so tia sound cycles
|
||||
_tia = new TIA(this, _pal, Settings.SECAMColors, CoreComm.VsyncRate > 55.0 ? 735 : 882);
|
||||
_tia.GetFrameRate(out CoreComm.VsyncNum, out CoreComm.VsyncDen);
|
||||
|
||||
// dcfilter coefficent is from real observed hardware behavior: a latched "1" will fully decay by ~170 or so tia sound cycles
|
||||
_dcfilter = DCFilter.AsISoundProvider(_tia, 256);
|
||||
_dcfilter = new DCFilter(_tia, 256);
|
||||
|
||||
M6532 = new M6532(this);
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
ser.Register<IDisassemblable>(Cpu);
|
||||
ser.Register<ITraceable>(Tracer);
|
||||
ser.Register<IVideoProvider>(_tia);
|
||||
ser.Register<ISoundProvider>(_dcfilter);
|
||||
}
|
||||
|
||||
public IEmulatorServiceProvider ServiceProvider { get; private set; }
|
||||
|
@ -80,17 +81,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
public CoreComm CoreComm { get; private set; }
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return _dcfilter; } }
|
||||
|
||||
// todo: make this not so ugly
|
||||
public ISyncSoundProvider SyncSoundProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
return new FakeSyncSound(_dcfilter, CoreComm.VsyncRate > 55.0 ? 735 : 882);
|
||||
}
|
||||
}
|
||||
|
||||
public ControllerDefinition ControllerDefinition { get { return Atari2600ControllerDefinition; } }
|
||||
|
||||
public IController Controller { get; set; }
|
||||
|
@ -123,10 +113,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
};
|
||||
}
|
||||
|
||||
public bool StartAsyncSound() { return true; }
|
||||
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public void ResetCounters()
|
||||
{
|
||||
_frame = 0;
|
||||
|
|
|
@ -7,7 +7,7 @@ using System.Numerics;
|
|||
namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||
{
|
||||
// Emulates the TIA
|
||||
public partial class TIA : IVideoProvider, IAsyncSoundProvider
|
||||
public partial class TIA : IVideoProvider, ISoundProvider
|
||||
{
|
||||
|
||||
#region palette
|
||||
|
@ -332,13 +332,14 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
//public byte[] current_audio_register = new byte[6];
|
||||
public short[] _local_audio_cycles = new short[2000];
|
||||
|
||||
public TIA(Atari2600 core, bool pal, bool secam)
|
||||
public TIA(Atari2600 core, bool pal, bool secam, int spf)
|
||||
{
|
||||
_core = core;
|
||||
_player0.ScanCnt = 8;
|
||||
_player1.ScanCnt = 8;
|
||||
_pal = pal;
|
||||
SetSECAM(secam);
|
||||
_spf = spf;
|
||||
}
|
||||
|
||||
public void SetSECAM(bool secam)
|
||||
|
@ -487,7 +488,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
if (vblank_delay > 0)
|
||||
{
|
||||
vblank_delay++;
|
||||
if (vblank_delay==3)
|
||||
if (vblank_delay == 3)
|
||||
{
|
||||
_vblankEnabled = (vblank_value & 0x02) != 0;
|
||||
vblank_delay = 0;
|
||||
|
@ -1033,10 +1034,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
|
||||
// do the audio sampling
|
||||
if (_hsyncCnt==36 || _hsyncCnt==148)
|
||||
if (_hsyncCnt == 36 || _hsyncCnt == 148)
|
||||
{
|
||||
_local_audio_cycles[_audioClocks] += (short)(AUD[0].Cycle()/2);
|
||||
_local_audio_cycles[_audioClocks] += (short)(AUD[1].Cycle()/2);
|
||||
_local_audio_cycles[_audioClocks] += (short)(AUD[0].Cycle() / 2);
|
||||
_local_audio_cycles[_audioClocks] += (short)(AUD[1].Cycle() / 2);
|
||||
_audioClocks++;
|
||||
}
|
||||
|
||||
|
@ -1082,7 +1083,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
|
||||
if (maskedAddr == 0x00) // CXM0P
|
||||
{
|
||||
coll=(byte)((((_player0.Missile.Collisions & CXP1) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXP0) != 0) ? 0x40 : 0x00));
|
||||
coll = (byte)((((_player0.Missile.Collisions & CXP1) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXP0) != 0) ? 0x40 : 0x00));
|
||||
mask = 0x3f;
|
||||
}
|
||||
|
||||
|
@ -1135,7 +1136,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
{
|
||||
if (_capCharging && _core.Cpu.TotalExecutedCycles - _capChargeStart >= 6105)
|
||||
{
|
||||
coll=0x80;
|
||||
coll = 0x80;
|
||||
} else
|
||||
{
|
||||
coll = 0x00;
|
||||
|
@ -1197,7 +1198,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
//some bits of the databus will be undriven when a read call is made. Our goal here is to sort out what
|
||||
// happens to the undriven pins. Most of the time, they will be in whatever state they were when previously
|
||||
//assigned in some other bus access, so let's go with that.
|
||||
coll+=(byte)(mask & bus_state);
|
||||
coll += (byte)(mask & bus_state);
|
||||
|
||||
if (!peek) bus_state = (int)coll;
|
||||
return coll;
|
||||
|
@ -1436,7 +1437,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
else if (maskedAddr == 0x15) // AUDC0
|
||||
{
|
||||
AUD[0].AUDC= (byte)(value & 15);
|
||||
AUD[0].AUDC = (byte)(value & 15);
|
||||
}
|
||||
else if (maskedAddr == 0x16) // AUDC1
|
||||
{
|
||||
|
@ -1577,13 +1578,29 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
frameEndCycles = _core.Cpu.TotalExecutedCycles;
|
||||
}
|
||||
|
||||
public void GetSamples(short[] samples)
|
||||
#endregion
|
||||
|
||||
#region ISoundProvider
|
||||
|
||||
private int _spf;
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
short[] ret = new short[_spf * 2];
|
||||
GetSamples(ret);
|
||||
samples = ret;
|
||||
nsamp = _spf;
|
||||
}
|
||||
|
||||
// Exposing this as GetSamplesAsync would allow this to provide async sound
|
||||
// However, it does nothing special for async sound so I don't see a point
|
||||
private void GetSamples(short[] samples)
|
||||
{
|
||||
if (_audioClocks > 0)
|
||||
{
|
||||
var samples31khz = new short[_audioClocks]; // mono
|
||||
|
||||
for (int i=0;i<_audioClocks;i++)
|
||||
for (int i = 0; i < _audioClocks; i++)
|
||||
{
|
||||
samples31khz[i] = _local_audio_cycles[i];
|
||||
_local_audio_cycles[i] = 0;
|
||||
|
@ -1604,6 +1621,29 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
_audioClocks = 0;
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new NotSupportedException("Async is not available");
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode != SyncSoundMode.Sync)
|
||||
{
|
||||
throw new InvalidOperationException("Only Sync mode is supported.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
|
|||
{
|
||||
ServiceProvider = new BasicServiceProvider(this);
|
||||
(ServiceProvider as BasicServiceProvider).Register<IVideoProvider>(avProvider);
|
||||
(ServiceProvider as BasicServiceProvider).Register<ISoundProvider>(avProvider);
|
||||
InputCallbacks = new InputCallbackSystem();
|
||||
CoreComm = comm;
|
||||
byte[] highscoreBIOS = comm.CoreFileProvider.GetFirmware("A78", "Bios_HSC", false, "Some functions may not work without the high score BIOS.");
|
||||
|
@ -206,14 +207,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
|
|||
|
||||
#region audio\video
|
||||
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return avProvider; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
|
||||
MyAVProvider avProvider = new MyAVProvider();
|
||||
|
||||
class MyAVProvider : IVideoProvider, ISyncSoundProvider, IDisposable
|
||||
class MyAVProvider : IVideoProvider, ISoundProvider, IDisposable
|
||||
{
|
||||
public FrameBuffer framebuffer { get; private set; }
|
||||
public void ConnectToMachine(MachineBase m, EMU7800.Win.GameProgram g)
|
||||
|
@ -231,7 +227,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
|
|||
resampler.Dispose();
|
||||
resampler = new SpeexResampler(3, newsamplerate, 44100, newsamplerate, 44100, null, null);
|
||||
samplerate = newsamplerate;
|
||||
dcfilter = DCFilter.DetatchedMode(256);
|
||||
dcfilter = new DCFilter(256);
|
||||
}
|
||||
if (g.MachineType == MachineType.A7800PAL || g.MachineType == MachineType.A2600PAL)
|
||||
palette = TIATables.PALPalette;
|
||||
|
@ -274,7 +270,14 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
|
|||
public int BufferHeight { get; private set; }
|
||||
public int BackgroundColor { get { return unchecked((int)0xff000000); } }
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
#region ISoundProvider
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
int nsampin = framebuffer.SoundBufferByteLength;
|
||||
unsafe
|
||||
|
@ -291,16 +294,36 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
|
|||
|
||||
}
|
||||
}
|
||||
resampler.GetSamples(out samples, out nsamp);
|
||||
resampler.GetSamplesSync(out samples, out nsamp);
|
||||
dcfilter.PushThroughSamples(samples, nsamp * 2);
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
if (resampler != null)
|
||||
resampler.DiscardSamples();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (resampler != null)
|
||||
|
@ -310,6 +333,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari7800
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Atari.Lynx
|
||||
{
|
||||
public partial class Lynx : ISoundProvider
|
||||
{
|
||||
private short[] soundbuff = new short[2048];
|
||||
private int numsamp;
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = soundbuff;
|
||||
nsamp = numsamp;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
|
|||
{
|
||||
[CoreAttributes("Handy", "K. Wilkins", true, true, "mednafen 0-9-34-1", "http://mednafen.sourceforge.net/")]
|
||||
[ServiceNotApplicable(typeof(ISettable<,>), typeof(IDriveLight), typeof(IRegionable))]
|
||||
public partial class Lynx : IEmulator, IVideoProvider, ISyncSoundProvider, ISaveRam, IStatable, IInputPollable
|
||||
public partial class Lynx : IEmulator, IVideoProvider, ISoundProvider, ISaveRam, IStatable, IInputPollable
|
||||
{
|
||||
IntPtr Core;
|
||||
|
||||
|
@ -192,27 +192,5 @@ namespace BizHawk.Emulation.Cores.Atari.Lynx
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SoundProvider
|
||||
|
||||
short[] soundbuff = new short[2048];
|
||||
int numsamp;
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = soundbuff;
|
||||
nsamp = numsamp;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Components;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.ColecoVision
|
||||
{
|
||||
// Sound refactor TODO: Implement ISoundProvider here and sort this mess out
|
||||
public partial class ColecoVision
|
||||
{
|
||||
public SN76489 PSG;
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return PSG; } }
|
||||
//public ISyncSoundProvider SyncSoundProvider { get { return new FakeSyncSound(SoundProvider, 735); } }
|
||||
}
|
||||
}
|
|
@ -16,13 +16,12 @@ namespace BizHawk.Emulation.Cores.ColecoVision
|
|||
// ROM
|
||||
public byte[] RomData;
|
||||
public int RomLength;
|
||||
|
||||
public byte[] BiosRom;
|
||||
|
||||
// Machine
|
||||
public Z80A Cpu;
|
||||
public TMS9918A VDP;
|
||||
public SN76489 PSG;
|
||||
|
||||
public byte[] Ram = new byte[1024];
|
||||
private readonly TraceBuffer Tracer = new TraceBuffer();
|
||||
|
||||
|
@ -167,12 +166,6 @@ namespace BizHawk.Emulation.Cores.ColecoVision
|
|||
public string SystemId { get { return "Coleco"; } }
|
||||
public GameInfo game;
|
||||
public CoreComm CoreComm { get; private set; }
|
||||
public IAsyncSoundProvider SoundProvider { get { return PSG; } }
|
||||
|
||||
public string BoardName { get { return null; } }
|
||||
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return new FakeSyncSound(SoundProvider, 735); } }
|
||||
public bool StartAsyncSound() { return true; }
|
||||
public void EndAsyncSound() { }
|
||||
}
|
||||
}
|
|
@ -7,28 +7,6 @@ namespace BizHawk.Emulation.Cores.Intellivision
|
|||
{
|
||||
public IEmulatorServiceProvider ServiceProvider { get; private set; }
|
||||
|
||||
private DCFilter _dcfilter;
|
||||
|
||||
public IAsyncSoundProvider SoundProvider
|
||||
{
|
||||
get { return _dcfilter; }
|
||||
}
|
||||
|
||||
public ISyncSoundProvider SyncSoundProvider
|
||||
{
|
||||
get { return new FakeSyncSound(_dcfilter, 735); }
|
||||
}
|
||||
|
||||
public bool StartAsyncSound()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void EndAsyncSound()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ControllerDefinition ControllerDefinition
|
||||
{
|
||||
get { return ControllerDeck.Definition; }
|
||||
|
|
|
@ -64,8 +64,6 @@ namespace BizHawk.Emulation.Cores.Intellivision
|
|||
(ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer);
|
||||
|
||||
SetupMemoryDomains();
|
||||
|
||||
_dcfilter = DCFilter.AsISoundProvider(_psg, 256); // not sure how the 256 will change for intellivision I just copied it from Atari for now
|
||||
}
|
||||
|
||||
public IntellivisionControllerDeck ControllerDeck { get; private set; }
|
||||
|
|
|
@ -5,7 +5,8 @@ using BizHawk.Emulation.Common;
|
|||
|
||||
namespace BizHawk.Emulation.Cores.Intellivision
|
||||
{
|
||||
public sealed class PSG : IAsyncSoundProvider
|
||||
// Sound refactor todo: Implement ISoundProvider, and register _psg in the Intellivision core
|
||||
public sealed class PSG
|
||||
{
|
||||
public ushort[] Register = new ushort[16];
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
{
|
||||
[CoreAttributes("mGBA", "endrift", true, true, "0.5.0", "https://mgba.io/", false)]
|
||||
[ServiceNotApplicable(typeof(IDriveLight), typeof(IRegionable))]
|
||||
public class MGBAHawk : IEmulator, IVideoProvider, ISyncSoundProvider, IGBAGPUViewable,
|
||||
public class MGBAHawk : IEmulator, IVideoProvider, ISoundProvider, IGBAGPUViewable,
|
||||
ISaveRam, IStatable, IInputPollable, ISettable<MGBAHawk.Settings, MGBAHawk.SyncSettings>
|
||||
{
|
||||
private IntPtr _core;
|
||||
|
@ -192,9 +192,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
#endregion
|
||||
|
||||
#region ISoundProvider
|
||||
|
||||
private readonly short[] soundbuff = new short[2048];
|
||||
private int nsamp;
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
nsamp = this.nsamp;
|
||||
samples = soundbuff;
|
||||
|
@ -204,10 +205,30 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
{
|
||||
nsamp = 0;
|
||||
}
|
||||
public IAsyncSoundProvider SoundProvider { get { throw new InvalidOperationException(); } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IMemoryDomains
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
singleInstance: true
|
||||
)]
|
||||
[ServiceNotApplicable(typeof(IDriveLight), typeof(IRegionable))]
|
||||
public partial class GBA : IEmulator, IVideoProvider, ISyncSoundProvider, IGBAGPUViewable, ISaveRam, IStatable, IInputPollable
|
||||
public partial class GBA : IEmulator, IVideoProvider, ISoundProvider, IGBAGPUViewable, ISaveRam, IStatable, IInputPollable
|
||||
{
|
||||
[CoreConstructor("GBA")]
|
||||
public GBA(CoreComm comm, byte[] file)
|
||||
|
@ -293,12 +293,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
short[] soundbuffer;
|
||||
GCHandle soundhandle;
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
uint nbytes = LibMeteor.libmeteor_emptysound();
|
||||
samples = soundbuffer;
|
||||
|
@ -313,6 +308,29 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
LibMeteor.libmeteor_emptysound();
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
||||
{
|
||||
public partial class VBANext : ISoundProvider
|
||||
{
|
||||
private short[] soundbuff = new short[2048];
|
||||
private int numsamp;
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = soundbuff;
|
||||
nsamp = numsamp;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using System.IO;
|
||||
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using Newtonsoft.Json;
|
||||
using System.ComponentModel;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Cores.Components.ARM;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
||||
{
|
||||
[CoreAttributes("VBA-Next", "many authors", true, true, "cd508312a29ed8c29dacac1b11c2dce56c338a54", "https://github.com/libretro/vba-next")]
|
||||
[ServiceNotApplicable(typeof(IDriveLight), typeof(IRegionable))]
|
||||
public partial class VBANext : IEmulator, IVideoProvider, ISyncSoundProvider, IInputPollable,
|
||||
public partial class VBANext : IEmulator, IVideoProvider, ISoundProvider, IInputPollable,
|
||||
IGBAGPUViewable, ISaveRam, IStatable, IDebuggable, ISettable<object, VBANext.SyncSettings>
|
||||
{
|
||||
IntPtr Core;
|
||||
|
@ -226,27 +219,5 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBA
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SoundProvider
|
||||
|
||||
short[] soundbuff = new short[2048];
|
||||
int numsamp;
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = soundbuff;
|
||||
nsamp = numsamp;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||
{
|
||||
public partial class Gameboy : ISoundProvider
|
||||
{
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
soundoutbuffcontains = 0;
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = soundoutbuff;
|
||||
nsamp = soundoutbuffcontains;
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
internal bool Muted
|
||||
{
|
||||
get { return _settings.Muted; }
|
||||
}
|
||||
|
||||
// sample pairs before resampling
|
||||
private short[] soundbuff = new short[(35112 + 2064) * 2];
|
||||
|
||||
private int soundoutbuffcontains = 0;
|
||||
|
||||
private short[] soundoutbuff = new short[2048];
|
||||
|
||||
private int latchL = 0;
|
||||
private int latchR = 0;
|
||||
|
||||
private BlipBuffer blipL, blipR;
|
||||
private uint blipAccumulate;
|
||||
|
||||
private void ProcessSound(int nsamp)
|
||||
{
|
||||
for (uint i = 0; i < nsamp; i++)
|
||||
{
|
||||
int curr = soundbuff[i * 2];
|
||||
|
||||
if (curr != latchL)
|
||||
{
|
||||
int diff = latchL - curr;
|
||||
latchL = curr;
|
||||
blipL.AddDelta(blipAccumulate, diff);
|
||||
}
|
||||
|
||||
curr = soundbuff[i * 2 + 1];
|
||||
|
||||
if (curr != latchR)
|
||||
{
|
||||
int diff = latchR - curr;
|
||||
latchR = curr;
|
||||
blipR.AddDelta(blipAccumulate, diff);
|
||||
}
|
||||
|
||||
blipAccumulate++;
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessSoundEnd()
|
||||
{
|
||||
blipL.EndFrame(blipAccumulate);
|
||||
blipR.EndFrame(blipAccumulate);
|
||||
blipAccumulate = 0;
|
||||
|
||||
soundoutbuffcontains = blipL.SamplesAvailable();
|
||||
if (soundoutbuffcontains != blipR.SamplesAvailable())
|
||||
{
|
||||
throw new InvalidOperationException("Audio processing error");
|
||||
}
|
||||
|
||||
blipL.ReadSamplesLeft(soundoutbuff, soundoutbuffcontains);
|
||||
blipR.ReadSamplesRight(soundoutbuff, soundoutbuffcontains);
|
||||
}
|
||||
|
||||
private void InitSound()
|
||||
{
|
||||
blipL = new BlipBuffer(1024);
|
||||
blipL.SetRates(TICKSPERSECOND, 44100);
|
||||
blipR = new BlipBuffer(1024);
|
||||
blipR.SetRates(TICKSPERSECOND, 44100);
|
||||
}
|
||||
|
||||
private void DisposeSound()
|
||||
{
|
||||
if (blipL != null)
|
||||
{
|
||||
blipL.Dispose();
|
||||
blipL = null;
|
||||
}
|
||||
if (blipR != null)
|
||||
{
|
||||
blipR.Dispose();
|
||||
blipR = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||
{
|
||||
|
@ -23,7 +17,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
portedUrl: "http://gambatte.sourceforge.net/"
|
||||
)]
|
||||
[ServiceNotApplicable(typeof(IDriveLight), typeof(IDriveLight))]
|
||||
public partial class Gameboy : IEmulator, IVideoProvider, ISyncSoundProvider, ISaveRam, IStatable, IInputPollable, ICodeDataLogger,
|
||||
public partial class Gameboy : IEmulator, IVideoProvider, ISoundProvider, ISaveRam, IStatable, IInputPollable, ICodeDataLogger,
|
||||
IDebuggable, ISettable<Gameboy.GambatteSettings, Gameboy.GambatteSyncSettings>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -566,103 +560,5 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ISoundProvider
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
/// <summary>
|
||||
/// sample pairs before resampling
|
||||
/// </summary>
|
||||
short[] soundbuff = new short[(35112 + 2064) * 2];
|
||||
|
||||
int soundoutbuffcontains = 0;
|
||||
|
||||
short[] soundoutbuff = new short[2048];
|
||||
|
||||
int latchL = 0;
|
||||
int latchR = 0;
|
||||
|
||||
BlipBuffer blipL, blipR;
|
||||
uint blipAccumulate;
|
||||
|
||||
private void ProcessSound(int nsamp)
|
||||
{
|
||||
for (uint i = 0; i < nsamp; i++)
|
||||
{
|
||||
int curr = soundbuff[i * 2];
|
||||
|
||||
if (curr != latchL)
|
||||
{
|
||||
int diff = latchL - curr;
|
||||
latchL = curr;
|
||||
blipL.AddDelta(blipAccumulate, diff);
|
||||
}
|
||||
curr = soundbuff[i * 2 + 1];
|
||||
|
||||
if (curr != latchR)
|
||||
{
|
||||
int diff = latchR - curr;
|
||||
latchR = curr;
|
||||
blipR.AddDelta(blipAccumulate, diff);
|
||||
}
|
||||
|
||||
blipAccumulate++;
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessSoundEnd()
|
||||
{
|
||||
blipL.EndFrame(blipAccumulate);
|
||||
blipR.EndFrame(blipAccumulate);
|
||||
blipAccumulate = 0;
|
||||
|
||||
soundoutbuffcontains = blipL.SamplesAvailable();
|
||||
if (soundoutbuffcontains != blipR.SamplesAvailable())
|
||||
throw new InvalidOperationException("Audio processing error");
|
||||
|
||||
blipL.ReadSamplesLeft(soundoutbuff, soundoutbuffcontains);
|
||||
blipR.ReadSamplesRight(soundoutbuff, soundoutbuffcontains);
|
||||
}
|
||||
|
||||
void InitSound()
|
||||
{
|
||||
blipL = new BlipBuffer(1024);
|
||||
blipL.SetRates(TICKSPERSECOND, 44100);
|
||||
blipR = new BlipBuffer(1024);
|
||||
blipR.SetRates(TICKSPERSECOND, 44100);
|
||||
}
|
||||
|
||||
void DisposeSound()
|
||||
{
|
||||
if (blipL != null)
|
||||
{
|
||||
blipL.Dispose();
|
||||
blipL = null;
|
||||
}
|
||||
if (blipR != null)
|
||||
{
|
||||
blipR.Dispose();
|
||||
blipR = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
soundoutbuffcontains = 0;
|
||||
}
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = soundoutbuff;
|
||||
nsamp = soundoutbuffcontains;
|
||||
}
|
||||
|
||||
public bool Muted { get { return _settings.Muted; } }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Nintendo.SNES;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
||||
{
|
||||
[CoreAttributes(
|
||||
|
@ -18,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
isReleased: true
|
||||
)]
|
||||
[ServiceNotApplicable(typeof(IDriveLight))]
|
||||
public partial class GambatteLink : IEmulator, IVideoProvider, ISyncSoundProvider, IInputPollable, ISaveRam, IStatable, ILinkable,
|
||||
public partial class GambatteLink : IEmulator, IVideoProvider, ISoundProvider, IInputPollable, ISaveRam, IStatable, ILinkable,
|
||||
IDebuggable, ISettable<GambatteLink.GambatteLinkSettings, GambatteLink.GambatteLinkSyncSettings>, ICodeDataLogger
|
||||
{
|
||||
public GambatteLink(CoreComm comm, GameInfo leftinfo, byte[] leftrom, GameInfo rightinfo, byte[] rightrom, object Settings, object SyncSettings, bool deterministic)
|
||||
|
@ -89,11 +83,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
|
||||
public IEmulatorServiceProvider ServiceProvider { get; private set; }
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public static readonly ControllerDefinition DualGbController = new ControllerDefinition
|
||||
{
|
||||
Name = "Dual Gameboy Controller",
|
||||
|
@ -327,7 +316,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
SampleBufferContains = count;
|
||||
}
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
nsamp = SampleBufferContains;
|
||||
samples = SampleBuffer;
|
||||
|
@ -338,6 +327,29 @@ namespace BizHawk.Emulation.Cores.Nintendo.Gameboy
|
|||
SampleBufferContains = 0;
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,6 +130,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
|||
_audioProvider = new N64Audio(api);
|
||||
_inputProvider = new N64Input(this.AsInputPollable(), api, comm, this._syncSettings.Controllers);
|
||||
(ServiceProvider as BasicServiceProvider).Register<IVideoProvider>(_videoProvider);
|
||||
(ServiceProvider as BasicServiceProvider).Register<ISoundProvider>(_audioProvider.Resampler);
|
||||
|
||||
string rsp;
|
||||
switch (_syncSettings.Rsp)
|
||||
|
@ -268,14 +269,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.N64
|
|||
|
||||
public DisplayType Region { get { return _display_type; } }
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return _audioProvider.Resampler; } }
|
||||
|
||||
public bool StartAsyncSound() { return false; }
|
||||
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public ControllerDefinition ControllerDefinition
|
||||
{
|
||||
get { return _inputProvider.ControllerDefinition; }
|
||||
|
|
|
@ -79,7 +79,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
magicSoundProvider = null;
|
||||
}
|
||||
|
||||
class MagicSoundProvider : IAsyncSoundProvider, ISyncSoundProvider, IDisposable
|
||||
// Sound refactor todo: do we want to support async?
|
||||
class MagicSoundProvider
|
||||
: ISoundProvider, IDisposable
|
||||
{
|
||||
BlipBuffer blip;
|
||||
NES nes;
|
||||
|
@ -99,30 +101,30 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
//output = new Sound.Utilities.DCFilter(actualMetaspu);
|
||||
}
|
||||
|
||||
public void GetSamples(short[] samples)
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
//Console.WriteLine("Sync: {0}", nes.apu.dlist.Count);
|
||||
int nsamp = samples.Length / 2;
|
||||
if (nsamp > blipbuffsize) // oh well.
|
||||
nsamp = blipbuffsize;
|
||||
uint targetclock = (uint)blip.ClocksNeeded(nsamp);
|
||||
uint actualclock = nes.apu.sampleclock;
|
||||
foreach (var d in nes.apu.dlist)
|
||||
blip.AddDelta(d.time * targetclock / actualclock, d.value);
|
||||
nes.apu.dlist.Clear();
|
||||
blip.EndFrame(targetclock);
|
||||
nes.apu.sampleclock = 0;
|
||||
|
||||
blip.ReadSamples(samples, nsamp, true);
|
||||
// duplicate to stereo
|
||||
for (int i = 0; i < nsamp * 2; i += 2)
|
||||
samples[i + 1] = samples[i];
|
||||
|
||||
//mix in the cart's extra sound circuit
|
||||
nes.Board.ApplyCustomAudio(samples);
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode != SyncSoundMode.Sync)
|
||||
{
|
||||
throw new NotSupportedException("Only sync mode is supported");
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new NotSupportedException("Async not supported");
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
//Console.WriteLine("ASync: {0}", nes.apu.dlist.Count);
|
||||
foreach (var d in nes.apu.dlist)
|
||||
|
|
|
@ -70,6 +70,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
Tracer = new TraceBuffer { Header = cpu.TraceHeader };
|
||||
ser.Register<ITraceable>(Tracer);
|
||||
ser.Register<IVideoProvider>(videoProvider);
|
||||
ser.Register<ISoundProvider>(magicSoundProvider);
|
||||
|
||||
if (Board is BANDAI_FCG_1)
|
||||
{
|
||||
|
@ -334,10 +335,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
}
|
||||
|
||||
MyVideoProvider videoProvider;
|
||||
public IAsyncSoundProvider SoundProvider { get { return magicSoundProvider; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return magicSoundProvider; } }
|
||||
public bool StartAsyncSound() { return true; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
[Obsolete] // with the changes to both nes and quicknes cores, nothing uses this anymore
|
||||
public static readonly ControllerDefinition NESController =
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
||||
{
|
||||
public partial class QuickNES : ISoundProvider
|
||||
{
|
||||
private short[] MonoBuff = new short[1024];
|
||||
private short[] StereoBuff = new short[2048];
|
||||
private int NumSamples = 0;
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = StereoBuff;
|
||||
nsamp = NumSamples;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
private void InitAudio()
|
||||
{
|
||||
LibQuickNES.ThrowStringError(QN.qn_set_sample_rate(Context, 44100));
|
||||
}
|
||||
|
||||
private void DrainAudio()
|
||||
{
|
||||
NumSamples = QN.qn_read_audio(Context, MonoBuff, MonoBuff.Length);
|
||||
unsafe
|
||||
{
|
||||
fixed (short* _src = &MonoBuff[0], _dst = &StereoBuff[0])
|
||||
{
|
||||
short* src = _src;
|
||||
short* dst = _dst;
|
||||
for (int i = 0; i < NumSamples; i++)
|
||||
{
|
||||
*dst++ = *src;
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.CollectionExtensions;
|
||||
using BizHawk.Emulation.Common.BizInvoke;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
||||
|
@ -24,7 +17,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
|||
portedUrl: "https://github.com/kode54/QuickNES"
|
||||
)]
|
||||
[ServiceNotApplicable(typeof(IDriveLight))]
|
||||
public partial class QuickNES : IEmulator, IVideoProvider, ISyncSoundProvider, ISaveRam, IInputPollable,
|
||||
public partial class QuickNES : IEmulator, IVideoProvider, ISoundProvider, ISaveRam, IInputPollable,
|
||||
IStatable, IDebuggable, ISettable<QuickNES.QuickNESSettings, QuickNES.QuickNESSyncSettings>, Cores.Nintendo.NES.INESPPUViewable
|
||||
{
|
||||
static readonly LibQuickNES QN;
|
||||
|
@ -320,52 +313,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
|||
throw new ObjectDisposedException(GetType().Name);
|
||||
}
|
||||
|
||||
#region SoundProvider
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
void InitAudio()
|
||||
{
|
||||
LibQuickNES.ThrowStringError(QN.qn_set_sample_rate(Context, 44100));
|
||||
}
|
||||
|
||||
void DrainAudio()
|
||||
{
|
||||
NumSamples = QN.qn_read_audio(Context, MonoBuff, MonoBuff.Length);
|
||||
unsafe
|
||||
{
|
||||
fixed (short* _src = &MonoBuff[0], _dst = &StereoBuff[0])
|
||||
{
|
||||
short* src = _src;
|
||||
short* dst = _dst;
|
||||
for (int i = 0; i < NumSamples; i++)
|
||||
{
|
||||
*dst++ = *src;
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
short[] MonoBuff = new short[1024];
|
||||
short[] StereoBuff = new short[2048];
|
||||
int NumSamples = 0;
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = StereoBuff;
|
||||
nsamp = NumSamples;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Blacklist
|
||||
|
||||
// These games are known to not work in quicknes but quicknes thinks it can run them, bail out if one of these is loaded
|
||||
|
|
|
@ -84,6 +84,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
|||
|
||||
// start up audio resampler
|
||||
InitAudio();
|
||||
(ServiceProvider as BasicServiceProvider).Register<ISoundProvider>(resampler);
|
||||
|
||||
//strip header
|
||||
if (romData != null)
|
||||
|
@ -1300,10 +1301,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES
|
|||
resampler.EnqueueSample((short)left, (short)right);
|
||||
}
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return resampler; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
#endregion audio stuff
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
|
@ -11,7 +10,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X
|
|||
{
|
||||
[CoreAttributes("Snes9x", "FIXME", true, false, "5e0319ab3ef9611250efb18255186d0dc0d7e125", "https://github.com/snes9xgit/snes9x", true)]
|
||||
[ServiceNotApplicable(typeof(IDriveLight))]
|
||||
public class Snes9x : IEmulator, IVideoProvider, ISyncSoundProvider
|
||||
public class Snes9x : IEmulator, IVideoProvider, ISoundProvider
|
||||
{
|
||||
#region controller
|
||||
|
||||
|
@ -72,15 +71,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X
|
|||
|
||||
#endregion
|
||||
|
||||
#region ISyncSoundProvider
|
||||
#region ISoundProvider
|
||||
|
||||
private short[] _sbuff = new short[2048];
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = _sbuff;
|
||||
nsamp = 735;
|
||||
|
@ -88,6 +83,30 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X
|
|||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -283,7 +283,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
|
|||
void AdpcmEmitSample()
|
||||
{
|
||||
if (AdpcmIsPlaying == false)
|
||||
SoundProvider.buffer.enqueue_sample(0, 0);
|
||||
SoundProvider.Buffer.enqueue_sample(0, 0);
|
||||
else
|
||||
{
|
||||
if (nextSampleTimer <= 0)
|
||||
|
@ -303,13 +303,13 @@ namespace BizHawk.Emulation.Cores.PCEngine
|
|||
}
|
||||
|
||||
short adjustedSample = (short)((playingSample - 2048) * MaxVolume / 2048);
|
||||
SoundProvider.buffer.enqueue_sample(adjustedSample, adjustedSample);
|
||||
SoundProvider.Buffer.enqueue_sample(adjustedSample, adjustedSample);
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamples(short[] samples)
|
||||
{
|
||||
SoundProvider.GetSamples(samples);
|
||||
SoundProvider.GetSamplesAsync(samples);
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
|
|||
public HuC6280PSG PSG;
|
||||
public CDAudio CDAudio;
|
||||
public SoundMixer SoundMixer;
|
||||
public MetaspuSoundProvider SoundSynchronizer;
|
||||
//public MetaspuSoundProvider SoundSynchronizer;
|
||||
|
||||
bool TurboGrafx { get { return Type == NecSystemType.TurboGrafx; } }
|
||||
bool SuperGrafx { get { return Type == NecSystemType.SuperGrafx; } }
|
||||
|
@ -171,7 +171,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
|
|||
Cpu.ReadMemory21 = ReadMemory;
|
||||
Cpu.WriteMemory21 = WriteMemory;
|
||||
Cpu.WriteVDC = VDC1.WriteVDC;
|
||||
soundProvider = PSG;
|
||||
soundProvider = new FakeSyncSound(PSG, 735);
|
||||
CDAudio = new CDAudio(null, 0);
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
|
|||
Cpu.ReadMemory21 = ReadMemorySGX;
|
||||
Cpu.WriteMemory21 = WriteMemorySGX;
|
||||
Cpu.WriteVDC = VDC1.WriteVDC;
|
||||
soundProvider = PSG;
|
||||
soundProvider = new FakeSyncSound(PSG, 735);
|
||||
CDAudio = new CDAudio(null, 0);
|
||||
}
|
||||
|
||||
|
@ -199,8 +199,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
|
|||
SetCDAudioCallback();
|
||||
PSG.MaxVolume = short.MaxValue * 3 / 4;
|
||||
SoundMixer = new SoundMixer(PSG, CDAudio, ADPCM);
|
||||
SoundSynchronizer = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
|
||||
soundProvider = SoundSynchronizer;
|
||||
soundProvider = new FakeSyncSound(SoundMixer, 735);
|
||||
Cpu.ThinkAction = (cycles) => { SCSI.Think(); ADPCM.Think(cycles); };
|
||||
}
|
||||
|
||||
|
@ -305,6 +304,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
|
|||
ser.Register<ITraceable>(Tracer);
|
||||
ser.Register<IDisassemblable>(Cpu);
|
||||
ser.Register<IVideoProvider>((IVideoProvider)VPC ?? VDC1);
|
||||
ser.Register<ISoundProvider>(soundProvider);
|
||||
SetupMemoryDomains();
|
||||
}
|
||||
|
||||
|
@ -384,8 +384,6 @@ namespace BizHawk.Emulation.Cores.PCEngine
|
|||
VDC1.ExecFrame(render);
|
||||
|
||||
PSG.EndFrame(Cpu.TotalExecutedCycles);
|
||||
if (TurboCD)
|
||||
SoundSynchronizer.PullSamples(SoundMixer);
|
||||
|
||||
if (lagged)
|
||||
{
|
||||
|
@ -406,14 +404,7 @@ namespace BizHawk.Emulation.Cores.PCEngine
|
|||
|
||||
public CoreComm CoreComm { get; private set; }
|
||||
|
||||
IAsyncSoundProvider soundProvider;
|
||||
public IAsyncSoundProvider SoundProvider
|
||||
{
|
||||
get { return soundProvider; }
|
||||
}
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return new FakeSyncSound(soundProvider, 735); } }
|
||||
public bool StartAsyncSound() { return true; }
|
||||
public void EndAsyncSound() { }
|
||||
private ISoundProvider soundProvider;
|
||||
|
||||
public string SystemId { get { return systemid; } }
|
||||
public string Region { get; set; }
|
||||
|
|
|
@ -301,13 +301,15 @@ namespace BizHawk.Emulation.Cores.Sega.Genesis
|
|||
|
||||
public CoreComm CoreComm { get; private set; }
|
||||
|
||||
// Sound refactor todo: Implement ISoundProvider
|
||||
/*
|
||||
public IAsyncSoundProvider SoundProvider
|
||||
{
|
||||
get { return SoundMixer; }
|
||||
}
|
||||
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return new FakeSyncSound(SoundMixer, 735); } }
|
||||
public bool StartAsyncSound() { return true; }
|
||||
public void EndAsyncSound() { }
|
||||
*/
|
||||
|
||||
public int Frame { get; set; }
|
||||
public int LagCount { get { return _lagcount; } set { _lagcount = value; } }
|
||||
|
|
|
@ -6,23 +6,6 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
|
|||
{
|
||||
public IEmulatorServiceProvider ServiceProvider { get; private set; }
|
||||
|
||||
public IAsyncSoundProvider SoundProvider
|
||||
{
|
||||
get { return ActiveSoundProvider; }
|
||||
}
|
||||
|
||||
public ISyncSoundProvider SyncSoundProvider
|
||||
{
|
||||
get { return new FakeSyncSound(ActiveSoundProvider, 735); }
|
||||
}
|
||||
|
||||
public bool StartAsyncSound()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public ControllerDefinition ControllerDefinition
|
||||
{
|
||||
get
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sega.MasterSystem
|
||||
{
|
||||
// Sound refactor TODO: Implement ISoundProvider without the need for FakeSyncSound
|
||||
public sealed partial class SMS
|
||||
{
|
||||
private FakeSyncSound _fakeSyncSound;
|
||||
private IAsyncSoundProvider ActiveSoundProvider;
|
||||
private SoundMixer SoundMixer;
|
||||
}
|
||||
}
|
|
@ -42,7 +42,6 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
|
|||
public VDP Vdp;
|
||||
private SN76489 PSG;
|
||||
private YM2413 YM2413;
|
||||
private SoundMixer SoundMixer;
|
||||
public bool IsGameGear { get; set; }
|
||||
public bool IsSG1000 { get; set; }
|
||||
|
||||
|
@ -119,6 +118,8 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
|
|||
if (HasYM2413 && game["WhenFMDisablePSG"])
|
||||
SoundMixer.DisableSource(PSG);
|
||||
ActiveSoundProvider = HasYM2413 ? (IAsyncSoundProvider)SoundMixer : PSG;
|
||||
_fakeSyncSound = new FakeSyncSound(ActiveSoundProvider, 735);
|
||||
(ServiceProvider as BasicServiceProvider).Register<ISoundProvider>(_fakeSyncSound);
|
||||
|
||||
SystemRam = new byte[0x2000];
|
||||
|
||||
|
@ -310,8 +311,6 @@ namespace BizHawk.Emulation.Cores.Sega.MasterSystem
|
|||
else if (port == 0xF2 && HasYM2413) YM2413.DetectionValue = value;
|
||||
}
|
||||
|
||||
private IAsyncSoundProvider ActiveSoundProvider;
|
||||
|
||||
private string _region;
|
||||
private string RegionStr
|
||||
{
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace BizHawk.Emulation.Cores.Sega.Saturn
|
|||
portedUrl: "http://yabause.org",
|
||||
singleInstance: true
|
||||
)]
|
||||
public partial class Yabause : IEmulator, IVideoProvider, ISyncSoundProvider, ISaveRam, IStatable, IInputPollable,
|
||||
public partial class Yabause : IEmulator, IVideoProvider, ISoundProvider, ISaveRam, IStatable, IInputPollable,
|
||||
ISettable<object, Yabause.SaturnSyncSettings>, IDriveLight
|
||||
{
|
||||
public static ControllerDefinition SaturnController = new ControllerDefinition
|
||||
|
@ -354,20 +354,39 @@ namespace BizHawk.Emulation.Cores.Sega.Saturn
|
|||
|
||||
#region ISyncSoundProvider
|
||||
|
||||
short[] SoundBuffer = new short[44100 * 2];
|
||||
int SoundNSamp = 0;
|
||||
private short[] SoundBuffer = new short[44100 * 2];
|
||||
private int SoundNSamp = 0;
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
nsamp = SoundNSamp;
|
||||
samples = SoundBuffer;
|
||||
}
|
||||
|
||||
public void DiscardSamples() { }
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -7,20 +7,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
{
|
||||
public IEmulatorServiceProvider ServiceProvider { get; private set; }
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
|
||||
public ISyncSoundProvider SyncSoundProvider
|
||||
{
|
||||
get { return this; }
|
||||
}
|
||||
|
||||
public bool StartAsyncSound()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public ControllerDefinition ControllerDefinition { get; private set; }
|
||||
|
||||
public IController Controller { get; set; }
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
||||
{
|
||||
public partial class GPGX : ISoundProvider
|
||||
{
|
||||
private short[] samples = new short[4096];
|
||||
private int nsamp = 0;
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
nsamp = this.nsamp;
|
||||
samples = this.samples;
|
||||
this.nsamp = 0;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
this.nsamp = 0;
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
private void update_audio()
|
||||
{
|
||||
IntPtr src = IntPtr.Zero;
|
||||
LibGPGX.gpgx_get_audio(ref nsamp, ref src);
|
||||
if (src != IntPtr.Zero)
|
||||
{
|
||||
Marshal.Copy(src, samples, 0, nsamp * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
portedUrl: "https://code.google.com/p/genplus-gx/",
|
||||
singleInstance: true
|
||||
)]
|
||||
public partial class GPGX : IEmulator, ISyncSoundProvider, IVideoProvider, ISaveRam, IStatable, IRegionable,
|
||||
public partial class GPGX : IEmulator, IVideoProvider, ISaveRam, IStatable, IRegionable,
|
||||
IInputPollable, IDebuggable, IDriveLight, ICodeDataLogger, IDisassemblable
|
||||
{
|
||||
static GPGX AttachedCore = null;
|
||||
|
@ -372,31 +372,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
LibGPGX.gpgx_flush_vram(); // fully regenerate internal caches as needed
|
||||
}
|
||||
|
||||
short[] samples = new short[4096];
|
||||
int nsamp = 0;
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
{
|
||||
nsamp = this.nsamp;
|
||||
samples = this.samples;
|
||||
this.nsamp = 0;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
this.nsamp = 0;
|
||||
}
|
||||
|
||||
void update_audio()
|
||||
{
|
||||
IntPtr src = IntPtr.Zero;
|
||||
LibGPGX.gpgx_get_audio(ref nsamp, ref src);
|
||||
if (src != IntPtr.Zero)
|
||||
{
|
||||
Marshal.Copy(src, samples, 0, nsamp * 2);
|
||||
}
|
||||
}
|
||||
|
||||
public DisplayType Region { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,24 +3,10 @@ using BizHawk.Emulation.Common;
|
|||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
|
||||
{
|
||||
public partial class GPGX : IEmulator
|
||||
public partial class GPGX : IEmulator, ISoundProvider
|
||||
{
|
||||
public IEmulatorServiceProvider ServiceProvider { get; private set; }
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
|
||||
public ISyncSoundProvider SyncSoundProvider
|
||||
{
|
||||
get { return this; }
|
||||
}
|
||||
|
||||
public bool StartAsyncSound()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public ControllerDefinition ControllerDefinition { get; private set; }
|
||||
|
||||
public IController Controller { get; set; }
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
|
||||
{
|
||||
public partial class GPGX : ISoundProvider
|
||||
{
|
||||
private short[] samples = new short[4096];
|
||||
private int nsamp = 0;
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
nsamp = this.nsamp;
|
||||
samples = this.samples;
|
||||
this.nsamp = 0;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
this.nsamp = 0;
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
}
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
private void update_audio()
|
||||
{
|
||||
IntPtr src = IntPtr.Zero;
|
||||
Core.gpgx_get_audio(ref nsamp, ref src);
|
||||
if (src != IntPtr.Zero)
|
||||
{
|
||||
Marshal.Copy(src, samples, 0, nsamp * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
|
|||
portedUrl: "https://code.google.com/p/genplus-gx/",
|
||||
singleInstance: false
|
||||
)]
|
||||
public partial class GPGX : IEmulator, ISyncSoundProvider, IVideoProvider, ISaveRam, IStatable, IRegionable,
|
||||
public partial class GPGX : IEmulator, IVideoProvider, ISaveRam, IStatable, IRegionable,
|
||||
IInputPollable, IDebuggable, IDriveLight, ICodeDataLogger, IDisassemblable
|
||||
{
|
||||
LibGPGX Core;
|
||||
|
@ -374,31 +374,6 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
|
|||
Core.gpgx_flush_vram(); // fully regenerate internal caches as needed
|
||||
}
|
||||
|
||||
short[] samples = new short[4096];
|
||||
int nsamp = 0;
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
{
|
||||
nsamp = this.nsamp;
|
||||
samples = this.samples;
|
||||
this.nsamp = 0;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
this.nsamp = 0;
|
||||
}
|
||||
|
||||
void update_audio()
|
||||
{
|
||||
IntPtr src = IntPtr.Zero;
|
||||
Core.gpgx_get_audio(ref nsamp, ref src);
|
||||
if (src != IntPtr.Zero)
|
||||
{
|
||||
Marshal.Copy(src, samples, 0, nsamp * 2);
|
||||
}
|
||||
}
|
||||
|
||||
public DisplayType Region { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
|
@ -15,7 +12,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSP
|
|||
isReleased: false,
|
||||
singleInstance: true
|
||||
)]
|
||||
public class PSP : IEmulator, IVideoProvider, ISyncSoundProvider
|
||||
public class PSP : IEmulator, IVideoProvider, ISoundProvider
|
||||
{
|
||||
public static readonly ControllerDefinition PSPController = new ControllerDefinition
|
||||
{
|
||||
|
@ -41,10 +38,6 @@ namespace BizHawk.Emulation.Cores.Sony.PSP
|
|||
}
|
||||
};
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
public ControllerDefinition ControllerDefinition { get { return PSPController; } }
|
||||
public IController Controller { get; set; }
|
||||
public bool DeterministicEmulation { get { return true; } }
|
||||
|
@ -186,7 +179,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSP
|
|||
|
||||
readonly short[] audiobuffer = new short[2048 * 2];
|
||||
int nsampavail = 0;
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = audiobuffer;
|
||||
nsamp = nsampavail;
|
||||
|
@ -195,5 +188,28 @@ namespace BizHawk.Emulation.Cores.Sony.PSP
|
|||
public void DiscardSamples()
|
||||
{
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
isPorted: true,
|
||||
isReleased: true
|
||||
)]
|
||||
public unsafe partial class Octoshock : IEmulator, IVideoProvider, ISyncSoundProvider, ISaveRam, IStatable, IDriveLight, ISettable<Octoshock.Settings, Octoshock.SyncSettings>, IRegionable, IInputPollable
|
||||
public unsafe partial class Octoshock : IEmulator, IVideoProvider, ISoundProvider, ISaveRam, IStatable, IDriveLight, ISettable<Octoshock.Settings, Octoshock.SyncSettings>, IRegionable, IInputPollable
|
||||
{
|
||||
public string SystemId { get { return "PSX"; } }
|
||||
|
||||
|
@ -861,12 +861,7 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
private short[] sbuff = new short[1611 * 2]; //need this for pal
|
||||
private int sbuffcontains = 0;
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { throw new InvalidOperationException(); } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = sbuff;
|
||||
nsamp = sbuffcontains;
|
||||
|
@ -877,6 +872,29 @@ namespace BizHawk.Emulation.Cores.Sony.PSX
|
|||
sbuffcontains = 0;
|
||||
}
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ISaveRam
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.WonderSwan
|
||||
{
|
||||
public partial class WonderSwan : ISoundProvider
|
||||
{
|
||||
private short[] sbuff = new short[1536];
|
||||
private int sbuffcontains = 0;
|
||||
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = sbuff;
|
||||
nsamp = sbuffcontains;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
sbuffcontains = 0;
|
||||
}
|
||||
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode == SyncSoundMode.Async)
|
||||
{
|
||||
throw new NotSupportedException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new InvalidOperationException("Async mode is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ namespace BizHawk.Emulation.Cores.WonderSwan
|
|||
{
|
||||
[CoreAttributes("Cygne/Mednafen", "Dox", true, true, "0.9.36.5", "http://mednafen.sourceforge.net/")]
|
||||
[ServiceNotApplicable(typeof(IDriveLight), typeof(IRegionable))]
|
||||
public partial class WonderSwan : IEmulator, IVideoProvider, ISyncSoundProvider,
|
||||
public partial class WonderSwan : IEmulator, IVideoProvider, ISoundProvider,
|
||||
IInputPollable, IDebuggable
|
||||
{
|
||||
[CoreConstructor("WSWAN")]
|
||||
|
@ -215,28 +215,5 @@ namespace BizHawk.Emulation.Cores.WonderSwan
|
|||
public int BackgroundColor { get { return unchecked((int)0xff000000); } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ISoundProvider
|
||||
|
||||
private short[] sbuff = new short[1536];
|
||||
private int sbuffcontains = 0;
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { throw new InvalidOperationException(); } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return this; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
{
|
||||
samples = sbuff;
|
||||
nsamp = sbuffcontains;
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
sbuffcontains = 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -496,6 +496,7 @@ namespace BizHawk.Emulation.Cores
|
|||
CoreComm.VsyncDen = 10000000;
|
||||
|
||||
SetupResampler(av.timing.fps, av.timing.sample_rate);
|
||||
(ServiceProvider as BasicServiceProvider).Register<ISoundProvider>(resampler);
|
||||
|
||||
ControllerDefinition = CreateControllerDefinition(_SyncSettings);
|
||||
|
||||
|
@ -737,11 +738,6 @@ namespace BizHawk.Emulation.Cores
|
|||
|
||||
#region ISoundProvider
|
||||
|
||||
public IAsyncSoundProvider SoundProvider { get { return null; } }
|
||||
public ISyncSoundProvider SyncSoundProvider { get { return resampler; } }
|
||||
public bool StartAsyncSound() { return false; }
|
||||
public void EndAsyncSound() { }
|
||||
|
||||
SpeexResampler resampler;
|
||||
|
||||
short[] sampbuff = new short[0];
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace BizHawk.Emulation.Cores.Components
|
|||
// Emulates PSG audio unit of a PC Engine / Turbografx-16 / SuperGrafx.
|
||||
// It is embedded on the CPU and doesn't have its own part number. None the less, it is emulated separately from the 6280 CPU.
|
||||
|
||||
// Sound refactor TODO: IMixedSoundProvider must inherit ISoundProvider
|
||||
public sealed class HuC6280PSG : IMixedSoundProvider
|
||||
{
|
||||
public class PSGChannel
|
||||
|
@ -144,6 +145,7 @@ namespace BizHawk.Emulation.Cores.Components
|
|||
}
|
||||
|
||||
public void DiscardSamples() { }
|
||||
|
||||
public void GetSamples(short[] samples)
|
||||
{
|
||||
int elapsedCycles = (int)(frameStopTime - frameStartTime);
|
||||
|
|
Loading…
Reference in New Issue