mirror of
https://github.com/emu-russia/pureikyubu.git
synced 2025-04-02 10:42:15 -04:00
2.4 KiB
2.4 KiB
GC DVD ADPCM Decoder
Based on dtkmake reversing.
Get next 32 Byte chunk
uint8_t adpcmBuf[32];
fread ( adpcmBuf, 1, 32, f);
Check
{
if ( buf[0] != buf[2] )
{
// invalid ADPCM file
}
if ( buf[1] != buf[3] )
{
// invalid ADPCM file
}
}
Decode 28 bytes of samples into 0x70 bytes PCM
uint8_t * adpcmData = &adpcmBuf[4];
typedef struct _LRSample
{
uint16_t l;
uint16_t r;
} LRSample;
LRSample pcmData[28];
for (int i=0; i<28; i++)
{
pcmData[i].l = DecodeLeftSample ( adpcmData[i] & 0xF, adpcmBuf[0], 0);
pcmData[i].r = DecodeRightSample ( adpcmData[i] >> 4, adpcmBuf[1], 0);
}
Decode Sample
typedef int Nibble;
int16_t DecodeLeftSample ( int arg_0, int arg_4, bool init)
{
int16_t res;
if (init)
{
Yn[0] = 0; // Для Right sample просто две других аналогичных переменных
Yn[1] = 0;
res = 0;
}
else
{
Nibble var_4 = arg_4 >> 4;
Nibble var_8 = arg_4 & 0xF;
int32_t var_18 = MulSomething(var_4, Yn[0], Yn[1]);
int16_t var_C = Shifts1(arg_0, var_8);
int32_t var_14 = Shifts2(var_C, var_18);
res = Clamp(var_14);
Yn[1] = Yn[0];
Yn[0] = var_14;
}
return res;
}
int32_t MulSomething(Nibble arg_0, int32_t arg_4, int32_t arg_8)
{
int16_t var_4 = 0;
int16_t var_8 = 0;
switch (arg_0)
{
case 0:
var_4 = 0;
var_8 = 0;
break;
case 1:
var_4 = 60;
var_8 = 0;
break;
case 2:
var_4 = 115;
var_8 = -52;
break;
case 3:
var_4 = 98;
var_8 = -55;
break;
}
int32_t edx = (int32_t)var_4 * arg_4;
int32_t eax = (int32_t)var_8 * arg_8;
int32_t var_C = (edx + eax + 32) >> 6;
return max(-0x200000, min(var_C, 0x1FFFFF) );
}
int16_t Shifts1(Nibble arg_0, Nibble arg_4)
{
int16_t var_4 = (int16_t)arg_0 << 12;
return var_4 >> arg_4;
}
int32_t Shifts2(int16_t arg_0, int32_t arg_4)
{
return ((int32_t)arg_0 << 6) + arg_4;
}
// Clamp
uint16_t Clamp(int32_t arg_0)
{
int32_t var_8 = arg_0 >> 6;
return (uint16_t)max(-0x8000, min(var_8, 0x7FFF));
}
Write chunk into WAV
fwrite ( &pcmData, 1, sizeof(pcmData), wav);