/// <summary> /// Allocates the unmanaged memory for the midi headers and buffers. /// </summary> private void AllocateBuffers() { if (this.BufferSize > 0 && this.BufferCount > 0) { this.memHeaders = MemoryUtil.Alloc(MemoryUtil.SizeOfMidiHeader * this.BufferCount); this.memBuffers = MemoryUtil.Alloc(this.BufferSize * this.BufferCount); GC.AddMemoryPressure((MemoryUtil.SizeOfMidiHeader + this.BufferSize) * this.BufferCount); IntPtr headerMem = IntPtr.Add(this.memHeaders, 0); IntPtr bufferMem = IntPtr.Add(this.memBuffers, 0); for (int i = 0; i < this.BufferCount; i++) { var buffer = new MidiBufferStream(headerMem, bufferMem, this.BufferSize, this.StreamAccess); try { this.unusedBuffers.Enqueue(buffer); this.mapBuffers.Add(headerMem, buffer); headerMem = IntPtr.Add(headerMem, MemoryUtil.SizeOfMidiHeader); bufferMem = IntPtr.Add(bufferMem, this.BufferSize); } catch { buffer.Dispose(); throw; } } } }
/// <summary> /// Reads a unsigned integer from the memory block at the <paramref name="byteOffset"/>. /// </summary> /// <param name="byteOffset">An offset from the start of the memory block where the writing should start. /// Make sure the <paramref name="byteOffset"/> is properly aligned (usually 16-bits).</param> /// <returns>Returns the value.</returns> public uint ReadUintAt(int byteOffset) { Check.IfArgumentOutOfRange(byteOffset, 0, int.MaxValue, nameof(byteOffset)); var size = MemoryUtil.SizeOf(typeof(uint)); ValidateAccess(byteOffset, size); IntPtr location = IntPtr.Add(_memory, byteOffset); return(*(uint *)location.ToPointer()); }
/// <summary> /// Writes a <paramref name="value"/> to the specified <paramref name="byteOffset"/>. /// </summary> /// <param name="byteOffset">An offset from the start of the memory block where the writing should start. /// Make sure the <paramref name="byteOffset"/> is properly aligned (usually 16-bits).</param> /// <param name="value">The value to write.</param> public void WriteUintAt(int byteOffset, uint value) { Check.IfArgumentOutOfRange(byteOffset, 0, int.MaxValue, nameof(byteOffset)); var size = MemoryUtil.SizeOf(typeof(uint)); ValidateAccess(byteOffset, size); IntPtr location = IntPtr.Add(_memory, byteOffset); *(uint *)location.ToPointer() = value; }
/// <summary> /// Reads a unsigned integer from the memory block at the <paramref name="byteOffset"/>. /// </summary> /// <param name="byteOffset">An offset from the start of the memory block where the writing should start. /// Make sure the <paramref name="byteOffset"/> is properly aligned (usually 16-bits).</param> /// <returns>Returns the value.</returns> public uint ReadUintAt(int byteOffset) { Contract.Requires(byteOffset >= 0); var size = MemoryUtil.SizeOf(typeof(uint)); this.ValidateAccess(byteOffset, size); IntPtr location = IntPtr.Add(this.memory, byteOffset); return(*(uint *)location.ToPointer()); }
/// <summary> /// Writes a <paramref name="value"/> to the specified <paramref name="byteOffset"/>. /// </summary> /// <param name="byteOffset">An offset from the start of the memory block where the writing should start. /// Make sure the <paramref name="byteOffset"/> is properly aligned (usually 16-bits).</param> /// <param name="value">The value to write.</param> public void WriteUintAt(int byteOffset, uint value) { Contract.Requires(byteOffset >= 0); var size = MemoryUtil.SizeOf(typeof(uint)); this.ValidateAccess(byteOffset, size); IntPtr location = IntPtr.Add(this.memory, byteOffset); *(uint *)location.ToPointer() = value; }
/// <summary> /// Frees the allocated memory. /// </summary> private void FreeBuffers() { if (this.memHeaders != IntPtr.Zero) { MemoryUtil.Free(this.memHeaders); this.memHeaders = IntPtr.Zero; } if (this.memBuffers != IntPtr.Zero) { MemoryUtil.Free(this.memBuffers); this.memBuffers = IntPtr.Zero; } var totalLength = (MemoryUtil.SizeOfMidiHeader + this.BufferSize) * this.BufferCount; if (totalLength > 0) { GC.RemoveMemoryPressure(totalLength); } }