Skip to content

Commit

Permalink
+ Added FastMix
Browse files Browse the repository at this point in the history
  • Loading branch information
MineCake147E committed Jul 6, 2019
1 parent 3165784 commit adf6e4a
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
9 changes: 9 additions & 0 deletions MonoAudio.Core/MonoAudio.Core.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions MonoAudio.Core/SystemExtensions/Memory/SpanExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,5 +143,41 @@ public static void FastScalarMultiply(this Span<float> span, float scale = defau
}
}
}

/// <summary>
/// Mixes the <paramref name="samplesToMix"/> to <paramref name="buffer"/>.
/// </summary>
/// <param name="samplesToMix">The samples to add.</param>
/// <param name="buffer">The buffer.</param>
/// <param name="scale">The scale to scale <paramref name="samplesToMix"/>.</param>
/// <exception cref="ArgumentException">samplesToMix</exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void FastMix(ReadOnlySpan<float> samplesToMix, Span<float> buffer, float scale)
{
if (samplesToMix.Length > buffer.Length) throw new ArgumentException("", nameof(samplesToMix));
unsafe
{
(int newLength, int remainder) = MathI.FloorStepRem(samplesToMix.Length, Vector<float>.Count);
if (newLength != 0)
{
var scaleV = new Vector<float>(scale);
var src = MemoryMarshal.Cast<float, Vector<float>>(samplesToMix);
var dst = MemoryMarshal.Cast<float, Vector<float>>(buffer);
for (int i = 0; i < src.Length; i++)
{
dst[i] += src[i] * scaleV;
}
}
if (remainder != 0)
{
var srcRem = samplesToMix.Slice(newLength);
var dstRem = buffer.Slice(newLength);
for (int i = 0; i < srcRem.Length; i++)
{
dstRem[i] += srcRem[i] * scale;
}
}
}
}
}
}
64 changes: 64 additions & 0 deletions Tests/MonoAudio.Core.Tests.CoreFx/SpanExtensionsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,5 +173,69 @@ public void FastScalarMultiplyFasterThanUnsafe(int length)
Console.WriteLine($"{nameof(SpanExtensions.FastScalarMultiply)} seems to be {(double)cntFast / cntStandard} times faster than unsafe loop.");
Assert.Greater(cntFast, cntStandard);
}

[Test]
public void FastMixMixesCorrectly()
{
Span<float> source = stackalloc float[32];
Span<float> destination = stackalloc float[48];
const int Value = 1;
source.FastFill(Value);
destination.FastFill(-1);

SpanExtensions.FastMix(source, destination, 2);
for (int i = 0; i < source.Length; i++)
{
if (destination[i] != 1) Assert.Fail("The FastMix doesn't mix correctly!");
}
Assert.Pass();
}

[TestCase(2459)] //Prime number
[TestCase(2048)] //2^11
public void FastMixFasterThanUnsafeMix(int length)
{
var sw = new Stopwatch();
Span<float> source = stackalloc float[length];
Span<float> destination = stackalloc float[length + 1024];
source.FastFill(1);
destination.FastFill(0);
long cntFast = 0;
long cntStandard = 0;
Thread.Sleep(50);
sw.Start();
do
{
SpanExtensions.FastMix(source, destination, 1.0f / cntFast);
cntFast++;
} while (sw.ElapsedMilliseconds < length);
sw.Stop();
Console.WriteLine(cntFast);
sw.Reset();
Thread.Sleep(50);
sw.Start();
do
{
var u = 1.0f / cntStandard;
unsafe
{
fixed (float* srcFx = source)
fixed (float* dstFx = destination)
{
var src = srcFx;
var dst = dstFx;
do
{
*dst++ += (*src++) * u;
} while (src < srcFx + source.Length);
}
}
cntStandard++;
} while (sw.ElapsedMilliseconds < length);
sw.Stop();
Console.WriteLine(cntStandard);
Console.WriteLine($"{nameof(SpanExtensions.FastAdd)} seems to be {(double)cntFast / cntStandard} times faster than unsafe loop.");
Assert.Greater(cntFast, cntStandard);
}
}
}

0 comments on commit adf6e4a

Please sign in to comment.