mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-29 19:37:30 +01:00
fix maxis xa
git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@682 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
parent
017010d22b
commit
5d0e2a4fb6
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user