diff --git a/NAudio.Core/NAudio.Core.csproj b/NAudio.Core/NAudio.Core.csproj index e122e9e9..3288fa0b 100644 --- a/NAudio.Core/NAudio.Core.csproj +++ b/NAudio.Core/NAudio.Core.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.0;netcoreapp3.0 Mark Heath 2.1.0 true diff --git a/NAudio.Core/Wave/WaveProviders/SilenceWaveProvider.cs b/NAudio.Core/Wave/WaveProviders/SilenceWaveProvider.cs index 1e187941..19bee898 100644 --- a/NAudio.Core/Wave/WaveProviders/SilenceWaveProvider.cs +++ b/NAudio.Core/Wave/WaveProviders/SilenceWaveProvider.cs @@ -1,5 +1,9 @@ using System; -using System.Linq; + +#if NETCOREAPP3_0_OR_GREATER +using System.Runtime.Intrinsics.X86; +using System.Runtime.Intrinsics; +#endif // ReSharper disable once CheckNamespace namespace NAudio.Wave @@ -16,14 +20,87 @@ public class SilenceProvider : IWaveProvider /// Desired WaveFormat (should be PCM / IEE float public SilenceProvider(WaveFormat wf) { WaveFormat = wf; } +#if NETCOREAPP3_0_OR_GREATER + /// + /// Read silence into the . + /// + /// The array to fill with silence. + /// The offset into the given where we will start filling with silence. + /// The number of bytes in the given to fill with silence. + /// buffer is null + /// + /// offset is less than the lower bound of array. -or- count is less than zero. -or- + /// The sum of offset and count is greater than the size of the buffer. + /// + public unsafe int Read(byte[] buffer, int offset, int count) + { + if (buffer == null) + throw new ArgumentNullException(nameof(buffer), $"{nameof(buffer)} is null"); + if (count < 0) + throw new ArgumentException("Count cannot be less than zero.", nameof(count)); + if (offset < 0) + throw new ArgumentException("Offset cannot be less than zero.", nameof(offset)); + if (offset + count > buffer.Length) + throw new IndexOutOfRangeException($"The sum of {nameof(offset)} and {nameof(count)} cannot be greater than the size of the {nameof(buffer)}."); + + fixed (byte* bufferBytes = buffer) + { + byte* bufferBytesWithOffset = bufferBytes + offset; + byte* topAddress = bufferBytesWithOffset + count; + + byte* ptr = bufferBytesWithOffset; + + if (Avx.IsSupported) + { + // We must ensure that the address range we are affecting is a multiple of 32 bytes (256 bits) + byte* topAddress256Aligned = topAddress; + topAddress256Aligned -= (topAddress - bufferBytesWithOffset) % 32; + + Vector256 zeroVec = Vector256.Zero; + while (ptr < topAddress256Aligned) + { + Avx.Store(ptr, zeroVec); + ptr += 32; + } + } + + if (Sse2.IsSupported) + { + // We must ensure that the address range we are affecting is a multiple of 16 bytes (128 bits) + byte* topAddress128Aligned = topAddress; + topAddress128Aligned -= (topAddress - bufferBytesWithOffset) % 16; + + Vector128 zeroVec = Vector128.Zero; + while (ptr < topAddress128Aligned) + { + Sse2.Store(ptr, zeroVec); + ptr += 16; + } + } + + // Clear any remaining bytes with a standard loop + while (ptr < topAddress) + { + *ptr = 0; + ptr++; + } + } + + return count; + } +#else /// - /// Read silence from into the buffer + /// Read silence into the . /// + /// The array to fill with silence. + /// The offset into the given where we will start filling with silence. + /// The number of bytes in the given to fill with silence. public int Read(byte[] buffer, int offset, int count) { Array.Clear(buffer, offset, count); return count; } +#endif /// /// WaveFormat of this silence producing wave provider