Files
korenkonder_PD_Tool/KKdSoundLib/VAG.cs
T
KujiKita 4c8b293beb Release v0.4.5.10
Some fixes and changes
2019-06-14 05:39:46 +03:00

820 lines
34 KiB
C#

using KKdMainLib;
using KKdMainLib.IO;
namespace KKdSoundLib
{
public unsafe class VAG
{
private int c, d0, d1, e, g, i, i1, i2, j, s, PrNR, ShF, PrNRCount;
private uint VBS;
private float f;
private ushort ch;
private const uint BS = 28; //VAGBlockSize
private int[] Samp1, Samp2, Samp3, Samp4;
private int* S1Ptr, S2Ptr, S3Ptr, S4Ptr;
private bool Success = false;
public VAGFile VAGData = new VAGFile();
public VAG() { VAGData = new VAGFile();
HEVAG1Ptr = HEVAG1.GetPtr(); HEVAG2Ptr = HEVAG2.GetPtr();
HEVAG3Ptr = HEVAG3.GetPtr(); HEVAG4Ptr = HEVAG4.GetPtr(); }
public void VAGReader(string file)
{
Success = false;
if (!File.Exists(file + ".vag")) return;
VAGData = new VAGFile();
Stream reader = File.OpenReader(file + ".vag", true);
if (reader.ReadUInt32() != 0x70474156) return;
VAGData.Version = reader.ReadUInt32Endian(true);
reader.ReadUInt32();
VAGData.Size = reader.ReadUInt32Endian(true);
VAGData.SampleRate = reader.ReadUInt32Endian(true);
reader.ReadUInt32();
reader.ReadUInt32();
reader.ReadUInt16();
VAGData.Channels = reader.ReadUInt16();
if (VAGData.Channels < 2) VAGData.Channels = 1;
VAGData.Name = reader.ReadString(0x10);
bool HEVAG = VAGData.Version == 0x00020001 || VAGData.Version == 0x00030000;
if (!HEVAG) VAGData.Channels = 1;
ch = VAGData.Channels;
VBS = BS * ch;
four_bit = new int[BS]; four_bitPtr = four_bit .GetPtr();
temp_buffer = new int[BS]; temp_bufferPtr = temp_buffer.GetPtr();
Samp1 = new int[VAGData.Channels]; S1Ptr = Samp1.GetPtr();
Samp2 = new int[VAGData.Channels]; S2Ptr = Samp2.GetPtr();
Samp3 = new int[VAGData.Channels]; S3Ptr = Samp3.GetPtr();
Samp4 = new int[VAGData.Channels]; S4Ptr = Samp4.GetPtr();
if (VAGData.Size + 0x30 > reader.LongLength) VAGData.Size = reader.UIntLength - 0x30;
VAGData.Size = (VAGData.Size / VAGData.Channels) >> 4;
VAGData.Flags = new byte [VAGData.Size];
VAGData.Data = new int[VAGData.Size * VBS];
VAGData.DataPtr = VAGData.Data.GetPtr();
VAGData.OriginDataPtr = VAGData.DataPtr;
if (HEVAG)
for (i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr += VBS)
for (c = 0; c < ch; c++)
{
s = reader.ReadByte();
PrNR = (s & 0xF0) >> 4;
ShF = s & 0x0F;
s = reader.ReadByte();
PrNR = (s & 0xF0) | PrNR;
VAGData.Flags[i1] = (byte)(s & 0xF);
for (i = 0, i2 = 1; i < BS; i += 2, i2 += 2)
{
s = reader.ReadByte();
four_bitPtr[i ] = s & 0x0F;
four_bitPtr[i2] = s & 0xF0;
four_bitPtr[i2] >>= 4;
}
HEVAG_1 = HEVAG1Ptr[PrNR]; HEVAG_2 = HEVAG2Ptr[PrNR];
HEVAG_3 = HEVAG3Ptr[PrNR]; HEVAG_4 = HEVAG4Ptr[PrNR];
tS1 = S1Ptr[c]; tS2 = S2Ptr[c]; tS3 = S3Ptr[c]; tS4 = S4Ptr[c];
DecodeHEVAG();
S1Ptr[c] = tS1; S2Ptr[c] = tS2; S3Ptr[c] = tS3; S4Ptr[c] = tS4;
for (i = 0, i2 = 1; i < BS; i += 2, i2 += 2)
{
VAGData.DataPtr[i * ch + c] = temp_bufferPtr[i ];
VAGData.DataPtr[i2 * ch + c] = temp_bufferPtr[i2];
}
}
else
for (i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr += VBS)
{
s = reader.ReadByte();
PrNR = (s & 0xF0) >> 4;
ShF = s & 0x0F;
s = reader.ReadByte();
VAGData.Flags[i1] = (byte)(s & 0xF);
for (i = 0, i2 = 1; i < BS; i += 2, i2 += 2)
{
s = reader.ReadByte();
four_bitPtr[i ] = s & 0x0F;
four_bitPtr[i2] = s & 0xF0;
four_bitPtr[i2] >>= 4;
}
VAG_1 = HEVAG1Ptr[PrNR]; VAG_2 = HEVAG2Ptr[PrNR];
tS1 = S1Ptr[c]; tS2 = S2Ptr[c];
i = 0; i2 = 1;
while (i < BS)
{
d0 = four_bitPtr[i];
d1 = four_bitPtr[i2];
if (d0 > 7) d0 -= 16;
if (d1 > 7) d1 -= 16;
d0 = d0 << (20 - ShF);
d1 = d1 << (20 - ShF);
g = ((tS1 >> 8) * VAG_1 + (tS2 >> 8) * VAG_2) >> 5;
tS2 = tS1; tS1 = g + d0;
g = ((tS1 >> 8) * VAG_1 + (tS2 >> 8) * VAG_2) >> 5;
tS2 = tS1; tS1 = g + d1;
temp_bufferPtr[i ] = tS2;
temp_bufferPtr[i2] = tS1;
i += 2;
i2 += 2;
}
S1Ptr[c] = tS1; S2Ptr[c] = tS2;
for (i = 0, i2 = 1; i < BS; i += 2, i2 += 2)
{
VAGData.DataPtr[i ] = temp_bufferPtr[i ];
VAGData.DataPtr[i2] = temp_bufferPtr[i2];
}
}
VAGData.DataPtr = VAGData.OriginDataPtr;
reader.Close();
Success = true;
}
private void DecodeHEVAG()
{
i = 0; i2 = 1;
while (i < BS)
{
d0 = four_bitPtr[i ];
d1 = four_bitPtr[i2];
if (d0 > 7) d0 -= 16;
if (d1 > 7) d1 -= 16;
d0 = d0 << (20 - ShF);
d1 = d1 << (20 - ShF);
g = ((tS1 >> 8) * HEVAG_1 + (tS2 >> 8) * HEVAG_2 +
(tS3 >> 8) * HEVAG_3 + (tS4 >> 8) * HEVAG_4) >> 5;
tS4 = tS3; tS3 = tS2; tS2 = tS1; tS1 = g + d0;
g = ((tS1 >> 8) * HEVAG_1 + (tS2 >> 8) * HEVAG_2 +
(tS3 >> 8) * HEVAG_3 + (tS4 >> 8) * HEVAG_4) >> 5;
tS4 = tS3; tS3 = tS2; tS2 = tS1; tS1 = g + d1;
temp_bufferPtr[i ] = tS2;
temp_bufferPtr[i2] = tS1;
i += 2;
i2 += 2;
}
}
public void WAVWriterStraight(string file, bool IgnoreEndFlags = false)
{
if (!Success) return;
byte Flag = VAGData.Flags[0];
if (Flag == 7) return;
WAV.Header Header = new WAV.Header();
Stream writer = File.OpenWriter(file + ".wav", true);
writer.LongPosition = 0x2C;
if (Flag < 8)
for (i = 0; i < BS; i++)
for (c = 0; c < ch; c++)
{
f = (float)(VAGData.DataPtr[i * ch + c] / 8388608.0);
writer.Write(f);
}
else
for (i = 0; i < BS; i++)
for (c = 0; c < ch; c++)
writer.Write(0f);
for (i1 = 0, i2 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr += VBS)
{
Flag = VAGData.Flags[i1];
if (!IgnoreEndFlags && Flag == 5 || Flag == 7) break;
if (Flag < 8)
for (i = 0; i < BS; i++)
for (c = 0; c < ch; c++)
{
f = (float)(VAGData.DataPtr[i * ch + c] / 8388608.0);
writer.Write(f);
}
else
for (i = 0; i < BS; i++)
for (c = 0; c < ch; c++)
writer.Write(0f);
if (!IgnoreEndFlags && Flag == 1) break;
}
VAGData.DataPtr = VAGData.OriginDataPtr;
Header = new WAV.Header { Bytes = 4, Channels = ch, Format = 3, SampleRate =
VAGData.SampleRate, Size = writer.UIntPosition - 0x2C };
writer.Write(Header, 0);
writer.Close();
}
public void WAVWriter(string file, bool IgnoreEndFlags = false)
{
if (!Success) return;
byte Flag = VAGData.Flags[0];
if (Flag == 7) return;
WAV.Header Header = new WAV.Header();
Stream writer;
if (!IgnoreEndFlags && Flag == 6) writer = File.OpenWriter(file + ".loop.0.wav", true);
else writer = File.OpenWriter(file + ".0.wav", true);
writer.LongPosition = 0x2C;
if (Flag < 8)
for (i = 0; i < BS; i++)
for (c = 0; c < ch; c++)
{
f = (float)(VAGData.DataPtr[i * ch + c] / 8388608.0);
writer.Write(f);
}
else
for (i = 0; i < BS; i++)
for (c = 0; c < ch; c++)
writer.Write(0f);
VAGData.DataPtr += VBS;
for (i1 = 1, i2 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr += VBS)
{
Flag = VAGData.Flags[i1];
if (!IgnoreEndFlags && Flag == 5 || Flag == 7) break;
else if (!IgnoreEndFlags && Flag == 6)
{
Header = new WAV.Header { Bytes = 4, Channels = ch, Format = 3, SampleRate =
VAGData.SampleRate, Size = writer.UIntPosition - 0x2C };
writer.Write(Header, 0);
writer.Close();
i2++;
writer = File.OpenWriter(file + "." + i2 + ".loop.wav", true);
writer.LongPosition = 0x2C;
}
if (!IgnoreEndFlags && Flag < 8)
for (i = 0; i < BS; i++)
for (c = 0; c < ch; c++)
{
f = (float)(VAGData.DataPtr[i * ch + c] / 8388608.0);
writer.Write(f);
}
else
for (i = 0; i < BS; i++)
for (c = 0; c < ch; c++)
writer.Write(0f);
if (!IgnoreEndFlags && Flag == 1) break;
else if (!IgnoreEndFlags && Flag == 3)
{
Header = new WAV.Header { Bytes = 4, Channels = ch, Format = 3, SampleRate =
VAGData.SampleRate, Size = writer.UIntPosition - 0x2C };
writer.Write(Header, 0);
writer.Close();
i2++;
if (VAGData.Size == i1 + 1)
writer = File.OpenWriter();
else
writer = File.OpenWriter(file + "." + i2 + ".wav", true);
writer.LongPosition = 0x2C;
}
}
VAGData.DataPtr = VAGData.OriginDataPtr;
Header = new WAV.Header { Bytes = 4, Channels = ch, Format = 3, SampleRate =
VAGData.SampleRate, Size = writer.UIntPosition - 0x2C };
writer.Write(Header, 0);
writer.Close();
}
public int WAVReaderStraight(string file, bool ExtendedFlagging = false)
{
Success = false;
VAGData = new VAGFile();
Stream reader = File.OpenReader(file + ".wav");
WAV.Header Header = reader.ReadWAVHeader();
if (!Header.IsSupported) { reader.Close(); return 1; }
ch = Header.Channels;
VBS = BS * ch;
VAGData.Size = Header.Size / Header.Bytes;
VAGData.Data = new int[VAGData.Size.Align(VBS)];
VAGData.DataPtr = VAGData.Data.GetPtr();
VAGData.OriginDataPtr = VAGData.DataPtr;
if (Header.Bytes == 1 && Header.Format == 0x01)
for (int i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr++)
*VAGData.DataPtr = (reader.ReadByte () - 0x80) << 16;
else if (Header.Bytes == 2 && Header.Format == 0x01)
for (int i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr++)
*VAGData.DataPtr = reader.ReadInt16 () << 8;
else if (Header.Bytes == 3 && Header.Format == 0x01)
for (int i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr++)
*VAGData.DataPtr = reader.ReadByte () | (reader.ReadInt16() << 8);
else if (Header.Bytes == 4 && Header.Format == 0x01)
for (int i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr++)
*VAGData.DataPtr = reader.ReadInt32 () >> 8;
else if (Header.Bytes == 4 && Header.Format == 0x03)
for (int i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr++)
*VAGData.DataPtr = (int)(reader.ReadSingle() * 8388608.0);
else if (Header.Bytes == 8 && Header.Format == 0x03)
for (int i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr++)
*VAGData.DataPtr = (int)(reader.ReadDouble() * 8388608.0);
VAGData.Size = VAGData.Size.Align(VBS, VBS);
VAGData.DataPtr = VAGData.OriginDataPtr;
VAGData.Channels = ch;
VAGData.SampleRate = Header.SampleRate;
VAGData.Flags = new byte[VAGData.Size];
if (ExtendedFlagging) VAGData.Flags[0] = 0x4;
VAGData.Flags[VAGData.Size - 1] = 0x1;
reader.Close();
Success = true;
return 0;
}
public int WAVReader(string file, bool ExtendedFlagging = false)
{
Success = false;
string[] Files;
bool HasLoop = false;
bool[] Loop;
{
if (!file.EndsWith(".0")) return WAVReaderStraight(file);
file = file.Remove(file.Length - 2);
i2 = 0;
System.Collections.Generic.List<string> files =
new System.Collections.Generic.List<string>();
System.Collections.Generic.List< bool> loop =
new System.Collections.Generic.List< bool>();
while (true)
{
if (File.Exists(file + "." + i2 + ".wav"))
{
files.Add(file + "." + i2 + ".wav");
loop.Add(false);
}
else if (File.Exists(file + "." + i2 + ".loop.wav"))
{
files.Add(file + "." + i2 + ".loop.wav");
loop.Add(true);
HasLoop = true;
}
else break;
i2++;
}
Files = files.ToArray();
Loop = loop .ToArray();
}
uint[] Sizes = new uint[Files.Length];
ushort Channels = 0;
uint AlignVAG, Size = 0, SampleRate = 0;
VAGData = new VAGFile();
Stream reader;
WAV.Header Header;
for (i = 0; i < Files.Length; i++)
{
reader = File.OpenReader(Files[i]);
Header = reader.ReadWAVHeader();
if (!Header.IsSupported) { reader.Close(); return 2; }
if (i == 0) { SampleRate = Header.SampleRate;
ch = Channels = Header.Channels; VBS = BS * ch; }
if (Header.Channels != Channels ) { reader.Close(); return 3; }
if (Header.SampleRate != SampleRate) { reader.Close(); return 4; }
Sizes[i] = Header.Size / Header.Bytes;
Size += Sizes[i].Align(VBS);
reader.Close();
}
VAGData.Data = new int[Size];
VAGData.DataPtr = VAGData.Data.GetPtr();
VAGData.OriginDataPtr = VAGData.DataPtr;
VAGData.Size = Size / VBS;
VAGData.Flags = new byte[VAGData.Size];
if (HasLoop)
for (i = 0; i < VAGData.Size; i++)
VAGData.Flags[i] = 0x2;
i2 = 0;
uint Start = 0, End = 0;
for (i = 0; i < Files.Length; i++)
{
reader = File.OpenReader(Files[i]);
Header = reader.ReadWAVHeader();
if (Header.Bytes == 1 && Header.Format == 0x01)
for (int i1 = 0; i1 < Sizes[i]; i1++, VAGData.DataPtr++)
*VAGData.DataPtr = (reader.ReadByte () - 0x80) << 16;
else if (Header.Bytes == 2 && Header.Format == 0x01)
for (int i1 = 0; i1 < Sizes[i]; i1++, VAGData.DataPtr++)
*VAGData.DataPtr = reader.ReadInt16 () << 8;
else if (Header.Bytes == 3 && Header.Format == 0x01)
for (int i1 = 0; i1 < Sizes[i]; i1++, VAGData.DataPtr++)
*VAGData.DataPtr = reader.ReadByte () | (reader.ReadInt16() << 8);
else if (Header.Bytes == 4 && Header.Format == 0x01)
for (int i1 = 0; i1 < Sizes[i]; i1++, VAGData.DataPtr++)
*VAGData.DataPtr = reader.ReadInt32 () >> 8;
else if (Header.Bytes == 4 && Header.Format == 0x03)
for (int i1 = 0; i1 < Sizes[i]; i1++, VAGData.DataPtr++)
*VAGData.DataPtr = (int)(reader.ReadSingle() * 8388608.0);
else if (Header.Bytes == 8 && Header.Format == 0x03)
for (int i1 = 0; i1 < Sizes[i]; i1++, VAGData.DataPtr++)
*VAGData.DataPtr = (int)(reader.ReadDouble() * 8388608.0);
reader.Close();
AlignVAG = Sizes[i].Align(VBS) - Sizes[i];
VAGData.DataPtr += AlignVAG;
AlignVAG = (Sizes[i] + AlignVAG) / VBS;
End += AlignVAG;
End--;
if (Loop[i] ) { VAGData.Flags[Start] = 0x6; VAGData.Flags[End] = 0x3; }
else if (ExtendedFlagging) VAGData.Flags[Start] = 0x4;
if (i + 1 == Files.Length && !Loop[i]) VAGData.Flags[End] = 0x1;
Start += AlignVAG;
End++;
}
VAGData.DataPtr = VAGData.OriginDataPtr;
VAGData.Channels = ch;
VAGData.SampleRate = SampleRate;
Success = true;
return 0;
}
public void VAGWriter(string file, bool HEVAG = true)
{
if (!Success) return;
VAGData.Name = Path.GetFileName(file);
Stream writer = File.OpenWriter(file + ".vag", true);
Samp1 = new int[ch]; S1Ptr = Samp1.GetPtr();
Samp2 = new int[ch]; S2Ptr = Samp2.GetPtr();
Samp3 = new int[ch]; S3Ptr = Samp3.GetPtr();
Samp4 = new int[ch]; S4Ptr = Samp4.GetPtr();
S_1 = new int[ch]; S_2 = new int[ch];
S_3 = new int[ch]; S_4 = new int[ch];
if (HEVAG) PrNRCount = 128;
else PrNRCount = 5;
max = new int[PrNRCount]; maxPtr = max .GetPtr();
error = new int[PrNRCount]; errorPtr = error .GetPtr();
four_bit = new int[BS]; four_bitPtr = four_bit .GetPtr();
data_buffer = new int[BS]; data_bufferPtr = data_buffer.GetPtr();
temp_buffer = new int[BS]; temp_bufferPtr = temp_buffer.GetPtr();
buffer = new int[PrNRCount, BS];
writer.Write(0x70474156);
if (HEVAG) writer.WriteEndian(0x00020001, true);
else writer.WriteEndian(0x00000020, true);
writer.Write(0);
if (HEVAG) writer.WriteEndian((VAGData.Size * ch + ch) << 4, true);
else writer.WriteEndian((VAGData.Size + 1) << 4, true);
writer.WriteEndian(VAGData.SampleRate, true);
writer.Write(0);
writer.Write(0);
writer.Write((ushort)0);
if (HEVAG) writer.Write(VAGData.Channels);
else writer.Write((ushort)0x1);
writer.Write(VAGData.Name);
writer.LongLength = 0x30;
writer.LongPosition = 0x30;
if (HEVAG)
for (i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr += VBS)
for (c = 0; c < ch; c++)
{
for (i = 0, s = 0; i < BS; i++)
{
data_bufferPtr[i] = VAGData.OriginDataPtr[i1 * BS * ch + i * ch + c];
s |= data_bufferPtr[i];
}
if (s == 0)
{
S_1[c] = S_2[c] = S_3[c] = S_4[c] = 0;
writer.WriteByte(0);
writer.WriteByte(VAGData.Flags[i1]);
writer.WriteByte(0);
writer.WriteByte(0);
writer.Write(0);
writer.Write(0);
writer.Write(0);
continue;
}
Calc4BitsHEVAG();
s = ((PrNR & 0xF) << 4) | (ShF & 0xF);
writer.WriteByte((byte)s);
s = (PrNR & 0xF0) | (VAGData.Flags[i1] & 0xF);
writer.WriteByte((byte)s);
for (i = 0, i2 = 1; i < BS; i += 2, i2 += 2)
{
s = (four_bitPtr[i2] << 4) | four_bitPtr[i];
writer.WriteByte((byte)s);
}
}
else
for (i1 = 0; i1 < VAGData.Size; i1++, VAGData.DataPtr += VBS)
{
for (i = 0; i < BS; i++)
{
for (c = 0, data_bufferPtr[i] = 0, s = 0; c < ch; c++)
data_bufferPtr[i] += VAGData.OriginDataPtr[i1 * BS * ch + i * ch + c];
data_bufferPtr[i] /= ch;
s |=data_bufferPtr[i];
c = 0;
}
if (s == 0)
{
S_1[c] = S_2[c] = 0;
writer.WriteByte(0);
writer.WriteByte(VAGData.Flags[i1]);
writer.WriteByte(0);
writer.WriteByte(0);
writer.Write(0);
writer.Write(0);
writer.Write(0);
continue;
}
Calc4BitsVAG();
s = ((PrNR & 0xF) << 4) | (ShF & 0xF);
writer.WriteByte((byte)s);
writer.WriteByte(VAGData.Flags[i1]);
for (i = 0, i2 = 1; i < BS; i += 2, i2 += 2)
{
s = (four_bitPtr[i2] << 4) | four_bitPtr[i];
writer.WriteByte((byte)s);
}
}
if (!HEVAG) ch = 1;
for (c = 0; c < ch; c++)
{
writer.Write(0x77770700);
writer.Write(0x77777777);
writer.Write(0x77777777);
writer.Write(0x77777777);
}
VAGData.DataPtr = VAGData.OriginDataPtr;
writer.Close();
}
private int min, ShM, S1, S2, S3, S4, tS1, tS2, tS3, tS4, PrNRf;
private int VAG_1, VAG_2, HEVAG_1, HEVAG_2, HEVAG_3, HEVAG_4;
private int[] data_buffer, error, four_bit, max, S_1, S_2, S_3, S_4, temp_buffer;
private int[,] buffer;
private int* data_bufferPtr, errorPtr, four_bitPtr, maxPtr, temp_bufferPtr;
private void Calc4BitsVAG()
{
ShF = min = 134217728;
for (j = 0; j < 5; j++)
{
maxPtr[j] = 0;
S1 = S1Ptr[c]; S2 = S2Ptr[c];
VAG_1 = HEVAG1Ptr[j]; VAG_2 = HEVAG2Ptr[j];
for (i = 0; i < 28; i++)
{
g = data_bufferPtr[i];
e = ((S1 >> 8) * VAG_1 + (S2 >> 8) * VAG_2) >> 5;
e = g - e;
if (e > 7864319) e = 7864319;
if (e < -7864320) e = -7864320;
buffer[j, i] = e;
if (e < 0) e = -e;
if (e > maxPtr[j]) maxPtr[j] = e;
S2 = S1; S1 = g;
}
if (maxPtr[j] < min) { PrNR = j; min = maxPtr[j]; }
}
S1Ptr[c] = S1; S2Ptr[c] = S2;
ShF = 0;
ShM = 0x4000;
min = min >> 8;
while (ShF < 12)
{
e = min + (ShM >> 3);
if ((ShM & e) == ShM)
break;
ShF++;
ShM >>= 1;
}
S1 = S_1[c]; S2 = S_2[c];
for (i = 0; i < 28; i++)
{
g = buffer[PrNR, i];
e = ((S1 >> 8) * HEVAG1Ptr[PrNR] + (S2 >> 8) * HEVAG2Ptr[PrNR]) >> 5;
e = g - e;
d1 = e << ShF;
d0 = (int)((uint)d1 + 0x80000) >> 20;
if (d0 > 7) d0 = 7;
if (d0 < -8) d0 = -8;
four_bitPtr[i] = d0 & 0xF;
d0 = d0 << (20 - ShF);
S2 = S1; S1 = d0 - e;
}
S_1[c] = S1; S_2[c] = S2;
}
private void Calc4BitsHEVAG()
{
PrNRf = 0;
min = 134217728;
for (j = 0; j < PrNRCount; j++)
{
PrNR = j;
Calc4Bits_HEVAG();
tS1 = S1Ptr[c]; tS2 = S2Ptr[c]; tS3 = S3Ptr[c]; tS4 = S4Ptr[c];
DecodeHEVAG();
i = 0;
errorPtr[j] = 0;
while (i < BS)
{
e = data_bufferPtr[i] - temp_bufferPtr[i];
if (e < 0) e = -e;
errorPtr[j] += e;
i++;
}
if (errorPtr[j] < min) { PrNRf = j; min = errorPtr[j]; }
}
PrNR = PrNRf;
Calc4Bits_HEVAG();
S1Ptr[c] = S1; S2Ptr[c] = S2; S3Ptr[c] = S3; S4Ptr[c] = S4;
S_1 [c] = tS1; S_2 [c] = tS2; S_3 [c] = tS3; S_4 [c] = tS4;
}
private void Calc4Bits_HEVAG()
{
S1 = S1Ptr[c]; S2 = S2Ptr[c]; S3 = S3Ptr[c]; S4 = S4Ptr[c];
HEVAG_1 = HEVAG1Ptr[PrNR]; HEVAG_2 = HEVAG2Ptr[PrNR];
HEVAG_3 = HEVAG3Ptr[PrNR]; HEVAG_4 = HEVAG4Ptr[PrNR];
i = 0;
maxPtr[PrNR] = 0;
while (i < BS)
{
g = data_bufferPtr[i];
e = ((S1 >> 8) * HEVAG_1 + (S2 >> 8) * HEVAG_2 +
(S3 >> 8) * HEVAG_3 + (S4 >> 8) * HEVAG_4) >> 5;
e = g - e;
if (e > 7864319) e = 7864319;
if (e < -7864320) e = -7864320;
temp_bufferPtr[i] = e;
if (e < 0) e = -e;
if (e > maxPtr[PrNR]) maxPtr[PrNR] = e;
S4 = S3; S3 = S2; S2 = S1; S1 = g;
i++;
}
for (ShF = 0, ShM = 0x400000; ShF < 15; ShF++, ShM >>= 1)
{ e = maxPtr[PrNR] + (ShM >> 3); if ((ShM & e) == ShM) break; }
tS1 = S_1[c]; tS2 = S_2[c]; tS3 = S_3[c]; tS4 = S_4[c];
i = 0;
while (i < BS)
{
g = temp_bufferPtr[i];
e = ((tS1 >> 8) * HEVAG_1 + (tS2 >> 8) * HEVAG_2 +
(tS3 >> 8) * HEVAG_3 + (tS4 >> 8) * HEVAG_4) >> 5;
e = g - e;
d1 = e << ShF;
d0 = (d1 + 0x80000) >> 20;
if (d0 > 7) d0 = 7;
if (d0 < -8) d0 = -8;
four_bitPtr[i] = d0 & 0xF;
d0 = d0 << (20 - ShF);
tS4 = tS3; tS3 = tS2; tS2 = tS1; tS1 = d0 - e;
i++;
}
}
public struct VAGFile
{
public uint Size;
public uint Version;
public uint SampleRate;
public ushort Channels;
public string Name;
public byte[] Flags;
public int[] Data;
public int* DataPtr;
public int* OriginDataPtr;
}
private int* HEVAG1Ptr, HEVAG2Ptr, HEVAG3Ptr, HEVAG4Ptr;
private readonly int[] HEVAG1 = new int[]
{
0, 7680, 14720, 12544, 15616, 14731, 14507, 13920,
13133, 12028, 10764, 9359, 7832, 6201, 4488, 2717,
910, -910, -2717, -4488, -6201, -7832, -9359, -10764,
-12028, -13133, -13920, -14507, -14731, 5376, -6400, -10496,
-167, -7430, -8001, 6018, 3798, -8237, 9199, 13021,
13112, -1668, 7819, 9571, 10032, -4745, -5896, -1193,
2783, -7334, 6127, 9457, 7876, -7172, -7358, -9170,
-2638, 1873, 9214, 13204, 12437, -2653, 9331, 1642,
4246, -8988, -2562, 3182, 7937, 10069, 8400, -8529,
9477, 75, -9143, -7270, -2740, 8993, 13101, 9543,
5272, -7696, 7309, 10275, 10940, 24, -8122, -8511,
326, 8895, 12073, 8729, 12950, 10038, 9385, -4720,
7869, 2450, 10192, 11313, 10154, 9638, 3854, 6699,
11082, -1026, 10396, 10287, 7953, 12689, 6641, -2348,
9290, 4633, 11247, 9807, 9736, 8440, 9307, 1698,
10214, 8390, 7201, -88, 6193, 12325, 13064, 5333,
};
private readonly int[] HEVAG2 = new int[]
{
0, 0, -6656, -7040, -7680, -7059, -7366, -7522,
-7680, -7680, -7680, -7680, -7680, -7680, -7680, -7680,
-7680, -7680, -7680, -7680, -7680, -7680, -7680, -7680,
-7680, -7680, -7522, -7366, -7059, -9216, -7168, -7424,
-2722, -2221, -3166, -4750, -6946, -2596, 1982, -3044,
-4487, -3744, -4328, -1336, -2562, -4122, 2378, -9117,
-7108, -2062, -2577, -1858, -4483, -1795, -2102, -3509,
-2647, 9183, 1859, -3012, -4792, -1144, -1048, -620,
-7585, -3891, -2735, -483, -3844, -2609, -3297, -2775,
-1882, -2241, -4160, -1958, 3745, 1948, -2835, -1961,
-4270, -3383, 2523, -2867, -3721, -310, -2411, -3067,
-3846, 2194, -1876, -3423, -3847, -2570, -2757, -5006,
-4326, -8597, -2763, -4213, -2716, -1417, -4554, -5659,
-3908, -9810, -3746, 988, 3878, -3375, 3166, -7354,
-4039, -6403, -4125, -2284, -1536, -3436, -1021, -9025,
-2791, 3248, 3316, -7809, -5189, -1290, -4075, 2999,
};
private readonly int[] HEVAG3 = new int[]
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 3328, -3328, -3584,
-494, -2298, -2814, 2649, 3875, -2071, -1382, -3792,
-2250, -6456, 2111, -757, 300, -5486, -4787, -1237,
-1575, -2212, -315, 102, 2126, -2069, -2233, -2674,
-1929, 1860, -1124, -4139, -256, -3182, -828, -946,
-533, -2807, -1730, -714, 2821, 314, 1551, -2432,
108, -298, -2963, -2156, 5936, -683, -3854, 130,
3124, -2907, 434, 391, 665, -1262, -2311, -2337,
419, -541, -2017, 1674, -3007, 302, 1008, -2852,
2135, 1299, 360, 833, 345, -737, 2843, 2249,
728, -805, 1367, -1915, -764, -3354, 231, -1944,
1885, 1748, 802, 219, -706, 1562, -835, 688,
368, -758, 46, -538, 2760, -3284, -2824, 775,
};
private readonly int[] HEVAG4 = new int[]
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, -3072, -2304, -1024,
-541, 424, 289, -1298, -1216, 227, -2316, 1267,
1665, 840, -506, 487, 199, -1493, -6947, -3114,
-1447, 446, -18, 258, -538, 482, 440, -391,
-1637, -5746, -2427, 1370, 622, -6878, 507, -4229,
-2259, 44, -1899, -1421, -1019, 195, -155, -336,
256, -6937, 5, 460, -1089, -2704, 1055, 250,
-3157, -456, -2461, 172, 97, 320, -271, 163,
-933, -2880, -601, -169, 1946, 198, 41, -1161,
-501, -2780, 181, 53, 185, 482, -3397, -1074,
80, -3462, -96, -1437, -3263, 2079, -2089, -4122,
-246, -1619, 61, 222, 473, -176, 509, -3037,
179, -2989, -2614, -4571, -1245, 253, 1877, -1132,
};
}
}