207 lines
4.6 KiB
C#
207 lines
4.6 KiB
C#
using System;
|
|
using System.IO;
|
|
|
|
namespace GMAssetCompiler
|
|
{
|
|
public class Wave
|
|
{
|
|
public struct SRIFF
|
|
{
|
|
public uint ChunkID;
|
|
|
|
public uint ChunkSize;
|
|
|
|
public uint Format;
|
|
|
|
public uint SubChunk1ID;
|
|
|
|
public uint SubChunk1Size;
|
|
|
|
public short AudioFormat;
|
|
|
|
public short NumChannels;
|
|
|
|
public uint SampleRate;
|
|
|
|
public uint ByteRate;
|
|
|
|
public short BlockAlign;
|
|
|
|
public short BitsPerSample;
|
|
|
|
public uint SubChunk2ID;
|
|
|
|
public uint SubChunk2Size;
|
|
}
|
|
|
|
private const int SAMPLES_PER_SECOND = 22050;
|
|
|
|
private const int MAX_CHANNELS = 1;
|
|
|
|
private const int BITS_PER_SAMPLE = 16;
|
|
|
|
public byte[] RawWavFile;
|
|
|
|
public string FileName;
|
|
|
|
private int DataIndex;
|
|
|
|
private int DataSize;
|
|
|
|
private ushort NumChannels;
|
|
|
|
private uint SampleRate;
|
|
|
|
private uint ByteRate;
|
|
|
|
private ushort BlockAlign;
|
|
|
|
private ushort BitsPerSample;
|
|
|
|
private ushort AudioFormat;
|
|
|
|
private static int fileID;
|
|
|
|
public Wave(IFF _iff, byte[] _wave, string _name)
|
|
{
|
|
RawWavFile = _wave;
|
|
FileName = _name;
|
|
if (!ReadHeader())
|
|
{
|
|
string text = Path.Combine(Program.OutputDir, _name);
|
|
Program.Out.WriteLine("writing audio file {0}...", text);
|
|
File.WriteAllBytes(text, _wave);
|
|
_iff.ExternalFiles.Add(text);
|
|
RawWavFile = new byte[128];
|
|
}
|
|
}
|
|
|
|
private uint Flip(uint _val)
|
|
{
|
|
return ((_val >> 24) & 0xFF) | ((_val >> 8) & 0xFF00) | ((_val & 0xFF) << 24) | ((_val & 0xFF00) << 8);
|
|
}
|
|
|
|
private unsafe void GetDataChunk(byte[] _pWave, out int _ChunkSize, out int _index)
|
|
{
|
|
int num = _pWave.Length;
|
|
fixed (byte* ptr = &_pWave[0])
|
|
{
|
|
SRIFF* ptr2 = (SRIFF*)ptr;
|
|
ptr2 = (SRIFF*)(ptr + (int)ptr2->SubChunk1Size + 20);
|
|
while (ptr2->ChunkID != 1635017060 && ptr2 < ptr + num)
|
|
{
|
|
ptr2 = (SRIFF*)((byte*)ptr2 + (int)ptr2->ChunkSize + 8);
|
|
}
|
|
_ChunkSize = (int)ptr2->ChunkSize;
|
|
_index = (int)((long)ptr2 - (long)ptr) + 8;
|
|
}
|
|
}
|
|
|
|
private bool ReadHeader()
|
|
{
|
|
uint val = BitConverter.ToUInt32(RawWavFile, 0);
|
|
BitConverter.ToUInt32(RawWavFile, 4);
|
|
uint val2 = BitConverter.ToUInt32(RawWavFile, 8);
|
|
val = Flip(val);
|
|
val2 = Flip(val2);
|
|
if (val != 1380533830)
|
|
{
|
|
return false;
|
|
}
|
|
if (val2 != 1463899717)
|
|
{
|
|
return false;
|
|
}
|
|
uint val3 = BitConverter.ToUInt32(RawWavFile, 12);
|
|
BitConverter.ToUInt32(RawWavFile, 16);
|
|
AudioFormat = BitConverter.ToUInt16(RawWavFile, 20);
|
|
val3 = Flip(val3);
|
|
if (val3 != 1718449184 || AudioFormat != 1)
|
|
{
|
|
return false;
|
|
}
|
|
NumChannels = BitConverter.ToUInt16(RawWavFile, 22);
|
|
SampleRate = BitConverter.ToUInt32(RawWavFile, 24);
|
|
ByteRate = BitConverter.ToUInt32(RawWavFile, 28);
|
|
BlockAlign = BitConverter.ToUInt16(RawWavFile, 32);
|
|
BitsPerSample = BitConverter.ToUInt16(RawWavFile, 34);
|
|
GetDataChunk(RawWavFile, out DataSize, out DataIndex);
|
|
RawWavFile = Resample();
|
|
return true;
|
|
}
|
|
|
|
private unsafe byte[] Resample()
|
|
{
|
|
if (AudioFormat == 1 && SampleRate == 22050 && NumChannels == 1 && BitsPerSample == 16)
|
|
{
|
|
return RawWavFile;
|
|
}
|
|
fixed (byte* ptr4 = &RawWavFile[0])
|
|
{
|
|
int num = (int)BitsPerSample / 8;
|
|
float num2 = (float)(double)SampleRate / 22050f;
|
|
float num3 = 0f;
|
|
int num4 = num * NumChannels;
|
|
int num5 = DataSize / num4;
|
|
int num6 = (int)((float)num5 / num2);
|
|
int num7 = (int)(2.0 * (double)num6);
|
|
byte[] array = new byte[num7 + 44];
|
|
fixed (byte* ptr = &array[0])
|
|
{
|
|
short* ptr2 = (short*)ptr;
|
|
SRIFF* ptr3 = (SRIFF*)ptr2;
|
|
ptr2 += 22;
|
|
ptr3->ChunkID = 1179011410u;
|
|
ptr3->ChunkSize = (uint)(36 + num7);
|
|
ptr3->Format = 1163280727u;
|
|
ptr3->SubChunk1ID = 544501094u;
|
|
ptr3->SubChunk1Size = 16u;
|
|
ptr3->AudioFormat = 1;
|
|
ptr3->NumChannels = 1;
|
|
ptr3->SampleRate = 22050u;
|
|
ptr3->ByteRate = ptr3->SampleRate * 2;
|
|
ptr3->BitsPerSample = 16;
|
|
ptr3->BlockAlign = 2;
|
|
ptr3->SubChunk2ID = 1635017060u;
|
|
ptr3->SubChunk2Size = (uint)num7;
|
|
byte* ptr5 = ptr4 + DataIndex;
|
|
int num8 = 0;
|
|
int num9 = 0;
|
|
while (num6 > 0)
|
|
{
|
|
int num10 = 0;
|
|
int num11 = num8 * num4;
|
|
switch (BitsPerSample)
|
|
{
|
|
case 8:
|
|
num10 = ptr5[num11] - 128 << 8;
|
|
if (NumChannels == 2)
|
|
{
|
|
byte b = ptr5[num11 + 1];
|
|
}
|
|
break;
|
|
case 16:
|
|
num10 = ((ptr5[num11] & 0xFF) | ((ptr5[num11 + 1] & 0xFF) << 8));
|
|
if (NumChannels == 2)
|
|
{
|
|
byte b2 = ptr5[num11 + 2];
|
|
byte b3 = ptr5[num11 + 3];
|
|
}
|
|
break;
|
|
}
|
|
ptr2[num9] = (short)num10;
|
|
num9++;
|
|
num3 += num2;
|
|
int num12 = (int)num3;
|
|
num3 -= (float)num12;
|
|
num8 += num12;
|
|
num6--;
|
|
}
|
|
fileID++;
|
|
return array;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|