Configurable DirectSound buffer size.
A bunch of changes in Sound / SoundOutputProvider to support this and behave nicely.
This commit is contained in:
parent
a04982bc84
commit
69c66d12b1
|
@ -228,6 +228,7 @@ namespace BizHawk.Client.Common
|
|||
public int SoundVolume = 100; // Range 0-100
|
||||
public bool SoundThrottle = false;
|
||||
public string SoundDevice = "";
|
||||
public int SoundBufferSizeMs = 100;
|
||||
public bool UseNewOutputBuffer = false;
|
||||
|
||||
// Log Window
|
||||
|
|
|
@ -2093,6 +2093,13 @@ namespace BizHawk.Client.EmuHawk
|
|||
Global.Config.DisplayInput ^= true;
|
||||
}
|
||||
|
||||
public static void ToggleSound()
|
||||
{
|
||||
Global.Config.SoundEnabled ^= true;
|
||||
GlobalWin.Sound.StopSound();
|
||||
GlobalWin.Sound.StartSound();
|
||||
}
|
||||
|
||||
private static void VolumeUp()
|
||||
{
|
||||
Global.Config.SoundVolume += 10;
|
||||
|
@ -2101,17 +2108,10 @@ namespace BizHawk.Client.EmuHawk
|
|||
Global.Config.SoundVolume = 100;
|
||||
}
|
||||
|
||||
GlobalWin.Sound.ChangeVolume(Global.Config.SoundVolume);
|
||||
GlobalWin.Sound.ApplyVolumeSettings();
|
||||
GlobalWin.OSD.AddMessage("Volume " + Global.Config.SoundVolume);
|
||||
}
|
||||
|
||||
public static void ToggleSound()
|
||||
{
|
||||
Global.Config.SoundEnabled ^= true;
|
||||
GlobalWin.Sound.UpdateSoundSettings();
|
||||
GlobalWin.Sound.StartSound();
|
||||
}
|
||||
|
||||
private static void VolumeDown()
|
||||
{
|
||||
Global.Config.SoundVolume -= 10;
|
||||
|
@ -2120,7 +2120,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
Global.Config.SoundVolume = 0;
|
||||
}
|
||||
|
||||
GlobalWin.Sound.ChangeVolume(Global.Config.SoundVolume);
|
||||
GlobalWin.Sound.ApplyVolumeSettings();
|
||||
GlobalWin.OSD.AddMessage("Volume " + Global.Config.SoundVolume);
|
||||
}
|
||||
|
||||
|
|
|
@ -43,18 +43,14 @@ namespace BizHawk.Client.EmuHawk
|
|||
private const int BytesPerSample = 2;
|
||||
private const int ChannelCount = 2;
|
||||
private const int BlockAlign = BytesPerSample * ChannelCount;
|
||||
private const int BufferSizeMilliseconds = 100;
|
||||
private const int BufferSizeSamples = SampleRate * BufferSizeMilliseconds / 1000;
|
||||
private const int BufferSizeBytes = BufferSizeSamples * BlockAlign;
|
||||
private const double BufferSizeSeconds = (double)(BufferSizeBytes / BlockAlign) / SampleRate;
|
||||
private const int MinBufferFullnessMilliseconds = 55;
|
||||
private const int MinBufferFullnessSamples = SampleRate * MinBufferFullnessMilliseconds / 1000;
|
||||
private const int MinBufferFullnessSamples = 55 * SampleRate / 1000;
|
||||
|
||||
private bool _muted;
|
||||
private bool _disposed;
|
||||
private DirectSound _device;
|
||||
private SecondarySoundBuffer _deviceBuffer;
|
||||
private readonly BufferedAsync _semiSync = new BufferedAsync();
|
||||
private readonly SoundOutputProvider _outputProvider = new SoundOutputProvider();
|
||||
private SoundOutputProvider _outputProvider;
|
||||
private ISoundProvider _asyncSoundProvider;
|
||||
private ISyncSoundProvider _syncSoundProvider;
|
||||
private int _actualWriteOffsetBytes = -1;
|
||||
|
@ -67,6 +63,24 @@ namespace BizHawk.Client.EmuHawk
|
|||
if (device == null) return;
|
||||
|
||||
device.SetCooperativeLevel(handle, CooperativeLevel.Priority);
|
||||
_device = device;
|
||||
}
|
||||
|
||||
private int BufferSizeMilliseconds { get; set; }
|
||||
|
||||
private int BufferSizeSamples
|
||||
{
|
||||
get { return SampleRate * BufferSizeMilliseconds / 1000; }
|
||||
}
|
||||
|
||||
private int BufferSizeBytes
|
||||
{
|
||||
get { return BufferSizeSamples * BlockAlign; }
|
||||
}
|
||||
|
||||
private void CreateDeviceBuffer()
|
||||
{
|
||||
BufferSizeMilliseconds = Global.Config.SoundBufferSizeMs;
|
||||
|
||||
var format = new WaveFormat
|
||||
{
|
||||
|
@ -81,25 +95,31 @@ namespace BizHawk.Client.EmuHawk
|
|||
var desc = new SoundBufferDescription
|
||||
{
|
||||
Format = format,
|
||||
Flags =
|
||||
BufferFlags.GlobalFocus | BufferFlags.Software | BufferFlags.GetCurrentPosition2 | BufferFlags.ControlVolume,
|
||||
Flags = BufferFlags.GlobalFocus | BufferFlags.Software | BufferFlags.GetCurrentPosition2 | BufferFlags.ControlVolume,
|
||||
SizeInBytes = BufferSizeBytes
|
||||
};
|
||||
|
||||
_deviceBuffer = new SecondarySoundBuffer(device, desc);
|
||||
_deviceBuffer = new SecondarySoundBuffer(_device, desc);
|
||||
}
|
||||
|
||||
ChangeVolume(Global.Config.SoundVolume);
|
||||
public void ApplyVolumeSettings()
|
||||
{
|
||||
if (_deviceBuffer == null) return;
|
||||
|
||||
//LogUnderruns = true;
|
||||
//_outputProvider.LogDebug = true;
|
||||
if (Global.Config.SoundVolume == 0)
|
||||
_deviceBuffer.Volume = -5000;
|
||||
else
|
||||
_deviceBuffer.Volume = 0 - ((100 - Global.Config.SoundVolume) * 45);
|
||||
}
|
||||
|
||||
public void StartSound()
|
||||
{
|
||||
if (_disposed) throw new ObjectDisposedException("Sound");
|
||||
if (Global.Config.SoundEnabled == false) return;
|
||||
if (_deviceBuffer == null) return;
|
||||
if (IsPlaying) return;
|
||||
if (!Global.Config.SoundEnabled) return;
|
||||
if (_deviceBuffer != null) return;
|
||||
|
||||
CreateDeviceBuffer();
|
||||
ApplyVolumeSettings();
|
||||
|
||||
_deviceBuffer.Write(new byte[BufferSizeBytes], 0, LockFlags.EntireBuffer);
|
||||
_deviceBuffer.CurrentPlayPosition = 0;
|
||||
|
@ -109,34 +129,33 @@ namespace BizHawk.Client.EmuHawk
|
|||
_filledBufferSizeBytes = 0;
|
||||
_lastWriteTime = 0;
|
||||
_lastWriteCursor = 0;
|
||||
}
|
||||
|
||||
bool IsPlaying
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_deviceBuffer == null) return false;
|
||||
if ((_deviceBuffer.Status & BufferStatus.Playing) != 0) return true;
|
||||
return false;
|
||||
}
|
||||
_outputProvider = new SoundOutputProvider();
|
||||
_outputProvider.HardCorrectionThresholdSamples = BufferSizeSamples - MinBufferFullnessSamples;
|
||||
_outputProvider.BaseSoundProvider = _syncSoundProvider;
|
||||
|
||||
//LogUnderruns = true;
|
||||
//_outputProvider.LogDebug = true;
|
||||
}
|
||||
|
||||
public void StopSound()
|
||||
{
|
||||
if (!IsPlaying) return;
|
||||
if (_deviceBuffer == null) return;
|
||||
|
||||
_deviceBuffer.Write(new byte[BufferSizeBytes], 0, LockFlags.EntireBuffer);
|
||||
_deviceBuffer.Stop();
|
||||
_deviceBuffer.Dispose();
|
||||
_deviceBuffer = null;
|
||||
|
||||
_outputProvider = null;
|
||||
|
||||
BufferSizeMilliseconds = 0;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
if (_deviceBuffer != null && _deviceBuffer.Disposed == false)
|
||||
{
|
||||
_deviceBuffer.Dispose();
|
||||
_deviceBuffer = null;
|
||||
}
|
||||
StopSound();
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
|
@ -150,7 +169,10 @@ namespace BizHawk.Client.EmuHawk
|
|||
_semiSync.DiscardSamples();
|
||||
_semiSync.BaseSoundProvider = null;
|
||||
_syncSoundProvider = source;
|
||||
_outputProvider.BaseSoundProvider = source;
|
||||
if (_outputProvider != null)
|
||||
{
|
||||
_outputProvider.BaseSoundProvider = source;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetAsyncInputPin(ISoundProvider source)
|
||||
|
@ -160,21 +182,29 @@ namespace BizHawk.Client.EmuHawk
|
|||
_syncSoundProvider.DiscardSamples();
|
||||
_syncSoundProvider = null;
|
||||
}
|
||||
_outputProvider.DiscardSamples();
|
||||
_outputProvider.BaseSoundProvider = null;
|
||||
if (_outputProvider != null)
|
||||
{
|
||||
_outputProvider.DiscardSamples();
|
||||
_outputProvider.BaseSoundProvider = null;
|
||||
}
|
||||
_asyncSoundProvider = source;
|
||||
_semiSync.BaseSoundProvider = source;
|
||||
_semiSync.RecalculateMagic(Global.CoreComm.VsyncRate);
|
||||
}
|
||||
|
||||
public bool InitializeBufferWithSilence
|
||||
private bool InitializeBufferWithSilence
|
||||
{
|
||||
get { return Global.Config.SoundThrottle; }
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public bool RecoverFromUnderrunsWithSilence
|
||||
private bool RecoverFromUnderrunsWithSilence
|
||||
{
|
||||
get { return Global.Config.SoundThrottle; }
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
private int SilenceLeaveRoomForFrameCount
|
||||
{
|
||||
get { return Global.Config.SoundThrottle ? 1 : 2; } // Why 2? I don't know, but it seems to work well with the clock throttle's behavior.
|
||||
}
|
||||
|
||||
public bool LogUnderruns { get; set; }
|
||||
|
@ -188,8 +218,9 @@ namespace BizHawk.Client.EmuHawk
|
|||
if (_actualWriteOffsetBytes != -1)
|
||||
{
|
||||
double elapsedSeconds = (currentWriteTime - _lastWriteTime) / (double)Stopwatch.Frequency;
|
||||
double bufferSizeSeconds = (double)BufferSizeSamples / SampleRate;
|
||||
int cursorDelta = CircularDistance(_lastWriteCursor, writeCursor, BufferSizeBytes);
|
||||
cursorDelta += BufferSizeBytes * (int)Math.Round((elapsedSeconds - (cursorDelta / (double)(SampleRate * BlockAlign))) / BufferSizeSeconds);
|
||||
cursorDelta += BufferSizeBytes * (int)Math.Round((elapsedSeconds - (cursorDelta / (double)(SampleRate * BlockAlign))) / bufferSizeSeconds);
|
||||
_filledBufferSizeBytes -= cursorDelta;
|
||||
if (_filledBufferSizeBytes < 0)
|
||||
{
|
||||
|
@ -206,9 +237,8 @@ namespace BizHawk.Client.EmuHawk
|
|||
int samplesNeeded = CircularDistance(_actualWriteOffsetBytes, playCursor, BufferSizeBytes) / BlockAlign;
|
||||
if ((isInitializing && InitializeBufferWithSilence) || (detectedUnderrun && RecoverFromUnderrunsWithSilence))
|
||||
{
|
||||
// Fill the buffer with silence but leave enough empty for one frame's audio
|
||||
int samplesPerFrame = (int)Math.Round(SampleRate / Global.Emulator.CoreComm.VsyncRate);
|
||||
int silenceSamples = Math.Max(samplesNeeded - samplesPerFrame, 0);
|
||||
int silenceSamples = Math.Max(samplesNeeded - (SilenceLeaveRoomForFrameCount * samplesPerFrame), 0);
|
||||
WriteSamples(new short[silenceSamples * 2], silenceSamples);
|
||||
samplesNeeded -= silenceSamples;
|
||||
}
|
||||
|
@ -244,7 +274,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
public void UpdateSound()
|
||||
{
|
||||
if (Global.Config.SoundEnabled == false || _disposed)
|
||||
if (!Global.Config.SoundEnabled || _deviceBuffer == null || _disposed)
|
||||
{
|
||||
if (_asyncSoundProvider != null) _asyncSoundProvider.DiscardSamples();
|
||||
if (_syncSoundProvider != null) _syncSoundProvider.DiscardSamples();
|
||||
|
@ -281,7 +311,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
samples = new short[samplesNeeded * ChannelCount];
|
||||
|
||||
samplesProvided = _outputProvider.GetSamples(samples, samplesNeeded, samplesNeeded - (BufferSizeSamples - MinBufferFullnessSamples));
|
||||
samplesProvided = _outputProvider.GetSamples(samples, samplesNeeded);
|
||||
}
|
||||
}
|
||||
else if (_asyncSoundProvider != null)
|
||||
|
@ -297,31 +327,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
WriteSamples(samples, samplesProvided);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Range: 0-100
|
||||
/// </summary>
|
||||
/// <param name="vol"></param>
|
||||
public void ChangeVolume(int vol)
|
||||
{
|
||||
if (vol > 100)
|
||||
vol = 100;
|
||||
if (vol < 0)
|
||||
vol = 0;
|
||||
Global.Config.SoundVolume = vol;
|
||||
UpdateSoundSettings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses Global.Config.SoundEnabled, this just notifies the object to read it
|
||||
/// </summary>
|
||||
public void UpdateSoundSettings()
|
||||
{
|
||||
if (!Global.Config.SoundEnabled || Global.Config.SoundVolume == 0)
|
||||
_deviceBuffer.Volume = -5000;
|
||||
else
|
||||
_deviceBuffer.Volume = 0 - ((100 - Global.Config.SoundVolume) * 45);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Dummy implementation for non-Windows platforms for now.
|
||||
|
|
|
@ -14,19 +14,14 @@ namespace BizHawk.Client.EmuHawk
|
|||
// samples here on average. As long as we're within +/-5 milliseconds we don't need
|
||||
// to touch the source audio. Once it goes outside of that window, we'll start to
|
||||
// perform a "soft" correction by resampling it to hopefully get back inside our
|
||||
// window shortly. If it ends up going too low (-45 ms) and depleting the output
|
||||
// device's buffer, or too high (+45 ms), we will perform a "hard" correction by
|
||||
// generating silence or discarding samples.
|
||||
// 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
|
||||
{
|
||||
private const int SampleRate = 44100;
|
||||
private const int ChannelCount = 2;
|
||||
private const int MaxExtraMilliseconds = 45;
|
||||
private const int MaxExtraSamples = SampleRate * MaxExtraMilliseconds / 1000;
|
||||
private const int MaxTargetOffsetMilliseconds = 5;
|
||||
private const int MaxTargetOffsetSamples = SampleRate * MaxTargetOffsetMilliseconds / 1000;
|
||||
private const int HardCorrectionMilliseconds = 20;
|
||||
private const int HardCorrectionSamples = SampleRate * HardCorrectionMilliseconds / 1000;
|
||||
private const int SoftCorrectionThresholdSamples = 5 * SampleRate / 1000;
|
||||
private const int StartupHardCorrectionThresholdSamples = 10 * SampleRate / 1000;
|
||||
private const int UsableHistoryLength = 20;
|
||||
private const int MaxHistoryLength = 60;
|
||||
private const int SoftCorrectionLength = 240;
|
||||
|
@ -34,7 +29,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
private const int BaseSampleRateMaxHistoryLength = 300;
|
||||
private const int MinResamplingDistanceSamples = 3;
|
||||
|
||||
private Queue<short> _buffer = new Queue<short>(MaxExtraSamples * ChannelCount);
|
||||
private Queue<short> _buffer = new Queue<short>();
|
||||
|
||||
private Queue<int> _extraCountHistory = new Queue<int>();
|
||||
private Queue<int> _outputCountHistory = new Queue<int>();
|
||||
|
@ -46,12 +41,14 @@ namespace BizHawk.Client.EmuHawk
|
|||
private short[] _resampleBuffer = new short[0];
|
||||
private double _resampleLengthRoundingError;
|
||||
|
||||
public ISyncSoundProvider BaseSoundProvider { get; set; }
|
||||
|
||||
public SoundOutputProvider()
|
||||
{
|
||||
}
|
||||
|
||||
public int HardCorrectionThresholdSamples { get; set; }
|
||||
|
||||
public ISyncSoundProvider BaseSoundProvider { get; set; }
|
||||
|
||||
public void DiscardSamples()
|
||||
{
|
||||
_buffer.Clear();
|
||||
|
@ -76,14 +73,14 @@ namespace BizHawk.Client.EmuHawk
|
|||
get { return SampleRate / Global.Emulator.CoreComm.VsyncRate; }
|
||||
}
|
||||
|
||||
public int GetSamples(short[] samples, int idealSampleCount, int minSampleCount)
|
||||
public int GetSamples(short[] samples, int idealSampleCount)
|
||||
{
|
||||
double scaleFactor = 1.0;
|
||||
|
||||
if (_extraCountHistory.Count >= UsableHistoryLength && !_hardCorrectionHistory.Any(c => c))
|
||||
{
|
||||
double offsetFromTarget = _extraCountHistory.Average();
|
||||
if (Math.Abs(offsetFromTarget) > MaxTargetOffsetSamples)
|
||||
if (Math.Abs(offsetFromTarget) > SoftCorrectionThresholdSamples)
|
||||
{
|
||||
double correctionSpan = _outputCountHistory.Average() * SoftCorrectionLength;
|
||||
scaleFactor *= correctionSpan / (correctionSpan + offsetFromTarget);
|
||||
|
@ -94,11 +91,13 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
int bufferSampleCount = _buffer.Count / ChannelCount;
|
||||
int extraSampleCount = bufferSampleCount - idealSampleCount;
|
||||
int hardCorrectionThresholdSamples = _extraCountHistory.Count >= UsableHistoryLength ? HardCorrectionThresholdSamples :
|
||||
Math.Min(StartupHardCorrectionThresholdSamples, HardCorrectionThresholdSamples);
|
||||
bool hardCorrected = false;
|
||||
|
||||
if (bufferSampleCount < minSampleCount)
|
||||
if (extraSampleCount < -hardCorrectionThresholdSamples)
|
||||
{
|
||||
int generateSampleCount = (minSampleCount - bufferSampleCount) + HardCorrectionSamples;
|
||||
int generateSampleCount = -extraSampleCount;
|
||||
if (LogDebug) Console.WriteLine("Generating " + generateSampleCount + " samples");
|
||||
for (int i = 0; i < generateSampleCount * ChannelCount; i++)
|
||||
{
|
||||
|
@ -106,9 +105,9 @@ namespace BizHawk.Client.EmuHawk
|
|||
}
|
||||
hardCorrected = true;
|
||||
}
|
||||
else if (extraSampleCount > MaxExtraSamples)
|
||||
else if (extraSampleCount > hardCorrectionThresholdSamples)
|
||||
{
|
||||
int discardSampleCount = (extraSampleCount - MaxExtraSamples) + HardCorrectionSamples;
|
||||
int discardSampleCount = extraSampleCount;
|
||||
if (LogDebug) Console.WriteLine("Discarding " + discardSampleCount + " samples");
|
||||
for (int i = 0; i < discardSampleCount * ChannelCount; i++)
|
||||
{
|
||||
|
@ -236,7 +235,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
return output;
|
||||
}
|
||||
|
||||
double roundingError = 0.0;
|
||||
for (int iOutput = 0; iOutput < outputCount; iOutput++)
|
||||
{
|
||||
double iInput = ((double)iOutput / (outputCount - 1)) * (inputCount - 1);
|
||||
|
@ -250,17 +248,11 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
for (int iChannel = 0; iChannel < ChannelCount; iChannel++)
|
||||
{
|
||||
double valueExact =
|
||||
double value =
|
||||
input[iInput0 * ChannelCount + iChannel] * input0Weight +
|
||||
input[iInput1 * ChannelCount + iChannel] * input1Weight +
|
||||
roundingError;
|
||||
input[iInput1 * ChannelCount + iChannel] * input1Weight;
|
||||
|
||||
if (valueExact < -32768.0) valueExact = -32768.0;
|
||||
if (valueExact > 32767.0) valueExact = 32767.0;
|
||||
|
||||
short value = (short)((int)(valueExact + 32768.5) - 32768);
|
||||
output[iOutput * ChannelCount + iChannel] = value;
|
||||
roundingError = valueExact - value;
|
||||
output[iOutput * ChannelCount + iChannel] = (short)((int)(value + 32768.5) - 32768);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,17 +37,21 @@
|
|||
this.SoundVolNumeric = new System.Windows.Forms.NumericUpDown();
|
||||
this.UseNewOutputBuffer = new System.Windows.Forms.CheckBox();
|
||||
this.listBoxSoundDevices = new System.Windows.Forms.ListBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.SoundDeviceLabel = new System.Windows.Forms.Label();
|
||||
this.BufferSizeLabel = new System.Windows.Forms.Label();
|
||||
this.BufferSizeNumeric = new System.Windows.Forms.NumericUpDown();
|
||||
this.BufferSizeUnitsLabel = new System.Windows.Forms.Label();
|
||||
this.SoundVolGroup.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SoundVolBar)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SoundVolNumeric)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.BufferSizeNumeric)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// Cancel
|
||||
//
|
||||
this.Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.Cancel.Location = new System.Drawing.Point(317, 209);
|
||||
this.Cancel.Location = new System.Drawing.Point(317, 244);
|
||||
this.Cancel.Name = "Cancel";
|
||||
this.Cancel.Size = new System.Drawing.Size(75, 23);
|
||||
this.Cancel.TabIndex = 0;
|
||||
|
@ -59,7 +63,7 @@
|
|||
//
|
||||
this.OK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.OK.DialogResult = System.Windows.Forms.DialogResult.OK;
|
||||
this.OK.Location = new System.Drawing.Point(236, 209);
|
||||
this.OK.Location = new System.Drawing.Point(236, 244);
|
||||
this.OK.Name = "OK";
|
||||
this.OK.Size = new System.Drawing.Size(75, 23);
|
||||
this.OK.TabIndex = 1;
|
||||
|
@ -135,19 +139,62 @@
|
|||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.listBoxSoundDevices.FormattingEnabled = true;
|
||||
this.listBoxSoundDevices.Location = new System.Drawing.Point(108, 108);
|
||||
this.listBoxSoundDevices.Location = new System.Drawing.Point(108, 102);
|
||||
this.listBoxSoundDevices.Name = "listBoxSoundDevices";
|
||||
this.listBoxSoundDevices.Size = new System.Drawing.Size(284, 95);
|
||||
this.listBoxSoundDevices.TabIndex = 6;
|
||||
//
|
||||
// label1
|
||||
// SoundDeviceLabel
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(108, 92);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(78, 13);
|
||||
this.label1.TabIndex = 7;
|
||||
this.label1.Text = "Sound Device:";
|
||||
this.SoundDeviceLabel.AutoSize = true;
|
||||
this.SoundDeviceLabel.Location = new System.Drawing.Point(108, 86);
|
||||
this.SoundDeviceLabel.Name = "SoundDeviceLabel";
|
||||
this.SoundDeviceLabel.Size = new System.Drawing.Size(78, 13);
|
||||
this.SoundDeviceLabel.TabIndex = 7;
|
||||
this.SoundDeviceLabel.Text = "Sound Device:";
|
||||
//
|
||||
// BufferSizeLabel
|
||||
//
|
||||
this.BufferSizeLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.BufferSizeLabel.AutoSize = true;
|
||||
this.BufferSizeLabel.Location = new System.Drawing.Point(105, 213);
|
||||
this.BufferSizeLabel.Name = "BufferSizeLabel";
|
||||
this.BufferSizeLabel.Size = new System.Drawing.Size(61, 13);
|
||||
this.BufferSizeLabel.TabIndex = 8;
|
||||
this.BufferSizeLabel.Text = "Buffer Size:";
|
||||
//
|
||||
// BufferSizeNumeric
|
||||
//
|
||||
this.BufferSizeNumeric.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.BufferSizeNumeric.Location = new System.Drawing.Point(172, 211);
|
||||
this.BufferSizeNumeric.Maximum = new decimal(new int[] {
|
||||
250,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.BufferSizeNumeric.Minimum = new decimal(new int[] {
|
||||
80,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.BufferSizeNumeric.Name = "BufferSizeNumeric";
|
||||
this.BufferSizeNumeric.Size = new System.Drawing.Size(59, 20);
|
||||
this.BufferSizeNumeric.TabIndex = 9;
|
||||
this.BufferSizeNumeric.Value = new decimal(new int[] {
|
||||
100,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
//
|
||||
// BufferSizeUnitsLabel
|
||||
//
|
||||
this.BufferSizeUnitsLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.BufferSizeUnitsLabel.AutoSize = true;
|
||||
this.BufferSizeUnitsLabel.Location = new System.Drawing.Point(237, 213);
|
||||
this.BufferSizeUnitsLabel.Name = "BufferSizeUnitsLabel";
|
||||
this.BufferSizeUnitsLabel.Size = new System.Drawing.Size(63, 13);
|
||||
this.BufferSizeUnitsLabel.TabIndex = 10;
|
||||
this.BufferSizeUnitsLabel.Text = "milliseconds";
|
||||
//
|
||||
// SoundConfig
|
||||
//
|
||||
|
@ -155,8 +202,11 @@
|
|||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.Cancel;
|
||||
this.ClientSize = new System.Drawing.Size(404, 244);
|
||||
this.Controls.Add(this.label1);
|
||||
this.ClientSize = new System.Drawing.Size(404, 279);
|
||||
this.Controls.Add(this.BufferSizeUnitsLabel);
|
||||
this.Controls.Add(this.BufferSizeNumeric);
|
||||
this.Controls.Add(this.BufferSizeLabel);
|
||||
this.Controls.Add(this.SoundDeviceLabel);
|
||||
this.Controls.Add(this.listBoxSoundDevices);
|
||||
this.Controls.Add(this.UseNewOutputBuffer);
|
||||
this.Controls.Add(this.SoundVolGroup);
|
||||
|
@ -174,6 +224,7 @@
|
|||
this.SoundVolGroup.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SoundVolBar)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.SoundVolNumeric)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.BufferSizeNumeric)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
|
@ -190,6 +241,9 @@
|
|||
private System.Windows.Forms.TrackBar SoundVolBar;
|
||||
private System.Windows.Forms.CheckBox UseNewOutputBuffer;
|
||||
private System.Windows.Forms.ListBox listBoxSoundDevices;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label SoundDeviceLabel;
|
||||
private System.Windows.Forms.Label BufferSizeLabel;
|
||||
private System.Windows.Forms.NumericUpDown BufferSizeNumeric;
|
||||
private System.Windows.Forms.Label BufferSizeUnitsLabel;
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
SoundOnCheckBox.Checked = Global.Config.SoundEnabled;
|
||||
MuteFrameAdvance.Checked = Global.Config.MuteFrameAdvance;
|
||||
UseNewOutputBuffer.Checked = Global.Config.UseNewOutputBuffer;
|
||||
BufferSizeNumeric.Value = Global.Config.SoundBufferSizeMs;
|
||||
SoundVolBar.Value = Global.Config.SoundVolume;
|
||||
SoundVolNumeric.Value = Global.Config.SoundVolume;
|
||||
UpdateSoundDialog();
|
||||
|
@ -45,10 +46,10 @@ namespace BizHawk.Client.EmuHawk
|
|||
Global.Config.SoundEnabled = SoundOnCheckBox.Checked;
|
||||
Global.Config.MuteFrameAdvance = MuteFrameAdvance.Checked;
|
||||
Global.Config.UseNewOutputBuffer = UseNewOutputBuffer.Checked;
|
||||
Global.Config.SoundBufferSizeMs = (int)BufferSizeNumeric.Value;
|
||||
Global.Config.SoundVolume = SoundVolBar.Value;
|
||||
Global.Config.SoundDevice = (string)listBoxSoundDevices.SelectedItem ?? "<default>";
|
||||
GlobalWin.Sound.ChangeVolume(Global.Config.SoundVolume);
|
||||
GlobalWin.Sound.UpdateSoundSettings();
|
||||
GlobalWin.Sound.StopSound();
|
||||
GlobalWin.Sound.StartSound();
|
||||
GlobalWin.OSD.AddMessage("Sound settings saved");
|
||||
Close();
|
||||
|
|
Loading…
Reference in New Issue