diff --git a/BizHawk.Client.Common/config/Config.cs b/BizHawk.Client.Common/config/Config.cs
index ad39a8341b..f41976c0ef 100644
--- a/BizHawk.Client.Common/config/Config.cs
+++ b/BizHawk.Client.Common/config/Config.cs
@@ -228,6 +228,7 @@ namespace BizHawk.Client.Common
public int SoundVolume = 100; // Range 0-100
public bool SoundThrottle = false;
public string SoundDevice = "";
+ public bool UseNewOutputBuffer = false;
// Log Window
public bool LogWindowSaveWindowPosition = true;
diff --git a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
index 492232d499..e6509610fd 100644
--- a/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
+++ b/BizHawk.Client.EmuHawk/BizHawk.Client.EmuHawk.csproj
@@ -616,6 +616,7 @@
RomStatusPicker.cs
+
diff --git a/BizHawk.Client.EmuHawk/MainForm.cs b/BizHawk.Client.EmuHawk/MainForm.cs
index 074b90b001..da7aed472f 100644
--- a/BizHawk.Client.EmuHawk/MainForm.cs
+++ b/BizHawk.Client.EmuHawk/MainForm.cs
@@ -1458,15 +1458,15 @@ namespace BizHawk.Client.EmuHawk
// note that the avi dumper has already rewired the emulator itself in this case.
GlobalWin.Sound.SetAsyncInputPin(_dumpProxy);
}
- else if (Global.Config.SoundThrottle)
+ else if (Global.Config.SoundThrottle || Global.Config.UseNewOutputBuffer)
{
- // for sound throttle, use sync mode
+ // for sound throttle and new output buffer, use sync mode
Global.Emulator.EndAsyncSound();
GlobalWin.Sound.SetSyncInputPin(Global.Emulator.SyncSoundProvider);
}
else
{
- // for vsync\clock throttle modes, use async
+ // for vsync\clock throttle modes through old output buffer, use async
GlobalWin.Sound.SetAsyncInputPin(
!Global.Emulator.StartAsyncSound()
? new MetaspuAsync(Global.Emulator.SyncSoundProvider, ESynchMethod.ESynchMethod_V)
diff --git a/BizHawk.Client.EmuHawk/Sound.cs b/BizHawk.Client.EmuHawk/Sound.cs
index c4865a1c09..3a991ae58a 100644
--- a/BizHawk.Client.EmuHawk/Sound.cs
+++ b/BizHawk.Client.EmuHawk/Sound.cs
@@ -47,11 +47,14 @@ namespace BizHawk.Client.EmuHawk
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 = 60;
+ private const int MinBufferFullnessSamples = SampleRate * MinBufferFullnessMilliseconds / 1000;
private bool _muted;
private bool _disposed;
private SecondarySoundBuffer _deviceBuffer;
private readonly BufferedAsync _semiSync = new BufferedAsync();
+ private readonly SoundOutputProvider _outputProvider = new SoundOutputProvider();
private ISoundProvider _asyncSoundProvider;
private ISyncSoundProvider _syncSoundProvider;
private int _actualWriteOffsetBytes = -1;
@@ -86,6 +89,9 @@ namespace BizHawk.Client.EmuHawk
_deviceBuffer = new SecondarySoundBuffer(device, desc);
ChangeVolume(Global.Config.SoundVolume);
+
+ //LogUnderruns = true;
+ //_outputProvider.LogDebug = true;
}
public void StartSound()
@@ -98,6 +104,11 @@ namespace BizHawk.Client.EmuHawk
_deviceBuffer.Write(new byte[BufferSizeBytes], 0, LockFlags.EntireBuffer);
_deviceBuffer.CurrentPlayPosition = 0;
_deviceBuffer.Play(0, PlayFlags.Looping);
+
+ _actualWriteOffsetBytes = -1;
+ _filledBufferSizeBytes = 0;
+ _lastWriteTime = 0;
+ _lastWriteCursor = 0;
}
bool IsPlaying
@@ -131,14 +142,26 @@ namespace BizHawk.Client.EmuHawk
public void SetSyncInputPin(ISyncSoundProvider source)
{
- _syncSoundProvider = source;
- _asyncSoundProvider = null;
+ if (_asyncSoundProvider != null)
+ {
+ _asyncSoundProvider.DiscardSamples();
+ _asyncSoundProvider = null;
+ }
_semiSync.DiscardSamples();
+ _semiSync.BaseSoundProvider = null;
+ _syncSoundProvider = source;
+ _outputProvider.BaseSoundProvider = source;
}
public void SetAsyncInputPin(ISoundProvider source)
{
- _syncSoundProvider = null;
+ if (_syncSoundProvider != null)
+ {
+ _syncSoundProvider.DiscardSamples();
+ _syncSoundProvider = null;
+ }
+ _outputProvider.DiscardSamples();
+ _outputProvider.BaseSoundProvider = null;
_asyncSoundProvider = source;
_semiSync.BaseSoundProvider = source;
_semiSync.RecalculateMagic(Global.CoreComm.VsyncRate);
@@ -225,6 +248,7 @@ namespace BizHawk.Client.EmuHawk
{
if (_asyncSoundProvider != null) _asyncSoundProvider.DiscardSamples();
if (_syncSoundProvider != null) _syncSoundProvider.DiscardSamples();
+ if (_outputProvider != null) _outputProvider.DiscardSamples();
return;
}
@@ -239,15 +263,25 @@ namespace BizHawk.Client.EmuHawk
if (_asyncSoundProvider != null) _asyncSoundProvider.DiscardSamples();
if (_syncSoundProvider != null) _syncSoundProvider.DiscardSamples();
+ if (_outputProvider != null) _outputProvider.DiscardSamples();
}
else if (_syncSoundProvider != null)
{
- _syncSoundProvider.GetSamples(out samples, out samplesProvided);
-
- while (samplesNeeded < samplesProvided && !Global.DisableSecondaryThrottling)
+ if (Global.Config.SoundThrottle)
{
- Thread.Sleep((samplesProvided - samplesNeeded) / (SampleRate / 1000)); // let audio clock control sleep time
- samplesNeeded = CalculateSamplesNeeded();
+ _syncSoundProvider.GetSamples(out samples, out samplesProvided);
+
+ while (samplesNeeded < samplesProvided && !Global.DisableSecondaryThrottling)
+ {
+ Thread.Sleep((samplesProvided - samplesNeeded) / (SampleRate / 1000)); // let audio clock control sleep time
+ samplesNeeded = CalculateSamplesNeeded();
+ }
+ }
+ else
+ {
+ samples = new short[samplesNeeded * ChannelCount];
+
+ samplesProvided = _outputProvider.GetSamples(samples, samplesNeeded, samplesNeeded - (BufferSizeSamples - MinBufferFullnessSamples));
}
}
else if (_asyncSoundProvider != null)
diff --git a/BizHawk.Client.EmuHawk/SoundOutputProvider.cs b/BizHawk.Client.EmuHawk/SoundOutputProvider.cs
new file mode 100644
index 0000000000..13602a2922
--- /dev/null
+++ b/BizHawk.Client.EmuHawk/SoundOutputProvider.cs
@@ -0,0 +1,241 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using BizHawk.Emulation.Common;
+using BizHawk.Client.Common;
+
+namespace BizHawk.Client.EmuHawk
+{
+ // This is intended to be a buffer between a synchronous sound provider and the
+ // output device (e.g. DirectSound). The idea is to take advantage of the samples
+ // buffered up in the output device so that we don't need to keep a bunch buffered
+ // up here. This will keep the latency at a minimum. The goal is to keep zero extra
+ // 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 (-40 ms) and depleting the output
+ // device's buffer, or too high (+40 ms), 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 = 40;
+ 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 UsableHistoryLength = 20;
+ private const int MaxHistoryLength = 60;
+ private const int SoftCorrectionLength = 240;
+
+ private Queue _buffer = new Queue(MaxExtraSamples * ChannelCount);
+
+ private Queue _extraCountHistory = new Queue();
+ private Queue _outputCountHistory = new Queue();
+ private Queue _hardCorrectionHistory = new Queue();
+
+ private short[] _resampleBuffer = new short[0];
+ private double _resampleLengthRoundingError;
+
+ public ISyncSoundProvider BaseSoundProvider { get; set; }
+
+ public SoundOutputProvider()
+ {
+ }
+
+ public void DiscardSamples()
+ {
+ _buffer.Clear();
+ _extraCountHistory.Clear();
+ _outputCountHistory.Clear();
+ _hardCorrectionHistory.Clear();
+ _resampleBuffer = new short[0];
+ _resampleLengthRoundingError = 0.0;
+
+ if (BaseSoundProvider != null)
+ {
+ BaseSoundProvider.DiscardSamples();
+ }
+ }
+
+ public bool LogDebug { get; set; }
+
+ private double SamplesPerFrame
+ {
+ get { return SampleRate / Global.Emulator.CoreComm.VsyncRate; }
+ }
+
+ public int GetSamples(short[] samples, int idealSampleCount, int minSampleCount)
+ {
+ double scaleFactor = 1.0;
+
+ if (_extraCountHistory.Count >= UsableHistoryLength && !_hardCorrectionHistory.Any(c => c))
+ {
+ double offsetFromTarget = _extraCountHistory.Average();
+ if (Math.Abs(offsetFromTarget) > MaxTargetOffsetSamples)
+ {
+ double correctionSpan = _outputCountHistory.Average() * SoftCorrectionLength;
+ scaleFactor *= correctionSpan / (correctionSpan + offsetFromTarget);
+ }
+ }
+
+ GetSamplesFromBase(scaleFactor);
+
+ int bufferSampleCount = _buffer.Count / ChannelCount;
+ int extraSampleCount = bufferSampleCount - idealSampleCount;
+ bool hardCorrected = false;
+
+ if (bufferSampleCount < minSampleCount)
+ {
+ int generateSampleCount = (minSampleCount - bufferSampleCount) + HardCorrectionSamples;
+ if (LogDebug) Console.WriteLine("Generating " + generateSampleCount + " samples");
+ for (int i = 0; i < generateSampleCount * ChannelCount; i++)
+ {
+ _buffer.Enqueue(0);
+ }
+ hardCorrected = true;
+ }
+ else if (extraSampleCount > MaxExtraSamples)
+ {
+ int discardSampleCount = (extraSampleCount - MaxExtraSamples) + HardCorrectionSamples;
+ if (LogDebug) Console.WriteLine("Discarding " + discardSampleCount + " samples");
+ for (int i = 0; i < discardSampleCount * ChannelCount; i++)
+ {
+ _buffer.Dequeue();
+ }
+ hardCorrected = true;
+ }
+
+ bufferSampleCount = _buffer.Count / ChannelCount;
+ extraSampleCount = bufferSampleCount - idealSampleCount;
+
+ int outputSampleCount = Math.Min(idealSampleCount, bufferSampleCount);
+
+ UpdateHistory(_extraCountHistory, extraSampleCount);
+ UpdateHistory(_outputCountHistory, outputSampleCount);
+ UpdateHistory(_hardCorrectionHistory, hardCorrected);
+
+ GetSamplesFromBuffer(samples, outputSampleCount);
+
+ if (LogDebug)
+ {
+ Console.WriteLine("Avg: {0:0.0} ms, Min: {1:0.0} ms, Max: {2:0.0} ms, Scale: {3:0.0000}",
+ _extraCountHistory.Average() * 1000.0 / SampleRate,
+ _extraCountHistory.Min() * 1000.0 / SampleRate,
+ _extraCountHistory.Max() * 1000.0 / SampleRate,
+ scaleFactor);
+ }
+
+ return outputSampleCount;
+ }
+
+ private void GetSamplesFromBase(double scaleFactor)
+ {
+ short[] samples;
+ int count;
+
+ BaseSoundProvider.GetSamples(out samples, out count);
+
+ scaleFactor *= SamplesPerFrame / count;
+
+ double newCountTarget = count * scaleFactor;
+ int newCount = (int)Math.Round(newCountTarget + _resampleLengthRoundingError);
+ // Do not resample for one-sample differences. With NTSC @ 59.94 FPS, for example,
+ // there are ~735.7 samples per frame so the source will oscillate between 735 and
+ // 736 samples. Our calculated number of samples will also oscillate between 735
+ // and 736, but likely out of phase. There's no point resampling to make up for
+ // something that will average out over time, so don't resample for these
+ // differences. We will, however, keep track of them as part of the rounding error
+ // in case they end up not averaging out as expected.
+ if (Math.Abs(newCount - count) > 1)
+ {
+ samples = Resample(samples, count, newCount);
+ count = newCount;
+ }
+ // Although the rounding error may seem insignificant, it definitely matters over
+ // time so we need to keep track of it. With NTSC @ 59.94 FPS, for example, if we
+ // were to always round to 736 samples per frame ignoring the rounding error, we
+ // would drift by ~22 milliseconds per minute.
+ _resampleLengthRoundingError += newCountTarget - count;
+
+ AddSamplesToBuffer(samples, count);
+ }
+
+ private void UpdateHistory(Queue queue, T value)
+ {
+ queue.Enqueue(value);
+ while (queue.Count > MaxHistoryLength)
+ {
+ queue.Dequeue();
+ }
+ }
+
+ private void GetSamplesFromBuffer(short[] samples, int count)
+ {
+ for (int i = 0; i < count * ChannelCount; i++)
+ {
+ samples[i] = _buffer.Dequeue();
+ }
+ }
+
+ private void AddSamplesToBuffer(short[] samples, int count)
+ {
+ for (int i = 0; i < count * ChannelCount; i++)
+ {
+ _buffer.Enqueue(samples[i]);
+ }
+ }
+
+ private short[] GetResampleBuffer(int count)
+ {
+ if (_resampleBuffer.Length < count * ChannelCount)
+ {
+ _resampleBuffer = new short[count * ChannelCount];
+ }
+ return _resampleBuffer;
+ }
+
+ // This uses simple linear interpolation which is supposedly not a great idea for
+ // resampling audio, but it sounds surprisingly good to me. Maybe it works well
+ // because we are typically stretching by very small amounts.
+ private short[] Resample(short[] input, int inputCount, int outputCount)
+ {
+ if (inputCount == outputCount)
+ {
+ return input;
+ }
+
+ short[] output = GetResampleBuffer(outputCount);
+
+ if (inputCount == 0 || outputCount == 0)
+ {
+ Array.Clear(output, 0, outputCount * ChannelCount);
+ return output;
+ }
+
+ for (int iOutput = 0; iOutput < outputCount; iOutput++)
+ {
+ double iInput = ((double)iOutput / (outputCount - 1)) * (inputCount - 1);
+ int iInput0 = (int)iInput;
+ int iInput1 = iInput0 + 1;
+ double input0Weight = iInput1 - iInput;
+ double input1Weight = iInput - iInput0;
+
+ if (iInput1 == inputCount)
+ iInput1 = inputCount - 1;
+
+ for (int iChannel = 0; iChannel < ChannelCount; iChannel++)
+ {
+ output[iOutput * ChannelCount + iChannel] = (short)
+ (input[iInput0 * ChannelCount + iChannel] * input0Weight +
+ input[iInput1 * ChannelCount + iChannel] * input1Weight);
+ }
+ }
+
+ return output;
+ }
+ }
+}
diff --git a/BizHawk.Client.EmuHawk/config/SoundConfig.Designer.cs b/BizHawk.Client.EmuHawk/config/SoundConfig.Designer.cs
index 9de445ed40..5c21b91162 100644
--- a/BizHawk.Client.EmuHawk/config/SoundConfig.Designer.cs
+++ b/BizHawk.Client.EmuHawk/config/SoundConfig.Designer.cs
@@ -28,154 +28,154 @@
///
private void InitializeComponent()
{
- this.Cancel = new System.Windows.Forms.Button();
- this.OK = new System.Windows.Forms.Button();
- this.SoundOnCheckBox = new System.Windows.Forms.CheckBox();
- this.MuteFrameAdvance = new System.Windows.Forms.CheckBox();
- this.SoundVolGroup = new System.Windows.Forms.GroupBox();
- this.SoundVolBar = new System.Windows.Forms.TrackBar();
- this.SoundVolNumeric = new System.Windows.Forms.NumericUpDown();
- this.ThrottlecheckBox = new System.Windows.Forms.CheckBox();
- this.listBoxSoundDevices = new System.Windows.Forms.ListBox();
- this.label1 = new System.Windows.Forms.Label();
- this.SoundVolGroup.SuspendLayout();
- ((System.ComponentModel.ISupportInitialize)(this.SoundVolBar)).BeginInit();
- ((System.ComponentModel.ISupportInitialize)(this.SoundVolNumeric)).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.Name = "Cancel";
- this.Cancel.Size = new System.Drawing.Size(75, 23);
- this.Cancel.TabIndex = 0;
- this.Cancel.Text = "&Cancel";
- this.Cancel.UseVisualStyleBackColor = true;
- this.Cancel.Click += new System.EventHandler(this.Cancel_Click);
- //
- // OK
- //
- 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.Name = "OK";
- this.OK.Size = new System.Drawing.Size(75, 23);
- this.OK.TabIndex = 1;
- this.OK.Text = "&Ok";
- this.OK.UseVisualStyleBackColor = true;
- this.OK.Click += new System.EventHandler(this.OK_Click);
- //
- // SoundOnCheckBox
- //
- this.SoundOnCheckBox.AutoSize = true;
- this.SoundOnCheckBox.Location = new System.Drawing.Point(147, 12);
- this.SoundOnCheckBox.Name = "SoundOnCheckBox";
- this.SoundOnCheckBox.Size = new System.Drawing.Size(74, 17);
- this.SoundOnCheckBox.TabIndex = 2;
- this.SoundOnCheckBox.Text = "Sound On";
- this.SoundOnCheckBox.UseVisualStyleBackColor = true;
- this.SoundOnCheckBox.CheckedChanged += new System.EventHandler(this.SoundOnCheckBox_CheckedChanged);
- //
- // MuteFrameAdvance
- //
- this.MuteFrameAdvance.AutoSize = true;
- this.MuteFrameAdvance.Location = new System.Drawing.Point(147, 35);
- this.MuteFrameAdvance.Name = "MuteFrameAdvance";
- this.MuteFrameAdvance.Size = new System.Drawing.Size(128, 17);
- this.MuteFrameAdvance.TabIndex = 3;
- this.MuteFrameAdvance.Text = "Mute Frame Advance";
- this.MuteFrameAdvance.UseVisualStyleBackColor = true;
- //
- // SoundVolGroup
- //
- this.SoundVolGroup.Controls.Add(this.SoundVolBar);
- this.SoundVolGroup.Controls.Add(this.SoundVolNumeric);
- this.SoundVolGroup.Location = new System.Drawing.Point(12, 12);
- this.SoundVolGroup.Name = "SoundVolGroup";
- this.SoundVolGroup.Size = new System.Drawing.Size(90, 219);
- this.SoundVolGroup.TabIndex = 4;
- this.SoundVolGroup.TabStop = false;
- this.SoundVolGroup.Text = "Volume";
- //
- // SoundVolBar
- //
- this.SoundVolBar.LargeChange = 10;
- this.SoundVolBar.Location = new System.Drawing.Point(23, 23);
- this.SoundVolBar.Maximum = 100;
- this.SoundVolBar.Name = "SoundVolBar";
- this.SoundVolBar.Orientation = System.Windows.Forms.Orientation.Vertical;
- this.SoundVolBar.Size = new System.Drawing.Size(45, 164);
- this.SoundVolBar.TabIndex = 1;
- this.SoundVolBar.TickFrequency = 10;
- this.SoundVolBar.Scroll += new System.EventHandler(this.trackBar1_Scroll);
- //
- // SoundVolNumeric
- //
- this.SoundVolNumeric.Location = new System.Drawing.Point(16, 190);
- this.SoundVolNumeric.Name = "SoundVolNumeric";
- this.SoundVolNumeric.Size = new System.Drawing.Size(59, 20);
- this.SoundVolNumeric.TabIndex = 0;
- this.SoundVolNumeric.ValueChanged += new System.EventHandler(this.SoundVolNumeric_ValueChanged);
- //
- // ThrottlecheckBox
- //
- this.ThrottlecheckBox.AutoSize = true;
- this.ThrottlecheckBox.Location = new System.Drawing.Point(147, 58);
- this.ThrottlecheckBox.Name = "ThrottlecheckBox";
- this.ThrottlecheckBox.Size = new System.Drawing.Size(96, 17);
- this.ThrottlecheckBox.TabIndex = 5;
- this.ThrottlecheckBox.Text = "Sound Throttle";
- this.ThrottlecheckBox.UseVisualStyleBackColor = true;
- //
- // listBoxSoundDevices
- //
- this.listBoxSoundDevices.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ this.Cancel = new System.Windows.Forms.Button();
+ this.OK = new System.Windows.Forms.Button();
+ this.SoundOnCheckBox = new System.Windows.Forms.CheckBox();
+ this.MuteFrameAdvance = new System.Windows.Forms.CheckBox();
+ this.SoundVolGroup = new System.Windows.Forms.GroupBox();
+ this.SoundVolBar = new System.Windows.Forms.TrackBar();
+ 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.SoundVolGroup.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.SoundVolBar)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.SoundVolNumeric)).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.Name = "Cancel";
+ this.Cancel.Size = new System.Drawing.Size(75, 23);
+ this.Cancel.TabIndex = 0;
+ this.Cancel.Text = "&Cancel";
+ this.Cancel.UseVisualStyleBackColor = true;
+ this.Cancel.Click += new System.EventHandler(this.Cancel_Click);
+ //
+ // OK
+ //
+ 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.Name = "OK";
+ this.OK.Size = new System.Drawing.Size(75, 23);
+ this.OK.TabIndex = 1;
+ this.OK.Text = "&Ok";
+ this.OK.UseVisualStyleBackColor = true;
+ this.OK.Click += new System.EventHandler(this.OK_Click);
+ //
+ // SoundOnCheckBox
+ //
+ this.SoundOnCheckBox.AutoSize = true;
+ this.SoundOnCheckBox.Location = new System.Drawing.Point(147, 12);
+ this.SoundOnCheckBox.Name = "SoundOnCheckBox";
+ this.SoundOnCheckBox.Size = new System.Drawing.Size(74, 17);
+ this.SoundOnCheckBox.TabIndex = 2;
+ this.SoundOnCheckBox.Text = "Sound On";
+ this.SoundOnCheckBox.UseVisualStyleBackColor = true;
+ this.SoundOnCheckBox.CheckedChanged += new System.EventHandler(this.SoundOnCheckBox_CheckedChanged);
+ //
+ // MuteFrameAdvance
+ //
+ this.MuteFrameAdvance.AutoSize = true;
+ this.MuteFrameAdvance.Location = new System.Drawing.Point(147, 35);
+ this.MuteFrameAdvance.Name = "MuteFrameAdvance";
+ this.MuteFrameAdvance.Size = new System.Drawing.Size(128, 17);
+ this.MuteFrameAdvance.TabIndex = 3;
+ this.MuteFrameAdvance.Text = "Mute Frame Advance";
+ this.MuteFrameAdvance.UseVisualStyleBackColor = true;
+ //
+ // SoundVolGroup
+ //
+ this.SoundVolGroup.Controls.Add(this.SoundVolBar);
+ this.SoundVolGroup.Controls.Add(this.SoundVolNumeric);
+ this.SoundVolGroup.Location = new System.Drawing.Point(12, 12);
+ this.SoundVolGroup.Name = "SoundVolGroup";
+ this.SoundVolGroup.Size = new System.Drawing.Size(90, 219);
+ this.SoundVolGroup.TabIndex = 4;
+ this.SoundVolGroup.TabStop = false;
+ this.SoundVolGroup.Text = "Volume";
+ //
+ // SoundVolBar
+ //
+ this.SoundVolBar.LargeChange = 10;
+ this.SoundVolBar.Location = new System.Drawing.Point(23, 23);
+ this.SoundVolBar.Maximum = 100;
+ this.SoundVolBar.Name = "SoundVolBar";
+ this.SoundVolBar.Orientation = System.Windows.Forms.Orientation.Vertical;
+ this.SoundVolBar.Size = new System.Drawing.Size(45, 164);
+ this.SoundVolBar.TabIndex = 1;
+ this.SoundVolBar.TickFrequency = 10;
+ this.SoundVolBar.Scroll += new System.EventHandler(this.trackBar1_Scroll);
+ //
+ // SoundVolNumeric
+ //
+ this.SoundVolNumeric.Location = new System.Drawing.Point(16, 190);
+ this.SoundVolNumeric.Name = "SoundVolNumeric";
+ this.SoundVolNumeric.Size = new System.Drawing.Size(59, 20);
+ this.SoundVolNumeric.TabIndex = 0;
+ this.SoundVolNumeric.ValueChanged += new System.EventHandler(this.SoundVolNumeric_ValueChanged);
+ //
+ // UseNewOutputBuffer
+ //
+ this.UseNewOutputBuffer.AutoSize = true;
+ this.UseNewOutputBuffer.Location = new System.Drawing.Point(147, 58);
+ this.UseNewOutputBuffer.Name = "UseNewOutputBuffer";
+ this.UseNewOutputBuffer.Size = new System.Drawing.Size(205, 17);
+ this.UseNewOutputBuffer.TabIndex = 5;
+ this.UseNewOutputBuffer.Text = "Use New Output Buffer (Experimental)";
+ this.UseNewOutputBuffer.UseVisualStyleBackColor = true;
+ //
+ // listBoxSoundDevices
+ //
+ this.listBoxSoundDevices.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| 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.Name = "listBoxSoundDevices";
- this.listBoxSoundDevices.Size = new System.Drawing.Size(284, 95);
- this.listBoxSoundDevices.TabIndex = 6;
- //
- // label1
- //
- 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:";
- //
- // SoundConfig
- //
- this.AcceptButton = this.OK;
- 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.Controls.Add(this.listBoxSoundDevices);
- this.Controls.Add(this.ThrottlecheckBox);
- this.Controls.Add(this.SoundVolGroup);
- this.Controls.Add(this.MuteFrameAdvance);
- this.Controls.Add(this.SoundOnCheckBox);
- this.Controls.Add(this.OK);
- this.Controls.Add(this.Cancel);
- this.MinimumSize = new System.Drawing.Size(279, 259);
- this.Name = "SoundConfig";
- this.ShowIcon = false;
- this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
- this.Text = "Sound Configuration";
- this.Load += new System.EventHandler(this.SoundConfig_Load);
- this.SoundVolGroup.ResumeLayout(false);
- this.SoundVolGroup.PerformLayout();
- ((System.ComponentModel.ISupportInitialize)(this.SoundVolBar)).EndInit();
- ((System.ComponentModel.ISupportInitialize)(this.SoundVolNumeric)).EndInit();
- this.ResumeLayout(false);
- this.PerformLayout();
+ this.listBoxSoundDevices.FormattingEnabled = true;
+ this.listBoxSoundDevices.Location = new System.Drawing.Point(108, 108);
+ this.listBoxSoundDevices.Name = "listBoxSoundDevices";
+ this.listBoxSoundDevices.Size = new System.Drawing.Size(284, 95);
+ this.listBoxSoundDevices.TabIndex = 6;
+ //
+ // label1
+ //
+ 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:";
+ //
+ // SoundConfig
+ //
+ this.AcceptButton = this.OK;
+ 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.Controls.Add(this.listBoxSoundDevices);
+ this.Controls.Add(this.UseNewOutputBuffer);
+ this.Controls.Add(this.SoundVolGroup);
+ this.Controls.Add(this.MuteFrameAdvance);
+ this.Controls.Add(this.SoundOnCheckBox);
+ this.Controls.Add(this.OK);
+ this.Controls.Add(this.Cancel);
+ this.MinimumSize = new System.Drawing.Size(279, 259);
+ this.Name = "SoundConfig";
+ this.ShowIcon = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Sound Configuration";
+ this.Load += new System.EventHandler(this.SoundConfig_Load);
+ this.SoundVolGroup.ResumeLayout(false);
+ this.SoundVolGroup.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.SoundVolBar)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.SoundVolNumeric)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
}
@@ -188,7 +188,7 @@
private System.Windows.Forms.GroupBox SoundVolGroup;
private System.Windows.Forms.NumericUpDown SoundVolNumeric;
private System.Windows.Forms.TrackBar SoundVolBar;
- private System.Windows.Forms.CheckBox ThrottlecheckBox;
+ private System.Windows.Forms.CheckBox UseNewOutputBuffer;
private System.Windows.Forms.ListBox listBoxSoundDevices;
private System.Windows.Forms.Label label1;
}
diff --git a/BizHawk.Client.EmuHawk/config/SoundConfig.cs b/BizHawk.Client.EmuHawk/config/SoundConfig.cs
index 6eeede2202..c2280e6476 100644
--- a/BizHawk.Client.EmuHawk/config/SoundConfig.cs
+++ b/BizHawk.Client.EmuHawk/config/SoundConfig.cs
@@ -20,14 +20,11 @@ namespace BizHawk.Client.EmuHawk
SoundOnCheckBox.Checked = Global.Config.SoundEnabled;
MuteFrameAdvance.Checked = Global.Config.MuteFrameAdvance;
- ThrottlecheckBox.Checked = Global.Config.SoundThrottle;
+ UseNewOutputBuffer.Checked = Global.Config.UseNewOutputBuffer;
SoundVolBar.Value = Global.Config.SoundVolume;
SoundVolNumeric.Value = Global.Config.SoundVolume;
UpdateSoundDialog();
- // vestigal
- ThrottlecheckBox.Visible = false;
-
var dd = SoundEnumeration.DeviceNames();
listBoxSoundDevices.Items.Add("");
listBoxSoundDevices.SelectedIndex = 0;
@@ -47,8 +44,8 @@ namespace BizHawk.Client.EmuHawk
{
Global.Config.SoundEnabled = SoundOnCheckBox.Checked;
Global.Config.MuteFrameAdvance = MuteFrameAdvance.Checked;
+ Global.Config.UseNewOutputBuffer = UseNewOutputBuffer.Checked;
Global.Config.SoundVolume = SoundVolBar.Value;
- Global.Config.SoundThrottle = ThrottlecheckBox.Checked;
Global.Config.SoundDevice = (string)listBoxSoundDevices.SelectedItem ?? "";
GlobalWin.Sound.ChangeVolume(Global.Config.SoundVolume);
GlobalWin.Sound.UpdateSoundSettings();
@@ -81,13 +78,10 @@ namespace BizHawk.Client.EmuHawk
{
UpdateSoundDialog();
}
+
private void UpdateSoundDialog()
{
- //Ocean Prince commented this out
- //SoundVolGroup.Enabled =
- MuteFrameAdvance.Enabled =
- ThrottlecheckBox.Enabled =
- SoundOnCheckBox.Checked;
+ MuteFrameAdvance.Enabled = SoundOnCheckBox.Checked;
}
}
}