From e4a6d7136810ed70656f22475bf1a7f12b47cc76 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Sun, 23 Jun 2024 12:54:37 +0700 Subject: [PATCH] Added a more accurate comparison of floating point variables. Added skipped memory release. --- NAudio.Core/Dsp/WdlResampler.cs | 7 +++-- NAudio.Core/Extensions.cs | 29 +++++++++++++++++++ .../FileFormats/SoundFont/SoundFont.cs | 2 +- NAudio.Core/Utils/IEEE.cs | 5 ++-- .../SampleProviders/VolumeSampleProvider.cs | 6 ++-- .../Wave/WaveOutputs/AiffFileWriter.cs | 2 ++ .../Wave/WaveOutputs/DirectSoundOut.cs | 12 ++++---- .../Wave/WaveOutputs/WaveFileWriter.cs | 1 + .../WaveProviders/VolumeWaveProvider16.cs | 9 +++--- NAudio.Core/Wave/WaveStreams/WaveChannel32.cs | 15 +++++----- 10 files changed, 63 insertions(+), 25 deletions(-) create mode 100644 NAudio.Core/Extensions.cs diff --git a/NAudio.Core/Dsp/WdlResampler.cs b/NAudio.Core/Dsp/WdlResampler.cs index 2693401f..b27fceef 100644 --- a/NAudio.Core/Dsp/WdlResampler.cs +++ b/NAudio.Core/Dsp/WdlResampler.cs @@ -23,6 +23,7 @@ // 3. This notice may not be removed or altered from any source distribution. +using NAudio.Core; using System; // default to floats for audio samples @@ -129,7 +130,7 @@ public void SetRates(double rate_in, double rate_out) { if (rate_in < 1.0) rate_in = 1.0; if (rate_out < 1.0) rate_out = 1.0; - if (rate_in != m_sratein || rate_out != m_srateout) + if (!rate_in.AreEqual(m_sratein) || !rate_out.AreEqual(m_srateout)) { m_sratein = rate_in; m_srateout = rate_out; @@ -193,7 +194,7 @@ public int ResamplePrepare(int out_samples, int nch, out WDL_ResampleSample[] in if (sreq < 0) sreq = 0; - again: + again: Array.Resize(ref m_rsinbuf, (m_samples_in_rsinbuf + sreq) * nch); int sz = m_rsinbuf.Length / ((nch != 0) ? nch : 1) - m_samples_in_rsinbuf; @@ -488,7 +489,7 @@ private void BuildLowPass(double filtpos) int wantsize = m_sincsize; int wantinterp = m_sincoversize; - if (m_filter_ratio != filtpos || + if (!m_filter_ratio.AreEqual(filtpos) || m_filter_coeffs_size != wantsize || m_lp_oversize != wantinterp) { diff --git a/NAudio.Core/Extensions.cs b/NAudio.Core/Extensions.cs new file mode 100644 index 00000000..ec4b96f0 --- /dev/null +++ b/NAudio.Core/Extensions.cs @@ -0,0 +1,29 @@ +using System; + +namespace NAudio.Core +{ + public static class Extensions + { + private const double Epsilon = 0.001; + + /// + /// Returns true if the floating-point values are equal within the specified margin of error. + /// + /// First value. + /// Second value. + public static bool AreEqual(this double val1, double val2) + { + return Math.Abs(val1 - val2) < Epsilon; + } + + /// + /// Returns true if the floating-point values are equal within the specified margin of error. + /// + /// First value. + /// Second value. + public static bool AreEqual(this float val1, float val2) + { + return Math.Abs(val1 - val2) < Epsilon; + } + } +} diff --git a/NAudio.Core/FileFormats/SoundFont/SoundFont.cs b/NAudio.Core/FileFormats/SoundFont/SoundFont.cs index 3b677698..2ed3169b 100644 --- a/NAudio.Core/FileFormats/SoundFont/SoundFont.cs +++ b/NAudio.Core/FileFormats/SoundFont/SoundFont.cs @@ -38,7 +38,7 @@ public SoundFont(Stream sfFile) throw new InvalidDataException(String.Format("Not a SoundFont ({0})", formHeader)); } RiffChunk list = riff.GetNextSubChunk(); - if (list.ChunkID == "LIST") + if (list != null && list.ChunkID == "LIST") { //RiffChunk r = list.GetNextSubChunk(); info = new InfoChunk(list); diff --git a/NAudio.Core/Utils/IEEE.cs b/NAudio.Core/Utils/IEEE.cs index f6832750..3d1ec867 100644 --- a/NAudio.Core/Utils/IEEE.cs +++ b/NAudio.Core/Utils/IEEE.cs @@ -1,4 +1,5 @@ -using System; +using NAudio.Core; +using System; namespace NAudio.Utils @@ -56,7 +57,7 @@ public static byte[] ConvertToIeeeExtended(double num) sign = 0; } - if (num == 0) + if (num.AreEqual(0)) { expon = 0; hiMant = 0; loMant = 0; } diff --git a/NAudio.Core/Wave/SampleProviders/VolumeSampleProvider.cs b/NAudio.Core/Wave/SampleProviders/VolumeSampleProvider.cs index 6deac089..40fc484f 100644 --- a/NAudio.Core/Wave/SampleProviders/VolumeSampleProvider.cs +++ b/NAudio.Core/Wave/SampleProviders/VolumeSampleProvider.cs @@ -1,4 +1,6 @@ -namespace NAudio.Wave.SampleProviders +using NAudio.Core; + +namespace NAudio.Wave.SampleProviders { /// /// Very simple sample provider supporting adjustable gain @@ -32,7 +34,7 @@ public VolumeSampleProvider(ISampleProvider source) public int Read(float[] buffer, int offset, int sampleCount) { int samplesRead = source.Read(buffer, offset, sampleCount); - if (Volume != 1f) + if (!Volume.AreEqual(1f)) { for (int n = 0; n < sampleCount; n++) { diff --git a/NAudio.Core/Wave/WaveOutputs/AiffFileWriter.cs b/NAudio.Core/Wave/WaveOutputs/AiffFileWriter.cs index 8cf56d77..ead679db 100644 --- a/NAudio.Core/Wave/WaveOutputs/AiffFileWriter.cs +++ b/NAudio.Core/Wave/WaveOutputs/AiffFileWriter.cs @@ -333,6 +333,8 @@ protected override void Dispose(bool disposing) // the GC thread if the code above caused an IOException (e.g. due to disk full) outStream.Dispose(); // will close the underlying base stream outStream = null; + writer.Dispose(); + writer = null; } } } diff --git a/NAudio.Core/Wave/WaveOutputs/DirectSoundOut.cs b/NAudio.Core/Wave/WaveOutputs/DirectSoundOut.cs index 0c14e3fa..e2b69453 100644 --- a/NAudio.Core/Wave/WaveOutputs/DirectSoundOut.cs +++ b/NAudio.Core/Wave/WaveOutputs/DirectSoundOut.cs @@ -1,4 +1,5 @@ -using System; +using NAudio.Core; +using System; using System.Runtime.InteropServices; using System.Security; using System.Threading; @@ -46,7 +47,8 @@ public class DirectSoundOut : IWavePlayer /// public static IEnumerable Devices { - get { + get + { devices = new List(); DirectSoundEnumerate(new DSEnumCallback(EnumCallback), IntPtr.Zero); return devices; @@ -355,7 +357,7 @@ public float Volume } set { - if (value != 1.0f) + if (!value.AreEqual(1.0f)) { throw new InvalidOperationException("Setting volume not supported on DirectSoundOut, adjust the volume on your WaveProvider instead"); } @@ -680,7 +682,7 @@ private int Feed(int bytesToCopy) //---------------------------------------------------------------------------------------------- // Minimal Native DirectSound COM interop interfaces //---------------------------------------------------------------------------------------------- -#region Native DirectSound COM Interface + #region Native DirectSound COM Interface [StructLayout(LayoutKind.Sequential, Pack = 2)] internal class BufferDescription @@ -915,7 +917,7 @@ internal interface IDirectSoundNotify /// HANDLE of the Desktop window [DllImport("user32.dll")] private static extern IntPtr GetDesktopWindow(); -#endregion + #endregion } /// diff --git a/NAudio.Core/Wave/WaveOutputs/WaveFileWriter.cs b/NAudio.Core/Wave/WaveOutputs/WaveFileWriter.cs index a6b99d82..cab9e279 100644 --- a/NAudio.Core/Wave/WaveOutputs/WaveFileWriter.cs +++ b/NAudio.Core/Wave/WaveOutputs/WaveFileWriter.cs @@ -387,6 +387,7 @@ protected override void Dispose(bool disposing) // the GC thread if the code above caused an IOException (e.g. due to disk full) outStream.Dispose(); // will close the underlying base stream outStream = null; + writer.Dispose(); } } } diff --git a/NAudio.Core/Wave/WaveProviders/VolumeWaveProvider16.cs b/NAudio.Core/Wave/WaveProviders/VolumeWaveProvider16.cs index 2a9650c9..fe486856 100644 --- a/NAudio.Core/Wave/WaveProviders/VolumeWaveProvider16.cs +++ b/NAudio.Core/Wave/WaveProviders/VolumeWaveProvider16.cs @@ -1,6 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Text; +using NAudio.Core; +using System; namespace NAudio.Wave { @@ -55,14 +54,14 @@ public int Read(byte[] buffer, int offset, int count) { // always read from the source int bytesRead = sourceProvider.Read(buffer, offset, count); - if (this.volume == 0.0f) + if (this.volume.AreEqual(0.0f)) { for (int n = 0; n < bytesRead; n++) { buffer[offset++] = 0; } } - else if (this.volume != 1.0f) + else if (!this.volume.AreEqual(1.0f)) { for (int n = 0; n < bytesRead; n += 2) { diff --git a/NAudio.Core/Wave/WaveStreams/WaveChannel32.cs b/NAudio.Core/Wave/WaveStreams/WaveChannel32.cs index b1b85f36..05a36710 100644 --- a/NAudio.Core/Wave/WaveStreams/WaveChannel32.cs +++ b/NAudio.Core/Wave/WaveStreams/WaveChannel32.cs @@ -1,5 +1,6 @@ -using System; +using NAudio.Core; using NAudio.Wave.SampleProviders; +using System; namespace NAudio.Wave { @@ -32,7 +33,7 @@ public WaveChannel32(WaveStream sourceStream, float volume, float pan) { PadWithZeroes = true; - var providers = new ISampleChunkConverter[] + var providers = new ISampleChunkConverter[] { new Mono8SampleChunkConverter(), new Stereo8SampleChunkConverter(), @@ -56,7 +57,7 @@ public WaveChannel32(WaveStream sourceStream, float volume, float pan) { throw new ArgumentException("Unsupported sourceStream format"); } - + // always outputs stereo 32 bit waveFormat = WaveFormat.CreateIeeeFloatWaveFormat(sourceStream.WaveFormat.SampleRate, 2); destBytesPerSample = 8; // includes stereo factoring @@ -147,7 +148,7 @@ public override int Read(byte[] destBuffer, int offset, int numBytes) // 1. fill with silence if (position < 0) { - bytesWritten = (int) Math.Min(numBytes, 0 - position); + bytesWritten = (int)Math.Min(numBytes, 0 - position); for (int n = 0; n < bytesWritten; n++) destBuffer[n + offset] = 0; } @@ -185,7 +186,7 @@ public override int Read(byte[] destBuffer, int offset, int numBytes) /// If true, Read always returns the number of bytes requested /// public bool PadWithZeroes { get; set; } - + /// /// @@ -223,7 +224,7 @@ public override bool HasData(int count) { if (position + count < 0) return false; - return (position < length) && (volume != 0); + return (position < length) && (!volume.AreEqual(0)); } return false; } @@ -254,7 +255,7 @@ protected override void Dispose(bool disposing) public event EventHandler Sample; // reuse the same object every time to avoid making lots of work for the garbage collector - private SampleEventArgs sampleEventArgs = new SampleEventArgs(0,0); + private SampleEventArgs sampleEventArgs = new SampleEventArgs(0, 0); /// /// Raise the sample event (no check for null because it has already been done)