|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
namespace SampleTagger.Parsers
{
/*
* This class provide all primitive to read a RIFF file
* in big endian or not.
*/
public abstract class BinaryFileReader
{
protected FileStream BinaryFile;
protected BinaryReader Reader;
protected SampleFileInfo info;
/*
* Here the main entry point. we ask to parse a specific filename
*/
public SampleFileInfo Parse(string filename)
{
info = new SampleFileInfo();
BinaryFile = new FileStream(filename, FileMode.Open, FileAccess.Read);
Reader = new BinaryReader(BinaryFile);
ReadContent();
Reader.Close();
BinaryFile.Close();
return info;
}
/*
* this method is called by Parse() and must be implemented
* in a subclass
*/
abstract protected void ReadContent();
/*
* Use this to convert a bunch of bytes in a struct
*/
protected T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
T stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),
typeof(T));
handle.Free();
return stuff;
}
/*
* return or set the stream position
*/
protected long Position
{
get
{
return Reader.BaseStream.Position;
}
set
{
Reader.BaseStream.Position = value;
}
}
protected byte[] ReadBytes(int count)
{
return Reader.ReadBytes(count);
}
protected long IndianSwap(long value)
{
return
(((value >> 56) & 0xFF) << 00) |
(((value >> 48) & 0xFF) << 08) |
(((value >> 40) & 0xFF) << 16) |
(((value >> 32) & 0xFF) << 24) |
(((value >> 24) & 0xFF) << 32) |
(((value >> 16) & 0xFF) << 40) |
(((value >> 08) & 0xFF) << 48) |
(((value >> 00) & 0xFF) << 56);
}
protected int IndianSwap(int value)
{
return (((value >> 24) & 0xFF) << 00) |
(((value >> 16) & 0xFF) << 08) |
(((value >> 08) & 0xFF) << 16) |
(((value >> 00) & 0xFF) << 24);
}
protected int IndianSwap(short value)
{
int lvalue = (int)value;
return
(((lvalue >> 08) & 0xFF) << 00) |
(((lvalue >> 00) & 0xFF) << 08);
}
protected int BigIndianReadInt32()
{
return IndianSwap(Reader.ReadInt32());
}
protected int ReadInt8()
{
return (int)Reader.ReadByte();
}
protected int ReadInt32()
{
return Reader.ReadInt32();
}
protected int BigIndianReadInt16()
{
return IndianSwap(Reader.ReadInt16());
}
protected int ReadInt16()
{
return Reader.ReadInt16();
}
protected long ReadInt64()
{
return IndianSwap(Reader.ReadInt64());
}
protected float ReadSingle()
{
byte[] data = ReadBytes(4);
return BitConverter.ToSingle(data, 0);
}
/*
* read the ID of a RIFF Chunk
* an ID is always 4 char long
*
* null is returned if we reach the end of stream or somthing is wrong
*/
protected String ReadID()
{
int c1;
// some buggy chunk terminate with 0
// so we skip it to start properly on the next chunk id
for (; ; )
{
if (Reader.BaseStream.Position == Reader.BaseStream.Length)
return null; // EOF
c1 = (int)Reader.ReadByte();
if (c1 == -1)
return null;
if (c1 >= ' ' && c1 <= 127)
break;
}
char[] chars = new char[4];
chars[0] = (char)c1;
chars[1] = Reader.ReadChar();
chars[2] = Reader.ReadChar();
chars[3] = Reader.ReadChar();
return new String(chars);
}
/*
* use this to read the samplefrequency in a AIFF file
*/
protected double ReadLongDouble()
{
byte[] b = Reader.ReadBytes(10);
return LongDouble.ToDouble(b, true);
}
protected String BytesToString(byte[] data)
{
String value = Encoding.ASCII.GetString(data).Trim();
int idx = value.IndexOf((char)0);
if (idx != -1)
return value.Substring(0, idx).Trim();
else
return value.Trim();
}
}
/*
* http://www.codeproject.com/KB/cs/longdouble.aspx
*/
class LongDouble
{
private static byte[] IndianSwap(byte[] data)
{
int size = data.Length;
byte[] swap = new byte[size];
for (int i = 0; i < 10; i++)
{
swap[i] = data[size - 1 - i];
}
return swap;
}
public static double ToDouble(byte[] Value, bool BigIndian)
{
if (Value == null)
throw new ArgumentNullException("Value");
if (Value.Length != 10)
throw new ArgumentException("Combination of Value length and StartIndex was not large enough.");
if (BigIndian)
{
Value = IndianSwap(Value);
}
//extract fields
byte s = (byte)(Value[9] & 0x80);
short e = (short)(((Value[9] & 0x7F) << 8) | Value[8]);
byte j = (byte)(Value[7] & 0x80);
long f = Value[7] & 0x7F;
for (sbyte i = 6; i >= 0; i--)
{
f <<= 8;
f |= Value[i];
}
if (e == 0) //subnormal, pseudo-denormal or zero
return 0;
if (j == 0)
throw new NotSupportedException();
if (e == 0x7FFF) //+infinity, -infinity or nan
{
if (f != 0)
return double.NaN;
if (s == 0)
return double.PositiveInfinity;
else
return double.NegativeInfinity;
}
//translate f
f >>= 11;
//translate e
e -= (0x3FFF - 0x3FF);
if (e >= 0x7FF) //outside the range of a double
throw new OverflowException();
else if (e < -51) //too small to translate into subnormal
return 0;
else if (e < 0) //too small for normal but big enough to represent as subnormal
{
f |= 0x10000000000000;
f >>= (1 - e);
e = 0;
}
byte[] newBytes = System.BitConverter.GetBytes(f);
newBytes[7] = (byte)(s | (e >> 4));
newBytes[6] = (byte)(((e & 0x0F) << 4) | newBytes[6]);
return System.BitConverter.ToDouble(newBytes, 0);
}
public static byte[] GetBytes(double Value, bool BigIndian)
{
byte[] oldBytes = System.BitConverter.GetBytes(Value);
//extract fields
byte s = (byte)(oldBytes[7] & 0x80);
short e = (short)(((oldBytes[7] & 0x7F) << 4) | ((oldBytes[6] & 0xF0) >> 4));
byte j = 0x80;
long f = oldBytes[6] & 0xF;
for (sbyte i = 5; i >= 0; i--)
{
f <<= 8;
f |= oldBytes[i];
}
//translate f
f <<= 11;
if (e == 0x7FF) //+infinity, -infinity or nan
e = 0x7FFF;
else if (e == 0 && f == 0) //zero
j = 0;
else //normal or subnormal
{
if (e == 0) //subnormal
{
f <<= 1;
while (f > 0)
{
e--;
f <<= 1;
}
f &= long.MaxValue;
}
e += (0x3FFF - 0x3FF); //translate e
}
byte[] newBytes = new byte[10];
System.BitConverter.GetBytes(f).CopyTo(newBytes, 0);
newBytes[9] = (byte)(s | (e >> 8));
newBytes[8] = (byte)(e & 0xFF);
newBytes[7] = (byte)(j | newBytes[7]);
if (BigIndian)
{
newBytes = IndianSwap(newBytes);
}
return newBytes;
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.