- Build system optimizations - Extended ProjectConverter: DX and SharpDX assemblies are now removed from linux projects to prevent errors - Fixed a bunch of compiler warnings - Removed DX11MetroShaderGenerator assembly. It is now included in ANX.Framework.Content.Pipeline - Removed HLSLParser assembly. It is now included in ANX.Framework.Content.Pipeline. - Removed shader parser from GL3-RenderSystem. It is now included in ANX.Framework.Content.Pipeline. - Removed RenderSystem dependencies from StockShaderCodeGenerator (sscg) tool
162 lines
4.3 KiB
C#
162 lines
4.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
|
|
// This file is part of the ANX.Framework and originally taken from
|
|
// the AC.AL OpenAL library, released under the MIT License.
|
|
// For details see: http://acal.codeplex.com/license
|
|
|
|
namespace WaveUtils
|
|
{
|
|
/// <summary>
|
|
/// This class contains all the loading process of a wave file.
|
|
/// <para />
|
|
/// http://www-mmsp.ece.mcgill.ca/documents/audioformats/wave/wave.html
|
|
/// <para />
|
|
/// Chunk information: http://www.sonicspot.com/guide/wavefiles.html
|
|
/// <para />
|
|
/// Audio Codecs: http://wiki.multimedia.cx/index.php?title=Category:Audio_Codecs
|
|
/// <para />
|
|
/// http://netghost.narod.ru/gff/vendspec/micriff/ms_riff.txt
|
|
/// <para />
|
|
/// Most interesting file about many formats:
|
|
/// http://icculus.org/SDL_sound/downloads/external_documentation/wavecomp.htm
|
|
/// <para />
|
|
/// http://sharkysoft.com/archive/lava/docs/javadocs/lava/riff/wave/doc-files/riffwave-content.htm
|
|
/// </summary>
|
|
public static class WaveFile
|
|
{
|
|
#region LoadData
|
|
public static WaveInfo LoadData(Stream stream, bool rememberUnloadedChunks = false)
|
|
{
|
|
WaveInfo result = new WaveInfo();
|
|
|
|
using (BinaryReader reader = new BinaryReader(stream))
|
|
{
|
|
if (CheckHeader(reader) == false)
|
|
{
|
|
throw new FormatException("The provided stream is not a valid WAVE file. Unable to load!");
|
|
}
|
|
|
|
#region Read Chunks
|
|
while (stream.Position < stream.Length - 8)
|
|
{
|
|
string identifier = new string(reader.ReadChars(4));
|
|
int chunkLength = reader.ReadInt32();
|
|
|
|
if (stream.Position + chunkLength > stream.Length)
|
|
{
|
|
break;
|
|
}
|
|
|
|
int startPosition = (int)reader.BaseStream.Position;
|
|
|
|
switch (identifier.ToLower())
|
|
{
|
|
case "fmt ":
|
|
{
|
|
#region Load fmt chunk
|
|
result.WaveFormat = (WaveFormat)reader.ReadInt16();
|
|
result.Channels = reader.ReadInt16();
|
|
result.SampleRate = reader.ReadInt32();
|
|
int avgBytesPerSec = reader.ReadInt32();
|
|
result.BlockAlign = reader.ReadInt16();
|
|
result.BitsPerSample = reader.ReadInt16();
|
|
|
|
if (chunkLength > 16)
|
|
{
|
|
short extensionSize = reader.ReadInt16();
|
|
|
|
if (chunkLength > 18)
|
|
{
|
|
result.ExtSamplesPerBlock = reader.ReadInt16();
|
|
int speakerPositionMask = reader.ReadInt32();
|
|
WaveFormat extFormat = (WaveFormat)reader.ReadInt16();
|
|
if (result.WaveFormat < 0)
|
|
{
|
|
result.WaveFormat = extFormat;
|
|
}
|
|
byte[] subFormat = reader.ReadBytes(14);
|
|
}
|
|
}
|
|
|
|
result.ALFormat = (result.Channels == 1 ?
|
|
(result.BitsPerSample == 8 ?
|
|
ALFormat.Mono8 :
|
|
ALFormat.Mono16) :
|
|
(result.BitsPerSample == 8 ?
|
|
ALFormat.Stereo8 :
|
|
ALFormat.Stereo16));
|
|
#endregion
|
|
}
|
|
break;
|
|
|
|
case "fact":
|
|
{
|
|
#region Load fact chunk
|
|
// per channel
|
|
int numberOfSamples = reader.ReadInt32();
|
|
// TODO: more
|
|
#endregion
|
|
}
|
|
break;
|
|
|
|
case "data":
|
|
result.Data = reader.ReadBytes(chunkLength);
|
|
break;
|
|
|
|
default:
|
|
if (rememberUnloadedChunks)
|
|
{
|
|
var value = new KeyValuePair<string, byte[]>(identifier, reader.ReadBytes(chunkLength));
|
|
result.UnloadedChunks.Add(value);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// If some chunks are incorrect in data length, we ensure that we
|
|
// end up in the right position.
|
|
int lengthRead = (int)reader.BaseStream.Position - startPosition;
|
|
if (lengthRead != chunkLength)
|
|
{
|
|
reader.BaseStream.Seek(chunkLength - lengthRead,
|
|
SeekOrigin.Current);
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
if (result.Data == null)
|
|
{
|
|
//Logger.Error("There was no data chunk available. Unable to load!");
|
|
return null;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
#region CheckHeader
|
|
private static bool CheckHeader(BinaryReader reader)
|
|
{
|
|
string RIFFmagic = new string(reader.ReadChars(4));
|
|
if(RIFFmagic != "RIFF")
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// filesize
|
|
reader.ReadInt32();
|
|
|
|
string identifierWAVE = new string(reader.ReadChars(4));
|
|
if(identifierWAVE != "WAVE")
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
#endregion
|
|
}
|
|
}
|