Sound cleanup.
This commit is contained in:
parent
a33a8252ff
commit
d95edc273e
|
@ -717,6 +717,7 @@
|
||||||
<Compile Include="RomStatusPicker.Designer.cs">
|
<Compile Include="RomStatusPicker.Designer.cs">
|
||||||
<DependentUpon>RomStatusPicker.cs</DependentUpon>
|
<DependentUpon>RomStatusPicker.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Sound\Interfaces\ISoundOutput.cs" />
|
||||||
<Compile Include="Sound\Output\DirectSoundSoundOutput.cs" />
|
<Compile Include="Sound\Output\DirectSoundSoundOutput.cs" />
|
||||||
<Compile Include="Sound\Output\DummySoundOutput.cs" />
|
<Compile Include="Sound\Output\DummySoundOutput.cs" />
|
||||||
<Compile Include="Sound\Output\OpenALSoundOutput.cs" />
|
<Compile Include="Sound\Output\OpenALSoundOutput.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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,10 +15,9 @@ namespace BizHawk.Client.EmuHawk
|
||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
private readonly ISoundOutput _outputDevice;
|
private readonly ISoundOutput _outputDevice;
|
||||||
private readonly SoundOutputProvider _outputProvider = new SoundOutputProvider();
|
private readonly SoundOutputProvider _outputProvider = new SoundOutputProvider(); // Buffer for Sync sources
|
||||||
private readonly BufferedAsync _bufferedAsync = new BufferedAsync();
|
private readonly BufferedAsync _bufferedAsync = new BufferedAsync(); // Buffer for Async sources
|
||||||
private ISoundProvider _sourceProvider;
|
private IBufferedSoundProvider _bufferedProvider; // One of the preceding buffers, or null if no source is set
|
||||||
private SyncSoundMode _syncMode;
|
|
||||||
|
|
||||||
public Sound(IntPtr mainWindowHandle)
|
public Sound(IntPtr mainWindowHandle)
|
||||||
{
|
{
|
||||||
|
@ -71,8 +70,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
|
|
||||||
_outputDevice.StopSound();
|
_outputDevice.StopSound();
|
||||||
|
|
||||||
_outputProvider.DiscardSamples();
|
if (_bufferedProvider != null) _bufferedProvider.DiscardSamples();
|
||||||
_bufferedAsync.DiscardSamples();
|
|
||||||
|
|
||||||
Global.SoundMaxBufferDeficitMs = 0;
|
Global.SoundMaxBufferDeficitMs = 0;
|
||||||
|
|
||||||
|
@ -86,28 +84,27 @@ namespace BizHawk.Client.EmuHawk
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SetInputPin(ISoundProvider source)
|
public void SetInputPin(ISoundProvider source)
|
||||||
{
|
{
|
||||||
_outputProvider.DiscardSamples();
|
if (_bufferedProvider != null)
|
||||||
_outputProvider.BaseSoundProvider = null;
|
|
||||||
|
|
||||||
_bufferedAsync.DiscardSamples();
|
|
||||||
_bufferedAsync.BaseSoundProvider = null;
|
|
||||||
|
|
||||||
_sourceProvider = source;
|
|
||||||
if (_sourceProvider == null)
|
|
||||||
{
|
{
|
||||||
return;
|
_bufferedProvider.BaseSoundProvider = null;
|
||||||
|
_bufferedProvider.DiscardSamples();
|
||||||
|
_bufferedProvider = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_syncMode = _sourceProvider.SyncMode;
|
if (source == null) return;
|
||||||
if (_syncMode == SyncSoundMode.Sync)
|
|
||||||
|
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);
|
_bufferedAsync.RecalculateMagic(Global.Emulator.CoreComm.VsyncRate);
|
||||||
|
_bufferedProvider = _bufferedAsync;
|
||||||
}
|
}
|
||||||
|
else throw new InvalidOperationException("Unsupported sync mode.");
|
||||||
|
|
||||||
|
_bufferedProvider.BaseSoundProvider = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool LogUnderruns { get; set; }
|
public bool LogUnderruns { get; set; }
|
||||||
|
@ -148,18 +145,12 @@ namespace BizHawk.Client.EmuHawk
|
||||||
|
|
||||||
public void UpdateSound(float atten)
|
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();
|
if (_bufferedProvider != null) _bufferedProvider.DiscardSamples();
|
||||||
_outputProvider.DiscardSamples();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_sourceProvider.SyncMode != _syncMode)
|
|
||||||
{
|
|
||||||
throw new Exception("Sync mode changed unexpectedly.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (atten < 0) atten = 0;
|
if (atten < 0) atten = 0;
|
||||||
if (atten > 1) atten = 1;
|
if (atten > 1) atten = 1;
|
||||||
_outputDevice.ApplyVolumeSettings(atten);
|
_outputDevice.ApplyVolumeSettings(atten);
|
||||||
|
@ -173,14 +164,13 @@ namespace BizHawk.Client.EmuHawk
|
||||||
samples = new short[samplesNeeded * ChannelCount];
|
samples = new short[samplesNeeded * ChannelCount];
|
||||||
samplesProvided = samplesNeeded;
|
samplesProvided = samplesNeeded;
|
||||||
|
|
||||||
_sourceProvider.DiscardSamples();
|
_bufferedProvider.DiscardSamples();
|
||||||
_outputProvider.DiscardSamples();
|
|
||||||
}
|
}
|
||||||
else if (_syncMode == SyncSoundMode.Sync)
|
else if (_bufferedProvider == _outputProvider)
|
||||||
{
|
{
|
||||||
if (Global.Config.SoundThrottle)
|
if (Global.Config.SoundThrottle)
|
||||||
{
|
{
|
||||||
_sourceProvider.GetSamplesSync(out samples, out samplesProvided);
|
_outputProvider.BaseSoundProvider.GetSamplesSync(out samples, out samplesProvided);
|
||||||
|
|
||||||
while (samplesNeeded < samplesProvided && !Global.DisableSecondaryThrottling)
|
while (samplesNeeded < samplesProvided && !Global.DisableSecondaryThrottling)
|
||||||
{
|
{
|
||||||
|
@ -197,7 +187,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
_outputProvider.GetSamples(samplesNeeded, out samples, out samplesProvided);
|
_outputProvider.GetSamples(samplesNeeded, out samples, out samplesProvided);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_syncMode == SyncSoundMode.Async)
|
else if (_bufferedProvider == _bufferedAsync)
|
||||||
{
|
{
|
||||||
samples = new short[samplesNeeded * ChannelCount];
|
samples = new short[samplesNeeded * ChannelCount];
|
||||||
|
|
||||||
|
@ -223,14 +213,4 @@ namespace BizHawk.Client.EmuHawk
|
||||||
return samples * 1000.0 / SampleRate;
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
// perform a "soft" correction by resampling it to hopefully get back inside our
|
// 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
|
// window shortly. If it ends up going too low or too high, we will perform a
|
||||||
// "hard" correction by generating silence or discarding samples.
|
// "hard" correction by generating silence or discarding samples.
|
||||||
public class SoundOutputProvider
|
public class SoundOutputProvider : IBufferedSoundProvider
|
||||||
{
|
{
|
||||||
private const int SampleRate = 44100;
|
private const int SampleRate = 44100;
|
||||||
private const int ChannelCount = 2;
|
private const int ChannelCount = 2;
|
||||||
|
|
|
@ -117,6 +117,7 @@
|
||||||
<Compile Include="EmulationExceptions.cs" />
|
<Compile Include="EmulationExceptions.cs" />
|
||||||
<Compile Include="Enums.cs" />
|
<Compile Include="Enums.cs" />
|
||||||
<Compile Include="Extensions.cs" />
|
<Compile Include="Extensions.cs" />
|
||||||
|
<Compile Include="Interfaces\IBufferedSoundProvider.cs" />
|
||||||
<Compile Include="Interfaces\IController.cs" />
|
<Compile Include="Interfaces\IController.cs" />
|
||||||
<Compile Include="Interfaces\ICoreFileProvider.cs" />
|
<Compile Include="Interfaces\ICoreFileProvider.cs" />
|
||||||
<Compile Include="Interfaces\IEmulator.cs" />
|
<Compile Include="Interfaces\IEmulator.cs" />
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace BizHawk.Emulation.Common
|
||||||
|
{
|
||||||
|
public interface IBufferedSoundProvider
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The source audio provider.
|
||||||
|
/// </summary>
|
||||||
|
ISoundProvider BaseSoundProvider { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears any internally buffered samples, and discards samples from the base provider (if set).
|
||||||
|
/// </summary>
|
||||||
|
void DiscardSamples();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
* TODO: For systems that _really_ don't need BufferedAsync (pce not turbocd, sms), make a way to signal
|
||||||
* that and then bypass the BufferedAsync.
|
* that and then bypass the BufferedAsync.
|
||||||
*/
|
*/
|
||||||
public sealed class BufferedAsync : ISoundProvider
|
public sealed class BufferedAsync : ISoundProvider, IBufferedSoundProvider
|
||||||
{
|
{
|
||||||
public ISoundProvider BaseSoundProvider { get; set; }
|
public ISoundProvider BaseSoundProvider { get; set; }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue