vgmstream/src/coding/ea_decoder.c

225 lines
9.9 KiB
C
Raw Normal View History

#include "coding.h"
#include "../util.h"
/* Various EA ADPCM codecs evolved from CDXA */
static const int32_t EA_XA_TABLE[28] = {
0,0,240,0,
460,-208,0x0188,-220,
0x0000,0x0000,0x00F0,0x0000,
0x01CC,0x0000,0x0188,0x0000,
0x0000,0x0000,0x0000,0x0000,
-208,-1,-220,-1,
0x0000,0x0000,0x0000,0x3F70
};
static const int EA_TABLE[20] = {
0, 240, 460, 392,
0, 0, -208, -220,
0, 1, 3, 4,
7, 8, 10, 11,
0, -1, -3, -4
};
/* EA XA v2 (inconsistently called EAXA or EA-XA too); like ea_xa_int but with "PCM samples" flag and doesn't add 128 on nibble expand */
void decode_ea_xa_v2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
uint8_t frame_info;
int32_t sample_count;
int32_t coef1, coef2;
int i, shift;
off_t channel_offset = stream->channel_start_offset; /* suboffset within frame */
first_sample = first_sample%28;
/* header */
frame_info = (uint8_t)read_8bit(stream->offset+channel_offset,stream->streamfile);
channel_offset++;
if (frame_info == 0xEE) { /* PCM frame (used in later revisions), samples always BE */
stream->adpcm_history1_32 = read_16bitBE(stream->offset+channel_offset+0x00,stream->streamfile);
stream->adpcm_history2_32 = read_16bitBE(stream->offset+channel_offset+0x02,stream->streamfile);
channel_offset += 4;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
outbuf[sample_count] = read_16bitBE(stream->offset+channel_offset,stream->streamfile);
channel_offset+=2;
}
/* Only increment offset on complete frame */
if (channel_offset-stream->channel_start_offset == (2*28)+5)
stream->channel_start_offset += (2*28)+5;
} else { /* ADPCM frame */
coef1 = EA_XA_TABLE[(((frame_info >> 4) & 0x0F) << 1)];
coef2 = EA_XA_TABLE[(((frame_info >> 4) & 0x0F) << 1) + 1];
shift = (frame_info & 0x0F) + 8;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t sample_byte = (uint8_t)read_8bit(stream->offset+channel_offset+i/2,stream->streamfile);
int32_t sample = ((((i&1?
sample_byte & 0x0F:
sample_byte >> 4
) << 0x1C) >> shift) +
(coef1 * stream->adpcm_history1_32) + (coef2 * stream->adpcm_history2_32)) >> 8;
sample = clamp16(sample);
outbuf[sample_count] = sample;
stream->adpcm_history2_32 = stream->adpcm_history1_32;
stream->adpcm_history1_32 = sample;
}
channel_offset += i/2;
/* Only increment offset on complete frame */
if (channel_offset - stream->channel_start_offset == 0x0F)
stream->channel_start_offset += 0x0F;
}
}
/* EA XA v1 stereo (aka "EA ADPCM") */
void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
uint8_t frame_info;
int32_t coef1, coef2;
int i, sample_count, shift;
off_t channel_offset = stream->channel_start_offset; /* suboffset within frame */
int hn = (channel==0); /* high nibble marker for stereo subinterleave, ch0/L=high nibble, ch1/R=low nibble */
first_sample = first_sample % 28;
/* header (coefs ch0+ch1 + shift ch0+ch1) */
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile);
channel_offset++;
coef1 = EA_TABLE[(hn ? frame_info >> 4 : frame_info & 0x0F) + 0];
coef2 = EA_TABLE[(hn ? frame_info >> 4 : frame_info & 0x0F) + 4];
shift = (frame_info & 0x0F) + 8;
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile);
channel_offset++;
shift = (hn ? frame_info >> 4 : frame_info & 0x0F) + 8;
/* samples */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t sample_byte, sample_nibble;
int32_t sample;
off_t byte_offset = (stream->offset + channel_offset + i);
sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile);
sample_nibble = (hn ? sample_byte >> 4 : sample_byte & 0x0F);
sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8;
sample = clamp16(sample);
outbuf[sample_count] = sample;
stream->adpcm_history2_32 = stream->adpcm_history1_32;
stream->adpcm_history1_32 = sample;
}
channel_offset += i;
/* Only increment offset on complete frame */
if(channel_offset - stream->channel_start_offset == 0x1E)
stream->channel_start_offset += 0x1E;
}
/* EA-XA v1 mono/interleave */
void decode_ea_xa_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
uint8_t frame_info;
int32_t coef1, coef2;
int i, sample_count, shift;
off_t channel_offset = stream->channel_start_offset; /* suboffset within frame */
first_sample = first_sample % 28;
/* header (coefs+shift ch0) */
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile);
channel_offset++;
coef1 = EA_TABLE[(frame_info >> 4) + 0];
coef2 = EA_TABLE[(frame_info >> 4) + 4];
shift = (frame_info & 0x0F) + 8;
/* samples */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t sample_byte, sample_nibble;
int32_t sample;
off_t byte_offset = (stream->offset + channel_offset + i/2);
sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile);
sample_nibble = (!(i%2) ? sample_byte >> 4 : sample_byte & 0x0F); /* i=even > high nibble */
sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8;
sample = clamp16(sample);
outbuf[sample_count] = sample;
stream->adpcm_history2_32 = stream->adpcm_history1_32;
stream->adpcm_history1_32 = sample;
}
channel_offset += i/2;
/* Only increment offset on complete frame */
if(channel_offset - stream->channel_start_offset == 0x0F)
stream->channel_start_offset += 0x0F;
}
/* Maxis EA-XA v1 (mono+stereo), differing slightly in the header layout in stereo mode */
void decode_maxis_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
uint8_t frame_info;
int32_t coef1, coef2;
int i, sample_count, shift;
off_t channel_offset = stream->channel_start_offset;
int frame_size = channelspacing * 15; /* mono samples have a frame of 15, stereo files have frames of 30 */
first_sample = first_sample % 28;
/* header (coefs+shift ch0 + coefs+shift ch1) */
frame_info = read_8bit(channel_offset,stream->streamfile);
channel_offset += channelspacing;
coef1 = EA_TABLE[(frame_info >> 4) + 0];
coef2 = EA_TABLE[(frame_info >> 4) + 4];
shift = (frame_info & 0x0F) + 8;
/* samples */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t sample_byte, sample_nibble;
int32_t sample;
off_t byte_offset = (stream->offset + channel_offset);
sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile);
sample_nibble = (i&1) ? sample_byte & 0x0F : sample_byte >> 4;
sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 128) >> 8;
sample = clamp16(sample);
outbuf[sample_count] = sample;
stream->adpcm_history2_32 = stream->adpcm_history1_32;
stream->adpcm_history1_32 = sample;
if(i&1)
stream->offset+=channelspacing;
}
channel_offset+=i;
/* Only increment offset on complete frame */
if (channel_offset - stream->channel_start_offset == frame_size) {
stream->channel_start_offset += frame_size;
stream->offset=0;
}
}
/* EA MicroTalk 10:1 / 5:1 */
/**
* Rarely used but can be found in the wild: FIFA 2001 (PS2), FIFA Soccer 2002 (PS2)
*
* Decoding algorithm is unknown; some info found by analyzing sx.exe output:
* - Comes in 10:1 or 5:1 compression varieties (the later's byte layout looks similar but has roughly double frame size)
* - Also with "PCM samples" flag before each frame (later version) or without (first version)
* - When PCM flag is 0xEE it has 16b ? + 16b num_samples + PCM samples placed right after the frame, but they
* are written *before* (presumably so they have something while the frame is decoded), like EALayer3.
* - VBR ADPCM, apparently similar to Westwood VBR ADPCM: first byte seems a header with mode+count, but after it may
* be 8 bytes(?) of coefs/hist (unlike Westwood's), then data. Samples per frame changes with the mode used.
* ex. decoding pure silence (0000) takes 0x2E (10:1) or 0x48 (5:1) into 432 samples (RLE mode)
* - Variable frame size but seems to range from 0x20 to 0x80 (in 5:1 at least)
* - After a new SCDl block, first byte (in each channel) is a flag but various values have no effect in the output
* (01=first block, 00=normal block?) and should be skipped in the block parser.
*
*/
//void decode_ea_mt10(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {