From 636a9a47354b369ecdb89d5c69290d48e2b744f1 Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Mon, 30 Nov 2020 16:16:22 +1000 Subject: [PATCH] Pass a callback to some sound internals to read the global IEmulator --- src/BizHawk.Client.EmuHawk/MainForm.Events.cs | 2 +- src/BizHawk.Client.EmuHawk/MainForm.cs | 6 +++--- src/BizHawk.Client.EmuHawk/Sound/Sound.cs | 13 +++++++++---- .../Sound/Utilities/SoundOutputProvider.cs | 7 +++++-- .../Sound/Utilities/SyncToAsyncProvider.cs | 9 ++++++--- 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/BizHawk.Client.EmuHawk/MainForm.Events.cs b/src/BizHawk.Client.EmuHawk/MainForm.Events.cs index 06913c66ee..34c8302dec 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.Events.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.Events.cs @@ -919,7 +919,7 @@ namespace BizHawk.Client.EmuHawk if (form.ApplyNewSoundDevice) { Sound.Dispose(); - Sound = new Sound(Handle, Config.SoundOutputMethod, Config.SoundDevice); + Sound = new Sound(Handle, Config.SoundOutputMethod, Config.SoundDevice, Emulator.VsyncRate); Sound.StartSound(); } else diff --git a/src/BizHawk.Client.EmuHawk/MainForm.cs b/src/BizHawk.Client.EmuHawk/MainForm.cs index 645928021b..68cd469cde 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.cs @@ -415,7 +415,7 @@ namespace BizHawk.Client.EmuHawk InputManager.AutofireStickyXorAdapter.SetOnOffPatternFromConfig(Config.AutofireOn, Config.AutofireOff); try { - GlobalWin.Sound = new Sound(Handle, Config.SoundOutputMethod, Config.SoundDevice); + GlobalWin.Sound = new Sound(Handle, Config.SoundOutputMethod, Config.SoundDevice, Emulator.VsyncRate); } catch { @@ -428,7 +428,7 @@ namespace BizHawk.Client.EmuHawk MessageBox.Show(message, "Initialization Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Config.SoundOutputMethod = ESoundOutputMethod.Dummy; - GlobalWin.Sound = new Sound(Handle, Config.SoundOutputMethod, Config.SoundDevice); + GlobalWin.Sound = new Sound(Handle, Config.SoundOutputMethod, Config.SoundDevice, Emulator.VsyncRate); } Sound.StartSound(); @@ -3294,7 +3294,7 @@ namespace BizHawk.Client.EmuHawk else { _currentSoundProvider.SetSyncMode(SyncSoundMode.Sync); - _aviSoundInputAsync = new SyncToAsyncProvider(_currentSoundProvider); + _aviSoundInputAsync = new SyncToAsyncProvider(Emulator.VsyncRate, _currentSoundProvider); } } diff --git a/src/BizHawk.Client.EmuHawk/Sound/Sound.cs b/src/BizHawk.Client.EmuHawk/Sound/Sound.cs index a87ec6cc96..18b5e112da 100644 --- a/src/BizHawk.Client.EmuHawk/Sound/Sound.cs +++ b/src/BizHawk.Client.EmuHawk/Sound/Sound.cs @@ -19,18 +19,23 @@ namespace BizHawk.Client.EmuHawk public int BlockAlign { get; } + private readonly Func _getCoreVsyncRateCallback; + private bool _disposed; private readonly ISoundOutput _outputDevice; - private readonly SoundOutputProvider _outputProvider = new SoundOutputProvider(); // Buffer for Sync sources + private readonly SoundOutputProvider _outputProvider; // Buffer for Sync sources private readonly BufferedAsync _bufferedAsync = new BufferedAsync(); // Buffer for Async sources private IBufferedSoundProvider _bufferedProvider; // One of the preceding buffers, or null if no source is set public int ConfigBufferSizeMs => GlobalWin.Config.SoundBufferSizeMs; - public Sound(IntPtr mainWindowHandle, ESoundOutputMethod soundOutputMethod, string soundDevice) + public Sound(IntPtr mainWindowHandle, ESoundOutputMethod soundOutputMethod, string soundDevice, Func getCoreVsyncRateCallback) { BlockAlign = BytesPerSample * ChannelCount; + _getCoreVsyncRateCallback = getCoreVsyncRateCallback; + _outputProvider = new SoundOutputProvider(_getCoreVsyncRateCallback); + if (OSTailoredCode.IsUnixHost) { // if DirectSound or XAudio is chosen, use OpenAL, otherwise comply with the user's choice @@ -118,7 +123,7 @@ namespace BizHawk.Client.EmuHawk } else if (source.SyncMode == SyncSoundMode.Async) { - _bufferedAsync.RecalculateMagic(GlobalWin.Emulator.VsyncRate()); + _bufferedAsync.RecalculateMagic(_getCoreVsyncRateCallback()); _bufferedProvider = _bufferedAsync; } else throw new InvalidOperationException("Unsupported sync mode."); @@ -131,7 +136,7 @@ namespace BizHawk.Client.EmuHawk public void HandleInitializationOrUnderrun(bool isUnderrun, ref int samplesNeeded) { // Fill device buffer with silence but leave enough room for one frame - int samplesPerFrame = (int)Math.Round(SampleRate / (double)GlobalWin.Emulator.VsyncRate()); + int samplesPerFrame = (int)Math.Round(SampleRate / _getCoreVsyncRateCallback()); int silenceSamples = Math.Max(samplesNeeded - samplesPerFrame, 0); _outputDevice.WriteSamples(new short[silenceSamples * 2], 0, silenceSamples); samplesNeeded -= silenceSamples; diff --git a/src/BizHawk.Client.EmuHawk/Sound/Utilities/SoundOutputProvider.cs b/src/BizHawk.Client.EmuHawk/Sound/Utilities/SoundOutputProvider.cs index 9e23de6e9f..4759ba24ef 100644 --- a/src/BizHawk.Client.EmuHawk/Sound/Utilities/SoundOutputProvider.cs +++ b/src/BizHawk.Client.EmuHawk/Sound/Utilities/SoundOutputProvider.cs @@ -31,6 +31,8 @@ namespace BizHawk.Client.EmuHawk private const int BaseSampleRateMaxHistoryLength = 300; private const int MinResamplingDistanceSamples = 3; + private readonly Func _getCoreVsyncRateCallback; + private readonly Queue _buffer = new Queue(); private readonly bool _standaloneMode; private readonly int _targetExtraSamples; @@ -51,8 +53,9 @@ namespace BizHawk.Client.EmuHawk private short[] _resampleBuffer = new short[0]; private double _resampleLengthRoundingError; - public SoundOutputProvider(bool standaloneMode = false) + public SoundOutputProvider(Func getCoreVsyncRateCallback, bool standaloneMode = false) { + _getCoreVsyncRateCallback = getCoreVsyncRateCallback; _standaloneMode = standaloneMode; if (_standaloneMode) { @@ -114,7 +117,7 @@ namespace BizHawk.Client.EmuHawk public bool LogDebug { get; set; } - private double AdvertisedSamplesPerFrame => SampleRate / GlobalWin.Emulator.VsyncRate(); + private double AdvertisedSamplesPerFrame => SampleRate / _getCoreVsyncRateCallback(); /// not constructed in standalone mode public void GetSamples(short[] samples) diff --git a/src/BizHawk.Client.EmuHawk/Sound/Utilities/SyncToAsyncProvider.cs b/src/BizHawk.Client.EmuHawk/Sound/Utilities/SyncToAsyncProvider.cs index 35fdd39aa1..2a51530e27 100644 --- a/src/BizHawk.Client.EmuHawk/Sound/Utilities/SyncToAsyncProvider.cs +++ b/src/BizHawk.Client.EmuHawk/Sound/Utilities/SyncToAsyncProvider.cs @@ -6,11 +6,14 @@ namespace BizHawk.Client.EmuHawk { public class SyncToAsyncProvider : ISoundProvider { - private readonly SoundOutputProvider _outputProvider = new SoundOutputProvider(standaloneMode: true); + private readonly SoundOutputProvider _outputProvider; - public SyncToAsyncProvider(ISoundProvider baseProvider) + public SyncToAsyncProvider(Func getCoreVsyncRateCallback, ISoundProvider baseProvider) { - _outputProvider.BaseSoundProvider = baseProvider; + _outputProvider = new SoundOutputProvider(getCoreVsyncRateCallback, standaloneMode: true) + { + BaseSoundProvider = baseProvider + }; } public void DiscardSamples()