Add xbox ima genh support.

Also fix xbox ima decoder, it was wrong if the decode didn't always start at the block start. Note that this and the nds ima decoder both rely on being run through the file linearly.
I wasn't able to test this on mono wavm or xwav yet, but I think it ought to work.


git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@217 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
halleyscometsw 2008-06-10 01:20:54 +00:00
parent 6f86773158
commit 6524994732
11 changed files with 55 additions and 67 deletions

View File

@ -15,7 +15,6 @@ LAYOUT_OBJS=layout/ast_blocked.o \
layout/interleave.o \
layout/nolayout.o \
layout/xa_blocked.o \
layout/xbox_blocked.o \
layout/caf_blocked.o \
layout/ea_block.o
@ -53,7 +52,7 @@ META_OBJS=meta/adx_header.o \
meta/ea_header.o \
meta/ngc_caf.o \
meta/ps2_vpk.o \
meta/psx_genh.o
meta/genh.o
OBJECTS=vgmstream.o streamfile.o util.o $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS)

View File

@ -77,17 +77,15 @@ void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspac
first_sample = first_sample % 64;
hist1 = read_16bitLE(offset,stream->streamfile);
step_index = read_16bitLE(offset+2,stream->streamfile);
/* Skip sample predictors */
offset+=(4*channelspacing)-5;
if (first_sample == 0) {
hist1 = read_16bitLE(offset+channel*4,stream->streamfile);
step_index = read_16bitLE(offset+channel*4+2,stream->streamfile);
}
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int step = ADPCMTable[step_index];
offset += (i%2?0:1);
if(!(i%8) && channelspacing>1) offset+=4;
offset = stream->offset + 4*channelspacing + (i/8*4*channelspacing+(i%8)/2+4*channel);
sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf;

View File

@ -51,9 +51,6 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
case layout_xa_blocked:
xa_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_xbox_blocked:
xbox_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_ea_blocked:
ea_block_update(vgmstream->next_block_offset,vgmstream);
break;

View File

@ -12,8 +12,6 @@ void halpst_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void xbox_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void ea_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void caf_block_update(off_t block_offset, VGMSTREAM * vgmstream);

View File

@ -1,15 +0,0 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void xbox_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = 36*vgmstream->channels;
vgmstream->next_block_offset = vgmstream->current_block_offset+(off_t)vgmstream->current_block_size;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset +
4*i;
}
}

View File

@ -1,9 +1,10 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
/* GENH is an artificial "generic" header for headerless streams */
VGMSTREAM * init_vgmstream_psx_genh(STREAMFILE *streamFile) {
VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
@ -13,6 +14,7 @@ VGMSTREAM * init_vgmstream_psx_genh(STREAMFILE *streamFile) {
int32_t loop_start;
int32_t loop_end;
char filename[260];
int coding;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -21,8 +23,20 @@ VGMSTREAM * init_vgmstream_psx_genh(STREAMFILE *streamFile) {
/* check header magic */
if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail;
/* check format (reserved for now) */
if (read_32bitLE(0x18,streamFile) != 0) goto fail;
/* check format */
/* 0 = PSX ADPCM */
/* 1 = XBOX IMA ADPCM (36 byte blocks) */
/* ... others to come */
switch (read_32bitLE(0x18,streamFile)) {
case 0:
coding = coding_PSX;
break;
case 1:
coding = coding_XBOX;
break;
default:
goto fail;
}
channel_count = read_32bitLE(0x4,streamFile);
interleave = read_32bitLE(0x8,streamFile);
@ -30,6 +44,8 @@ VGMSTREAM * init_vgmstream_psx_genh(STREAMFILE *streamFile) {
loop_start = read_32bitLE(0x10,streamFile);
loop_end = read_32bitLE(0x14,streamFile);
if (coding == coding_XBOX && channel_count != 2) goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,(loop_start!=-1));
if (!vgmstream) goto fail;
@ -38,27 +54,36 @@ VGMSTREAM * init_vgmstream_psx_genh(STREAMFILE *streamFile) {
vgmstream->channels = channel_count;
vgmstream->sample_rate = sample_rate;
vgmstream->interleave_block_size = interleave;
vgmstream->num_samples = loop_end;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
vgmstream->loop_flag = (loop_start != -1);
vgmstream->coding_type = coding_PSX;
if (channel_count > 1)
{
vgmstream->layout_type = layout_interleave;
} else {
vgmstream->layout_type = layout_none;
vgmstream->coding_type = coding;
switch (coding) {
case coding_PSX:
vgmstream->interleave_block_size = interleave;
if (channel_count > 1)
{
vgmstream->layout_type = layout_interleave;
} else {
vgmstream->layout_type = layout_none;
}
break;
case coding_XBOX:
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 36;
break;
}
vgmstream->meta_type = meta_PSX_GENH;
vgmstream->meta_type = meta_GENH;
/* open the file for reading by each channel */
{
int i;
for (i=0;i<channel_count;i++) {
if (channel_count > 1)
if (channel_count > 1 && vgmstream->layout_type == layout_interleave)
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,interleave);
else
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);

View File

@ -79,6 +79,6 @@ VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_psx_genh(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile);
#endif

View File

@ -1,5 +1,4 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
/* WAVM
@ -16,7 +15,6 @@ VGMSTREAM * init_vgmstream_xbox_wavm(STREAMFILE *streamFile) {
int loop_flag=0;
int channel_count;
off_t start_offset;
int i;
/* check extension, case insensitive */
@ -40,20 +38,16 @@ VGMSTREAM * init_vgmstream_xbox_wavm(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile) / 36 * 64 / vgmstream->channels);
vgmstream->layout_type = layout_xbox_blocked;
vgmstream->current_block_size=36*vgmstream->channels;
vgmstream->current_block_offset=0;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size=36;
xbox_block_update(0,vgmstream);
vgmstream->meta_type = meta_XBOX_WAVM;
start_offset = 0;
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = 0;
if (!vgmstream->ch[i].streamfile) goto fail;
}

View File

@ -1,5 +1,4 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
/* XWAV
@ -61,18 +60,16 @@ VGMSTREAM * init_vgmstream_xbox_xwav(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = read_32bitLE(start_offset,streamFile) / 36 * 64 / vgmstream->channels;
vgmstream->layout_type = layout_xbox_blocked;
vgmstream->current_block_size=36*vgmstream->channels;
vgmstream->current_block_offset=start_offset+4;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size=36;
xbox_block_update(start_offset+4,vgmstream);
vgmstream->meta_type = meta_XBOX_RIFF;
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = start_offset+4;
if (!vgmstream->ch[i].streamfile) goto fail;
}

View File

@ -54,7 +54,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
init_vgmstream_ea,
init_vgmstream_caf,
init_vgmstream_ps2_vpk,
init_vgmstream_psx_genh,
init_vgmstream_genh,
};
#define INIT_VGMSTREAM_FCNS (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0]))
@ -231,7 +231,6 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
case layout_ast_blocked:
case layout_halpst_blocked:
case layout_xa_blocked:
case layout_xbox_blocked:
case layout_ea_blocked:
case layout_caf_blocked:
render_vgmstream_blocked(buffer,sample_count,vgmstream);
@ -302,7 +301,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_XA:
return 14*vgmstream->channels;
case coding_XBOX:
return 64+(4*vgmstream->channels);
return 36;
case coding_EAXA:
return 1; // the frame is variant in size
default:
@ -611,9 +610,6 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
break;
case layout_xa_blocked:
snprintf(temp,TEMPSIZE,"CD-ROM XA");
break;
case layout_xbox_blocked:
snprintf(temp,TEMPSIZE,"XBOX blocked");
break;
case layout_ea_blocked:
snprintf(temp,TEMPSIZE,"Electronic Arts Audio Blocks");
@ -795,8 +791,8 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case meta_PS2_VPK:
snprintf(temp,TEMPSIZE,"VPK Header");
break;
case meta_PSX_GENH:
snprintf(temp,TEMPSIZE,"GENH Generic PSX ADPCM Header");
case meta_GENH:
snprintf(temp,TEMPSIZE,"GENH Generic Header");
break;
default:
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");

View File

@ -42,7 +42,6 @@ typedef enum {
layout_ast_blocked, /* .ast STRM with BLCK blocks*/
layout_halpst_blocked, /* blocks with HALPST-format header */
layout_xa_blocked,
layout_xbox_blocked,
layout_ea_blocked,
layout_caf_blocked,
#if 0
@ -107,7 +106,6 @@ typedef enum {
meta_PSX_XA, /* CD-XA with RIFF header */
meta_PS2_VAGs, /* VAG Stereo from Kingdom Hearts */
meta_PS2_VPK, /* VPK Audio File */
meta_PSX_GENH, /* generic header for PSX ADPCM */
meta_XBOX_WAVM, /* XBOX WAVM File */
meta_XBOX_RIFF, /* XBOX RIFF/WAVE File */
@ -118,6 +116,7 @@ typedef enum {
meta_RAW, /* RAW PCM file */
meta_GENH, /* generic header */
} meta_t;
typedef struct {