fix maxis xa

git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@682 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
fastelbja 2009-09-01 21:28:55 +00:00
parent 017010d22b
commit 5d0e2a4fb6
5 changed files with 88 additions and 19 deletions

View File

@ -55,6 +55,7 @@ void init_get_high_nibble(VGMSTREAM * vgmstream);
void decode_eaxa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_ea_adpcm(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);
#ifdef VGM_USE_VORBIS
void decode_ogg_vorbis(ogg_vorbis_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels);

View File

@ -96,8 +96,12 @@ void decode_ea_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing,
channel_offset++;
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,stream->streamfile);
int32_t sample = ((((vgmstream->get_high_nibble?
uint8_t sample_byte;
int32_t sample;
sample_byte = (uint8_t)read_8bit(stream->offset+channel_offset+i,stream->streamfile);
sample = ((((vgmstream->get_high_nibble?
sample_byte & 0x0F:
sample_byte >> 4
) << 0x1C) >> shift) +
@ -115,3 +119,49 @@ void decode_ea_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing,
stream->channel_start_offset+=0x1E;
}
void decode_maxis_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
uint8_t frame_info;
int32_t sample_count;
long coef1,coef2;
int i,shift;
VGMSTREAMCHANNEL *stream = &(vgmstream->ch[channel]);
off_t channel_offset=stream->channel_start_offset;
first_sample = first_sample%28;
frame_info = read_8bit(channel_offset,stream->streamfile);
coef1 = EA_TABLE[frame_info >> 4];
coef2 = EA_TABLE[(frame_info >> 4) + 4];
shift = (frame_info & 0x0F)+8;
channel_offset+=2;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t sample_byte;
int32_t sample;
sample_byte = (uint8_t)read_8bit(stream->offset+channel_offset+i/2,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;
outbuf[sample_count] = clamp16(sample);
stream->adpcm_history2_32 = stream->adpcm_history1_32;
stream->adpcm_history1_32 = sample;
if(i&1)
stream->offset++;
}
channel_offset+=i;
// Only increment offset on complete frame
if(channel_offset-stream->channel_start_offset==0x1E) {
stream->channel_start_offset+=0x1E;
stream->offset=0;
}
}

View File

@ -1,7 +1,7 @@
#include "meta.h"
#include "../util.h"
/* GCUB - found in 'Sega Soccer Slam' */
/* Maxis XA - found in 'Sim City 3000' */
VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[260];
@ -28,19 +28,12 @@ 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_EA_ADPCM;
vgmstream->num_samples = vgmstream->num_samples = (int32_t)((get_streamfile_size(streamFile)-start_offset)* 2 / vgmstream->channels);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitBE(0x0C,streamFile)-start_offset)/8/channel_count*14;
}
vgmstream->coding_type = coding_MAXIS_ADPCM;
vgmstream->num_samples = read_32bitLE(0x04,streamFile)/2/channel_count;
vgmstream->layout_type = layout_none;
// vgmstream->interleave_block_size = 0x8000; // read_32bitBE(0x04,streamFile);
vgmstream->meta_type = meta_MAXIS_XA;
/* open the file for reading */
{
int i;
@ -49,11 +42,8 @@ VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) {
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
vgmstream->ch[i].channel_start_offset=start_offset+i;
vgmstream->ch[i].offset=0;
}
}

View File

@ -709,7 +709,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_EAXA:
return 28;
case coding_EA_ADPCM:
return 14*vgmstream->channels;
case coding_MAXIS_ADPCM:
return 14*vgmstream->channels;
case coding_WS:
/* only works if output sample size is 8 bit, which is always
is for WS ADPCM */
@ -962,9 +963,19 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
break;
case coding_PSX:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_psx(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
if(vgmstream->skip_last_channel)
{
if(chan!=vgmstream->channels-1) {
decode_psx(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do);
}
} else {
decode_psx(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do);
}
}
break;
case coding_PSX_badflags:
@ -1009,6 +1020,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do,chan);
}
break;
case coding_MAXIS_ADPCM:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_maxis_adpcm(vgmstream,buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do,chan);
}
break;
#ifdef VGM_USE_VORBIS
case coding_ogg_vorbis:
decode_ogg_vorbis(vgmstream->codec_data,
@ -1392,6 +1410,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case coding_EACS_IMA:
snprintf(temp,TEMPSIZE,"EACS 4-bit IMA ADPCM");
break;
case coding_MAXIS_ADPCM:
snprintf(temp,TEMPSIZE,"Maxis XA (EA ADPCM Variant)");
break;
case coding_INT_IMA:
snprintf(temp,TEMPSIZE,"Interleaved 4-bit IMA ADPCM");
break;
@ -2252,6 +2273,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case meta_CAFF:
snprintf(temp,TEMPSIZE,"Apple Core Audio Format Header");
break;
case meta_MAXIS_XA:
snprintf(temp,TEMPSIZE,"Maxis XAI Header");
break;
default:
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");
}

View File

@ -58,6 +58,7 @@ typedef enum {
coding_INT_XBOX, /* XBOX 'real interleaved' IMA */
coding_EAXA, /* EA/XA ADPCM */
coding_EA_ADPCM, /* EA ADPCM */
coding_MAXIS_ADPCM, /* MAXIS ADPCM */
coding_NDS_PROCYON, /* NDS Procyon Studio ADPCM */
#ifdef VGM_USE_VORBIS
@ -118,6 +119,7 @@ typedef enum {
layout_halpst_blocked, /* blocks with HALPST-format header */
layout_xa_blocked,
layout_ea_blocked,
layout_maxis_blocked,
layout_eacs_blocked,
layout_caf_blocked,
layout_wsi_blocked,
@ -514,6 +516,8 @@ typedef struct {
void * start_vgmstream; /* a copy of the VGMSTREAM as it was at the beginning of the stream */
int32_t thpNextFrameSize;
int skip_last_channel;
/* Data the codec needs for the whole stream. This is for codecs too
* different from vgmstream's structure to be reasonably shoehorned into