diff --git a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
index 77279a2c15..632a6603eb 100644
--- a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
+++ b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
@@ -717,6 +717,7 @@
RomStatusPicker.cs
+
diff --git a/BizHawk.Client.EmuHawk/Sound/Interfaces/ISoundOutput.cs b/BizHawk.Client.EmuHawk/Sound/Interfaces/ISoundOutput.cs
new file mode 100644
index 0000000000..f6dce3be8d
--- /dev/null
+++ b/BizHawk.Client.EmuHawk/Sound/Interfaces/ISoundOutput.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace BizHawk.Client.EmuHawk
+{
+ public interface ISoundOutput : IDisposable
+ {
+ void StartSound();
+ void StopSound();
+ void ApplyVolumeSettings(double volume);
+ int MaxSamplesDeficit { get; }
+ int CalculateSamplesNeeded();
+ void WriteSamples(short[] samples, int sampleCount);
+ }
+}
diff --git a/BizHawk.Client.EmuHawk/Sound/Sound.cs b/BizHawk.Client.EmuHawk/Sound/Sound.cs
index e3135a3547..4c10058d60 100644
--- a/BizHawk.Client.EmuHawk/Sound/Sound.cs
+++ b/BizHawk.Client.EmuHawk/Sound/Sound.cs
@@ -15,10 +15,9 @@ namespace BizHawk.Client.EmuHawk
private bool _disposed;
private readonly ISoundOutput _outputDevice;
- private readonly SoundOutputProvider _outputProvider = new SoundOutputProvider();
- private readonly BufferedAsync _bufferedAsync = new BufferedAsync();
- private ISoundProvider _sourceProvider;
- private SyncSoundMode _syncMode;
+ private readonly SoundOutputProvider _outputProvider = new SoundOutputProvider(); // 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 Sound(IntPtr mainWindowHandle)
{
@@ -71,8 +70,7 @@ namespace BizHawk.Client.EmuHawk
_outputDevice.StopSound();
- _outputProvider.DiscardSamples();
- _bufferedAsync.DiscardSamples();
+ if (_bufferedProvider != null) _bufferedProvider.DiscardSamples();
Global.SoundMaxBufferDeficitMs = 0;
@@ -86,28 +84,27 @@ namespace BizHawk.Client.EmuHawk
///
public void SetInputPin(ISoundProvider source)
{
- _outputProvider.DiscardSamples();
- _outputProvider.BaseSoundProvider = null;
-
- _bufferedAsync.DiscardSamples();
- _bufferedAsync.BaseSoundProvider = null;
-
- _sourceProvider = source;
- if (_sourceProvider == null)
+ if (_bufferedProvider != null)
{
- return;
+ _bufferedProvider.BaseSoundProvider = null;
+ _bufferedProvider.DiscardSamples();
+ _bufferedProvider = null;
}
- _syncMode = _sourceProvider.SyncMode;
- if (_syncMode == SyncSoundMode.Sync)
+ if (source == null) return;
+
+ if (source.SyncMode == SyncSoundMode.Sync)
{
- _outputProvider.BaseSoundProvider = _sourceProvider;
+ _bufferedProvider = _outputProvider;
}
- else
+ else if (source.SyncMode == SyncSoundMode.Async)
{
- _bufferedAsync.BaseSoundProvider = _sourceProvider;
_bufferedAsync.RecalculateMagic(Global.Emulator.CoreComm.VsyncRate);
+ _bufferedProvider = _bufferedAsync;
}
+ else throw new InvalidOperationException("Unsupported sync mode.");
+
+ _bufferedProvider.BaseSoundProvider = source;
}
public bool LogUnderruns { get; set; }
@@ -148,18 +145,12 @@ namespace BizHawk.Client.EmuHawk
public void UpdateSound(float atten)
{
- if (!Global.Config.SoundEnabled || !IsStarted || _sourceProvider == null || _disposed)
+ if (!Global.Config.SoundEnabled || !IsStarted || _bufferedProvider == null || _disposed)
{
- if (_sourceProvider != null) _sourceProvider.DiscardSamples();
- _outputProvider.DiscardSamples();
+ if (_bufferedProvider != null) _bufferedProvider.DiscardSamples();
return;
}
- if (_sourceProvider.SyncMode != _syncMode)
- {
- throw new Exception("Sync mode changed unexpectedly.");
- }
-
if (atten < 0) atten = 0;
if (atten > 1) atten = 1;
_outputDevice.ApplyVolumeSettings(atten);
@@ -173,14 +164,13 @@ namespace BizHawk.Client.EmuHawk
samples = new short[samplesNeeded * ChannelCount];
samplesProvided = samplesNeeded;
- _sourceProvider.DiscardSamples();
- _outputProvider.DiscardSamples();
+ _bufferedProvider.DiscardSamples();
}
- else if (_syncMode == SyncSoundMode.Sync)
+ else if (_bufferedProvider == _outputProvider)
{
if (Global.Config.SoundThrottle)
{
- _sourceProvider.GetSamplesSync(out samples, out samplesProvided);
+ _outputProvider.BaseSoundProvider.GetSamplesSync(out samples, out samplesProvided);
while (samplesNeeded < samplesProvided && !Global.DisableSecondaryThrottling)
{
@@ -197,7 +187,7 @@ namespace BizHawk.Client.EmuHawk
_outputProvider.GetSamples(samplesNeeded, out samples, out samplesProvided);
}
}
- else if (_syncMode == SyncSoundMode.Async)
+ else if (_bufferedProvider == _bufferedAsync)
{
samples = new short[samplesNeeded * ChannelCount];
@@ -223,14 +213,4 @@ namespace BizHawk.Client.EmuHawk
return samples * 1000.0 / SampleRate;
}
}
-
- public interface ISoundOutput : IDisposable
- {
- void StartSound();
- void StopSound();
- void ApplyVolumeSettings(double volume);
- int MaxSamplesDeficit { get; }
- int CalculateSamplesNeeded();
- void WriteSamples(short[] samples, int sampleCount);
- }
}
diff --git a/BizHawk.Client.EmuHawk/Sound/Utilities/SoundOutputProvider.cs b/BizHawk.Client.EmuHawk/Sound/Utilities/SoundOutputProvider.cs
index 0d03ce0e34..33ef5471a7 100644
--- a/BizHawk.Client.EmuHawk/Sound/Utilities/SoundOutputProvider.cs
+++ b/BizHawk.Client.EmuHawk/Sound/Utilities/SoundOutputProvider.cs
@@ -16,7 +16,7 @@ namespace BizHawk.Client.EmuHawk
// perform a "soft" correction by resampling it to hopefully get back inside our
// window shortly. If it ends up going too low or too high, we will perform a
// "hard" correction by generating silence or discarding samples.
- public class SoundOutputProvider
+ public class SoundOutputProvider : IBufferedSoundProvider
{
private const int SampleRate = 44100;
private const int ChannelCount = 2;
diff --git a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj
index 519f52259c..508fdec95e 100644
--- a/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj
+++ b/BizHawk.Emulation.Common/BizHawk.Emulation.Common.csproj
@@ -117,6 +117,7 @@
+
diff --git a/BizHawk.Emulation.Common/Interfaces/IBufferedSoundProvider.cs b/BizHawk.Emulation.Common/Interfaces/IBufferedSoundProvider.cs
new file mode 100644
index 0000000000..aec9efda87
--- /dev/null
+++ b/BizHawk.Emulation.Common/Interfaces/IBufferedSoundProvider.cs
@@ -0,0 +1,15 @@
+namespace BizHawk.Emulation.Common
+{
+ public interface IBufferedSoundProvider
+ {
+ ///
+ /// The source audio provider.
+ ///
+ ISoundProvider BaseSoundProvider { get; set; }
+
+ ///
+ /// Clears any internally buffered samples, and discards samples from the base provider (if set).
+ ///
+ void DiscardSamples();
+ }
+}
diff --git a/BizHawk.Emulation.Common/Sound/Utilities/BufferedAsync.cs b/BizHawk.Emulation.Common/Sound/Utilities/BufferedAsync.cs
index b74965d313..aab88f280b 100644
--- a/BizHawk.Emulation.Common/Sound/Utilities/BufferedAsync.cs
+++ b/BizHawk.Emulation.Common/Sound/Utilities/BufferedAsync.cs
@@ -28,7 +28,7 @@ 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 : ISoundProvider
+ public sealed class BufferedAsync : ISoundProvider, IBufferedSoundProvider
{
public ISoundProvider BaseSoundProvider { get; set; }