mirror of
https://github.com/blueskythlikesclouds/SonicAudioTools.git
synced 2024-11-24 07:00:11 +01:00
527 lines
15 KiB
C#
527 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace SonicAudioLib.IO
|
|
{
|
|
public static class DataStream
|
|
{
|
|
[StructLayout(LayoutKind.Explicit)]
|
|
private struct SingleUnion
|
|
{
|
|
[FieldOffset(0)]
|
|
public float Single;
|
|
|
|
[FieldOffset(0)]
|
|
public uint UInt;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Explicit)]
|
|
private struct DoubleUnion
|
|
{
|
|
[FieldOffset(0)]
|
|
public double Double;
|
|
|
|
[FieldOffset(0)]
|
|
public ulong ULong;
|
|
}
|
|
|
|
// Not thread safe... but I guess it's OK.
|
|
private static byte[] buffer = new byte[8];
|
|
|
|
public static void CopyTo(Stream source, Stream destination)
|
|
{
|
|
CopyTo(source, destination, 4096);
|
|
}
|
|
|
|
public static void CopyTo(Stream source, Stream destination, int bufferSize)
|
|
{
|
|
int read;
|
|
byte[] buffer = new byte[bufferSize];
|
|
|
|
while ((read = source.Read(buffer, 0, buffer.Length)) != 0)
|
|
{
|
|
destination.Write(buffer, 0, read);
|
|
}
|
|
}
|
|
|
|
public static void CopyPartTo(Stream source, Stream destination, long length, int bufferSize)
|
|
{
|
|
int num;
|
|
byte[] buffer = new byte[bufferSize];
|
|
|
|
long copiedBytes = 0;
|
|
while (copiedBytes < length && (num = source.Read(buffer, 0, bufferSize)) != 0)
|
|
{
|
|
if (copiedBytes + num >= length)
|
|
{
|
|
num = (int)(length - copiedBytes);
|
|
}
|
|
|
|
copiedBytes += num;
|
|
destination.Write(buffer, 0, num);
|
|
}
|
|
}
|
|
|
|
public static void CopyPartTo(Stream source, Stream destination, long position, long length, int bufferSize)
|
|
{
|
|
source.Seek(position, SeekOrigin.Begin);
|
|
CopyPartTo(source, destination, length, bufferSize);
|
|
}
|
|
|
|
public static byte[] ReadBytes(Stream source, int length)
|
|
{
|
|
byte[] buffer = new byte[length];
|
|
source.Read(buffer, 0, length);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
public static byte[] ReadBytesAt(Stream source, int length, long position)
|
|
{
|
|
long oldPosition = source.Position;
|
|
source.Seek(position, SeekOrigin.Begin);
|
|
var result = ReadBytes(source, length);
|
|
source.Seek(oldPosition, SeekOrigin.Begin);
|
|
|
|
return result;
|
|
}
|
|
|
|
public static void WriteBytes(Stream destination, byte[] value)
|
|
{
|
|
destination.Write(value, 0, value.Length);
|
|
}
|
|
|
|
public static void WriteBytes(Stream destination, byte[] value, int length)
|
|
{
|
|
destination.Write(value, 0, length);
|
|
}
|
|
|
|
public static byte ReadByte(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 1);
|
|
|
|
return buffer[0];
|
|
}
|
|
|
|
public static byte ReadByteAt(Stream source, long position)
|
|
{
|
|
long oldPosition = source.Position;
|
|
source.Seek(position, SeekOrigin.Begin);
|
|
|
|
byte value = ReadByte(source);
|
|
source.Seek(oldPosition, SeekOrigin.Begin);
|
|
|
|
return value;
|
|
}
|
|
|
|
public static void WriteByte(Stream destination, byte value)
|
|
{
|
|
buffer[0] = value;
|
|
|
|
destination.Write(buffer, 0, 1);
|
|
}
|
|
|
|
public static void WriteByteAt(Stream destination, byte value, long position)
|
|
{
|
|
long oldPosition = destination.Position;
|
|
destination.Seek(position, SeekOrigin.Begin);
|
|
|
|
WriteByte(destination, value);
|
|
destination.Seek(oldPosition, SeekOrigin.Begin);
|
|
}
|
|
|
|
public static bool ReadBoolean(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 1);
|
|
|
|
return buffer[0] == 1;
|
|
}
|
|
|
|
public static void WriteBoolean(Stream destination, bool value)
|
|
{
|
|
buffer[0] = (byte)(value ? 1 : 0);
|
|
|
|
destination.Write(buffer, 0, 1);
|
|
}
|
|
|
|
public static sbyte ReadSByte(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 1);
|
|
|
|
return (sbyte)buffer[0];
|
|
}
|
|
|
|
public static void WriteSByte(Stream destination, sbyte value)
|
|
{
|
|
buffer[0] = (byte)value;
|
|
|
|
destination.Write(buffer, 0, 1);
|
|
}
|
|
|
|
public static ushort ReadUInt16(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 2);
|
|
|
|
return (ushort)(buffer[0] | buffer[1] << 8);
|
|
}
|
|
|
|
public static ushort ReadUInt16BE(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 2);
|
|
|
|
return (ushort)(buffer[0] << 8 | buffer[1]);
|
|
}
|
|
|
|
public static void WriteUInt16(Stream destination, ushort value)
|
|
{
|
|
buffer[0] = (byte)(value);
|
|
buffer[1] = (byte)(value >> 8);
|
|
|
|
destination.Write(buffer, 0, 2);
|
|
}
|
|
|
|
public static void WriteUInt16BE(Stream destination, ushort value)
|
|
{
|
|
buffer[0] = (byte)(value >> 8);
|
|
buffer[1] = (byte)(value);
|
|
|
|
destination.Write(buffer, 0, 2);
|
|
}
|
|
|
|
public static short ReadInt16(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 2);
|
|
|
|
return (short)(buffer[0] | buffer[1] << 8);
|
|
}
|
|
|
|
public static short ReadInt16BE(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 2);
|
|
|
|
return (short)(buffer[0] << 8 | buffer[1]);
|
|
}
|
|
|
|
public static void WriteInt16(Stream destination, short value)
|
|
{
|
|
buffer[0] = (byte)(value);
|
|
buffer[1] = (byte)(value >> 8);
|
|
|
|
destination.Write(buffer, 0, 2);
|
|
}
|
|
|
|
public static void WriteInt16BE(Stream destination, short value)
|
|
{
|
|
buffer[0] = (byte)(value >> 8);
|
|
buffer[1] = (byte)(value);
|
|
|
|
destination.Write(buffer, 0, 2);
|
|
}
|
|
|
|
public static uint ReadUInt32(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 4);
|
|
|
|
return (uint)(buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24);
|
|
}
|
|
|
|
public static uint ReadUInt32BE(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 4);
|
|
|
|
return (uint)(buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]);
|
|
}
|
|
|
|
public static void WriteUInt32(Stream destination, uint value)
|
|
{
|
|
buffer[0] = (byte)(value);
|
|
buffer[1] = (byte)(value >> 8);
|
|
buffer[2] = (byte)(value >> 16);
|
|
buffer[3] = (byte)(value >> 24);
|
|
|
|
destination.Write(buffer, 0, 4);
|
|
}
|
|
|
|
public static void WriteUInt32BE(Stream destination, uint value)
|
|
{
|
|
buffer[0] = (byte)((value >> 24));
|
|
buffer[1] = (byte)((value >> 16));
|
|
buffer[2] = (byte)((value >> 8));
|
|
buffer[3] = (byte)(value);
|
|
|
|
destination.Write(buffer, 0, 4);
|
|
}
|
|
|
|
public static int ReadInt32(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 4);
|
|
|
|
return buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24;
|
|
}
|
|
|
|
public static int ReadInt32BE(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 4);
|
|
|
|
return buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
|
|
}
|
|
|
|
public static void WriteInt32(Stream destination, int value)
|
|
{
|
|
buffer[0] = (byte)(value);
|
|
buffer[1] = (byte)(value >> 8);
|
|
buffer[2] = (byte)(value >> 16);
|
|
buffer[3] = (byte)(value >> 24);
|
|
|
|
destination.Write(buffer, 0, 4);
|
|
}
|
|
|
|
public static void WriteInt32BE(Stream destination, int value)
|
|
{
|
|
buffer[0] = (byte)((value >> 24));
|
|
buffer[1] = (byte)((value >> 16));
|
|
buffer[2] = (byte)((value >> 8));
|
|
buffer[3] = (byte)(value);
|
|
|
|
destination.Write(buffer, 0, 4);
|
|
}
|
|
|
|
public static ulong ReadUInt64(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 8);
|
|
|
|
return (buffer[0] | (ulong)buffer[1] << 8 |
|
|
(ulong)buffer[2] << 16 | (ulong)buffer[3] << 24 |
|
|
(ulong)buffer[4] << 32 | (ulong)buffer[5] << 40 |
|
|
(ulong)buffer[6] << 48 | (ulong)buffer[7] << 56);
|
|
}
|
|
|
|
public static ulong ReadUInt64BE(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 8);
|
|
|
|
return ((ulong)buffer[0] << 56 | (ulong)buffer[1] << 48 |
|
|
(ulong)buffer[2] << 40 | (ulong)buffer[3] << 32 |
|
|
(ulong)buffer[4] << 24 | (ulong)buffer[5] << 16 |
|
|
(ulong)buffer[6] << 8 | buffer[7]);
|
|
}
|
|
|
|
public static void WriteUInt64(Stream destination, ulong value)
|
|
{
|
|
buffer[0] = (byte)(value);
|
|
buffer[1] = (byte)(value >> 8);
|
|
buffer[2] = (byte)(value >> 16);
|
|
buffer[3] = (byte)(value >> 24);
|
|
buffer[4] = (byte)(value >> 32);
|
|
buffer[5] = (byte)(value >> 40);
|
|
buffer[6] = (byte)(value >> 48);
|
|
buffer[7] = (byte)(value >> 56);
|
|
|
|
destination.Write(buffer, 0, 8);
|
|
}
|
|
|
|
public static void WriteUInt64BE(Stream destination, ulong value)
|
|
{
|
|
buffer[0] = (byte)((value >> 56));
|
|
buffer[1] = (byte)((value >> 48));
|
|
buffer[2] = (byte)((value >> 40));
|
|
buffer[3] = (byte)((value >> 32));
|
|
buffer[4] = (byte)((value >> 24));
|
|
buffer[5] = (byte)((value >> 16));
|
|
buffer[6] = (byte)((value >> 8));
|
|
buffer[7] = (byte)(value);
|
|
|
|
destination.Write(buffer, 0, 8);
|
|
}
|
|
|
|
public static long ReadInt64(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 8);
|
|
|
|
return buffer[0] | buffer[1] << 8 |
|
|
buffer[2] << 16 | buffer[3] << 24 |
|
|
buffer[4] << 32 | buffer[5] << 40 |
|
|
buffer[6] << 48 | buffer[7] << 56;
|
|
}
|
|
|
|
public static long ReadInt64BE(Stream source)
|
|
{
|
|
source.Read(buffer, 0, 8);
|
|
|
|
return buffer[0] << 56 | buffer[1] << 48 |
|
|
buffer[2] << 40 | buffer[3] << 32 |
|
|
buffer[4] << 24 | buffer[5] << 16 |
|
|
buffer[6] << 8 | buffer[7];
|
|
}
|
|
|
|
public static void WriteInt64(Stream destination, long value)
|
|
{
|
|
buffer[0] = (byte)(value);
|
|
buffer[1] = (byte)(value >> 8);
|
|
buffer[2] = (byte)(value >> 16);
|
|
buffer[3] = (byte)(value >> 24);
|
|
buffer[4] = (byte)(value >> 32);
|
|
buffer[5] = (byte)(value >> 40);
|
|
buffer[6] = (byte)(value >> 48);
|
|
buffer[7] = (byte)(value >> 56);
|
|
|
|
destination.Write(buffer, 0, 8);
|
|
}
|
|
|
|
public static void WriteInt64BE(Stream destination, long value)
|
|
{
|
|
buffer[0] = (byte)((value >> 56));
|
|
buffer[1] = (byte)((value >> 48));
|
|
buffer[2] = (byte)((value >> 40));
|
|
buffer[3] = (byte)((value >> 32));
|
|
buffer[4] = (byte)((value >> 24));
|
|
buffer[5] = (byte)((value >> 16));
|
|
buffer[6] = (byte)((value >> 8));
|
|
buffer[7] = (byte)(value);
|
|
|
|
destination.Write(buffer, 0, 8);
|
|
}
|
|
|
|
public static float ReadSingle(Stream source)
|
|
{
|
|
var union = new SingleUnion();
|
|
union.UInt = ReadUInt32(source);
|
|
|
|
return union.Single;
|
|
}
|
|
|
|
public static float ReadSingleBE(Stream source)
|
|
{
|
|
var union = new SingleUnion();
|
|
union.UInt = ReadUInt32BE(source);
|
|
|
|
return union.Single;
|
|
}
|
|
|
|
public static void WriteSingle(Stream destination, float value)
|
|
{
|
|
var union = new SingleUnion();
|
|
union.Single = value;
|
|
|
|
WriteUInt32(destination, union.UInt);
|
|
}
|
|
|
|
public static void WriteSingleBE(Stream destination, float value)
|
|
{
|
|
var union = new SingleUnion();
|
|
union.Single = value;
|
|
|
|
WriteUInt32BE(destination, union.UInt);
|
|
}
|
|
|
|
public static double ReadDouble(Stream source)
|
|
{
|
|
var union = new DoubleUnion();
|
|
union.ULong = ReadUInt64(source);
|
|
|
|
return union.Double;
|
|
}
|
|
|
|
public static double ReadDoubleBE(Stream source)
|
|
{
|
|
var union = new DoubleUnion();
|
|
union.ULong = ReadUInt64BE(source);
|
|
|
|
return union.Double;
|
|
}
|
|
|
|
public static void WriteDouble(Stream destination, double value)
|
|
{
|
|
var union = new DoubleUnion();
|
|
union.Double = value;
|
|
|
|
WriteUInt64(destination, union.ULong);
|
|
}
|
|
|
|
public static void WriteDoubleBE(Stream destination, double value)
|
|
{
|
|
var union = new DoubleUnion();
|
|
union.Double = value;
|
|
|
|
WriteUInt64BE(destination, union.ULong);
|
|
}
|
|
|
|
public static string ReadCString(Stream source)
|
|
{
|
|
return ReadCString(source, Encoding.ASCII);
|
|
}
|
|
|
|
public static string ReadCString(Stream source, Encoding encoding)
|
|
{
|
|
var characters = new List<byte>();
|
|
|
|
source.Read(buffer, 0, 1);
|
|
while (buffer[0] != 0)
|
|
{
|
|
characters.Add(buffer[0]);
|
|
source.Read(buffer, 0, 1);
|
|
}
|
|
|
|
return encoding.GetString(characters.ToArray());
|
|
}
|
|
|
|
public static void WriteCString(Stream destination, string value)
|
|
{
|
|
WriteCString(destination, value, Encoding.ASCII);
|
|
}
|
|
|
|
public static void WriteCString(Stream destination, string value, Encoding encoding)
|
|
{
|
|
byte[] buffer = encoding.GetBytes(value);
|
|
|
|
destination.Write(buffer, 0, buffer.Length);
|
|
|
|
buffer[0] = 0;
|
|
destination.Write(buffer, 0, 1);
|
|
}
|
|
|
|
public static string ReadCString(Stream source, int length)
|
|
{
|
|
return ReadCString(source, length, Encoding.ASCII);
|
|
}
|
|
|
|
public static string ReadCString(Stream source, int length, Encoding encoding)
|
|
{
|
|
byte[] buffer = new byte[length];
|
|
source.Read(buffer, 0, length);
|
|
|
|
for (int i = 0; i < buffer.Length; i++)
|
|
{
|
|
if (buffer[i] == 0)
|
|
{
|
|
return encoding.GetString(buffer, 0, i);
|
|
}
|
|
}
|
|
|
|
return encoding.GetString(buffer);
|
|
}
|
|
|
|
public static void WriteCString(Stream destination, string value, int length)
|
|
{
|
|
WriteCString(destination, value, length, Encoding.ASCII);
|
|
}
|
|
|
|
public static void WriteCString(Stream destination, string value, int length, Encoding encoding)
|
|
{
|
|
byte[] buffer = encoding.GetBytes(value.ToCharArray(), 0, length);
|
|
destination.Write(buffer, 0, length);
|
|
}
|
|
|
|
public static void Pad(Stream destination, long alignment)
|
|
{
|
|
while (destination.Position % alignment != 0)
|
|
{
|
|
WriteByte(destination, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|