From 652499473214bd52038323d06b7ac321abe454d2 Mon Sep 17 00:00:00 2001 From: halleyscometsw Date: Tue, 10 Jun 2008 01:20:54 +0000 Subject: [PATCH] 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 --- src/Makefile | 3 +- src/coding/ima_decoder.c | 12 ++++---- src/layout/blocked.c | 3 -- src/layout/layout.h | 2 -- src/layout/xbox_blocked.c | 15 ---------- src/meta/{psx_genh.c => genh.c} | 49 +++++++++++++++++++++++++-------- src/meta/meta.h | 2 +- src/meta/xbox_wavm.c | 12 ++------ src/meta/xbox_xwav.c | 9 ++---- src/vgmstream.c | 12 +++----- src/vgmstream.h | 3 +- 11 files changed, 55 insertions(+), 67 deletions(-) delete mode 100644 src/layout/xbox_blocked.c rename src/meta/{psx_genh.c => genh.c} (63%) diff --git a/src/Makefile b/src/Makefile index 36e51591..d58c4dc3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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) diff --git a/src/coding/ima_decoder.c b/src/coding/ima_decoder.c index 5e91b0fd..d4611ea4 100644 --- a/src/coding/ima_decoder.c +++ b/src/coding/ima_decoder.c @@ -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; i1) 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; diff --git a/src/layout/blocked.c b/src/layout/blocked.c index 761c41d0..e0eb2fc9 100644 --- a/src/layout/blocked.c +++ b/src/layout/blocked.c @@ -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; diff --git a/src/layout/layout.h b/src/layout/layout.h index 4b7b5f76..72872d95 100644 --- a/src/layout/layout.h +++ b/src/layout/layout.h @@ -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); diff --git a/src/layout/xbox_blocked.c b/src/layout/xbox_blocked.c deleted file mode 100644 index 9b56ef1d..00000000 --- a/src/layout/xbox_blocked.c +++ /dev/null @@ -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;ichannels;i++) { - vgmstream->ch[i].offset = vgmstream->current_block_offset + - 4*i; - } -} diff --git a/src/meta/psx_genh.c b/src/meta/genh.c similarity index 63% rename from src/meta/psx_genh.c rename to src/meta/genh.c index 68501a65..685f8a21 100644 --- a/src/meta/psx_genh.c +++ b/src/meta/genh.c @@ -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 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); diff --git a/src/meta/meta.h b/src/meta/meta.h index f425c870..8ee84b01 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -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 diff --git a/src/meta/xbox_wavm.c b/src/meta/xbox_wavm.c index 34d380fd..d3ce66f7 100644 --- a/src/meta/xbox_wavm.c +++ b/src/meta/xbox_wavm.c @@ -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;ich[i].streamfile = streamFile->open(streamFile,filename,36); + vgmstream->ch[i].offset = 0; if (!vgmstream->ch[i].streamfile) goto fail; } diff --git a/src/meta/xbox_xwav.c b/src/meta/xbox_xwav.c index 493efb3c..46e04ea1 100644 --- a/src/meta/xbox_xwav.c +++ b/src/meta/xbox_xwav.c @@ -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;ich[i].streamfile = streamFile->open(streamFile,filename,36); + vgmstream->ch[i].offset = start_offset+4; if (!vgmstream->ch[i].streamfile) goto fail; } diff --git a/src/vgmstream.c b/src/vgmstream.c index e05bad73..f430ebf4 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -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"); diff --git a/src/vgmstream.h b/src/vgmstream.h index 616bc3be..692683d9 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -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 {