diff --git a/BizHawk.Client.EmuHawk/AVOut/AVSync.cs b/BizHawk.Client.EmuHawk/AVOut/AVSync.cs index b58ec79ae9..12b9bc4cd9 100644 --- a/BizHawk.Client.EmuHawk/AVOut/AVSync.cs +++ b/BizHawk.Client.EmuHawk/AVOut/AVSync.cs @@ -1,4 +1,5 @@ using System; +using System.Windows.Forms; using BizHawk.Emulation.Common; @@ -9,7 +10,7 @@ namespace BizHawk.Client.EmuHawk { public AudioStretcher(IVideoWriter w) { - this.w = w; + this.W = w; } private long _soundRemainder; // audio timekeeping for video dumping @@ -18,7 +19,7 @@ namespace BizHawk.Client.EmuHawk /// 's mode is not , or /// A/V parameters haven't been set (need to call and ) /// - public void DumpAV(IVideoProvider v, ISoundProvider asyncSoundProvider, out short[] samples, out int samplesprovided) + public void DumpAV(IVideoProvider v, ISoundProvider asyncSoundProvider, out short[] samples, out int samplesProvided) { // Sound refactor TODO: we could try set it here, but we want the client to be responsible for mode switching? There may be non-trivial complications with when to switch modes that we don't want this object worrying about if (asyncSoundProvider.SyncMode != SyncSoundMode.Async) @@ -26,21 +27,21 @@ namespace BizHawk.Client.EmuHawk throw new InvalidOperationException("Only async mode is supported, set async mode before passing in the sound provider"); } - if (!aset || !vset) + if (!ASet || !VSet) throw new InvalidOperationException("Must set params first!"); - long nsampnum = samplerate * (long)fpsden + _soundRemainder; - long nsamp = nsampnum / fpsnum; + long nSampNum = Samplerate * (long)FpsDen + _soundRemainder; + long nsamp = nSampNum / FpsNum; // exactly remember fractional parts of an audio sample - _soundRemainder = nsampnum % fpsnum; + _soundRemainder = nSampNum % FpsNum; - samples = new short[nsamp * channels]; + samples = new short[nsamp * Channels]; asyncSoundProvider.GetSamplesAsync(samples); - samplesprovided = (int)nsamp; + samplesProvided = (int)nsamp; - w.AddFrame(v); - w.AddSamples(samples); + W.AddFrame(v); + W.AddSamples(samples); } } @@ -49,41 +50,41 @@ namespace BizHawk.Client.EmuHawk { public VideoStretcher(IVideoWriter w) { - this.w = w; + W = w; } private short[] _samples = new short[0]; - // how many extra audio samples there are (* fpsnum) - private long exaudio_num; + // how many extra audio samples there are (* fpsNum) + private long _exAudioNum; - private bool pset = false; - private long threshone; - private long threshmore; - private long threshtotal; + private bool _pSet; + private long _threshOne; + private long _threshMore; + private long _threshTotal; private void VerifyParams() { - if (!aset || !vset) + if (!ASet || !VSet) { throw new InvalidOperationException("Must set params first!"); } - if (!pset) + if (!_pSet) { - pset = true; + _pSet = true; - // each video frame committed counts as (fpsden * samplerate / fpsnum) audio samples - threshtotal = fpsden * (long)samplerate; + // each video frame committed counts as (fpsDen * samplerate / fpsNum) audio samples + _threshTotal = FpsDen * (long)Samplerate; // blah blah blah - threshone = (long)(threshtotal * 0.4); - threshmore = (long)(threshtotal * 0.9); + _threshOne = (long)(_threshTotal * 0.4); + _threshMore = (long)(_threshTotal * 0.9); } } /// 's mode is not - public void DumpAV(IVideoProvider v, ISoundProvider syncSoundProvider, out short[] samples, out int samplesprovided) + public void DumpAV(IVideoProvider v, ISoundProvider syncSoundProvider, out short[] samples, out int samplesProvided) { // Sound refactor TODO: we could just set it here, but we want the client to be responsible for mode switching? There may be non-trivial complications with when to switch modes that we don't want this object worrying about if (syncSoundProvider.SyncMode != SyncSoundMode.Sync) @@ -92,78 +93,78 @@ namespace BizHawk.Client.EmuHawk } VerifyParams(); - syncSoundProvider.GetSamplesSync(out samples, out samplesprovided); - exaudio_num += samplesprovided * (long)fpsnum; + syncSoundProvider.GetSamplesSync(out samples, out samplesProvided); + _exAudioNum += samplesProvided * (long)FpsNum; // todo: scan for duplicate frames (ie, video content exactly matches previous frame) and for them, skip the threshone step // this is a good idea, but expensive on time. is it worth it? - if (exaudio_num >= threshone) + if (_exAudioNum >= _threshOne) { // add frame once - w.AddFrame(v); - exaudio_num -= threshtotal; + W.AddFrame(v); + _exAudioNum -= _threshTotal; } else { Console.WriteLine("Dropped Frame!"); } - while (exaudio_num >= threshmore) + while (_exAudioNum >= _threshMore) { // add frame again! - w.AddFrame(v); - exaudio_num -= threshtotal; + W.AddFrame(v); + _exAudioNum -= _threshTotal; Console.WriteLine("Dupped Frame!"); } // a bit of hackey due to the fact that this api can't read a // usable buffer length separately from the actual length of the buffer - if (samples.Length == samplesprovided * channels) + if (samples.Length == samplesProvided * Channels) { - w.AddSamples(samples); + W.AddSamples(samples); } else { - if (_samples.Length != samplesprovided * channels) + if (_samples.Length != samplesProvided * Channels) { - _samples = new short[samplesprovided * channels]; + _samples = new short[samplesProvided * Channels]; } - Buffer.BlockCopy(samples, 0, _samples, 0, samplesprovided * channels * sizeof(short)); - w.AddSamples(_samples); + Buffer.BlockCopy(samples, 0, _samples, 0, samplesProvided * Channels * sizeof(short)); + W.AddSamples(_samples); } } } - public abstract class AVStretcher : VWWrap, IVideoWriter + public abstract class AVStretcher : VwWrap, IVideoWriter { - protected int fpsnum; - protected int fpsden; - protected bool vset = false; + protected int FpsNum; + protected int FpsDen; + protected bool VSet; - protected int samplerate; - protected int channels; - protected int bits; - protected bool aset = false; + protected int Samplerate; + protected int Channels; + protected int Bits; + protected bool ASet; /// already set - public new virtual void SetMovieParameters(int fpsnum, int fpsden) + public new virtual void SetMovieParameters(int fpsNum, int fpsDen) { - if (vset) + if (VSet) { throw new InvalidOperationException(); } - vset = true; - this.fpsnum = fpsnum; - this.fpsden = fpsden; + VSet = true; + FpsNum = fpsNum; + FpsDen = fpsDen; - base.SetMovieParameters(fpsnum, fpsden); + base.SetMovieParameters(fpsNum, fpsDen); } /// already set, or is not 16 public new virtual void SetAudioParameters(int sampleRate, int channels, int bits) { - if (aset) + if (ASet) { throw new InvalidOperationException(); } @@ -173,10 +174,10 @@ namespace BizHawk.Client.EmuHawk throw new InvalidOperationException("Only 16 bit audio is supported!"); } - aset = true; - this.samplerate = sampleRate; - this.channels = channels; - this.bits = bits; + ASet = true; + Samplerate = sampleRate; + Channels = channels; + Bits = bits; base.SetAudioParameters(sampleRate, channels, bits); } @@ -197,85 +198,84 @@ namespace BizHawk.Client.EmuHawk { throw new InvalidOperationException("Must call AddAV()!"); } - } - public abstract class VWWrap : IVideoWriter + public abstract class VwWrap : IVideoWriter { - protected IVideoWriter w; + protected IVideoWriter W; - public bool UsesAudio => w.UsesAudio; + public bool UsesAudio => W.UsesAudio; - public bool UsesVideo => w.UsesVideo; + public bool UsesVideo => W.UsesVideo; public void SetVideoCodecToken(IDisposable token) { - w.SetVideoCodecToken(token); + W.SetVideoCodecToken(token); } public void SetDefaultVideoCodecToken() { - w.SetDefaultVideoCodecToken(); + W.SetDefaultVideoCodecToken(); } public void OpenFile(string baseName) { - w.OpenFile(baseName); + W.OpenFile(baseName); } public void CloseFile() { - w.CloseFile(); + W.CloseFile(); } public void SetFrame(int frame) { - w.SetFrame(frame); + W.SetFrame(frame); } public void AddFrame(IVideoProvider source) { - w.AddFrame(source); + W.AddFrame(source); } public void AddSamples(short[] samples) { - w.AddSamples(samples); + W.AddSamples(samples); } - public IDisposable AcquireVideoCodecToken(System.Windows.Forms.IWin32Window hwnd) + public IDisposable AcquireVideoCodecToken(IWin32Window hwnd) { - return w.AcquireVideoCodecToken(hwnd); + return W.AcquireVideoCodecToken(hwnd); } - public void SetMovieParameters(int fpsnum, int fpsden) + public void SetMovieParameters(int fpsNum, int fpsDen) { - w.SetMovieParameters(fpsnum, fpsden); + W.SetMovieParameters(fpsNum, fpsDen); } public void SetVideoParameters(int width, int height) { - w.SetVideoParameters(width, height); + W.SetVideoParameters(width, height); } public void SetAudioParameters(int sampleRate, int channels, int bits) { - w.SetAudioParameters(sampleRate, channels, bits); + W.SetAudioParameters(sampleRate, channels, bits); } - public void SetMetaData(string gameName, string authors, ulong lengthMS, ulong rerecords) + public void SetMetaData(string gameName, string authors, ulong lengthMs, ulong rerecords) { - w.SetMetaData(gameName, authors, lengthMS, rerecords); + W.SetMetaData(gameName, authors, lengthMs, rerecords); } public string DesiredExtension() { - return w.DesiredExtension(); + return W.DesiredExtension(); } public void Dispose() { - w.Dispose(); + W.Dispose(); } } } diff --git a/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs b/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs index 6fe0efa9c2..fc735e1214 100644 --- a/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs +++ b/BizHawk.Client.EmuHawk/AVOut/AviWriter.cs @@ -345,15 +345,15 @@ namespace BizHawk.Client.EmuHawk /// /// set basic movie timing parameters for the avi file. must be set before the file is opened. /// - public void SetMovieParameters(int fps, int fps_scale) + public void SetMovieParameters(int fpsNum, int fpsDen) { bool change = false; - change |= fps != parameters.fps; - parameters.fps = fps; + change |= fpsNum != parameters.fps; + parameters.fps = fpsNum; - change |= parameters.fps_scale != fps_scale; - parameters.fps_scale = fps_scale; + change |= parameters.fps_scale != fpsDen; + parameters.fps_scale = fpsDen; if (change) { diff --git a/BizHawk.Client.EmuHawk/AVOut/BmpVideoProvder.cs b/BizHawk.Client.EmuHawk/AVOut/BmpVideoProvder.cs index 0045e87c1c..367c3b33cd 100644 --- a/BizHawk.Client.EmuHawk/AVOut/BmpVideoProvder.cs +++ b/BizHawk.Client.EmuHawk/AVOut/BmpVideoProvder.cs @@ -1,5 +1,7 @@ using System; using System.Drawing; +using System.Drawing.Imaging; +using System.Runtime.InteropServices; using BizHawk.Emulation.Common; @@ -12,11 +14,11 @@ namespace BizHawk.Client.EmuHawk { private Bitmap _bmp; - public BmpVideoProvider(Bitmap bmp, int vsyncnum, int vsyncden) + public BmpVideoProvider(Bitmap bmp, int vsyncNum, int vsyncDen) { _bmp = bmp; - VsyncNumerator = vsyncnum; - VsyncDenominator = vsyncden; + VsyncNumerator = vsyncNum; + VsyncDenominator = vsyncDen; } public void Dispose() @@ -31,12 +33,12 @@ namespace BizHawk.Client.EmuHawk public int[] GetVideoBuffer() { // is there a faster way to do this? - var data = _bmp.LockBits(new Rectangle(0, 0, _bmp.Width, _bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + var data = _bmp.LockBits(new Rectangle(0, 0, _bmp.Width, _bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); int[] ret = new int[_bmp.Width * _bmp.Height]; // won't work if stride is messed up - System.Runtime.InteropServices.Marshal.Copy(data.Scan0, ret, 0, _bmp.Width * _bmp.Height); + Marshal.Copy(data.Scan0, ret, 0, _bmp.Width * _bmp.Height); _bmp.UnlockBits(data); return ret; } @@ -52,8 +54,8 @@ namespace BizHawk.Client.EmuHawk public int BackgroundColor => 0; - public int VsyncNumerator { get; private set; } + public int VsyncNumerator { get; } - public int VsyncDenominator { get; private set; } + public int VsyncDenominator { get; } } } diff --git a/BizHawk.Client.EmuHawk/AVOut/FFmpegWriter.cs b/BizHawk.Client.EmuHawk/AVOut/FFmpegWriter.cs index de8fc8423c..326fa8c9bc 100644 --- a/BizHawk.Client.EmuHawk/AVOut/FFmpegWriter.cs +++ b/BizHawk.Client.EmuHawk/AVOut/FFmpegWriter.cs @@ -225,10 +225,10 @@ namespace BizHawk.Client.EmuHawk /// private int fpsnum, fpsden, width, height, sampleRate, channels; - public void SetMovieParameters(int fpsnum, int fpsden) + public void SetMovieParameters(int fpsNum, int fpsDen) { - this.fpsnum = fpsnum; - this.fpsden = fpsden; + this.fpsnum = fpsNum; + this.fpsden = fpsDen; } public void SetVideoParameters(int width, int height) diff --git a/BizHawk.Client.EmuHawk/AVOut/GifWriter.cs b/BizHawk.Client.EmuHawk/AVOut/GifWriter.cs index ff4eb2cb67..b73da4a3f5 100644 --- a/BizHawk.Client.EmuHawk/AVOut/GifWriter.cs +++ b/BizHawk.Client.EmuHawk/AVOut/GifWriter.cs @@ -220,10 +220,10 @@ namespace BizHawk.Client.EmuHawk Delay[1] = (byte)(delay >> 8 & 0xff); } - public void SetMovieParameters(int fpsnum, int fpsden) + public void SetMovieParameters(int fpsNum, int fpsDen) { - this.fpsnum = fpsnum; - this.fpsden = fpsden; + this.fpsnum = fpsNum; + this.fpsden = fpsDen; CalcDelay(); } diff --git a/BizHawk.Client.EmuHawk/AVOut/IVideoWriter.cs b/BizHawk.Client.EmuHawk/AVOut/IVideoWriter.cs index ca93ae6c19..2408564cb3 100644 --- a/BizHawk.Client.EmuHawk/AVOut/IVideoWriter.cs +++ b/BizHawk.Client.EmuHawk/AVOut/IVideoWriter.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; - using BizHawk.Emulation.Common; -using BizHawk.Common.ReflectionExtensions; namespace BizHawk.Client.EmuHawk { @@ -19,12 +17,12 @@ namespace BizHawk.Client.EmuHawk void SetDefaultVideoCodecToken(); /// - /// Returns whether this videowriter dumps audio + /// Returns whether this VideoWriter dumps audio /// bool UsesAudio { get; } /// - /// Returns whether this videowriter dumps video + /// Returns whether this VideoWriter dumps video /// bool UsesVideo { get; } @@ -67,9 +65,9 @@ namespace BizHawk.Client.EmuHawk IDisposable AcquireVideoCodecToken(System.Windows.Forms.IWin32Window hwnd); /// - /// set framerate to fpsnum/fpsden (assumed to be unchanging over the life of the stream) + /// set framerate to fpsNum/fpsDen (assumed to be unchanging over the life of the stream) /// - void SetMovieParameters(int fpsnum, int fpsden); + void SetMovieParameters(int fpsNum, int fpsDen); /// /// set resolution parameters (width x height) @@ -90,43 +88,16 @@ namespace BizHawk.Client.EmuHawk /// /// The name of the game loaded /// Authors on movie file - /// Length of movie file in milliseconds + /// Length of movie file in milliseconds /// Number of rerecords on movie file - void SetMetaData(string gameName, string authors, UInt64 lengthMS, UInt64 rerecords); + void SetMetaData(string gameName, string authors, ulong lengthMs, ulong rerecords); -// /// -// /// short description of this IVideoWriter -// /// -// string WriterDescription(); /// /// what default extension this writer would like to put on its output /// string DesiredExtension(); -// /// -// /// name that command line parameters can refer to -// /// -// string ShortName(); } - public static class VideoWriterExtensions - { - public static string WriterDescription(this IVideoWriter w) - { - return w.GetAttribute().Description; - } - - public static string ShortName(this IVideoWriter w) - { - return w.GetAttribute().ShortName; - } - - public static string LongName(this IVideoWriter w) - { - return w.GetAttribute().Name; - } - } - - [AttributeUsage(AttributeTargets.Class)] public class VideoWriterAttribute : Attribute { @@ -150,7 +121,7 @@ namespace BizHawk.Client.EmuHawk public class VideoWriterInfo { public VideoWriterAttribute Attribs { get; } - private Type _type; + private readonly Type _type; public VideoWriterInfo(VideoWriterAttribute attribs, Type type) { @@ -158,15 +129,9 @@ namespace BizHawk.Client.EmuHawk Attribs = attribs; } - public IVideoWriter Create() - { - return (IVideoWriter)Activator.CreateInstance(_type); - } + public IVideoWriter Create() => (IVideoWriter)Activator.CreateInstance(_type); - public override string ToString() - { - return Attribs.Name; - } + public override string ToString() => Attribs.Name; } /// @@ -174,7 +139,7 @@ namespace BizHawk.Client.EmuHawk /// public static class VideoWriterInventory { - private static Dictionary vws = new Dictionary(); + private static readonly Dictionary VideoWriters = new Dictionary(); static VideoWriterInventory() { @@ -186,28 +151,21 @@ namespace BizHawk.Client.EmuHawk && t.GetCustomAttributes(typeof(VideoWriterIgnoreAttribute), false).Length == 0) { var a = (VideoWriterAttribute)t.GetCustomAttributes(typeof(VideoWriterAttribute), false)[0]; - vws.Add(a.ShortName, new VideoWriterInfo(a, t)); + VideoWriters.Add(a.ShortName, new VideoWriterInfo(a, t)); } } } - public static IEnumerable GetAllWriters() - { - return vws.Values; - } + public static IEnumerable GetAllWriters() => VideoWriters.Values; /// /// find an IVideoWriter by its short name /// public static IVideoWriter GetVideoWriter(string name) { - VideoWriterInfo ret; - if (vws.TryGetValue(name, out ret)) - { - return ret.Create(); - } - - return null; + return VideoWriters.TryGetValue(name, out var ret) + ? ret.Create() + : null; } } } diff --git a/BizHawk.Client.EmuHawk/AVOut/ImageSequenceWriter.cs b/BizHawk.Client.EmuHawk/AVOut/ImageSequenceWriter.cs index a34867fe81..3cc1242cef 100644 --- a/BizHawk.Client.EmuHawk/AVOut/ImageSequenceWriter.cs +++ b/BizHawk.Client.EmuHawk/AVOut/ImageSequenceWriter.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Drawing.Imaging; using System.Windows.Forms; using BizHawk.Bizware.BizwareGL; @@ -44,19 +45,17 @@ namespace BizHawk.Client.EmuHawk public void AddFrame(IVideoProvider source) { - string ext = Path.GetExtension(_baseName); - var name = Path.Combine(Path.GetDirectoryName(_baseName), $"{Path.GetFileNameWithoutExtension(_baseName)}_{_frame}{ext}"); + string ext = Path.GetExtension(_baseName) ?? ""; + var name = Path.Combine(Path.GetDirectoryName(_baseName) ?? "", $"{Path.GetFileNameWithoutExtension(_baseName)}_{_frame}{ext}"); BitmapBuffer bb = new BitmapBuffer(source.BufferWidth, source.BufferHeight, source.GetVideoBuffer()); - using (var bmp = bb.ToSysdrawingBitmap()) + using var bmp = bb.ToSysdrawingBitmap(); + if (ext.ToUpper() == ".PNG") { - if (ext.ToUpper() == ".PNG") - { - bmp.Save(name, System.Drawing.Imaging.ImageFormat.Png); - } - else if (ext.ToUpper() == ".JPG") - { - bmp.Save(name, System.Drawing.Imaging.ImageFormat.Jpeg); - } + bmp.Save(name, ImageFormat.Png); + } + else if (ext.ToUpper() == ".JPG") + { + bmp.Save(name, ImageFormat.Jpeg); } _frame++; @@ -78,7 +77,7 @@ namespace BizHawk.Client.EmuHawk return new CodecToken(); } - public void SetMovieParameters(int fpsnum, int fpsden) + public void SetMovieParameters(int fpsNum, int fpsDen) { } @@ -90,14 +89,11 @@ namespace BizHawk.Client.EmuHawk { } - public void SetMetaData(string gameName, string authors, ulong lengthMS, ulong rerecords) + public void SetMetaData(string gameName, string authors, ulong lengthMs, ulong rerecords) { } - public string DesiredExtension() - { - return "png"; - } + public string DesiredExtension() => "png"; public void Dispose() { diff --git a/BizHawk.Client.EmuHawk/AVOut/JMDForm.Designer.cs b/BizHawk.Client.EmuHawk/AVOut/JMDForm.Designer.cs index 10f15895ed..07638aefd8 100644 --- a/BizHawk.Client.EmuHawk/AVOut/JMDForm.Designer.cs +++ b/BizHawk.Client.EmuHawk/AVOut/JMDForm.Designer.cs @@ -1,6 +1,6 @@ namespace BizHawk.Client.EmuHawk { - partial class JMDForm + partial class JmdForm { /// /// Required designer variable. @@ -52,7 +52,6 @@ this.okButton.TabIndex = 0; this.okButton.Text = "OK"; this.okButton.UseVisualStyleBackColor = true; - this.okButton.Click += new System.EventHandler(this.okButton_Click); // // threadsBar // @@ -60,7 +59,7 @@ this.threadsBar.Name = "threadsBar"; this.threadsBar.Size = new System.Drawing.Size(104, 45); this.threadsBar.TabIndex = 5; - this.threadsBar.Scroll += new System.EventHandler(this.threadsBar_Scroll); + this.threadsBar.Scroll += new System.EventHandler(this.ThreadsBar_Scroll); // // compressionBar // @@ -68,7 +67,7 @@ this.compressionBar.Name = "compressionBar"; this.compressionBar.Size = new System.Drawing.Size(104, 45); this.compressionBar.TabIndex = 9; - this.compressionBar.Scroll += new System.EventHandler(this.compressionBar_Scroll); + this.compressionBar.Scroll += new System.EventHandler(this.CompressionBar_Scroll); // // threadLeft // @@ -136,7 +135,6 @@ this.cancelButton.TabIndex = 1; this.cancelButton.Text = "Cancel"; this.cancelButton.UseVisualStyleBackColor = true; - this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); // // JMDForm // @@ -155,7 +153,7 @@ this.Controls.Add(this.compressionBar); this.Controls.Add(this.threadsBar); this.Controls.Add(this.okButton); - this.Name = "JMDForm"; + this.Name = "JmdForm"; this.ShowIcon = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "JMD Compression Options"; diff --git a/BizHawk.Client.EmuHawk/AVOut/JMDForm.cs b/BizHawk.Client.EmuHawk/AVOut/JMDForm.cs index 613274208a..7183e98a91 100644 --- a/BizHawk.Client.EmuHawk/AVOut/JMDForm.cs +++ b/BizHawk.Client.EmuHawk/AVOut/JMDForm.cs @@ -1,34 +1,25 @@ using System; using System.Windows.Forms; +using BizHawk.Client.EmuHawk.WinFormExtensions; namespace BizHawk.Client.EmuHawk { /// /// implements a minimal dialog for configuring JMDWriter /// - public partial class JMDForm : Form + public partial class JmdForm : Form { - public JMDForm() + public JmdForm() { InitializeComponent(); } - private void okButton_Click(object sender, EventArgs e) - { - - } - - private void cancelButton_Click(object sender, EventArgs e) - { - - } - - private void threadsBar_Scroll(object sender, EventArgs e) + private void ThreadsBar_Scroll(object sender, EventArgs e) { threadTop.Text = $"Number of compression threads: {threadsBar.Value}"; } - private void compressionBar_Scroll(object sender, EventArgs e) + private void CompressionBar_Scroll(object sender, EventArgs e) { compressionTop.Text = compressionBar.Value == compressionBar.Minimum ? "Compression Level: NONE" @@ -39,43 +30,37 @@ namespace BizHawk.Client.EmuHawk /// Show a configuration dialog (modal) for JMDWriter /// /// number of threads - /// compression level - /// minimum possible number of threads - /// maximum possible number of threads - /// minimum compression level, assumed to be "no compression" - /// maximum compression level + /// compression level + /// minimum possible number of threads + /// maximum possible number of threads + /// minimum compression level, assumed to be "no compression" + /// maximum compression level /// hwnd of parent /// false if user canceled; true if user consented - public static bool DoCompressionDlg(ref int threads, ref int complevel, int tmin, int tmax, int cmin, int cmax, IWin32Window hwnd) + public static bool DoCompressionDlg(ref int threads, ref int compLevel, int tMin, int tMax, int cMin, int cMax, IWin32Window hwnd) { - JMDForm j = new JMDForm(); - j.threadsBar.Minimum = tmin; - j.threadsBar.Maximum = tmax; - j.compressionBar.Minimum = cmin; - j.compressionBar.Maximum = cmax; + var j = new JmdForm + { + threadsBar = { Minimum = tMin, Maximum = tMax }, + compressionBar = { Minimum = cMin, Maximum = cMax } + }; + j.threadsBar.Value = threads; - j.compressionBar.Value = complevel; - j.threadsBar_Scroll(null, null); - j.compressionBar_Scroll(null, null); - j.threadLeft.Text = $"{tmin}"; - j.threadRight.Text = $"{tmax}"; - j.compressionLeft.Text = $"{cmin}"; - j.compressionRight.Text = $"{cmax}"; + j.compressionBar.Value = compLevel; + j.ThreadsBar_Scroll(null, null); + j.CompressionBar_Scroll(null, null); + j.threadLeft.Text = $"{tMin}"; + j.threadRight.Text = $"{tMax}"; + j.compressionLeft.Text = $"{cMin}"; + j.compressionRight.Text = $"{cMax}"; DialogResult d = j.ShowDialog(hwnd); threads = j.threadsBar.Value; - complevel = j.compressionBar.Value; + compLevel = j.compressionBar.Value; j.Dispose(); - if (d == DialogResult.OK) - { - return true; - } - - return false; + return d.IsOk(); } - - } } diff --git a/BizHawk.Client.EmuHawk/AVOut/JMDWriter.cs b/BizHawk.Client.EmuHawk/AVOut/JMDWriter.cs index e0621b74f0..b65a1b935c 100644 --- a/BizHawk.Client.EmuHawk/AVOut/JMDWriter.cs +++ b/BizHawk.Client.EmuHawk/AVOut/JMDWriter.cs @@ -1,7 +1,10 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Text; +using System.Threading; +using System.Windows.Forms; using ICSharpCode.SharpZipLib.Zip.Compression.Streams; using ICSharpCode.SharpZipLib.Zip.Compression; @@ -18,12 +21,12 @@ namespace BizHawk.Client.EmuHawk /// they can be processed with JPC-rr streamtools or JMDSource (avisynth) /// [VideoWriter("jmd", "JMD writer", "Writes a JPC-rr multidump file (JMD). These can be read and further processed with jpc-streamtools. One JMD file contains all audio (uncompressed) and video (compressed).")] - class JMDWriter : IVideoWriter + public class JmdWriter : IVideoWriter { /// /// carries private compression information data /// - class CodecToken : IDisposable + private class CodecToken : IDisposable { public void Dispose() { @@ -32,202 +35,162 @@ namespace BizHawk.Client.EmuHawk /// /// how hard the zlib compressor works /// - public int compressionlevel - { - get; - set; - } + public int CompressionLevel { get; set; } /// /// number of threads to be used for video compression (sort of) /// - public int numthreads - { - get; - set; - } + public int NumThreads { get; set; } /// /// instantiates a CodecToken with default parameters /// public CodecToken() { - compressionlevel = Deflater.DEFAULT_COMPRESSION; - numthreads = 3; + CompressionLevel = Deflater.DEFAULT_COMPRESSION; + NumThreads = 3; } } - /// - /// stores compression parameters - /// - CodecToken token; + // stores compression parameters + private CodecToken _token; - /// - /// fps numerator, constant - /// - int fpsnum; + // fps numerator, constant + private int _fpsNum; - /// - /// fps denominator, constant - /// - int fpsden; + // fps denominator, constant + private int _fpsDen; - /// - /// audio samplerate, constant - /// - int audiosamplerate; + // audio samplerate, constant + private int _audioSampleRate; /// /// audio number of channels, constant; 1 or 2 only /// - int audiochannels; + private int _audioChannels; - /// - /// audio bits per sample, constant; only 16 supported - /// - int audiobits; - - /// - /// actual disk file being written - /// - JMDfile jmdfile; + // actual disk file being written + private JmdFile _jmdFile; /// /// metadata for a movie /// not needed if we aren't dumping something that's not a movie /// - class MovieMetaData + private class MovieMetaData { /// /// name of the game (rom) /// - public string gamename; + public string GameName { get; set; } + /// /// author(s) names /// - public string authors; + public string Authors { get; set; } + /// /// total length of the movie: ms /// - public UInt64 lengthms; + public ulong LengthMs { get; set; } + /// /// number of rerecords /// - public UInt64 rerecords; + public ulong Rerecords { get; set; } } - /// - /// represents the metadata for the active movie (if applicable) - /// - MovieMetaData moviemetadata; + // represents the metadata for the active movie (if applicable) + private MovieMetaData _movieMetadata; /// /// represents a JMD file packet ready to be written except for sorting and timestamp offset /// - class JMDPacket + private class JmdPacket { - public UInt16 stream; - public UInt64 timestamp; // final muxed timestamp will be relative to previous - public byte subtype; - public byte[] data; + public ushort Stream { get; set; } + public ulong Timestamp { get; set; } // final muxed timestamp will be relative to previous + public byte Subtype { get; set; } + public byte[] Data { get; set; } } /// - /// writes JMDfile packets to an underlying bytestream + /// writes JMD file packets to an underlying bytestream /// handles one video, one pcm audio, and one metadata track /// - class JMDfile + private class JmdFile { - /// - /// current timestamp position - /// - UInt64 timestampoff; + // current timestamp position + private ulong _timestampOff; - /// - /// total number of video frames written - /// - UInt64 totalframes; + // total number of video frames written + private ulong _totalFrames; - /// - /// total number of sample pairs written - /// - UInt64 totalsamples; + // total number of sample pairs written + private ulong _totalSamples; - /// - /// fps of the video stream is fpsnum/fpsden - /// - int fpsnum; + // fps of the video stream is fpsNum/fpsDen + private readonly int _fpsNum; - /// - /// fps of the video stream is fpsnum/fpsden - /// - int fpsden; + // fps of the video stream is fpsNum/fpsDen + private readonly int _fpsDen; - /// - /// audio samplerate in hz - /// - int audiosamplerate; + // audio samplerate in hz + private readonly int _audioSamplerate; - /// - /// true if input will be stereo; mono otherwise - /// output stream is always stereo - /// - bool stereo; + // true if input will be stereo; mono otherwise + // output stream is always stereo + private readonly bool _stereo; - /// /// underlying bytestream that is being written to - /// - Stream f; + private readonly Stream _f; /// cannot be written to - public JMDfile(Stream f, int fpsnum, int fpsden, int audiosamplerate, bool stereo) + public JmdFile(Stream f, int fpsNum, int fpsDen, int audioSamplerate, bool stereo) { if (!f.CanWrite) { throw new ArgumentException($"{nameof(Stream)} must be writable!"); } - this.f = f; - this.fpsnum = fpsnum; - this.fpsden = fpsden; - this.audiosamplerate = audiosamplerate; - this.stereo = stereo; + _f = f; + _fpsNum = fpsNum; + _fpsDen = fpsDen; + _audioSamplerate = audioSamplerate; + _stereo = stereo; - timestampoff = 0; - totalframes = 0; - totalsamples = 0; + _timestampOff = 0; + _totalFrames = 0; + _totalSamples = 0; - astorage = new Queue(); - vstorage = new Queue(); + _audioStorage = new Queue(); + _videoStorage = new Queue(); - writeheader(); + WriteHeader(); } - /// - /// write header to the JPC file - /// assumes one video, one audio, and one metadata stream, with hardcoded IDs - /// - void writeheader() + // write header to the JPC file + // assumes one video, one audio, and one metadata stream, with hardcoded IDs + private void WriteHeader() { // write JPC MAGIC - writeBE16(0xffff); - f.Write(Encoding.ASCII.GetBytes("JPCRRMULTIDUMP"), 0, 14); + WriteBe16(0xffff); + _f.Write(Encoding.ASCII.GetBytes("JPCRRMULTIDUMP"), 0, 14); // write channel table - writeBE16(3); // number of streams + WriteBe16(3); // number of streams // for each stream - writeBE16(0); // channel 0 - writeBE16(0); // video - writeBE16(0); // no name + WriteBe16(0); // channel 0 + WriteBe16(0); // video + WriteBe16(0); // no name - writeBE16(1); // channel 1 - writeBE16(1); // pcm audio - writeBE16(0); // no name + WriteBe16(1); // channel 1 + WriteBe16(1); // pcm audio + WriteBe16(0); // no name - writeBE16(2); // channel 2 - writeBE16(5); // metadata - writeBE16(0); // no name + WriteBe16(2); // channel 2 + WriteBe16(5); // metadata + WriteBe16(0); // no name } /// @@ -235,46 +198,46 @@ namespace BizHawk.Client.EmuHawk /// can be called at any time /// /// metadata to write - public void writemetadata(MovieMetaData mmd) + public void WriteMetadata(MovieMetaData mmd) { - byte[] temp; // write metadatas - writeBE16(2); // data channel + WriteBe16(2); // data channel writeBE32(0); // timestamp (same time as previous packet) - f.WriteByte(71); // gamename - temp = Encoding.UTF8.GetBytes(mmd.gamename); + _f.WriteByte(71); // GameName + + var temp = Encoding.UTF8.GetBytes(mmd.GameName); writeVar(temp.Length); - f.Write(temp, 0, temp.Length); + _f.Write(temp, 0, temp.Length); - writeBE16(2); + WriteBe16(2); writeBE32(0); - f.WriteByte(65); // authors - temp = Encoding.UTF8.GetBytes(mmd.authors); + _f.WriteByte(65); // authors + temp = Encoding.UTF8.GetBytes(mmd.Authors); writeVar(temp.Length); - f.Write(temp, 0, temp.Length); + _f.Write(temp, 0, temp.Length); - writeBE16(2); + WriteBe16(2); writeBE32(0); - f.WriteByte(76); // length + _f.WriteByte(76); // length writeVar(8); - writeBE64(mmd.lengthms * 1000000); + writeBE64(mmd.LengthMs * 1000000); - writeBE16(2); + WriteBe16(2); writeBE32(0); - f.WriteByte(82); // rerecords + _f.WriteByte(82); // rerecords writeVar(8); - writeBE64(mmd.rerecords); + writeBE64(mmd.Rerecords); } /// /// write big endian 16 bit unsigned /// - void writeBE16(UInt16 v) + private void WriteBe16(ushort v) { byte[] b = new byte[2]; b[0] = (byte)(v >> 8); b[1] = (byte)(v & 255); - f.Write(b, 0, 2); + _f.Write(b, 0, 2); } /// @@ -287,7 +250,7 @@ namespace BizHawk.Client.EmuHawk b[1] = (byte)(v >> 16); b[2] = (byte)(v >> 8); b[3] = (byte)(v & 255); - f.Write(b, 0, 4); + _f.Write(b, 0, 4); } /// @@ -301,7 +264,7 @@ namespace BizHawk.Client.EmuHawk b[i] = (byte)(v & 255); v >>= 8; } - f.Write(b, 0, 8); + _f.Write(b, 0, 8); } /// @@ -321,10 +284,10 @@ namespace BizHawk.Client.EmuHawk v /= 128; } if (i == 0) - f.WriteByte(0); + _f.WriteByte(0); else for (; i > 0; i--) - f.WriteByte(b[i - 1]); + _f.WriteByte(b[i - 1]); } /// @@ -362,27 +325,27 @@ namespace BizHawk.Client.EmuHawk /// actually write a packet to file /// timestamp sequence must be nondecreasing /// - void writeActual(JMDPacket j) + void writeActual(JmdPacket j) { - if (j.timestamp < timestampoff) + if (j.Timestamp < _timestampOff) { throw new ArithmeticException("JMD Timestamp problem?"); } - UInt64 timestampout = j.timestamp - timestampoff; + UInt64 timestampout = j.Timestamp - _timestampOff; while (timestampout > 0xffffffff) { timestampout -= 0xffffffff; // write timestamp skipper for (int i = 0; i < 6; i++) - f.WriteByte(0xff); + _f.WriteByte(0xff); } - timestampoff = j.timestamp; - writeBE16(j.stream); + _timestampOff = j.Timestamp; + WriteBe16(j.Stream); writeBE32((UInt32)timestampout); - f.WriteByte(j.subtype); - writeVar((UInt64)j.data.LongLength); - f.Write(j.data, 0, j.data.Length); + _f.WriteByte(j.Subtype); + writeVar((UInt64)j.Data.LongLength); + _f.Write(j.Data, 0, j.Data.Length); } /// @@ -391,13 +354,13 @@ namespace BizHawk.Client.EmuHawk /// zlibed frame with width and height prepended public void AddVideo(byte[] source) { - var j = new JMDPacket(); - j.stream = 0; - j.subtype = 1; // zlib compressed, other possibility is 0 = uncompressed - j.data = source; - j.timestamp = timestampcalc(fpsnum, fpsden, (UInt64)totalframes); - totalframes++; - writevideo(j); + var j = new JmdPacket(); + j.Stream = 0; + j.Subtype = 1; // zlib compressed, other possibility is 0 = uncompressed + j.Data = source; + j.Timestamp = timestampcalc(_fpsNum, _fpsDen, (UInt64)_totalFrames); + _totalFrames++; + WriteVideo(j); } /// @@ -406,7 +369,7 @@ namespace BizHawk.Client.EmuHawk /// public void AddSamples(short[] samples) { - if (!stereo) + if (!_stereo) for (int i = 0; i < samples.Length; i++) doaudiopacket(samples[i], samples[i]); else @@ -421,90 +384,80 @@ namespace BizHawk.Client.EmuHawk /// right sample void doaudiopacket(short l, short r) { - var j = new JMDPacket(); - j.stream = 1; - j.subtype = 1; // raw PCM audio - j.data = new byte[4]; - j.data[0] = (byte)(l >> 8); - j.data[1] = (byte)(l & 255); - j.data[2] = (byte)(r >> 8); - j.data[3] = (byte)(r & 255); + var j = new JmdPacket(); + j.Stream = 1; + j.Subtype = 1; // raw PCM audio + j.Data = new byte[4]; + j.Data[0] = (byte)(l >> 8); + j.Data[1] = (byte)(l & 255); + j.Data[2] = (byte)(r >> 8); + j.Data[3] = (byte)(r & 255); - j.timestamp = timestampcalc(audiosamplerate, 1, totalsamples); - totalsamples++; - writesound(j); + j.Timestamp = timestampcalc(_audioSamplerate, 1, _totalSamples); + _totalSamples++; + WriteSound(j); } // ensure outputs are in order - // JMD packets must be in nondecreasing timestamp order, but there's no obligation - // for us to get handed that. this code is a bit overcomplex to handle edge cases + // JMD packets must be in non-decreasing timestamp order, but there's no obligation + // for us to get handed that. This code is a bit overly complex to handle edge cases // that may not be a problem with the current system? - /// - /// collection of JMDpackets yet to be written (audio) - /// - Queue astorage; - /// - /// collection of JMDpackets yet to be written (video) - /// - Queue vstorage; + // collection of JMD packets yet to be written (audio) + private readonly Queue _audioStorage; - /// - /// add a sound packet to the file write queue - /// will be written when order-appropriate wrt video - /// the sound packets added must be internally ordered (but need not match video order) - /// - void writesound(JMDPacket j) + // collection of JMD packets yet to be written (video) + private readonly Queue _videoStorage; + + // add a sound packet to the file write queue + // will be written when order-appropriate wrt video + // the sound packets added must be internally ordered (but need not match video order) + private void WriteSound(JmdPacket j) { - while (vstorage.Count > 0) + while (_videoStorage.Count > 0) { - var p = vstorage.Peek(); - if (p.timestamp <= j.timestamp) - writeActual(vstorage.Dequeue()); + var p = _videoStorage.Peek(); + if (p.Timestamp <= j.Timestamp) + writeActual(_videoStorage.Dequeue()); else break; } - astorage.Enqueue(j); + _audioStorage.Enqueue(j); } - /// - /// add a video packet to the file write queue - /// will be written when order-appropriate wrt audio - /// the video packets added must be internally ordered (but need not match audio order) - /// - void writevideo(JMDPacket j) + // add a video packet to the file write queue + // will be written when order-appropriate wrt audio + // the video packets added must be internally ordered (but need not match audio order) + private void WriteVideo(JmdPacket j) { - while (astorage.Count > 0) + while (_audioStorage.Count > 0) { - var p = astorage.Peek(); - if (p.timestamp <= j.timestamp) - writeActual(astorage.Dequeue()); + var p = _audioStorage.Peek(); + if (p.Timestamp <= j.Timestamp) + writeActual(_audioStorage.Dequeue()); else break; } - vstorage.Enqueue(j); + _videoStorage.Enqueue(j); } - /// - /// flush all remaining JMDPackets to file - /// call before closing the file - /// - void flushpackets() + // flush all remaining JMDPackets to file + // call before closing the file + private void FlushPackets() { - while (astorage.Count > 0 && vstorage.Count > 0) + while (_audioStorage.Count > 0 && _videoStorage.Count > 0) { - var ap = astorage.Peek(); - var av = vstorage.Peek(); - if (ap.timestamp <= av.timestamp) - writeActual(astorage.Dequeue()); - else - writeActual(vstorage.Dequeue()); + var ap = _audioStorage.Peek(); + var av = _videoStorage.Peek(); + writeActual(ap.Timestamp <= av.Timestamp + ? _audioStorage.Dequeue() + : _videoStorage.Dequeue()); } - while (astorage.Count > 0) - writeActual(astorage.Dequeue()); - while (vstorage.Count > 0) - writeActual(vstorage.Dequeue()); + while (_audioStorage.Count > 0) + writeActual(_audioStorage.Dequeue()); + while (_videoStorage.Count > 0) + writeActual(_videoStorage.Dequeue()); } /// @@ -512,24 +465,23 @@ namespace BizHawk.Client.EmuHawk /// public void Close() { - flushpackets(); - f.Close(); + FlushPackets(); + _f.Close(); } } /// /// sets default (probably wrong) parameters /// - public JMDWriter() + public JmdWriter() { - fpsnum = 25; - fpsden = 1; - audiosamplerate = 22050; - audiochannels = 1; - audiobits = 8; - token = null; + _fpsNum = 25; + _fpsDen = 1; + _audioSampleRate = 22050; + _audioChannels = 1; + _token = null; - moviemetadata = null; + _movieMetadata = null; } public void Dispose() @@ -538,11 +490,11 @@ namespace BizHawk.Client.EmuHawk } /// sets the codec token to be used for video compression - /// does not inherit + /// does not inherit public void SetVideoCodecToken(IDisposable token) { - if (token is CodecToken) - this.token = (CodecToken)token; + if (token is CodecToken codecToken) + this._token = codecToken; else throw new ArgumentException("codec token must be of right type"); } @@ -561,22 +513,22 @@ namespace BizHawk.Client.EmuHawk int c = Math.Min(Math.Max(Global.Config.JMDCompression, Deflater.NO_COMPRESSION), Deflater.BEST_COMPRESSION); - if (!JMDForm.DoCompressionDlg(ref t, ref c, 1, 6, Deflater.NO_COMPRESSION, Deflater.BEST_COMPRESSION, hwnd)) + if (!JmdForm.DoCompressionDlg(ref t, ref c, 1, 6, Deflater.NO_COMPRESSION, Deflater.BEST_COMPRESSION, hwnd)) return null; - Global.Config.JMDThreads = ret.numthreads = t; - Global.Config.JMDCompression = ret.compressionlevel = c; + Global.Config.JMDThreads = ret.NumThreads = t; + Global.Config.JMDCompression = ret.CompressionLevel = c; return ret; } /// - /// set framerate to fpsnum/fpsden (assumed to be unchanging over the life of the stream) + /// set framerate to fpsNum/fpsDen (assumed to be unchanging over the life of the stream) /// - public void SetMovieParameters(int fpsnum, int fpsden) + public void SetMovieParameters(int fpsNum, int fpsDen) { - this.fpsnum = fpsnum; - this.fpsden = fpsden; + _fpsNum = fpsNum; + _fpsDen = fpsDen; } /// @@ -597,10 +549,12 @@ namespace BizHawk.Client.EmuHawk // the sampleRate limits are arbitrary, just to catch things which are probably silly-wrong // if a larger range of sampling rates is needed, it should be supported if (sampleRate < 8000 || sampleRate > 96000 || channels < 1 || channels > 2 || bits != 16) + { throw new ArgumentException("Audio parameters out of range!"); - audiosamplerate = sampleRate; - audiochannels = channels; - audiobits = bits; + } + + _audioSampleRate = sampleRate; + _audioChannels = channels; } /// @@ -611,57 +565,66 @@ namespace BizHawk.Client.EmuHawk { string ext = Path.GetExtension(baseName); if (ext == null || ext.ToLower() != ".jmd") + { baseName = baseName + ".jmd"; + } - jmdfile = new JMDfile(File.Open(baseName, FileMode.Create), fpsnum, fpsden, audiosamplerate, audiochannels == 2); + _jmdFile = new JmdFile(File.Open(baseName, FileMode.Create), _fpsNum, _fpsDen, _audioSampleRate, _audioChannels == 2); - - if (moviemetadata != null) - jmdfile.writemetadata(moviemetadata); + if (_movieMetadata != null) + { + _jmdFile.WriteMetadata(_movieMetadata); + } // start up thread // problem: since audio chunks and video frames both go through here, exactly how many zlib workers // gives is not known without knowing how the emulator will chunk audio packets // this shouldn't affect results though, just performance - threadQ = new System.Collections.Concurrent.BlockingCollection(token.numthreads * 2); - workerT = new System.Threading.Thread(new System.Threading.ThreadStart(threadproc)); - workerT.Start(); - GzipFrameDelegate = new GzipFrameD(GzipFrame); + _threadQ = new BlockingCollection(_token.NumThreads * 2); + _workerT = new Thread(ThreadProc); + _workerT.Start(); + _gzipFrameDelegate = GzipFrame; } // some of this code is copied from AviWriter... not sure how if at all it should be abstracted /// - /// blocking threadsafe queue, used for communication between main program and file writing thread + /// blocking thread safe queue, used for communication between main program and file writing thread /// - System.Collections.Concurrent.BlockingCollection threadQ; + private BlockingCollection _threadQ; + /// /// file writing thread; most of the work happens here /// - System.Threading.Thread workerT; + private Thread _workerT; /// - /// filewriting thread's loop + /// file writing thread's loop /// - void threadproc() + private void ThreadProc() { try { while (true) { - Object o = threadQ.Take(); - if (o is IAsyncResult) - jmdfile.AddVideo(GzipFrameDelegate.EndInvoke((IAsyncResult)o)); - else if (o is short[]) - jmdfile.AddSamples((short[])o); + object o = _threadQ.Take(); + if (o is IAsyncResult result) + { + _jmdFile.AddVideo(_gzipFrameDelegate.EndInvoke(result)); + } + else if (o is short[] shorts) + { + _jmdFile.AddSamples(shorts); + } else + { // anything else is assumed to be quit time return; + } } } catch (Exception e) { - System.Windows.Forms.MessageBox.Show($"JMD Worker Thread died:\n\n{e}"); - return; + MessageBox.Show($"JMD Worker Thread died:\n\n{e}"); } } @@ -670,26 +633,26 @@ namespace BizHawk.Client.EmuHawk /// public void CloseFile() { - threadQ.Add(new Object()); // acts as stop message - workerT.Join(); - - jmdfile.Close(); + _threadQ.Add(new object()); // acts as stop message + _workerT.Join(); + _jmdFile.Close(); } /// /// makes a copy of an IVideoProvider /// handles conversion to a byte array suitable for compression by zlib /// - class VideoCopy + public class VideoCopy { - public byte[] VideoBuffer; + public byte[] VideoBuffer { get; set; } - public int BufferWidth; - public int BufferHeight; + public int BufferWidth { get; set; } + public int BufferHeight { get; set; } public VideoCopy(IVideoProvider c) { int[] vb = c.GetVideoBuffer(); VideoBuffer = new byte[vb.Length * sizeof(int)]; + // we have to switch RGB ordering here for (int i = 0; i < vb.Length; i++) { @@ -698,7 +661,7 @@ namespace BizHawk.Client.EmuHawk VideoBuffer[i * 4 + 2] = (byte)(vb[i] & 255); VideoBuffer[i * 4 + 3] = 0; } - //Buffer.BlockCopy(vb, 0, VideoBuffer, 0, VideoBuffer.Length); + BufferWidth = c.BufferWidth; BufferHeight = c.BufferHeight; } @@ -711,19 +674,24 @@ namespace BizHawk.Client.EmuHawk /// /// video frame to compress /// zlib compressed frame, with width and height prepended - byte[] GzipFrame(VideoCopy v) + private byte[] GzipFrame(VideoCopy v) { - MemoryStream m = new MemoryStream(); + var m = new MemoryStream(); + // write frame height and width first m.WriteByte((byte)(v.BufferWidth >> 8)); m.WriteByte((byte)(v.BufferWidth & 255)); m.WriteByte((byte)(v.BufferHeight >> 8)); m.WriteByte((byte)(v.BufferHeight & 255)); - var g = new DeflaterOutputStream(m, new Deflater(token.compressionlevel)); - g.IsStreamOwner = false; // leave memory stream open so we can pick its contents + var g = new DeflaterOutputStream(m, new Deflater(_token.CompressionLevel)) + { + IsStreamOwner = false // leave memory stream open so we can pick its contents + }; + g.Write(v.VideoBuffer, 0, v.VideoBuffer.Length); g.Flush(); g.Close(); + byte[] ret = m.GetBuffer(); Array.Resize(ref ret, (int)m.Length); m.Close(); @@ -735,21 +703,23 @@ namespace BizHawk.Client.EmuHawk /// /// VideoCopy to compress /// gzipped stream with width and height prepended - delegate byte[] GzipFrameD(VideoCopy v); - /// - /// delegate for GzipFrame - /// - GzipFrameD GzipFrameDelegate; + private delegate byte[] GzipFrameD(VideoCopy v); + + // delegate for GzipFrame + private GzipFrameD _gzipFrameDelegate; /// /// adds a frame to the stream /// public void AddFrame(IVideoProvider source) { - if (!workerT.IsAlive) + if (!_workerT.IsAlive) + { // signal some sort of error? return; - threadQ.Add(GzipFrameDelegate.BeginInvoke(new VideoCopy(source), null, null)); + } + + _threadQ.Add(_gzipFrameDelegate.BeginInvoke(new VideoCopy(source), null, null)); } /// @@ -758,10 +728,13 @@ namespace BizHawk.Client.EmuHawk /// public void AddSamples(short[] samples) { - if (!workerT.IsAlive) + if (!_workerT.IsAlive) + { // signal some sort of error? return; - threadQ.Add((short[])samples.Clone()); + } + + _threadQ.Add((short[])samples.Clone()); } /// @@ -769,11 +742,11 @@ namespace BizHawk.Client.EmuHawk /// public void SetMetaData(string gameName, string authors, UInt64 lengthMS, UInt64 rerecords) { - moviemetadata = new MovieMetaData(); - moviemetadata.gamename = gameName; - moviemetadata.authors = authors; - moviemetadata.lengthms = lengthMS; - moviemetadata.rerecords = rerecords; + _movieMetadata = new MovieMetaData(); + _movieMetadata.GameName = gameName; + _movieMetadata.Authors = authors; + _movieMetadata.LengthMs = lengthMS; + _movieMetadata.Rerecords = rerecords; } public string DesiredExtension() @@ -790,10 +763,10 @@ namespace BizHawk.Client.EmuHawk int c = Math.Min(Math.Max(Global.Config.JMDCompression, Deflater.NO_COMPRESSION), Deflater.BEST_COMPRESSION); - ct.compressionlevel = c; - ct.numthreads = t; + ct.CompressionLevel = c; + ct.NumThreads = t; - token = ct; + _token = ct; } public void SetFrame(int frame) { } diff --git a/BizHawk.Client.EmuHawk/AVOut/NumericTextBox.cs b/BizHawk.Client.EmuHawk/AVOut/NumericTextBox.cs index ba0cdefa99..16b23f05c0 100644 --- a/BizHawk.Client.EmuHawk/AVOut/NumericTextBox.cs +++ b/BizHawk.Client.EmuHawk/AVOut/NumericTextBox.cs @@ -1,5 +1,4 @@ -using System; -using System.Windows.Forms; +using System.Windows.Forms; using System.Globalization; namespace BizHawk.Client.EmuHawk @@ -20,7 +19,7 @@ namespace BizHawk.Client.EmuHawk string keyInput = e.KeyChar.ToString(); - if (Char.IsDigit(e.KeyChar)) + if (char.IsDigit(e.KeyChar)) { // Digits are OK } @@ -34,16 +33,12 @@ namespace BizHawk.Client.EmuHawk } else if (keyInput.Equals(groupSeparator)) { - // group seperator is ok + // group separator is ok } else if (e.KeyChar == '\b') { // Backspace key is OK } - // else if ((ModifierKeys & (Keys.Control | Keys.Alt)) != 0) - // { - // // Let the edit control handle control and alt key combinations - // } else if (AllowSpace && e.KeyChar == ' ') { @@ -58,8 +53,6 @@ namespace BizHawk.Client.EmuHawk public int IntValue => int.Parse(Text); - public decimal DecimalValue => decimal.Parse(Text); - public bool AllowSpace { get; set; } public bool AllowDecimal { get; set; } diff --git a/BizHawk.Client.EmuHawk/AVOut/NutMuxer.cs b/BizHawk.Client.EmuHawk/AVOut/NutMuxer.cs index a56bc28051..403360e87c 100644 --- a/BizHawk.Client.EmuHawk/AVOut/NutMuxer.cs +++ b/BizHawk.Client.EmuHawk/AVOut/NutMuxer.cs @@ -11,7 +11,7 @@ namespace BizHawk.Client.EmuHawk /// implements a simple muxer for the NUT media format /// http://ffmpeg.org/~michael/nut.txt /// - class NutMuxer + public class NutMuxer { // this code isn't really any good for general purpose nut creation @@ -19,8 +19,8 @@ namespace BizHawk.Client.EmuHawk public class ReusableBufferPool { - private List _available = new List(); - private ICollection _inuse = new HashSet(); + private readonly List _available = new List(); + private readonly ICollection _inUse = new HashSet(); private readonly int _capacity; @@ -32,13 +32,15 @@ namespace BizHawk.Client.EmuHawk private T[] GetBufferInternal(int length, bool zerofill, Func criteria) { - if (_inuse.Count == _capacity) + if (_inUse.Count == _capacity) + { throw new InvalidOperationException(); + } T[] candidate = _available.FirstOrDefault(criteria); if (candidate == null) { - if (_available.Count + _inuse.Count == _capacity) + if (_available.Count + _inUse.Count == _capacity) { // out of space! should not happen often Console.WriteLine("Purging"); @@ -49,10 +51,14 @@ namespace BizHawk.Client.EmuHawk else { if (zerofill) + { Array.Clear(candidate, 0, candidate.Length); + } + _available.Remove(candidate); } - _inuse.Add(candidate); + + _inUse.Add(candidate); return candidate; } @@ -69,8 +75,11 @@ namespace BizHawk.Client.EmuHawk /// is not in use public void ReleaseBuffer(T[] buffer) { - if (!_inuse.Remove(buffer)) + if (!_inUse.Remove(buffer)) + { throw new ArgumentException(); + } + _available.Add(buffer); } } @@ -82,7 +91,7 @@ namespace BizHawk.Client.EmuHawk /// /// variable length value, unsigned /// - static void WriteVarU(ulong v, Stream stream) + private static void WriteVarU(ulong v, Stream stream) { byte[] b = new byte[10]; int i = 0; @@ -94,8 +103,11 @@ namespace BizHawk.Client.EmuHawk b[i++] = (byte)(v & 127); v /= 128; } while (v > 0); + for (; i > 0; i--) + { stream.WriteByte(b[i - 1]); + } } /// @@ -104,37 +116,30 @@ namespace BizHawk.Client.EmuHawk static void WriteVarU(int v, Stream stream) { if (v < 0) + { throw new ArgumentOutOfRangeException(nameof(v), "unsigned must be non-negative"); + } + WriteVarU((ulong)v, stream); } /// /// variable length value, unsigned /// - static void WriteVarU(long v, Stream stream) + private static void WriteVarU(long v, Stream stream) { if (v < 0) + { throw new ArgumentOutOfRangeException(nameof(v), "unsigned must be non-negative"); - WriteVarU((ulong)v, stream); - } + } - /// - /// variable length value, signed - /// - static void WriteVarS(long v, Stream stream) - { - ulong temp; - if (v < 0) - temp = 1 + 2 * (ulong)(-v); - else - temp = 2 * (ulong)(v); - WriteVarU(temp - 1, stream); + WriteVarU((ulong)v, stream); } /// /// utf-8 string with length prepended /// - static void WriteString(string s, Stream stream) + private static void WriteString(string s, Stream stream) { WriteBytes(Encoding.UTF8.GetBytes(s), stream); } @@ -151,7 +156,7 @@ namespace BizHawk.Client.EmuHawk /// /// big endian 64 bit unsigned /// - static void WriteBE64(ulong v, Stream stream) + private static void WriteBe64(ulong v, Stream stream) { byte[] b = new byte[8]; for (int i = 7; i >= 0; i--) @@ -159,13 +164,14 @@ namespace BizHawk.Client.EmuHawk b[i] = (byte)(v & 255); v >>= 8; } + stream.Write(b, 0, 8); } /// /// big endian 32 bit unsigned /// - static void WriteBE32(uint v, Stream stream) + private static void WriteBe32(uint v, Stream stream) { byte[] b = new byte[4]; for (int i = 3; i >= 0; i--) @@ -173,20 +179,7 @@ namespace BizHawk.Client.EmuHawk b[i] = (byte)(v & 255); v >>= 8; } - stream.Write(b, 0, 4); - } - /// - /// big endian 32 bit unsigned - /// - static void WriteBE32(int v, Stream stream) - { - byte[] b = new byte[4]; - for (int i = 3; i >= 0; i--) - { - b[i] = (byte)(v & 255); - v >>= 8; - } stream.Write(b, 0, 4); } @@ -194,7 +187,7 @@ namespace BizHawk.Client.EmuHawk #region CRC calculator - static readonly uint[] CRCtable = new uint[] + private static readonly uint[] CrcTable = { 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, @@ -206,14 +199,14 @@ namespace BizHawk.Client.EmuHawk /// seems to be different than standard CRC32????? /// /// crc32, nut variant - static uint NutCRC32(byte[] buf) + private static uint NutCRC32(byte[] buf) { uint crc = 0; - for (int i = 0; i < buf.Length; i++) + foreach (var b in buf) { - crc ^= (uint)buf[i] << 24; - crc = (crc << 4) ^ CRCtable[crc >> 28]; - crc = (crc << 4) ^ CRCtable[crc >> 28]; + crc ^= (uint)b << 24; + crc = (crc << 4) ^ CrcTable[crc >> 28]; + crc = (crc << 4) ^ CrcTable[crc >> 28]; } return crc; } @@ -221,9 +214,9 @@ namespace BizHawk.Client.EmuHawk #endregion /// - /// writes a single packet out, including checksums + /// writes a single packet out, including CheckSums /// - class NutPacket : Stream + private class NutPacket : Stream { public enum StartCode : ulong { @@ -234,23 +227,22 @@ namespace BizHawk.Client.EmuHawk Info = 0x4e49ab68b596ba78 }; - MemoryStream data; - StartCode startcode; - Stream underlying; + private MemoryStream _data; + private readonly StartCode _startCode; + private readonly Stream _underlying; /// /// create a new NutPacket /// - /// startcode for this packet + /// startCode for this packet /// stream to write to - public NutPacket(StartCode startcode, Stream underlying) + public NutPacket(StartCode startCode, Stream underlying) { - data = new MemoryStream(); - this.startcode = startcode; - this.underlying = underlying; + _data = new MemoryStream(); + _startCode = startCode; + _underlying = underlying; } - public override bool CanRead => false; public override bool CanSeek => false; @@ -265,38 +257,29 @@ namespace BizHawk.Client.EmuHawk { // first, prep header var header = new MemoryStream(); - WriteBE64((ulong)startcode, header); - WriteVarU(data.Length + 4, header); // +4 for checksum - if (data.Length > 4092) + WriteBe64((ulong)_startCode, header); + WriteVarU(_data.Length + 4, header); // +4 for checksum + if (_data.Length > 4092) { - WriteBE32(NutCRC32(header.ToArray()), header); + WriteBe32(NutCRC32(header.ToArray()), header); } var tmp = header.ToArray(); - underlying.Write(tmp, 0, tmp.Length); + _underlying.Write(tmp, 0, tmp.Length); - tmp = data.ToArray(); - underlying.Write(tmp, 0, tmp.Length); - WriteBE32(NutCRC32(tmp), underlying); + tmp = _data.ToArray(); + _underlying.Write(tmp, 0, tmp.Length); + WriteBe32(NutCRC32(tmp), _underlying); - data = null; + _data = null; } - public override long Length - { - get { throw new NotImplementedException(); } - } + public override long Length => throw new NotImplementedException(); public override long Position { - get - { - throw new NotImplementedException(); - } - set - { - throw new NotImplementedException(); - } + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); } public override int Read(byte[] buffer, int offset, int count) @@ -316,7 +299,7 @@ namespace BizHawk.Client.EmuHawk public override void Write(byte[] buffer, int offset, int count) { - data.Write(buffer, offset, count); + _data.Write(buffer, offset, count); } } @@ -325,59 +308,51 @@ namespace BizHawk.Client.EmuHawk /// /// stores basic AV parameters /// - class AVParams + private class AVParams { - public int width, height, samplerate, fpsnum, fpsden, channels; + public int Width { get; set; } + public int Height { get; set; } + public int Samplerate { get; set; } + public int FpsNum { get; set; } + public int FpsDen { get; set; } + public int Channels { get; set; } + /// - /// puts fpsnum, fpsden in lowest terms + /// puts fpsNum, fpsDen in lowest terms /// public void Reduce() { - int gcd = (int) BigInteger.GreatestCommonDivisor(new BigInteger(fpsnum), new BigInteger(fpsden)); - fpsnum /= gcd; - fpsden /= gcd; + int gcd = (int)BigInteger.GreatestCommonDivisor(new BigInteger(FpsNum), new BigInteger(FpsDen)); + FpsNum /= gcd; + FpsDen /= gcd; } } - /// - /// stores basic AV parameters - /// - AVParams avparams; + // stores basic AV parameters + private readonly AVParams _avParams; - /// - /// target output for nut stream - /// - Stream output; + // target output for nut stream + private Stream _output; - /// - /// PTS of video stream. timebase is 1/framerate, so this is equal to number of frames - /// - ulong videopts; + // PTS of video stream. timebase is 1/framerate, so this is equal to number of frames + private ulong _videoOpts; - /// - /// PTS of audio stream. timebase is 1/samplerate, so this is equal to number of samples - /// - ulong audiopts; + // PTS of audio stream. timebase is 1/samplerate, so this is equal to number of samples + private ulong _audioPts; - /// - /// has EOR been writen on this stream? - /// - bool videodone; - /// - /// has EOR been written on this stream? - /// - bool audiodone; + // has EOR been written on this stream? + private bool _videoDone; + + // has EOR been written on this stream? + private bool _audioDone; - /// - /// video packets waiting to be written - /// - Queue videoqueue; - /// - /// audio packets waiting to be written - /// - Queue audioqueue; + // video packets waiting to be written + private readonly Queue _videoQueue; + + // audio packets waiting to be written + private readonly Queue _audioQueue; - ReusableBufferPool _bufferpool = new ReusableBufferPool(12); + readonly ReusableBufferPool _bufferPool = new ReusableBufferPool(12); #endregion @@ -386,13 +361,13 @@ namespace BizHawk.Client.EmuHawk /// /// write out the main header /// - void writemainheader() + private void WriteMainHeader() { // note: this file starttag not actually part of main headers var tmp = Encoding.ASCII.GetBytes("nut/multimedia container\0"); - output.Write(tmp, 0, tmp.Length); + _output.Write(tmp, 0, tmp.Length); - var header = new NutPacket(NutPacket.StartCode.Main, output); + var header = new NutPacket(NutPacket.StartCode.Main, _output); WriteVarU(3, header); // version WriteVarU(2, header); // stream_count @@ -400,15 +375,15 @@ namespace BizHawk.Client.EmuHawk WriteVarU(2, header); // time_base_count // timebase is length of single frame, so reversed num+den is intentional - WriteVarU(avparams.fpsden, header); // time_base_num[0] - WriteVarU(avparams.fpsnum, header); // time_base_den[0] + WriteVarU(_avParams.FpsDen, header); // time_base_num[0] + WriteVarU(_avParams.FpsNum, header); // time_base_den[0] WriteVarU(1, header); // time_base_num[1] - WriteVarU(avparams.samplerate, header); // time_base_den[1] + WriteVarU(_avParams.Samplerate, header); // time_base_den[1] // frame flag compression is ignored for simplicity for (int i = 0; i < 255; i++) // not 256 because entry 0x4e is skipped (as it would indicate a startcode) { - WriteVarU((1 << 12), header); // tmp_flag = FLAG_CODED + WriteVarU(1 << 12, header); // tmp_flag = FLAG_CODED WriteVarU(0, header); // tmp_fields } @@ -421,12 +396,10 @@ namespace BizHawk.Client.EmuHawk header.Flush(); } - /// - /// write out the 0th stream header (video) - /// - void writevideoheader() + // write out the 0th stream header (video) + private void WriteVideoHeader() { - var header = new NutPacket(NutPacket.StartCode.Stream, output); + var header = new NutPacket(NutPacket.StartCode.Stream, _output); WriteVarU(0, header); // stream_id WriteVarU(0, header); // stream_class = video WriteString("BGRA", header); // fourcc = "BGRA" @@ -438,8 +411,8 @@ namespace BizHawk.Client.EmuHawk WriteBytes(new byte[0], header); // codec_specific_data // stream_class = video - WriteVarU(avparams.width, header); // width - WriteVarU(avparams.height, header); // height + WriteVarU(_avParams.Width, header); // width + WriteVarU(_avParams.Height, header); // height WriteVarU(1, header); // sample_width WriteVarU(1, header); // sample_height WriteVarU(18, header); // colorspace_type = full range rec709 (avisynth's "PC.709") @@ -447,26 +420,24 @@ namespace BizHawk.Client.EmuHawk header.Flush(); } - /// - /// write out the 1st stream header (audio) - /// - void writeaudioheader() + // write out the 1st stream header (audio) + private void WriteAudioHeader() { - var header = new NutPacket(NutPacket.StartCode.Stream, output); + var header = new NutPacket(NutPacket.StartCode.Stream, _output); WriteVarU(1, header); // stream_id WriteVarU(1, header); // stream_class = audio WriteString("\x01\x00\x00\x00", header); // fourcc = 01 00 00 00 WriteVarU(1, header); // time_base_id = 1 WriteVarU(8, header); // msb_pts_shift - WriteVarU(avparams.samplerate, header); // max_pts_distance + WriteVarU(_avParams.Samplerate, header); // max_pts_distance WriteVarU(0, header); // decode_delay WriteVarU(0, header); // stream_flags = none; no FIXED_FPS because we aren't guaranteeing same-size audio chunks WriteBytes(new byte[0], header); // codec_specific_data // stream_class = audio - WriteVarU(avparams.samplerate, header); // samplerate_num + WriteVarU(_avParams.Samplerate, header); // samplerate_num WriteVarU(1, header); // samplerate_den - WriteVarU(avparams.channels, header); // channel_count + WriteVarU(_avParams.Channels, header); // channel_count header.Flush(); } @@ -477,75 +448,84 @@ namespace BizHawk.Client.EmuHawk /// stores a single frame with syncpoint, in mux-ready form /// used because reordering of audio and video can be needed for proper interleave /// - class NutFrame + private class NutFrame { /// /// data ready to be written to stream/disk /// - byte[] data; + private readonly byte[] _data; /// /// valid length of the data /// - int actual_length; + private readonly int _actualLength; /// /// presentation timestamp /// - ulong pts; + private readonly ulong _pts; /// /// fraction of the specified timebase /// - ulong ptsnum, ptsden; + private readonly ulong _ptsNum; - ReusableBufferPool _pool; + /// + /// fraction of the specified timebase + /// + private readonly ulong _ptsDen; + + private readonly ReusableBufferPool _pool; /// frame data - /// actual length of frame data + /// actual length of frame data /// presentation timestamp - /// numerator of timebase - /// denominator of timebase - /// which timestamp base is used, assumed to be also stream number - public NutFrame(byte[] payload, int payloadlen, ulong pts, ulong ptsnum, ulong ptsden, int ptsindex, ReusableBufferPool pool) + /// numerator of timebase + /// denominator of timebase + /// which timestamp base is used, assumed to be also stream number + public NutFrame(byte[] payload, int payLoadLen, ulong pts, ulong ptsNum, ulong ptsDen, int ptsIndex, ReusableBufferPool pool) { - this.pts = pts; - this.ptsnum = ptsnum; - this.ptsden = ptsden; + _pts = pts; + _ptsNum = ptsNum; + _ptsDen = ptsDen; - this._pool = pool; - data = pool.GetBufferAtLeast(payloadlen + 2048); - var frame = new MemoryStream(data); + _pool = pool; + _data = pool.GetBufferAtLeast(payLoadLen + 2048); + var frame = new MemoryStream(_data); // create syncpoint var sync = new NutPacket(NutPacket.StartCode.Syncpoint, frame); - WriteVarU(pts * 2 + (ulong)ptsindex, sync); // global_key_pts + WriteVarU(pts * 2 + (ulong)ptsIndex, sync); // global_key_pts WriteVarU(1, sync); // back_ptr_div_16, this is wrong sync.Flush(); - var frameheader = new MemoryStream(); - frameheader.WriteByte(0); // frame_code + var frameHeader = new MemoryStream(); + frameHeader.WriteByte(0); // frame_code + // frame_flags = FLAG_CODED, so: int flags = 0; flags |= 1 << 0; // FLAG_KEY - if (payloadlen == 0) + if (payLoadLen == 0) + { flags |= 1 << 1; // FLAG_EOR + } + flags |= 1 << 3; // FLAG_CODED_PTS flags |= 1 << 4; // FLAG_STREAM_ID flags |= 1 << 5; // FLAG_SIZE_MSB flags |= 1 << 6; // FLAG_CHECKSUM - WriteVarU(flags, frameheader); - WriteVarU(ptsindex, frameheader); // stream_id - WriteVarU(pts + 256, frameheader); // coded_pts = pts + 1 << msb_pts_shift - WriteVarU(payloadlen, frameheader); // data_size_msb + WriteVarU(flags, frameHeader); + WriteVarU(ptsIndex, frameHeader); // stream_id + WriteVarU(pts + 256, frameHeader); // coded_pts = pts + 1 << msb_pts_shift + WriteVarU(payLoadLen, frameHeader); // data_size_msb - var frameheaderarr = frameheader.ToArray(); - frame.Write(frameheaderarr, 0, frameheaderarr.Length); - WriteBE32(NutCRC32(frameheaderarr), frame); // checksum - frame.Write(payload, 0, payloadlen); + var frameHeaderArr = frameHeader.ToArray(); + frame.Write(frameHeaderArr, 0, frameHeaderArr.Length); + WriteBe32(NutCRC32(frameHeaderArr), frame); // checksum + frame.Write(payload, 0, payLoadLen); - actual_length = (int)frame.Position; + _actualLength = (int)frame.Position; } /// @@ -553,19 +533,19 @@ namespace BizHawk.Client.EmuHawk /// public static bool operator <=(NutFrame lhs, NutFrame rhs) { - BigInteger left = new BigInteger(lhs.pts); - left = left * lhs.ptsnum * rhs.ptsden; - BigInteger right = new BigInteger(rhs.pts); - right = right * rhs.ptsnum * lhs.ptsden; + BigInteger left = new BigInteger(lhs._pts); + left = left * lhs._ptsNum * rhs._ptsDen; + BigInteger right = new BigInteger(rhs._pts); + right = right * rhs._ptsNum * lhs._ptsDen; return left <= right; } public static bool operator >=(NutFrame lhs, NutFrame rhs) { - BigInteger left = new BigInteger(lhs.pts); - left = left * lhs.ptsnum * rhs.ptsden; - BigInteger right = new BigInteger(rhs.pts); - right = right * rhs.ptsnum * lhs.ptsden; + BigInteger left = new BigInteger(lhs._pts); + left = left * lhs._ptsNum * rhs._ptsDen; + BigInteger right = new BigInteger(rhs._pts); + right = right * rhs._ptsNum * lhs._ptsDen; return left >= right; } @@ -575,9 +555,8 @@ namespace BizHawk.Client.EmuHawk /// public void WriteData(Stream dest) { - dest.Write(data, 0, actual_length); - _pool.ReleaseBuffer(data); - //dbg.WriteLine($"{pts},{ptsnum},{ptsden}"); + dest.Write(_data, 0, _actualLength); + _pool.ReleaseBuffer(_data); } } @@ -587,21 +566,26 @@ namespace BizHawk.Client.EmuHawk /// already written EOR public void WriteVideoFrame(int[] video) { - if (videodone) + if (_videoDone) throw new InvalidOperationException("Can't write data after end of relevance!"); - if (audioqueue.Count > 5) + if (_audioQueue.Count > 5) throw new Exception("A/V Desync?"); - int datalen = video.Length * sizeof(int); - byte[] data = _bufferpool.GetBufferAtLeast(datalen); - Buffer.BlockCopy(video, 0, data, 0, datalen); - if (datalen == 0) - videodone = true; - var f = new NutFrame(data, datalen, videopts, (ulong) avparams.fpsden, (ulong) avparams.fpsnum, 0, _bufferpool); - _bufferpool.ReleaseBuffer(data); - videopts++; - videoqueue.Enqueue(f); - while (audioqueue.Count > 0 && f >= audioqueue.Peek()) - audioqueue.Dequeue().WriteData(output); + int dataLen = video.Length * sizeof(int); + byte[] data = _bufferPool.GetBufferAtLeast(dataLen); + Buffer.BlockCopy(video, 0, data, 0, dataLen); + if (dataLen == 0) + { + _videoDone = true; + } + + var f = new NutFrame(data, dataLen, _videoOpts, (ulong) _avParams.FpsDen, (ulong) _avParams.FpsNum, 0, _bufferPool); + _bufferPool.ReleaseBuffer(data); + _videoOpts++; + _videoQueue.Enqueue(f); + while (_audioQueue.Count > 0 && f >= _audioQueue.Peek()) + { + _audioQueue.Dequeue().WriteData(_output); + } } /// write an audio frame to the stream @@ -610,22 +594,32 @@ namespace BizHawk.Client.EmuHawk /// already written EOR public void WriteAudioFrame(short[] samples) { - if (audiodone) + if (_audioDone) + { throw new Exception("Can't write audio after end of relevance!"); - if (videoqueue.Count > 5) - throw new Exception("A/V Desync?"); - int datalen = samples.Length * sizeof(short); - byte[] data = _bufferpool.GetBufferAtLeast(datalen); - Buffer.BlockCopy(samples, 0, data, 0, datalen); - if (datalen == 0) - audiodone = true; + } - var f = new NutFrame(data, datalen, audiopts, 1, (ulong)avparams.samplerate, 1, _bufferpool); - _bufferpool.ReleaseBuffer(data); - audiopts += (ulong)samples.Length / (ulong)avparams.channels; - audioqueue.Enqueue(f); - while (videoqueue.Count > 0 && f >= videoqueue.Peek()) - videoqueue.Dequeue().WriteData(output); + if (_videoQueue.Count > 5) + { + throw new Exception("A/V Desync?"); + } + + int dataLen = samples.Length * sizeof(short); + byte[] data = _bufferPool.GetBufferAtLeast(dataLen); + Buffer.BlockCopy(samples, 0, data, 0, dataLen); + if (dataLen == 0) + { + _audioDone = true; + } + + var f = new NutFrame(data, dataLen, _audioPts, 1, (ulong)_avParams.Samplerate, 1, _bufferPool); + _bufferPool.ReleaseBuffer(data); + _audioPts += (ulong)samples.Length / (ulong)_avParams.Channels; + _audioQueue.Enqueue(f); + while (_videoQueue.Count > 0 && f >= _videoQueue.Peek()) + { + _videoQueue.Dequeue().WriteData(_output); + } } /// @@ -633,35 +627,38 @@ namespace BizHawk.Client.EmuHawk /// /// video width /// video height - /// fps numerator - /// fps denominator + /// fps numerator + /// fps denominator /// audio samplerate /// audio number of channels /// Stream to write to - public NutMuxer(int width, int height, int fpsnum, int fpsden, int samplerate, int channels, Stream underlying) + public NutMuxer(int width, int height, int fpsNum, int fpsDen, int samplerate, int channels, Stream underlying) { - avparams = new AVParams(); - avparams.width = width; - avparams.height = height; - avparams.fpsnum = fpsnum; - avparams.fpsden = fpsden; - avparams.Reduce(); // timebases in nut MUST be relatively prime - avparams.samplerate = samplerate; - avparams.channels = channels; - output = underlying; + _avParams = new AVParams + { + Width = width, + Height = height, + FpsNum = fpsNum, + FpsDen = fpsDen + }; - audiopts = 0; - videopts = 0; + _avParams.Reduce(); // TimeBases in nut MUST be relatively prime + _avParams.Samplerate = samplerate; + _avParams.Channels = channels; + _output = underlying; - audioqueue = new Queue(); - videoqueue = new Queue(); + _audioPts = 0; + _videoOpts = 0; - writemainheader(); - writevideoheader(); - writeaudioheader(); + _audioQueue = new Queue(); + _videoQueue = new Queue(); - videodone = false; - audiodone = false; + WriteMainHeader(); + WriteVideoHeader(); + WriteAudioHeader(); + + _videoDone = false; + _audioDone = false; } /// @@ -670,26 +667,41 @@ namespace BizHawk.Client.EmuHawk /// public void Finish() { - if (!videodone) + if (!_videoDone) + { WriteVideoFrame(new int[0]); - if (!audiodone) + } + + if (!_audioDone) + { WriteAudioFrame(new short[0]); + } // flush any remaining queued packets - while (audioqueue.Count > 0 && videoqueue.Count > 0) + while (_audioQueue.Count > 0 && _videoQueue.Count > 0) { - if (audioqueue.Peek() <= videoqueue.Peek()) - audioqueue.Dequeue().WriteData(output); + if (_audioQueue.Peek() <= _videoQueue.Peek()) + { + _audioQueue.Dequeue().WriteData(_output); + } else - videoqueue.Dequeue().WriteData(output); + { + _videoQueue.Dequeue().WriteData(_output); + } } - while (audioqueue.Count > 0) - audioqueue.Dequeue().WriteData(output); - while (videoqueue.Count > 0) - videoqueue.Dequeue().WriteData(output); - output.Close(); - output = null; + while (_audioQueue.Count > 0) + { + _audioQueue.Dequeue().WriteData(_output); + } + + while (_videoQueue.Count > 0) + { + _videoQueue.Dequeue().WriteData(_output); + } + + _output.Close(); + _output = null; } } } diff --git a/BizHawk.Client.EmuHawk/AVOut/NutWriter.cs b/BizHawk.Client.EmuHawk/AVOut/NutWriter.cs index bdf0ce996f..251e29bbf9 100644 --- a/BizHawk.Client.EmuHawk/AVOut/NutWriter.cs +++ b/BizHawk.Client.EmuHawk/AVOut/NutWriter.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Windows.Forms; using BizHawk.Emulation.Common; @@ -10,12 +11,12 @@ namespace BizHawk.Client.EmuHawk /// uncompressed video and audio /// [VideoWriter("nut", "NUT writer", "Writes a series of .nut files to disk, a container format which can be opened by ffmpeg. All data is uncompressed. Splits occur on resolution changes. NOT RECCOMENDED FOR USE.")] - class NutWriter : IVideoWriter + public class NutWriter : IVideoWriter { /// /// dummy codec token class /// - class NutWriterToken : IDisposable + private class NutWriterToken : IDisposable { public void Dispose() { @@ -28,37 +29,36 @@ namespace BizHawk.Client.EmuHawk { // ignored } - public IDisposable AcquireVideoCodecToken(System.Windows.Forms.IWin32Window hwnd) + public IDisposable AcquireVideoCodecToken(IWin32Window hwnd) { return new NutWriterToken(); } - /// - /// avparams - /// - private int fpsnum, fpsden, width, height, sampleRate, channels; - private NutMuxer _current = null; + // avParams + private int _fpsNum, _fpsDen, _width, _height, _sampleRate, _channels; + + private NutMuxer _current; private string _baseName; private int _segment; public void OpenFile(string baseName) { _baseName = Path.Combine( - Path.GetDirectoryName(baseName), - Path.GetFileNameWithoutExtension(baseName)); + Path.GetDirectoryName(baseName) ?? "", + Path.GetFileNameWithoutExtension(baseName) ?? ""); _segment = 0; - startsegment(); + StartSegment(); } - private void startsegment() + private void StartSegment() { - var currentfile = File.Open($"{_baseName}_{_segment,4:D4}.nut", FileMode.Create, FileAccess.Write); - _current = new NutMuxer(width, height, fpsnum, fpsden, sampleRate, channels, currentfile); + var currentFile = File.Open($"{_baseName}_{_segment,4:D4}.nut", FileMode.Create, FileAccess.Write); + _current = new NutMuxer(_width, _height, _fpsNum, _fpsDen, _sampleRate, _channels, currentFile); } - private void endsegment() + private void EndSegment() { _current.Finish(); _current = null; @@ -66,12 +66,12 @@ namespace BizHawk.Client.EmuHawk public void CloseFile() { - endsegment(); + EndSegment(); } public void AddFrame(IVideoProvider source) { - if (source.BufferHeight != height || source.BufferWidth != width) + if (source.BufferHeight != _height || source.BufferWidth != _width) { SetVideoParameters(source.BufferWidth, source.BufferHeight); } @@ -84,27 +84,27 @@ namespace BizHawk.Client.EmuHawk _current.WriteAudioFrame(samples); } - public void SetMovieParameters(int fpsnum, int fpsden) + public void SetMovieParameters(int fpsNum, int fpsDen) { - this.fpsnum = fpsnum; - this.fpsden = fpsden; + _fpsNum = fpsNum; + _fpsDen = fpsDen; if (_current != null) { - endsegment(); + EndSegment(); _segment++; - startsegment(); + StartSegment(); } } public void SetVideoParameters(int width, int height) { - this.width = width; - this.height = height; + _width = width; + _height = height; if (_current != null) { - endsegment(); + EndSegment(); _segment++; - startsegment(); + StartSegment(); } } @@ -116,11 +116,11 @@ namespace BizHawk.Client.EmuHawk throw new ArgumentOutOfRangeException(nameof(bits), "Audio depth must be 16 bit!"); } - this.sampleRate = sampleRate; - this.channels = channels; + _sampleRate = sampleRate; + _channels = channels; } - public void SetMetaData(string gameName, string authors, ulong lengthMS, ulong rerecords) + public void SetMetaData(string gameName, string authors, ulong lengthMs, ulong rerecords) { // could be implemented? } @@ -129,16 +129,13 @@ namespace BizHawk.Client.EmuHawk { if (_current != null) { - endsegment(); + EndSegment(); } _baseName = null; } - public string DesiredExtension() - { - return "nut"; - } + public string DesiredExtension() => "nut"; public void SetDefaultVideoCodecToken() { diff --git a/BizHawk.Client.EmuHawk/AVOut/SynclessRecorder.cs b/BizHawk.Client.EmuHawk/AVOut/SynclessRecorder.cs index c0a969abc2..a2d5a9beb0 100644 --- a/BizHawk.Client.EmuHawk/AVOut/SynclessRecorder.cs +++ b/BizHawk.Client.EmuHawk/AVOut/SynclessRecorder.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Collections.Generic; +using System.Drawing.Imaging; using System.Text; using System.Windows.Forms; @@ -26,24 +27,24 @@ namespace BizHawk.Client.EmuHawk public void SetFrame(int frame) { - mCurrFrame = frame; + _mCurrFrame = frame; } - private int mCurrFrame; - private string mBaseDirectory, mFramesDirectory; - private string mProjectFile; + private int _mCurrFrame; + private string _mBaseDirectory, _mFramesDirectory; + private string _mProjectFile; public void OpenFile(string projFile) { - mProjectFile = projFile; - mBaseDirectory = Path.GetDirectoryName(mProjectFile); + _mProjectFile = projFile; + _mBaseDirectory = Path.GetDirectoryName(_mProjectFile) ?? ""; string basename = Path.GetFileNameWithoutExtension(projFile); string framesDirFragment = $"{basename}_frames"; - mFramesDirectory = Path.Combine(mBaseDirectory, framesDirFragment); - StringBuilder sb = new StringBuilder(); + _mFramesDirectory = Path.Combine(_mBaseDirectory, framesDirFragment); + var sb = new StringBuilder(); sb.AppendLine("version=1"); sb.AppendLine($"framesdir={framesDirFragment}"); - File.WriteAllText(mProjectFile, sb.ToString()); + File.WriteAllText(_mProjectFile, sb.ToString()); } public void CloseFile() @@ -53,17 +54,17 @@ namespace BizHawk.Client.EmuHawk public void AddFrame(IVideoProvider source) { using var bb = new BitmapBuffer(source.BufferWidth, source.BufferHeight, source.GetVideoBuffer()); - string subPath = GetAndCreatePathForFrameNum(mCurrFrame); + string subPath = GetAndCreatePathForFrameNum(_mCurrFrame); string path = $"{subPath}.png"; - bb.ToSysdrawingBitmap().Save(path, System.Drawing.Imaging.ImageFormat.Png); + bb.ToSysdrawingBitmap().Save(path, ImageFormat.Png); } public void AddSamples(short[] samples) { - string subPath = GetAndCreatePathForFrameNum(mCurrFrame); + string subPath = GetAndCreatePathForFrameNum(_mCurrFrame); string path = $"{subPath}.wav"; - WavWriterV wwv = new WavWriterV(); - wwv.SetAudioParameters(paramSampleRate, paramChannels, paramBits); + var wwv = new WavWriterV(); + wwv.SetAudioParameters(_paramSampleRate, _paramChannels, _paramBits); wwv.OpenFile(path); wwv.AddSamples(samples); wwv.CloseFile(); @@ -86,7 +87,7 @@ namespace BizHawk.Client.EmuHawk return new DummyDisposable(); } - public void SetMovieParameters(int fpsnum, int fpsden) + public void SetMovieParameters(int fpsNum, int fpsDen) { //should probably todo in here } @@ -96,24 +97,21 @@ namespace BizHawk.Client.EmuHawk // may want to todo } - private int paramSampleRate, paramChannels, paramBits; + private int _paramSampleRate, _paramChannels, _paramBits; public void SetAudioParameters(int sampleRate, int channels, int bits) { - paramSampleRate = sampleRate; - paramChannels = channels; - paramBits = bits; + _paramSampleRate = sampleRate; + _paramChannels = channels; + _paramBits = bits; } - public void SetMetaData(string gameName, string authors, ulong lengthMS, ulong rerecords) + public void SetMetaData(string gameName, string authors, ulong lengthMs, ulong rerecords) { // not needed } - public string DesiredExtension() - { - return "syncless.txt"; - } + public string DesiredExtension() => "syncless.txt"; /// /// splits the string into chunks of length s @@ -145,18 +143,18 @@ namespace BizHawk.Client.EmuHawk private string GetAndCreatePathForFrameNum(int index) { string subPath = GetPathFragmentForFrameNum(index); - string path = mFramesDirectory; + string path = _mFramesDirectory; path = Path.Combine(path, subPath); - string fpath = $"{path}.nothing"; - Directory.CreateDirectory(Path.GetDirectoryName(fpath)); + string fPath = $"{path}.nothing"; + Directory.CreateDirectory(Path.GetDirectoryName(fPath) ?? ""); return path; } public static string GetPathFragmentForFrameNum(int index) { var chunks = StringChunkSplit(index.ToString(), 2); - string subpath = string.Join("/", chunks); - return subpath; + string subPath = string.Join("/", chunks); + return subPath; } } } diff --git a/BizHawk.Client.EmuHawk/AVOut/SynclessRecordingTools.cs b/BizHawk.Client.EmuHawk/AVOut/SynclessRecordingTools.cs index 30438c9e07..a502825996 100644 --- a/BizHawk.Client.EmuHawk/AVOut/SynclessRecordingTools.cs +++ b/BizHawk.Client.EmuHawk/AVOut/SynclessRecordingTools.cs @@ -19,14 +19,14 @@ namespace BizHawk.Client.EmuHawk private void GetPaths(int index, out string png, out string wav) { string subPath = SynclessRecorder.GetPathFragmentForFrameNum(index); - string path = mFramesDirectory; + string path = _mFramesDirectory; path = Path.Combine(path, subPath); png = $"{path}.png"; wav = $"{path}.wav"; } - private string mSynclessConfigFile; - private string mFramesDirectory; + private string _mSynclessConfigFile; + private string _mFramesDirectory; public void Run() { @@ -41,12 +41,12 @@ namespace BizHawk.Client.EmuHawk return; } - mSynclessConfigFile = ofd.FileName; + _mSynclessConfigFile = ofd.FileName; //---- this is pretty crappy: - var lines = File.ReadAllLines(mSynclessConfigFile); + var lines = File.ReadAllLines(_mSynclessConfigFile); - string framesdir = ""; + string framesDir = ""; foreach (var line in lines) { int idx = line.IndexOf('='); @@ -54,11 +54,11 @@ namespace BizHawk.Client.EmuHawk string value = line.Substring(idx + 1, line.Length - (idx + 1)); if (key == "framesdir") { - framesdir = value; + framesDir = value; } } - mFramesDirectory = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(mSynclessConfigFile)), framesdir); + _mFramesDirectory = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(_mSynclessConfigFile)), framesDir); // scan frames directory int frame = 1; // hacky! skip frame 0, because we have a problem with dumping that frame somehow @@ -70,7 +70,7 @@ namespace BizHawk.Client.EmuHawk break; } - mFrameInfos.Add(new FrameInfo + _mFrameInfos.Add(new FrameInfo { pngPath = png, wavPath = wav @@ -82,7 +82,7 @@ namespace BizHawk.Client.EmuHawk ShowDialog(); } - private readonly List mFrameInfos = new List(); + private readonly List _mFrameInfos = new List(); struct FrameInfo { @@ -92,13 +92,13 @@ namespace BizHawk.Client.EmuHawk private void btnExport_Click(object sender, EventArgs e) { - if (mFrameInfos.Count == 0) + if (_mFrameInfos.Count == 0) { return; } int width, height; - using(var bmp = new Bitmap(mFrameInfos[0].pngPath)) + using(var bmp = new Bitmap(_mFrameInfos[0].pngPath)) { width = bmp.Width; height = bmp.Height; @@ -106,7 +106,7 @@ namespace BizHawk.Client.EmuHawk var sfd = new SaveFileDialog { - FileName = Path.ChangeExtension(mSynclessConfigFile, ".avi") + FileName = Path.ChangeExtension(_mSynclessConfigFile, ".avi") }; sfd.InitialDirectory = Path.GetDirectoryName(sfd.FileName); if (sfd.ShowDialog() == DialogResult.Cancel) @@ -121,7 +121,7 @@ namespace BizHawk.Client.EmuHawk var token = avw.AcquireVideoCodecToken(this); avw.SetVideoCodecToken(token); avw.OpenFile(sfd.FileName); - foreach (var fi in mFrameInfos) + foreach (var fi in _mFrameInfos) { using (var bb = new BitmapBuffer(fi.pngPath, new BitmapLoadOptions())) { @@ -133,13 +133,13 @@ namespace BizHawk.Client.EmuHawk var wavBytes = File.ReadAllBytes(fi.wavPath); var ms = new MemoryStream(wavBytes) { Position = 44 }; var br = new BinaryReader(ms); - var sampledata = new List(); + var sampleData = new List(); while (br.BaseStream.Position != br.BaseStream.Length) { - sampledata.Add(br.ReadInt16()); + sampleData.Add(br.ReadInt16()); } - avw.AddSamples(sampledata.ToArray()); + avw.AddSamples(sampleData.ToArray()); } avw.CloseFile(); diff --git a/BizHawk.Client.EmuHawk/AVOut/VideoWriterChooserForm.Designer.cs b/BizHawk.Client.EmuHawk/AVOut/VideoWriterChooserForm.Designer.cs index 923daaced3..a2ba908aac 100644 --- a/BizHawk.Client.EmuHawk/AVOut/VideoWriterChooserForm.Designer.cs +++ b/BizHawk.Client.EmuHawk/AVOut/VideoWriterChooserForm.Designer.cs @@ -62,7 +62,7 @@ this.checkBoxResize.TabIndex = 9; this.checkBoxResize.Text = "Resize Video"; this.checkBoxResize.UseVisualStyleBackColor = true; - this.checkBoxResize.CheckedChanged += new System.EventHandler(this.checkBoxResize_CheckedChanged); + this.checkBoxResize.CheckedChanged += new System.EventHandler(this.CheckBoxResize_CheckedChanged); // // listBox1 // @@ -73,7 +73,7 @@ this.listBox1.Name = "listBox1"; this.listBox1.Size = new System.Drawing.Size(329, 202); this.listBox1.TabIndex = 0; - this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged); + this.listBox1.SelectedIndexChanged += new System.EventHandler(this.ListBox1_SelectedIndexChanged); // // buttonOK // @@ -85,7 +85,7 @@ this.buttonOK.TabIndex = 1; this.buttonOK.Text = "OK"; this.buttonOK.UseVisualStyleBackColor = true; - this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click); + this.buttonOK.Click += new System.EventHandler(this.ButtonOK_Click); // // buttonCancel // @@ -161,7 +161,7 @@ this.buttonAuto.TabIndex = 14; this.buttonAuto.Text = "/\\ Set As Resize"; this.buttonAuto.UseVisualStyleBackColor = true; - this.buttonAuto.Click += new System.EventHandler(this.buttonAuto_Click); + this.buttonAuto.Click += new System.EventHandler(this.ButtonAuto_Click); // // panelSizeSelect // diff --git a/BizHawk.Client.EmuHawk/AVOut/VideoWriterChooserForm.cs b/BizHawk.Client.EmuHawk/AVOut/VideoWriterChooserForm.cs index 594a3a3f6e..a5c65a22fc 100644 --- a/BizHawk.Client.EmuHawk/AVOut/VideoWriterChooserForm.cs +++ b/BizHawk.Client.EmuHawk/AVOut/VideoWriterChooserForm.cs @@ -118,14 +118,14 @@ namespace BizHawk.Client.EmuHawk return ret; } - private void listBox1_SelectedIndexChanged(object sender, EventArgs e) + private void ListBox1_SelectedIndexChanged(object sender, EventArgs e) { labelDescriptionBody.Text = listBox1.SelectedIndex != -1 ? ((VideoWriterInfo)listBox1.SelectedItem).Attribs.Description : ""; } - private void checkBoxResize_CheckedChanged(object sender, EventArgs e) + private void CheckBoxResize_CheckedChanged(object sender, EventArgs e) { foreach (Control c in panelSizeSelect.Controls) { @@ -133,13 +133,13 @@ namespace BizHawk.Client.EmuHawk } } - private void buttonAuto_Click(object sender, EventArgs e) + private void ButtonAuto_Click(object sender, EventArgs e) { numericTextBoxW.Text = _captureWidth.ToString(); numericTextBoxH.Text = _captureHeight.ToString(); } - private void buttonOK_Click(object sender, EventArgs e) + private void ButtonOK_Click(object sender, EventArgs e) { if (checkBoxResize.Checked) { diff --git a/BizHawk.Client.EmuHawk/AVOut/WavWriter.cs b/BizHawk.Client.EmuHawk/AVOut/WavWriter.cs index ee0818d734..0975c53f33 100644 --- a/BizHawk.Client.EmuHawk/AVOut/WavWriter.cs +++ b/BizHawk.Client.EmuHawk/AVOut/WavWriter.cs @@ -17,121 +17,125 @@ namespace BizHawk.Client.EmuHawk /// /// underlying file being written to /// - BinaryWriter file; + private BinaryWriter _file; /// /// sequence of files to write to (split on 32 bit limit) /// - IEnumerator filechain; + private IEnumerator _fileChain; /// /// samplerate in HZ /// - int samplerate; + private int _sampleRate; /// /// number of audio channels /// - int numchannels; + private int _numChannels; /// /// number of bytes of PCM data written to current file /// - UInt64 numbytes; + private ulong _numBytes; /// /// number of bytes after which a file split should be made /// - const UInt64 splitpoint = 2 * 1000 * 1000 * 1000; + private const ulong SplitPoint = 2 * 1000 * 1000 * 1000; /// /// write riff headers to current file /// - private void writeheaders() + private void WriteHeaders() { - file.Write(Encoding.ASCII.GetBytes("RIFF")); // ChunkID - file.Write((uint)0); // ChunkSize - file.Write(Encoding.ASCII.GetBytes("WAVE")); // Format + _file.Write(Encoding.ASCII.GetBytes("RIFF")); // ChunkID + _file.Write((uint)0); // ChunkSize + _file.Write(Encoding.ASCII.GetBytes("WAVE")); // Format - file.Write(Encoding.ASCII.GetBytes("fmt ")); // SubchunkID - file.Write((uint)16); // SubchunkSize - file.Write((ushort)1); // AudioFormat (PCM) - file.Write((ushort)numchannels); // NumChannels - file.Write((uint)samplerate); // SampleRate - file.Write((uint)(samplerate * numchannels * 2)); // ByteRate - file.Write((ushort)(numchannels * 2)); // BlockAlign - file.Write((ushort)16); // BitsPerSample + _file.Write(Encoding.ASCII.GetBytes("fmt ")); // SubchunkID + _file.Write((uint)16); // SubchunkSize + _file.Write((ushort)1); // AudioFormat (PCM) + _file.Write((ushort)_numChannels); // NumChannels + _file.Write((uint)_sampleRate); // SampleRate + _file.Write((uint)(_sampleRate * _numChannels * 2)); // ByteRate + _file.Write((ushort)(_numChannels * 2)); // BlockAlign + _file.Write((ushort)16); // BitsPerSample - file.Write(Encoding.ASCII.GetBytes("data")); // SubchunkID - file.Write((uint)0); // SubchunkSize + _file.Write(Encoding.ASCII.GetBytes("data")); // SubchunkID + _file.Write((uint)0); // SubchunkSize } /// /// seek back to beginning of file and fix header sizes (if possible) /// - private void finalizeheaders() + private void FinalizeHeaders() { - if (numbytes + 36 >= 0x100000000) + if (_numBytes + 36 >= 0x100000000) + { // passed 4G limit, nothing to be done return; + } + try { - file.Seek(4, SeekOrigin.Begin); - file.Write((uint)(36 + numbytes)); - file.Seek(40, SeekOrigin.Begin); - file.Write((uint)(numbytes)); + _file.Seek(4, SeekOrigin.Begin); + _file.Write((uint)(36 + _numBytes)); + _file.Seek(40, SeekOrigin.Begin); + _file.Write((uint)(_numBytes)); } catch (NotSupportedException) - { // unseekable; oh well + { + // unseekable; oh well } } /// /// close current underlying stream /// - private void closecurrent() + private void CloseCurrent() { - if (file != null) + if (_file != null) { - finalizeheaders(); - file.Close(); - file.Dispose(); + FinalizeHeaders(); + _file.Close(); + _file.Dispose(); } - file = null; + _file = null; } /// /// open a new underlying stream /// - private void opencurrent(Stream next) + private void OpenCurrent(Stream next) { - file = new BinaryWriter(next, Encoding.ASCII); - numbytes = 0; - writeheaders(); + _file = new BinaryWriter(next, Encoding.ASCII); + _numBytes = 0; + WriteHeaders(); } /// /// write samples to file /// /// samples to write; should contain one for each channel - public void writesamples(short[] samples) + public void WriteSamples(short[] samples) { - file.Write(samples); - numbytes += (ulong)(samples.Length * sizeof(short)); + _file.Write(samples); + _numBytes += (ulong)(samples.Length * sizeof(short)); // try splitting if we can - if (numbytes >= splitpoint && filechain != null) + if (_numBytes >= SplitPoint && _fileChain != null) { - if (!filechain.MoveNext()) + if (!_fileChain.MoveNext()) { // out of files, just keep on writing to this one - filechain = null; + _fileChain = null; } else { - Stream next = filechain.Current; - closecurrent(); - opencurrent(next); + Stream next = _fileChain.Current; + CloseCurrent(); + OpenCurrent(next); } } } @@ -146,15 +150,15 @@ namespace BizHawk.Client.EmuHawk /// public void Close() { - closecurrent(); + CloseCurrent(); } /// /// checks sampling rate, number of channels for validity /// - private void checkargs() + private void CheckArgs() { - if (samplerate < 1 || numchannels < 1) + if (_sampleRate < 1 || _numChannels < 1) { throw new ArgumentException("Bad samplerate/numchannels"); } @@ -165,15 +169,15 @@ namespace BizHawk.Client.EmuHawk /// no attempt is made to split /// /// WavWriter now owns this stream - /// sampling rate in HZ - /// number of audio channels - public WavWriter(Stream s, int samplerate, int numchannels) + /// sampling rate in HZ + /// number of audio channels + public WavWriter(Stream s, int sampleRate, int numChannels) { - this.samplerate = samplerate; - this.numchannels = numchannels; - filechain = null; - checkargs(); - opencurrent(s); + _sampleRate = sampleRate; + _numChannels = numChannels; + _fileChain = null; + CheckArgs(); + OpenCurrent(s); } /// @@ -182,23 +186,23 @@ namespace BizHawk.Client.EmuHawk /// if the enumerator runs out before the audio stream does, the last file could be >2G /// /// WavWriter now owns any of these streams that it enumerates - /// sampling rate in HZ - /// number of audio channels + /// sampling rate in HZ + /// number of audio channels /// cannot be progressed - public WavWriter(IEnumerator ss, int samplerate, int numchannels) + public WavWriter(IEnumerator ss, int sampleRate, int numChannels) { - this.samplerate = samplerate; - this.numchannels = numchannels; - checkargs(); - filechain = ss; + _sampleRate = sampleRate; + _numChannels = numChannels; + CheckArgs(); + _fileChain = ss; // advance to first - if (!filechain.MoveNext()) + if (!_fileChain.MoveNext()) { throw new ArgumentException("Iterator was empty!"); } - opencurrent(ss.Current); + OpenCurrent(ss.Current); } } @@ -210,7 +214,7 @@ namespace BizHawk.Client.EmuHawk { public void SetVideoCodecToken(IDisposable token) { } public void AddFrame(IVideoProvider source) { } - public void SetMovieParameters(int fpsnum, int fpsden) { } + public void SetMovieParameters(int fpsNum, int fpsDen) { } public void SetVideoParameters(int width, int height) { } public void SetFrame(int frame) { } @@ -232,35 +236,35 @@ namespace BizHawk.Client.EmuHawk /// is not 16 public void SetAudioParameters(int sampleRate, int channels, int bits) { - this.sampleRate = sampleRate; - this.channels = channels; + this._sampleRate = sampleRate; + this._channels = channels; if (bits != 16) { throw new ArgumentException("Only support 16bit audio!"); } } - public void SetMetaData(string gameName, string authors, ulong lengthMS, ulong rerecords) + public void SetMetaData(string gameName, string authors, ulong lengthMs, ulong rerecords) { // not implemented } public void Dispose() { - wavwriter?.Dispose(); + _wavWriter?.Dispose(); } - private WavWriter wavwriter = null; - private int sampleRate = 0; - private int channels = 0; + private WavWriter _wavWriter; + private int _sampleRate; + private int _channels; /// /// create a simple wav stream iterator /// private static IEnumerator CreateStreamIterator(string template) { - string dir = Path.GetDirectoryName(template); - string baseName = Path.GetFileNameWithoutExtension(template); + string dir = Path.GetDirectoryName(template) ?? ""; + string baseName = Path.GetFileNameWithoutExtension(template) ?? ""; string ext = Path.GetExtension(template); yield return new FileStream(template, FileMode.Create); int counter = 1; @@ -273,25 +277,22 @@ namespace BizHawk.Client.EmuHawk public void OpenFile(string baseName) { - wavwriter = new WavWriter(CreateStreamIterator(baseName), sampleRate, channels); + _wavWriter = new WavWriter(CreateStreamIterator(baseName), _sampleRate, _channels); } public void CloseFile() { - wavwriter.Close(); - wavwriter.Dispose(); - wavwriter = null; + _wavWriter.Close(); + _wavWriter.Dispose(); + _wavWriter = null; } public void AddSamples(short[] samples) { - wavwriter.writesamples(samples); + _wavWriter.WriteSamples(samples); } - public string DesiredExtension() - { - return "wav"; - } + public string DesiredExtension() => "wav"; public void SetDefaultVideoCodecToken() { diff --git a/BizHawk.sln.DotSettings b/BizHawk.sln.DotSettings index 839260d942..f906baeba0 100644 --- a/BizHawk.sln.DotSettings +++ b/BizHawk.sln.DotSettings @@ -184,6 +184,7 @@ True True True + True True True True @@ -191,6 +192,7 @@ True True True + True True True True @@ -204,7 +206,9 @@ True True True + True True + True True True True @@ -230,6 +234,7 @@ True True True + True True True True @@ -239,6 +244,7 @@ True True True + True True True True @@ -297,11 +303,13 @@ True True True + True True True True True True + True True True True @@ -338,6 +346,7 @@ True True True + True True True True @@ -352,14 +361,18 @@ True True True + True True True + True True True True True True + True True + True True True True @@ -382,6 +395,7 @@ True True True + True True True True