mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 23:10:10 +01:00
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:
parent
6f86773158
commit
6524994732
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user