mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-12-20 18:35:52 +01:00
99 lines
4.5 KiB
C
99 lines
4.5 KiB
C
|
#include "coding.h"
|
||
|
|
||
|
|
||
|
/* a somewhat IMA-like mix of step+step index all in one */
|
||
|
static const int32_t ptadpcm_table[(16+16)*16] = { /* 16 of (step+index) + 16 values in a nibble */
|
||
|
-14, 2, -10, 2, -7, 1, -5, 1, -3, 0, -2, 0, -1, 0, 0, 0,
|
||
|
0, 0, 1, 0, 2, 0, 3, 0, 5, 1, 7, 1, 10, 2, 14, 2,
|
||
|
-28, 3, -20, 3, -14, 2, -10, 2, -7, 1, -5, 1, -3, 1, -1, 0,
|
||
|
1, 0, 3, 1, 5, 1, 7, 1, 10, 2, 14, 2, 20, 3, 28, 3,
|
||
|
-56, 4, -40, 4, -28, 3, -20, 3, -14, 2, -10, 2, -6, 2, -2, 1,
|
||
|
2, 1, 6, 2, 10, 2, 14, 2, 20, 3, 28, 3, 40, 4, 56, 4,
|
||
|
-112, 5, -80, 5, -56, 4, -40, 4, -28, 3, -20, 3, -12, 3, -4, 2,
|
||
|
4, 2, 12, 3, 20, 3, 28, 3, 40, 4, 56, 4, 80, 5, 112, 5,
|
||
|
-224, 6, -160, 6, -112, 5, -80, 5, -56, 4, -40, 4, -24, 4, -8, 3,
|
||
|
8, 3, 24, 4, 40, 4, 56, 4, 80, 5, 112, 5, 160, 6, 224, 6,
|
||
|
-448, 7, -320, 7, -224, 6, -160, 6, -112, 5, -80, 5, -48, 5, -16, 4,
|
||
|
16, 4, 48, 5, 80, 5, 112, 5, 160, 6, 224, 6, 320, 7, 448, 7,
|
||
|
-896, 8, -640, 8, -448, 7, -320, 7, -224, 6, -160, 6, -96, 6, -32, 5,
|
||
|
32, 5, 96, 6, 160, 6, 224, 6, 320, 7, 448, 7, 640, 8, 896, 8,
|
||
|
-1792, 9, -1280, 9, -896, 8, -640, 8, -448, 7, -320, 7, -192, 7, -64, 6,
|
||
|
64, 6, 192, 7, 320, 7, 448, 7, 640, 8, 896, 8, 1280, 9, 1792, 9,
|
||
|
-3584, 10, -2560, 10, -1792, 9, -1280, 9, -896, 8, -640, 8, -384, 8, -128, 7,
|
||
|
128, 7, 384, 8, 640, 8, 896, 8, 1280, 9, 1792, 9, 2560, 10, 3584, 10,
|
||
|
-7168, 11, -5120, 11, -3584, 10, -2560, 10, -1792, 9, -1280, 9, -768, 9, -256, 8,
|
||
|
256, 8, 768, 9, 1280, 9, 1792, 9, 2560, 10, 3584, 10, 5120, 11, 7168, 11,
|
||
|
-14336, 11, -10240, 11, -7168, 11, -5120, 11, -3584, 10, -2560, 10, -1536, 10, -512, 9,
|
||
|
512, 9, 1536, 10, 2560, 10, 3584, 10, 5120, 11, 7168, 11, 10240, 11, 14336, 11,
|
||
|
-28672, 11, -20480, 11, -14336, 11, -10240, 11, -7168, 11, -5120, 11, -3072, 11, -1024, 10,
|
||
|
1024, 10, 3072, 11, 5120, 11, 7168, 11, 10240, 11, 14336, 11, 20480, 11, 28672, 11,
|
||
|
/* rest is 0s */
|
||
|
};
|
||
|
|
||
|
/* Platinum "PtADPCM" custom ADPCM for Wwise (reverse engineered from .exes). */
|
||
|
void decode_ptadpcm(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size) {
|
||
|
off_t frame_offset;
|
||
|
int i, frames_in, sample_count = 0, samples_done = 0;
|
||
|
size_t bytes_per_frame, samples_per_frame;
|
||
|
int16_t hist1, hist2;
|
||
|
int index, step;
|
||
|
|
||
|
/* external interleave (variable size), mono */
|
||
|
bytes_per_frame = frame_size;
|
||
|
samples_per_frame = 2 + (frame_size - 0x05) * 2;
|
||
|
frames_in = first_sample / samples_per_frame;
|
||
|
first_sample = first_sample % samples_per_frame;
|
||
|
|
||
|
/* parse frame header */
|
||
|
frame_offset = stream->offset + bytes_per_frame*frames_in;
|
||
|
hist2 = read_16bitLE(frame_offset+0x00,stream->streamfile);
|
||
|
hist1 = read_16bitLE(frame_offset+0x02,stream->streamfile);
|
||
|
index = (uint8_t)read_8bit(frame_offset+0x04,stream->streamfile);
|
||
|
|
||
|
VGM_ASSERT_ONCE(index > 12, "PTADPCM: incorrect index at %x\n", (uint32_t)frame_offset);
|
||
|
|
||
|
/* write header samples (needed) */
|
||
|
if (sample_count >= first_sample && samples_done < samples_to_do) {
|
||
|
outbuf[samples_done * channelspacing] = hist2;
|
||
|
samples_done++;
|
||
|
}
|
||
|
sample_count++;
|
||
|
if (sample_count >= first_sample && samples_done < samples_to_do) {
|
||
|
outbuf[samples_done * channelspacing] = hist1;
|
||
|
samples_done++;
|
||
|
}
|
||
|
sample_count++;
|
||
|
|
||
|
/* decode nibbles */
|
||
|
for (i = first_sample; i < first_sample + samples_to_do; i++) {
|
||
|
int32_t new_sample;
|
||
|
uint8_t nibbles = (uint8_t)read_8bit(frame_offset+0x05 + i/2,stream->streamfile);
|
||
|
uint8_t nibble;
|
||
|
|
||
|
nibble = !(i&1) ? /* low nibble first */
|
||
|
(nibbles >> 0) & 0xF :
|
||
|
(nibbles >> 4) & 0xF;
|
||
|
|
||
|
step = ptadpcm_table[2*(nibble + 16*index) + 0];
|
||
|
index = ptadpcm_table[2*(nibble + 16*index) + 1];
|
||
|
new_sample = clamp16(step + 2*hist1 - hist2);
|
||
|
|
||
|
if (sample_count >= first_sample && samples_done < samples_to_do) {
|
||
|
outbuf[samples_done * channelspacing] = new_sample;
|
||
|
samples_done++;
|
||
|
}
|
||
|
sample_count++;
|
||
|
|
||
|
hist2 = hist1;
|
||
|
hist1 = new_sample;
|
||
|
}
|
||
|
|
||
|
//stream->adpcm_history1_32 = hist1;
|
||
|
//stream->adpcm_history2_32 = hist2;
|
||
|
}
|
||
|
|
||
|
size_t ptadpcm_bytes_to_samples(size_t bytes, int channels, size_t frame_size) {
|
||
|
if (channels <= 0 || frame_size < 0x06) return 0;
|
||
|
return (bytes / channels / frame_size) * ((frame_size-0x05) * 2);
|
||
|
}
|