mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-28 00:20:47 +01:00
Add EA SCHl Saturn + MT10 mono/int; changed Maxis_ADPCM to Maxis_MT10
Also fixed some issues with ADPCM hist in EA SCHl blocks
This commit is contained in:
parent
a493a8f09d
commit
cce72d7aa5
@ -283,6 +283,7 @@ DECLARE_MULTIPLE_FILE_TYPE("SVS Audio File (*.SVS)", svs);
|
||||
DECLARE_MULTIPLE_FILE_TYPE("SWAG Audio File (*.SWAG)", swag);
|
||||
DECLARE_MULTIPLE_FILE_TYPE("SWAV Audio File (*.SWAV)", swav);
|
||||
DECLARE_MULTIPLE_FILE_TYPE("SWD Audio File (*.SWD)", swd);
|
||||
DECLARE_MULTIPLE_FILE_TYPE("SX Audio File (*.SX)", sx);
|
||||
DECLARE_MULTIPLE_FILE_TYPE("SXD Audio File (*.SXD)", sxd);
|
||||
DECLARE_MULTIPLE_FILE_TYPE("SXD2 Audio File (*.SXD2)", sxd2);
|
||||
|
||||
|
@ -75,8 +75,9 @@ void init_get_high_nibble(VGMSTREAM * vgmstream);
|
||||
|
||||
/* ea_decoder */
|
||||
void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||
void decode_ea_mt10(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_maxis_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_ea_mt10(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_ea_mt10_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_maxis_mt10(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
|
||||
/* sdx2_decoder */
|
||||
void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "coding.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* Various EA ADPCM codecs */
|
||||
/* Various EA ADPCM codecs evolved from CDXA */
|
||||
|
||||
static const int32_t EA_XA_TABLE[28] = {
|
||||
0,0,240,0,
|
||||
@ -13,21 +13,21 @@ static const int32_t EA_XA_TABLE[28] = {
|
||||
0x0000,0x0000,0x0000,0x3F70
|
||||
};
|
||||
|
||||
static const int32_t EA_TABLE[20]= {
|
||||
0x00000000, 0x000000F0, 0x000001CC, 0x00000188,
|
||||
0x00000000, 0x00000000, 0xFFFFFF30, 0xFFFFFF24,
|
||||
0x00000000, 0x00000001, 0x00000003, 0x00000004,
|
||||
0x00000007, 0x00000008, 0x0000000A, 0x0000000B,
|
||||
0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFC
|
||||
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 EAXA, evolved from CDXA */
|
||||
/* EA's main ADPCM, inconsistently called EAXA or EA-XA */
|
||||
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 sample_count;
|
||||
int32_t coef1, coef2;
|
||||
int i, shift;
|
||||
off_t channel_offset = stream->channel_start_offset; //suboffset within channel
|
||||
off_t channel_offset = stream->channel_start_offset; /* suboffset within frame */
|
||||
|
||||
first_sample = first_sample%28;
|
||||
|
||||
@ -45,7 +45,7 @@ void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing
|
||||
channel_offset+=2;
|
||||
}
|
||||
|
||||
// Only increment offset on complete frame
|
||||
/* Only increment offset on complete frame */
|
||||
if (channel_offset-stream->channel_start_offset == (2*28)+5)
|
||||
stream->channel_start_offset += (2*28)+5;
|
||||
|
||||
@ -66,50 +66,45 @@ void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing
|
||||
stream->adpcm_history2_32 = stream->adpcm_history1_32;
|
||||
stream->adpcm_history1_32 = sample;
|
||||
}
|
||||
|
||||
channel_offset += i/2;
|
||||
|
||||
// Only increment offset on complete frame
|
||||
/* Only increment offset on complete frame */
|
||||
if (channel_offset - stream->channel_start_offset == 0x0F)
|
||||
stream->channel_start_offset += 0x0F;
|
||||
}
|
||||
}
|
||||
|
||||
/* EA MicroTalk 10:1 (aka "EA ADPCM") */
|
||||
void decode_ea_mt10(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
|
||||
/* EA MicroTalk 10:1 stereo (aka "EA ADPCM") */
|
||||
void decode_ea_mt10(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;
|
||||
VGMSTREAMCHANNEL *stream = &(vgmstream->ch[channel]);
|
||||
off_t channel_offset=stream->channel_start_offset;
|
||||
|
||||
vgmstream->get_high_nibble = !vgmstream->get_high_nibble; /* for stereo subinterleave, L=high nibble, R=low nibble */
|
||||
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 */ //todo mono/interleave decoder
|
||||
/* header (coefs ch0+ch1 + shift ch0+ch1) */
|
||||
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile);
|
||||
channel_offset++;
|
||||
coef1 = EA_TABLE[(vgmstream->get_high_nibble ? frame_info & 0x0F: frame_info >> 4)];
|
||||
coef2 = EA_TABLE[(vgmstream->get_high_nibble ? frame_info & 0x0F: frame_info >> 4) + 4];
|
||||
coef1 = EA_TABLE[(hn ? frame_info >> 4 : frame_info & 0x0F) + 0];
|
||||
coef2 = EA_TABLE[(hn ? frame_info >> 4 : frame_info & 0x0F) + 4];
|
||||
|
||||
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile);
|
||||
channel_offset++;
|
||||
shift = (vgmstream->get_high_nibble ? frame_info & 0x0F : frame_info >> 4) + 8;
|
||||
|
||||
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;
|
||||
uint8_t sample_byte, sample_nibble;
|
||||
int32_t sample;
|
||||
off_t byte_offset = (stream->offset + channel_offset + i);
|
||||
|
||||
sample_byte = (uint8_t)read_8bit(stream->offset+channel_offset+i,stream->streamfile);
|
||||
sample_byte = (uint8_t)read_8bit(byte_offset,stream->streamfile);
|
||||
sample_nibble = (hn ? sample_byte >> 4 : sample_byte & 0x0F);
|
||||
|
||||
sample = ((((vgmstream->get_high_nibble?
|
||||
sample_byte & 0x0F:
|
||||
sample_byte >> 4
|
||||
) << 0x1C) >> shift) +
|
||||
(coef1 * stream->adpcm_history1_32) + (coef2 * stream->adpcm_history2_32) + 0x80) >> 8;
|
||||
sample = (sample_nibble << 28) >> shift; /* sign extend to 32b and shift */
|
||||
sample = (sample + coef1 * stream->adpcm_history1_32 + coef2 * stream->adpcm_history2_32 + 0x80) >> 8;
|
||||
|
||||
outbuf[sample_count] = clamp16(sample);
|
||||
stream->adpcm_history2_32 = stream->adpcm_history1_32;
|
||||
@ -117,47 +112,79 @@ void decode_ea_mt10(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing,
|
||||
}
|
||||
channel_offset += i;
|
||||
|
||||
// Only increment offset on complete frame
|
||||
/* Only increment offset on complete frame */
|
||||
if(channel_offset - stream->channel_start_offset == 0x1E)
|
||||
stream->channel_start_offset += 0x1E;
|
||||
}
|
||||
|
||||
|
||||
/* EA MicroTalk 5:1, unknown variation */
|
||||
//void decode_ea_mt5(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel)
|
||||
|
||||
|
||||
/* Maxis EAXA, yet another CDXA variation */
|
||||
void decode_maxis_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
|
||||
/* EA MicroTalk 10:1 mono/interleave */
|
||||
void decode_ea_mt10_int(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;
|
||||
int frameSize = channelspacing*15;//mono samples have a frame of 15, stereo files have frames of 30
|
||||
VGMSTREAMCHANNEL *stream = &(vgmstream->ch[channel]);
|
||||
off_t channel_offset=stream->channel_start_offset;
|
||||
int i, sample_count, shift;
|
||||
off_t channel_offset = stream->channel_start_offset; /* suboffset within frame */
|
||||
|
||||
first_sample = first_sample % 28;
|
||||
frame_info = read_8bit(channel_offset,stream->streamfile);
|
||||
|
||||
/* 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 + 0x80) >> 8;
|
||||
|
||||
outbuf[sample_count] = clamp16(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 MicroTalk 5:1, unknown variation with optional PCM blocks */
|
||||
//void decode_ea_mt5(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel)
|
||||
|
||||
/* Maxis MicroTalk 10:1 (mono+stereo), differing slightly in the header layout in stereo mode */
|
||||
void decode_maxis_mt10(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 frameSize = 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];
|
||||
coef2 = EA_TABLE[(frame_info >> 4) + 4];
|
||||
shift = (frame_info & 0x0F)+8;
|
||||
|
||||
channel_offset+=channelspacing;
|
||||
//stream->offset = first_sample*channelspacing/2;
|
||||
|
||||
/* samples */
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
uint8_t sample_byte;
|
||||
uint8_t sample_byte, sample_nibble;
|
||||
int32_t sample;
|
||||
off_t byte_offset = (stream->offset + channel_offset);
|
||||
|
||||
sample_byte = (uint8_t)read_8bit(stream->offset+channel_offset,stream->streamfile);
|
||||
|
||||
sample = (((((i&1)?
|
||||
sample_byte & 0x0F:
|
||||
sample_byte >> 4
|
||||
) << 0x1C) >> shift) +
|
||||
(coef1 * stream->adpcm_history1_32) + (coef2 * stream->adpcm_history2_32) + 0x80) >> 8;
|
||||
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 + 0x80) >> 8;
|
||||
|
||||
outbuf[sample_count] = clamp16(sample);
|
||||
stream->adpcm_history2_32 = stream->adpcm_history1_32;
|
||||
@ -166,11 +193,9 @@ void decode_maxis_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspaci
|
||||
if(i&1)
|
||||
stream->offset+=channelspacing;
|
||||
}
|
||||
|
||||
channel_offset+=i;
|
||||
|
||||
// Only increment offset on complete frame
|
||||
|
||||
/* Only increment offset on complete frame */
|
||||
if (channel_offset - stream->channel_start_offset == frameSize) {
|
||||
stream->channel_start_offset += frameSize;
|
||||
stream->offset=0;
|
||||
|
@ -275,6 +275,7 @@ static const char* extension_list[] = {
|
||||
"swag",
|
||||
"swav",
|
||||
"swd",
|
||||
"sx",
|
||||
"sxd",
|
||||
"sxd2",
|
||||
|
||||
@ -421,6 +422,8 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_XBOX_int, "XBOX 4-bit IMA ADPCM (interleaved)"},
|
||||
{coding_EA_XA, "Electronic Arts EA-XA 4-bit ADPCM"},
|
||||
{coding_EA_MT10, "Electronic Arts MicroTalk (10:1) 4-bit ADPCM"},
|
||||
{coding_EA_MT10_int, "Electronic Arts MicroTalk (10:1) 4-bit ADPCM (interleaved)"},
|
||||
{coding_MAXIS_MT10, "Maxis MicroTalk (10:1) 4-bit ADPCM"},
|
||||
{coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"},
|
||||
{coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"},
|
||||
{coding_CBD2, "Cuberoot-delta-exact (CBD2) 8-bit DPCM"},
|
||||
@ -428,7 +431,6 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_DVI_IMA, "Intel DVI 4-bit IMA ADPCM"},
|
||||
{coding_DVI_IMA_int, "Intel DVI 4-bit IMA ADPCM (interleaved)"},
|
||||
{coding_EACS_IMA, "EACS 4-bit IMA ADPCM"},
|
||||
{coding_MAXIS_ADPCM, "Maxis XA ADPCM"},
|
||||
{coding_IMA_int, "IMA 4-bit ADPCM (interleaved)"},
|
||||
{coding_IMA, "IMA 4-bit ADPCM"},
|
||||
{coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"},
|
||||
|
@ -9,17 +9,16 @@ void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
uint32_t id;
|
||||
size_t file_size, block_size = 0, block_samples;
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE;
|
||||
int16_t (*read_16bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_16bitBE : read_16bitLE;
|
||||
|
||||
|
||||
init_get_high_nibble(vgmstream); /* swap nibble for codecs with stereo subinterleave */
|
||||
|
||||
/* find target block ID and skip the rest */
|
||||
file_size = get_streamfile_size(streamFile);
|
||||
while (block_offset < file_size) {
|
||||
id = read_32bitBE(block_offset+0x00,streamFile);
|
||||
|
||||
block_size = read_32bitLE(block_offset+0x04,streamFile);
|
||||
if (block_size > 0xF0000000) /* size size is always LE, except in early MAC apparently */
|
||||
if (block_size > 0x00F00000) /* size size is always LE, except in early SS/MAC */
|
||||
block_size = read_32bitBE(block_offset+0x04,streamFile);
|
||||
|
||||
if (id == 0x5343446C) /* "SCDl" data block found */
|
||||
@ -63,49 +62,69 @@ void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* set new channel offsets */
|
||||
|
||||
/* set new channel offsets and ADPCM history */
|
||||
/* ADPCM hist could be considered part of the stream/decoder (some EAXA decoders call it "EAXA R1" when it has hist), and BNKs
|
||||
* (with no blocks) also have them in the first offset. To simplify and since DSP also have them, we read them here instead. */
|
||||
switch(vgmstream->coding_type) {
|
||||
/* id, size, unk1, unk2, interleaved data */
|
||||
case coding_PSX:
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
size_t interleave = ((block_size-0x10)/vgmstream->channels) * i;
|
||||
vgmstream->ch[i].offset = block_offset + 0x10 + interleave;
|
||||
size_t interleave = (block_size-0x10) / vgmstream->channels;
|
||||
vgmstream->ch[i].offset = block_offset + 0x10 + i*interleave;
|
||||
}
|
||||
/* at 0x08/0x0c: unknown */
|
||||
/* 0x08/0x0c: unknown (doesn't look like hist or offsets, as 1ch files has them too) */
|
||||
|
||||
break;
|
||||
|
||||
/* id, size, samples, hists-per-channel, stereo/interleaved data */
|
||||
case coding_EA_MT10:
|
||||
case coding_EA_MT10_int:
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
int is_interleaved = vgmstream->coding_type == coding_EA_MT10_int;
|
||||
size_t interleave;
|
||||
|
||||
/* read ADPCM history from all channels before data */
|
||||
vgmstream->ch[i].adpcm_history1_32 = read_16bit(block_offset + 0x0C + (i*0x04) + 0x00,streamFile);
|
||||
vgmstream->ch[i].adpcm_history2_32 = read_16bit(block_offset + 0x0C + (i*0x04) + 0x02,streamFile);
|
||||
|
||||
/* the block can have padding so find the channel size from num_samples */
|
||||
interleave = is_interleaved ? (block_samples / 28 * 0x0f) : 0;
|
||||
vgmstream->ch[i].offset = block_offset + 0x0c + vgmstream->channels*0x04 + i*interleave;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* id, size, samples, offsets-per-channel, interleaved data (w/ optional hist per channel) */
|
||||
default:
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
off_t channel_start;
|
||||
if (vgmstream->coding_type == coding_EA_MT10 && vgmstream->codec_version == 0)
|
||||
channel_start = 0; /* MT10 R1 (codec1 v0) uses stereo, R2 (codec2 v1+) interleaved mono */
|
||||
else
|
||||
channel_start = read_32bit(block_offset+0x0C+(0x04*i),streamFile);
|
||||
off_t channel_start = read_32bit(block_offset + 0x0C + (0x04*i),streamFile);
|
||||
vgmstream->ch[i].offset = block_offset + 0x0C + (0x04*vgmstream->channels) + channel_start;
|
||||
}
|
||||
|
||||
/* read ADPCM history before each channel if needed (there is a small diff vs decoded hist) */
|
||||
if ((vgmstream->coding_type == coding_NGC_DSP) ||
|
||||
(vgmstream->coding_type == coding_EA_XA && vgmstream->codec_version == 0)) {
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
vgmstream->ch[i].adpcm_history1_32 = read_16bit(vgmstream->ch[i].offset+0x00,streamFile);
|
||||
vgmstream->ch[i].adpcm_history3_32 = read_16bit(vgmstream->ch[i].offset+0x02,streamFile);
|
||||
vgmstream->ch[i].offset += 4;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
vgmstream->current_block_offset = block_offset;
|
||||
vgmstream->next_block_offset = block_offset + block_size;
|
||||
vgmstream->current_block_size = 0;
|
||||
vgmstream->current_block_samples = block_samples;
|
||||
|
||||
/* read ADPCM history (there is a small diff vs decoded hist) */
|
||||
if (vgmstream->coding_type == coding_NGC_DSP
|
||||
|| (vgmstream->coding_type == coding_EA_XA && vgmstream->codec_version == 0)
|
||||
) {
|
||||
//int16_t (*read_16bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_16bitBE : read_16bitLE;
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
/* makes the output glitchy in rare cases (Harry Potter and the Chamber of Secrets (Xbox)) */
|
||||
//vgmstream->ch[i].adpcm_history2_32 = read_16bit(vgmstream->ch[i].offset+0x00,streamFile);
|
||||
//vgmstream->ch[i].adpcm_history1_32 = read_16bit(vgmstream->ch[i].offset+0x02,streamFile);
|
||||
vgmstream->ch[i].offset += 4;
|
||||
}
|
||||
}
|
||||
vgmstream->current_block_size = 0; /* uses current_block_samples instead */
|
||||
|
||||
|
||||
/* reset channel sub offset */
|
||||
if (vgmstream->coding_type == coding_EA_MT10 || vgmstream->coding_type == coding_EA_XA) {
|
||||
/* reset channel sub offset for codecs using it */
|
||||
if (vgmstream->coding_type == coding_EA_MT10
|
||||
|| vgmstream->coding_type == coding_EA_MT10_int
|
||||
|| vgmstream->coding_type == coding_EA_XA) {
|
||||
for(i=0;i<vgmstream->channels;i++) {
|
||||
vgmstream->ch[i].channel_start_offset=0;
|
||||
}
|
||||
@ -136,7 +155,7 @@ void eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
vgmstream->current_block_size=block_size-8;
|
||||
|
||||
if(vgmstream->coding_type==coding_EACS_IMA) {
|
||||
init_get_high_nibble(vgmstream);
|
||||
init_get_high_nibble(vgmstream); /* swap nibble marker for codecs with stereo subinterleave */
|
||||
vgmstream->current_block_size=read_32bitLE(block_offset,vgmstream->ch[0].streamfile);
|
||||
|
||||
for(i=0;i<vgmstream->channels;i++) {
|
||||
|
@ -15,7 +15,7 @@
|
||||
#define EA_PLATFORM_PSX 0x01
|
||||
#define EA_PLATFORM_N64 0x02
|
||||
#define EA_PLATFORM_MAC 0x03
|
||||
//#define EA_PLATFORM_SAT 0x04 // ?
|
||||
#define EA_PLATFORM_SAT 0x04
|
||||
#define EA_PLATFORM_PS2 0x05
|
||||
#define EA_PLATFORM_GC_WII 0x06 // reused later for Wii
|
||||
#define EA_PLATFORM_XBOX 0x07
|
||||
@ -28,7 +28,7 @@
|
||||
#define EA_CODEC1_NONE -1
|
||||
//#define EA_CODEC1_S16BE 0x00 //LE too?
|
||||
//#define EA_CODEC1_VAG 0x01
|
||||
#define EA_CODEC1_MT10 0x07 // Need for Speed 2 PC
|
||||
#define EA_CODEC1_MT10 0x07 // Need for Speed 2 PC, Fifa 98 SAT
|
||||
//#define EA_CODEC1_N64 ?
|
||||
|
||||
#define EA_CODEC2_NONE -1
|
||||
@ -84,7 +84,7 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) {
|
||||
|
||||
/* check extension; exts don't seem enforced by EA's tools, but usually:
|
||||
* STR/ASF/MUS ~early, EAM ~mid, SNG/AUD ~late, rest uncommon/one game (ex. STRM: MySims Kingdom Wii) */
|
||||
if (!check_extensions(streamFile,"str,asf,mus,eam,sng,aud,strm,xa,xsf,exa,stm"))
|
||||
if (!check_extensions(streamFile,"str,asf,mus,eam,sng,aud,sx,strm,xa,xsf,exa,stm"))
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
@ -95,7 +95,7 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) {
|
||||
goto fail;
|
||||
|
||||
header_size = read_32bitLE(0x04,streamFile);
|
||||
if (header_size > 0xF0000000) /* size is always LE, except in early MAC apparently */
|
||||
if (header_size > 0x00F00000) /* size is always LE, except in early SS/MAC */
|
||||
header_size = read_32bitBE(0x04,streamFile);
|
||||
|
||||
memset(&ea,0,sizeof(ea_header));
|
||||
@ -132,6 +132,9 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) {
|
||||
break;
|
||||
|
||||
case EA_CODEC2_MT10: /* MicroTalk (10:1), aka EA ADPCM (stereo or interleaved) */
|
||||
if (ea.codec_version==1 || ea.channels == 1)
|
||||
vgmstream->coding_type = coding_EA_MT10_int;
|
||||
else
|
||||
vgmstream->coding_type = coding_EA_MT10;
|
||||
break;
|
||||
|
||||
@ -211,7 +214,6 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) {
|
||||
|
||||
ea_schl_block_update(start_offset,vgmstream);
|
||||
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
@ -395,6 +397,7 @@ static int parse_stream_header(STREAMFILE* streamFile, ea_header* ea, off_t begi
|
||||
|
||||
case 0xFF: /* header end (then 0-padded) */
|
||||
is_header_end = 1;
|
||||
/* offset always 32 padded (ex SHOW.eam) */
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -403,7 +406,8 @@ static int parse_stream_header(STREAMFILE* streamFile, ea_header* ea, off_t begi
|
||||
}
|
||||
}
|
||||
|
||||
if (ea->id && ea->id != 0x65) /* very rarely not specified (FIFA 14) */
|
||||
/* always 0x65 for non-BNK streams, rarely not specified (FIFA 14, some BNKs) */
|
||||
if (ea->id && ea->id != 0x65)
|
||||
goto fail;
|
||||
if (ea->channels > EA_MAX_CHANNELS)
|
||||
goto fail;
|
||||
@ -426,6 +430,7 @@ static int parse_stream_header(STREAMFILE* streamFile, ea_header* ea, off_t begi
|
||||
case EA_PLATFORM_PSX: ea->version = EA_VERSION_V0; break; // assumed
|
||||
case EA_PLATFORM_N64: ea->version = EA_VERSION_V0; break; // assumed
|
||||
case EA_PLATFORM_MAC: ea->version = EA_VERSION_V0; break;
|
||||
case EA_PLATFORM_SAT: ea->version = EA_VERSION_V0; break;
|
||||
case EA_PLATFORM_PS2: ea->version = EA_VERSION_V1; break;
|
||||
case EA_PLATFORM_GC_WII: ea->version = EA_VERSION_V2; break;
|
||||
case EA_PLATFORM_XBOX: ea->version = EA_VERSION_V2; break;
|
||||
@ -475,6 +480,7 @@ static int parse_stream_header(STREAMFILE* streamFile, ea_header* ea, off_t begi
|
||||
case EA_PLATFORM_PSX: ea->sample_rate = 22050; break;
|
||||
case EA_PLATFORM_N64: ea->sample_rate = 22050; break;
|
||||
case EA_PLATFORM_MAC: ea->sample_rate = 22050; break;
|
||||
case EA_PLATFORM_SAT: ea->sample_rate = 22050; break;
|
||||
case EA_PLATFORM_PS2: ea->sample_rate = 22050; break;
|
||||
case EA_PLATFORM_GC_WII: ea->sample_rate = 24000; break;
|
||||
case EA_PLATFORM_XBOX: ea->sample_rate = 24000; break;
|
||||
@ -490,6 +496,7 @@ static int parse_stream_header(STREAMFILE* streamFile, ea_header* ea, off_t begi
|
||||
/* affects blocks/codecs */
|
||||
if (ea->platform == EA_PLATFORM_N64
|
||||
|| ea->platform == EA_PLATFORM_MAC
|
||||
|| ea->platform == EA_PLATFORM_SAT
|
||||
|| ea->platform == EA_PLATFORM_GC_WII
|
||||
|| ea->platform == EA_PLATFORM_X360
|
||||
|| ea->platform == EA_PLATFORM_GENERIC) {
|
||||
@ -498,8 +505,9 @@ static int parse_stream_header(STREAMFILE* streamFile, ea_header* ea, off_t begi
|
||||
|
||||
/* config MT/EAXA variations */
|
||||
if (ea->codec2 == EA_CODEC2_MT10) {
|
||||
if (ea->version > EA_VERSION_V0)
|
||||
ea->codec_version = 1; /* 0=stereo (early), 1:interleaved */
|
||||
if (ea->version > EA_VERSION_V0 ||
|
||||
(ea->platform == EA_PLATFORM_SAT && ea->version == EA_VERSION_V0))
|
||||
ea->codec_version = 1; /* 0=stereo (early), 1=interleaved */
|
||||
}
|
||||
else if (ea->codec2 == EA_CODEC2_EAXA) {
|
||||
/* console EAXA V2 uses hist, as does PC/MAC V1 */
|
||||
@ -530,8 +538,7 @@ static int get_ea_total_samples(STREAMFILE* streamFile, off_t start_offset, cons
|
||||
id = read_32bitBE(block_offset+0x00,streamFile);
|
||||
|
||||
block_size = read_32bitLE(block_offset+0x04,streamFile);
|
||||
VGM_ASSERT(block_size > 0xF0000000, "EA: BE block size in MAC\n");
|
||||
if (block_size > 0xF0000000) /* size is always LE, except in early MAC apparently */
|
||||
if (block_size > 0x00F00000) /* size is always LE, except in early SS/MAC */
|
||||
block_size = read_32bitBE(block_offset+0x04,streamFile);
|
||||
|
||||
if (id == 0x5343446C) { /* "SCDl" data block found */
|
||||
@ -589,7 +596,7 @@ static off_t get_ea_mpeg_start_offset(STREAMFILE* streamFile, off_t start_offset
|
||||
id = read_32bitBE(block_offset+0x00,streamFile);
|
||||
|
||||
block_size = read_32bitLE(block_offset+0x04,streamFile);
|
||||
if (block_size > 0xF0000000) /* size is always LE, except in early MAC apparently */
|
||||
if (block_size > 0x00F00000) /* size is always LE, except in early SS/MAC */
|
||||
block_size = read_32bitBE(block_offset+0x04,streamFile);
|
||||
|
||||
if (id == 0x5343446C) { /* "SCDl" data block found */
|
||||
|
@ -29,7 +29,7 @@ VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) {
|
||||
start_offset = 0x18;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitLE(0x0C,streamFile);
|
||||
vgmstream->coding_type = coding_MAXIS_ADPCM;
|
||||
vgmstream->coding_type = coding_MAXIS_MT10;
|
||||
vgmstream->num_samples = read_32bitLE(0x04,streamFile)/2/channel_count;
|
||||
|
||||
if (loop_flag) {
|
||||
@ -37,7 +37,6 @@ VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) {
|
||||
vgmstream->loop_end_sample = (read_32bitBE(0x0C,streamFile)-start_offset)/8/channel_count*14;
|
||||
}
|
||||
|
||||
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->meta_type = meta_MAXIS_XA;
|
||||
|
||||
|
@ -1044,10 +1044,11 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
case coding_XBOX_int:
|
||||
case coding_FSB_IMA:
|
||||
return 64;
|
||||
case coding_EA_MT10:
|
||||
case coding_EA_MT10_int:
|
||||
case coding_EA_XA:
|
||||
return 28;
|
||||
case coding_MAXIS_ADPCM:
|
||||
case coding_EA_MT10:
|
||||
case coding_MAXIS_MT10:
|
||||
return 14*vgmstream->channels;
|
||||
case coding_WS:
|
||||
/* only works if output sample size is 8 bit, which always is for WS ADPCM */
|
||||
@ -1189,10 +1190,12 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
case coding_XBOX_int:
|
||||
case coding_FSB_IMA:
|
||||
return 36;
|
||||
case coding_MAXIS_ADPCM:
|
||||
return 15*vgmstream->channels;
|
||||
case coding_EA_MT10:
|
||||
return 30;
|
||||
return 0x1E;
|
||||
case coding_EA_MT10_int:
|
||||
return 0x0F;
|
||||
case coding_MAXIS_MT10:
|
||||
return 0x0F*vgmstream->channels;
|
||||
case coding_EA_XA:
|
||||
return 1; // the frame is variant in size
|
||||
case coding_WS:
|
||||
@ -1492,14 +1495,21 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
break;
|
||||
case coding_EA_MT10:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_ea_mt10(vgmstream,buffer+samples_written*vgmstream->channels+chan,
|
||||
decode_ea_mt10(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
samples_to_do,chan);
|
||||
}
|
||||
break;
|
||||
case coding_MAXIS_ADPCM:
|
||||
case coding_EA_MT10_int:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_maxis_adpcm(vgmstream,buffer+samples_written*vgmstream->channels+chan,
|
||||
decode_ea_mt10_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
samples_to_do,chan);
|
||||
}
|
||||
break;
|
||||
case coding_MAXIS_MT10:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_maxis_mt10(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
samples_to_do,chan);
|
||||
}
|
||||
|
@ -105,9 +105,10 @@ typedef enum {
|
||||
coding_PSX_cfg, /* Sony PS ADPCM with configurable frame size (FF XI, SGXD type 5, Bizarre Creations) */
|
||||
coding_HEVAG, /* Sony PSVita ADPCM */
|
||||
|
||||
coding_EA_MT10, /* Electronic Arts MicroTalk (10:1) ADPCM ('EA ADPCM')*/
|
||||
coding_EA_MT10, /* Electronic Arts MicroTalk (10:1) ADPCM (stereo) aka EA ADPCM */
|
||||
coding_EA_MT10_int, /* Electronic Arts MicroTalk (10:1) ADPCM (mono/interleave) */
|
||||
coding_MAXIS_MT10, /* Maxis MicroTalk (10:1) ADPCM */
|
||||
coding_EA_XA, /* Electronic Arts EA-XA ADPCM */
|
||||
coding_MAXIS_ADPCM, /* Maxis ADPCM */
|
||||
|
||||
coding_XBOX, /* XBOX IMA ADPCM */
|
||||
coding_XBOX_int, /* XBOX IMA ADPCM (interleaved) */
|
||||
|
Loading…
Reference in New Issue
Block a user