mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2025-01-10 23:59:27 +08:00
Added EncodeADPCM, optimised DecodeADPCM
This commit is contained in:
parent
84419cc2b7
commit
6c1afda9a2
@ -1048,23 +1048,18 @@ namespace CodeWalker.GameFiles
|
|||||||
public static byte[] DecodeADPCM(byte[] data, int sampleCount)
|
public static byte[] DecodeADPCM(byte[] data, int sampleCount)
|
||||||
{
|
{
|
||||||
byte[] dataPCM = new byte[data.Length * 4];
|
byte[] dataPCM = new byte[data.Length * 4];
|
||||||
int predictor = 0, step_index = 0, step = 0;
|
int predictor = 0, stepIndex = 0;
|
||||||
int readingOffset = 0, writingOffset = 0, bytesInBlock = 0;
|
int readingOffset = 0, writingOffset = 0, bytesInBlock = 0;
|
||||||
|
|
||||||
void parseNibble(byte nibble)
|
void parseNibble(byte nibble)
|
||||||
{
|
{
|
||||||
step_index = clip(step_index + ima_index_table[nibble], 0, 88);
|
var step = ima_step_table[stepIndex];
|
||||||
|
int diff = ((((nibble & 7) << 1) + 1) * step) >> 3;
|
||||||
int diff = step >> 3;
|
if ((nibble & 8) != 0) diff = -diff;
|
||||||
if ((nibble & 4) > 0) diff += step;
|
predictor = predictor + diff;
|
||||||
if ((nibble & 2) > 0) diff += step >> 1;
|
stepIndex = clip(stepIndex + ima_index_table[nibble], 0, 88);
|
||||||
if ((nibble & 1) > 0) diff += step >> 2;
|
|
||||||
if ((nibble & 8) > 0) predictor -= diff;
|
|
||||||
else predictor += diff;
|
|
||||||
|
|
||||||
step = ima_step_table[step_index];
|
|
||||||
|
|
||||||
int samplePCM = clip(predictor, -32768, 32767);
|
int samplePCM = clip(predictor, -32768, 32767);
|
||||||
|
|
||||||
dataPCM[writingOffset] = (byte)(samplePCM & 0xFF);
|
dataPCM[writingOffset] = (byte)(samplePCM & 0xFF);
|
||||||
dataPCM[writingOffset + 1] = (byte)((samplePCM >> 8) & 0xFF);
|
dataPCM[writingOffset + 1] = (byte)((samplePCM >> 8) & 0xFF);
|
||||||
writingOffset += 2;
|
writingOffset += 2;
|
||||||
@ -1074,9 +1069,8 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
if (bytesInBlock == 0)
|
if (bytesInBlock == 0)
|
||||||
{
|
{
|
||||||
step_index = clip(data[readingOffset], 0, 88);
|
stepIndex = clip(data[readingOffset], 0, 88);
|
||||||
predictor = BitConverter.ToInt16(data, readingOffset + 2);
|
predictor = BitConverter.ToInt16(data, readingOffset + 2);
|
||||||
step = ima_step_table[step_index];
|
|
||||||
bytesInBlock = 2044;
|
bytesInBlock = 2044;
|
||||||
readingOffset += 4;
|
readingOffset += 4;
|
||||||
}
|
}
|
||||||
@ -1093,6 +1087,91 @@ namespace CodeWalker.GameFiles
|
|||||||
return dataPCM;
|
return dataPCM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] EncodeADPCM(byte[] data, int sampleCount)
|
||||||
|
{
|
||||||
|
byte[] dataPCM = new byte[data.Length / 4];
|
||||||
|
|
||||||
|
int predictor = 0, stepIndex = 0;
|
||||||
|
int readingOffset = 0, writingOffset = 0, bytesInBlock = 0;
|
||||||
|
|
||||||
|
short readSample()
|
||||||
|
{
|
||||||
|
var s = BitConverter.ToInt16(data, readingOffset);
|
||||||
|
readingOffset += 2;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeInt16(short v)
|
||||||
|
{
|
||||||
|
var ba = BitConverter.GetBytes(v);
|
||||||
|
dataPCM[writingOffset++] = ba[0];
|
||||||
|
dataPCM[writingOffset++] = ba[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
byte encodeNibble(int pcm16)
|
||||||
|
{
|
||||||
|
int delta = pcm16 - predictor;
|
||||||
|
uint value = 0;
|
||||||
|
if (delta < 0)
|
||||||
|
{
|
||||||
|
value = 8;
|
||||||
|
delta = -delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
var step = ima_step_table[stepIndex];
|
||||||
|
var diff = step >> 3;
|
||||||
|
if (delta > step)
|
||||||
|
{
|
||||||
|
value |= 4;
|
||||||
|
delta -= step;
|
||||||
|
diff += step;
|
||||||
|
}
|
||||||
|
step >>= 1;
|
||||||
|
if (delta > step)
|
||||||
|
{
|
||||||
|
value |= 2;
|
||||||
|
delta -= step;
|
||||||
|
diff += step;
|
||||||
|
}
|
||||||
|
step >>= 1;
|
||||||
|
if (delta > step)
|
||||||
|
{
|
||||||
|
value |= 1;
|
||||||
|
diff += step;
|
||||||
|
}
|
||||||
|
|
||||||
|
predictor += (((value & 8) != 0) ? -diff : diff);
|
||||||
|
predictor = clip(predictor, short.MinValue, short.MaxValue);
|
||||||
|
|
||||||
|
stepIndex += ima_index_table[value & 7];
|
||||||
|
stepIndex = clip(stepIndex, 0, 88);
|
||||||
|
|
||||||
|
return (byte)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((writingOffset < dataPCM.Length) && (sampleCount > 0))
|
||||||
|
{
|
||||||
|
if (bytesInBlock == 0)
|
||||||
|
{
|
||||||
|
writeInt16((short)stepIndex);
|
||||||
|
writeInt16((short)predictor);
|
||||||
|
bytesInBlock = 2044;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var s0 = readSample();
|
||||||
|
var s1 = readSample();
|
||||||
|
var b0 = encodeNibble(s0);
|
||||||
|
var b1 = encodeNibble(s1);
|
||||||
|
var b = (b0 & 0x0F) + ((b1 & 0x0F) << 4);
|
||||||
|
dataPCM[writingOffset++] = (byte)b;
|
||||||
|
bytesInBlock--;
|
||||||
|
sampleCount -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataPCM;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user