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
BizHawk.Client.EmuHawk
BizHawk.Emulation.Common
BizHawk.Emulation.Cores
BizHawk.Emulation.Cores.csproj
Calculator
Computers
AppleII
Commodore64
Consoles
Atari
Coleco
Intellivision
Nintendo
GBA
Gameboy
N64
NES
QuickNES
SNES
SNES9X
PC Engine
Sega
Genesis
SMS
Saturn
gpgx
gpgx64
Sony
WonderSwan
Libretro
Sound
|
@ -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);
|
||||
}
|
||||
|
||||
if (filterwidth < 8 || filterwidth > 65536)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
depth = DepthFromFilterwidth(filterwidth);
|
||||
|
||||
_soundProvider = input;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return new DCFilter(null, null, filterwidth);
|
||||
}
|
||||
|
||||
DCFilter(IAsyncSoundProvider input, ISyncSoundProvider syncinput, int filterwidth)
|
||||
// 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 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");
|
||||
}
|
||||
}
|
||||
|
||||
public class MetaspuSoundProvider : IAsyncSoundProvider
|
||||
// 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,13 +33,17 @@ 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.
|
||||
|
|
|
@ -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,13 +138,8 @@ 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]
|
||||
|
||||
[SaveState.DoNotSave]
|
||||
public ControllerDefinition ControllerDefinition { get { return C64ControllerDefinition; } }
|
||||
[SaveState.DoNotSave]
|
||||
public IController Controller { get { return _board.Controller; } set { _board.Controller = value; } }
|
||||
|
@ -167,9 +164,16 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
|||
while (_frameCycles != 0);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
private void DoCycle()
|
||||
#region ISoundProvider
|
||||
|
||||
[SaveState.DoNotSave]
|
||||
public ISoundProvider _soundProvider { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
private void DoCycle()
|
||||
{
|
||||
if (_frameCycles == 0) {
|
||||
_board.InputRead = false;
|
||||
|
|
|
@ -1,41 +1,57 @@
|
|||
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 int MaxVolume
|
||||
{
|
||||
get { return short.MaxValue; }
|
||||
set { }
|
||||
}
|
||||
public sealed partial class Sid : ISoundProvider
|
||||
{
|
||||
public bool CanProvideAsync
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
_outputBufferIndex = 0;
|
||||
}
|
||||
public SyncSoundMode SyncMode
|
||||
{
|
||||
get { return SyncSoundMode.Sync; }
|
||||
}
|
||||
|
||||
public void GetSamples(short[] samples)
|
||||
{
|
||||
Flush();
|
||||
var length = Math.Min(samples.Length, _outputBufferIndex);
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
samples[i] = _outputBuffer[i];
|
||||
}
|
||||
_outputBufferIndex = 0;
|
||||
}
|
||||
public void SetSyncMode(SyncSoundMode mode)
|
||||
{
|
||||
if (mode != SyncSoundMode.Sync)
|
||||
{
|
||||
throw new InvalidOperationException("Only Sync mode is supported.");
|
||||
}
|
||||
}
|
||||
|
||||
public void GetSamples(out short[] samples, out int nsamp)
|
||||
{
|
||||
Flush();
|
||||
samples = _outputBuffer;
|
||||
nsamp = _outputBufferIndex >> 1;
|
||||
_outputBufferIndex = 0;
|
||||
}
|
||||
}
|
||||
public void GetSamplesAsync(short[] samples)
|
||||
{
|
||||
throw new NotSupportedException("Async is not available");
|
||||
}
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
_outputBufferIndex = 0;
|
||||
}
|
||||
|
||||
// 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);
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
samples[i] = _outputBuffer[i];
|
||||
}
|
||||
_outputBufferIndex = 0;
|
||||
}
|
||||
|
||||
public void GetSamplesSync(out short[] samples, out int nsamp)
|
||||
{
|
||||
Flush();
|
||||
samples = _outputBuffer;
|
||||
nsamp = _outputBufferIndex >> 1;
|
||||
_outputBufferIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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