Skip to content

Instantly share code, notes, and snippets.

@ArcticEcho
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ArcticEcho/185ee36167d89bcdc55b to your computer and use it in GitHub Desktop.
Save ArcticEcho/185ee36167d89bcdc55b to your computer and use it in GitHub Desktop.
// Read32BitSamples is called first.
private float[] Read32BitSamples(FileStream stream, int sampleStartIndex, int sampleEndIndex)
{
var bytesLength = 0;
var allocation = ReadBytes(stream, sampleStartIndex, sampleEndIndex, out bytesLength);
var bytes = (byte*)allocation.Allocation;
var samples = new float[bytesLength / 4];
if (audioFormat == WavFormat.PCM)
{
for (var i = 0; i < bytesLength; i += 4)
{
samples[i / 4] = (bytes[i] | bytes[i + 1] << 8 | bytes[i + 2] << 16 | bytes[i + 3] << 24) / 2147483648f;
}
}
else
{
for (var i = 0; i < bytesLength; i += 4)
{
var temp = bytes[i] | bytes[i + 1] << 8 | bytes[i + 2] << 16 | bytes[i + 3] << 24;
samples[i / 4] = *(float*)&temp;
}
}
allocation.Dispose();
return samples;
}
private StackAllocation ReadBytes(FileStream stream, int startIndex, int endIndex, out int outputBytesCount)
{
var ch = ChannelPosition.GetChannelNumber();
var byteDepth = bitDepth / 8;
var a = startIndex + ch;
var b = (endIndex * channels * byteDepth) + ch;
outputBytesCount = b - a;
var c = byteDepth * channels;
var temp = new byte[outputBytesCount * channels + byteDepth];
var selectedBytes = (byte*)allocator.AllocateBytes(outputBytesCount).Allocation;
stream.Position = headerSize;
stream.Read(temp, 0, outputBytesCount * channels);
if (audioFormat == WavFormat.PCM)
{
for (; a < b; a += c)
{
for (var ii = byteDepth + a; ii > a; ii--)
{
selectedBytes[ii] = temp[ii];
}
}
}
else
{
for (; a < b; a += c)
{
for (var ii = a; ii < byteDepth + a; ii++)
{
selectedBytes[ii] = temp[ii];
}
}
}
return allocator.Allocations[0];
}
public unsafe class StackAllocation : IDisposable
{
private bool dispose;
public IntPtr Allocation { get; private set; }
public int Size { get; private set; }
public Thread Allocator { get; private set; }
public bool IsDisposing
{
get
{
return dispose;
}
}
public StackAllocation(IntPtr allocation, int allocationSize, Thread allocator)
{
Allocator = allocator;
Allocation = allocation;
Size = allocationSize;
}
public void Dispose()
{
dispose = true; // Buffer overrun caused
}
}
public StackAllocation AllocateBytes(int count)
{
if ((ulong)(count + totalAllocated) > new Microsoft.VisualBasic.Devices.ComputerInfo().AvailablePhysicalMemory) { throw new OutOfMemoryException(); }
var ptr = IntPtr.Zero;
Thread t = null;
StackAllocation allocation = null;
t = new Thread(() =>
{
try
{
var p = stackalloc byte[count];
ptr = (IntPtr)p;
t.Priority = ThreadPriority.Lowest;
while (allocation == null) { Thread.Sleep(0); } // Wait for allocation to be instantiated.
while (!allocation.IsDisposing) { Thread.Sleep(0); } // Wait for Dispose to be called from either variable "allocation" or from the allocator (this).
}
finally
{
totalAllocated -= count;
if (allocations.Contains(allocation)) allocations.Remove(allocation);
allocation = null;
}
}, count) { Priority = ThreadPriority.AboveNormal };
t.Start();
while (ptr == IntPtr.Zero) { Thread.Sleep(0); } // Wait for memory to be allocated.
allocation = new StackAllocation(ptr, count, t);
allocations.Add(allocation);
totalAllocated += count;
return allocation;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment