add .str CTRL support

git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@274 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
halleyscometsw 2008-07-02 03:57:21 +00:00
parent c1ef5cf529
commit cb58b5f241
12 changed files with 201 additions and 4 deletions

View File

@ -92,6 +92,7 @@ File types supported by this version of vgmstream:
- .wsi (Wii DSP ADPCM) - .wsi (Wii DSP ADPCM)
- .aifc (SDX2 DPCM, DVI IMA ADPCM) - .aifc (SDX2 DPCM, DVI IMA ADPCM)
- .aiff (8/16 bit PCM) - .aiff (8/16 bit PCM)
- .str (SDX2 DPCM)
Enjoy! Enjoy!
-hcs -hcs

View File

@ -19,7 +19,8 @@ LAYOUT_OBJS=layout/ast_blocked.o \
layout/xa_blocked.o \ layout/xa_blocked.o \
layout/caf_blocked.o \ layout/caf_blocked.o \
layout/ea_block.o \ layout/ea_block.o \
layout/wsi_blocked.o layout/wsi_blocked.o \
layout/str_ctrl_blocked.o
META_OBJS=meta/adx_header.o \ META_OBJS=meta/adx_header.o \
meta/afc_header.o \ meta/afc_header.o \
@ -58,7 +59,8 @@ META_OBJS=meta/adx_header.o \
meta/genh.o \ meta/genh.o \
meta/ogg_vorbis_file.o \ meta/ogg_vorbis_file.o \
meta/ps2_bmdx.o \ meta/ps2_bmdx.o \
meta/aifc.o meta/aifc.o \
meta/str_ctrl.o
OBJECTS=vgmstream.o streamfile.o util.o $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS) OBJECTS=vgmstream.o streamfile.o util.o $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS)

View File

@ -4,6 +4,6 @@ AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir)
AM_MAKEFLAGS=-f Makefile.unix AM_MAKEFLAGS=-f Makefile.unix
liblayout_la_LDFLAGS = liblayout_la_LDFLAGS =
liblayout_la_SOURCES = ast_blocked.c blocked.c caf_blocked.c ea_block.c halpst_blocked.c interleave.c nolayout.c xa_blocked.c wsi_blocked.c liblayout_la_SOURCES = ast_blocked.c blocked.c caf_blocked.c ea_block.c halpst_blocked.c interleave.c nolayout.c xa_blocked.c wsi_blocked.c str_ctrl_blocked.c
EXTRA_DIST = layout.h EXTRA_DIST = layout.h

View File

@ -60,6 +60,9 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
case layout_wsi_blocked: case layout_wsi_blocked:
wsi_block_update(vgmstream->next_block_offset,vgmstream); wsi_block_update(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_str_ctrl_blocked:
str_ctrl_block_update(vgmstream->next_block_offset,vgmstream);
break;
default: default:
break; break;
} }

View File

@ -18,6 +18,8 @@ void caf_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void wsi_block_update(off_t block_offset, VGMSTREAM * vgmstream); void wsi_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void str_ctrl_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_nolayout(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); void render_vgmstream_nolayout(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);

View File

@ -0,0 +1,54 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void str_ctrl_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
off_t current_chunk;
size_t file_size;
int i;
STREAMFILE *streamfile;
int FoundSSMP = 0;
off_t SSMP_offset = -1;
current_chunk = block_offset;
streamfile = vgmstream->ch[0].streamfile;
file_size = get_streamfile_size(streamfile);
/* we may have to skip some chunks */
while (!FoundSSMP && current_chunk < file_size) {
if (current_chunk+read_32bitBE(current_chunk+4,streamfile)>=file_size)
break;
switch (read_32bitBE(current_chunk,streamfile)) {
case 0x534e4453: /* SNDS */
/* SSMP */
if (read_32bitBE(current_chunk+0x10,streamfile)==0x53534d50) {
FoundSSMP = 1;
SSMP_offset = current_chunk;
}
break;
case 0x46494c4c: /* FILL, the main culprit */
default:
break;
}
current_chunk += read_32bitBE(current_chunk+4,streamfile);
}
if (!FoundSSMP) {
/* if we couldn't find it all we can do is try playing the current
* block, which is going to suck */
vgmstream->current_block_offset = block_offset;
}
vgmstream->current_block_offset = SSMP_offset;
vgmstream->current_block_size = (read_32bitBE(
vgmstream->current_block_offset+4,
vgmstream->ch[0].streamfile) - 0x18) * vgmstream->channels;
vgmstream->next_block_offset = vgmstream->current_block_offset +
read_32bitBE(vgmstream->current_block_offset+4,
vgmstream->ch[0].streamfile);
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x18;
}
}

View File

@ -346,6 +346,10 @@
RelativePath=".\meta\aifc.c" RelativePath=".\meta\aifc.c"
> >
</File> </File>
<File
RelativePath=".\meta\str_ctrl.c"
>
</File>
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter
@ -466,6 +470,10 @@
RelativePath=".\layout\wsi_blocked.c" RelativePath=".\layout\wsi_blocked.c"
> >
</File> </File>
<File
RelativePath=".\layout\str_ctrl_blocked.c"
>
</File>
</Filter> </Filter>
</Filter> </Filter>
</Files> </Files>

View File

@ -4,6 +4,6 @@ AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir)
AM_MAKEFLAGS=-f Makefile.unix AM_MAKEFLAGS=-f Makefile.unix
libmeta_la_LDFLAGS = libmeta_la_LDFLAGS =
libmeta_la_SOURCES = Cstr.c adx_header.c afc_header.c agsc.c ast.c brstm.c ea_header.c gcsw.c halpst.c nds_strm.c ngc_adpdtk.c ngc_caf.c ngc_dsp_std.c ps2_ads.c ps2_exst.c ps2_ild.c ps2_int.c ps2_mib.c ps2_mic.c ps2_npsf.c ps2_pnb.c ps2_rxw.c ps2_str.c ps2_svag.c ps2_vag.c ps2_vpk.c psx_cdxa.c raw.c rs03.c rsf.c rwsd.c psx_gms.c xbox_xwav.c xbox_wavm.c genh.c ogg_vorbis_file.c ps2_bmdx.c aifc.c libmeta_la_SOURCES = Cstr.c adx_header.c afc_header.c agsc.c ast.c brstm.c ea_header.c gcsw.c halpst.c nds_strm.c ngc_adpdtk.c ngc_caf.c ngc_dsp_std.c ps2_ads.c ps2_exst.c ps2_ild.c ps2_int.c ps2_mib.c ps2_mic.c ps2_npsf.c ps2_pnb.c ps2_rxw.c ps2_str.c ps2_svag.c ps2_vag.c ps2_vpk.c psx_cdxa.c raw.c rs03.c rsf.c rwsd.c psx_gms.c xbox_xwav.c xbox_wavm.c genh.c ogg_vorbis_file.c ps2_bmdx.c aifc.c str_ctrl.c
EXTRA_DIST = meta.h EXTRA_DIST = meta.h

View File

@ -93,4 +93,6 @@ VGMSTREAM * init_vgmstream_wsi(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_aifc(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_aifc(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_str_ctrl(STREAMFILE * streamFile);
#endif #endif

115
src/meta/str_ctrl.c Normal file
View File

@ -0,0 +1,115 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../layout/layout.h"
#include "../util.h"
/* 3DO format, .str extension and CTRL header, blocks and AIFF-C style
* format specifier. Blocks are not IFF-compliant. */
VGMSTREAM * init_vgmstream_str_ctrl(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[260];
int channel_count;
int loop_flag = 0;
off_t SHDR_offset = -1;
int FoundSHDR = 0;
size_t file_size;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("str",filename_extension(filename))) goto fail;
/* check for opening CTRL chunk */
if (read_32bitBE(0x0,streamFile) != 0x4354524c) /* CTRL */
goto fail;
file_size = get_streamfile_size(streamFile);
/* scan chunks until we find a SNDS containing a SHDR */
{
off_t current_chunk;
current_chunk = read_32bitBE(0x4,streamFile) + 0;
while (!FoundSHDR && current_chunk < file_size) {
if (current_chunk < 0) goto fail;
if (current_chunk+read_32bitBE(current_chunk+4,streamFile) >=
file_size) goto fail;
switch (read_32bitBE(current_chunk,streamFile)) {
case 0x534e4453: /* SNDS */
switch (read_32bitBE(current_chunk+16,streamFile)) {
case 0x53484452: /* SHDR */
FoundSHDR = 1;
SHDR_offset = current_chunk+16;
break;
default:
break;
}
break;
default:
/* ignore others for now */
break;
}
current_chunk += read_32bitBE(current_chunk+4,streamFile);
}
}
if (!FoundSHDR) goto fail;
/* details */
channel_count = read_32bitBE(SHDR_offset+0x20,streamFile);
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples =
read_32bitBE(SHDR_offset+0x2c,streamFile) * /* frame count? */
read_32bitBE(SHDR_offset+0x18,streamFile); /* frame size? */
vgmstream->sample_rate = read_32bitBE(SHDR_offset+0x1c,streamFile);
/* channels and loop flag are set by allocate_vgmstream */
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
switch (read_32bitBE(SHDR_offset+0x24,streamFile)) {
case 0x53445832: /* SDX2 */
vgmstream->coding_type = coding_SDX2;
vgmstream->interleave_block_size = 1;
break;
default:
goto fail;
}
vgmstream->layout_type = layout_str_ctrl_blocked;
vgmstream->meta_type = meta_STR_CTRL;
/* open the file for reading by each channel */
{
int i;
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,
STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[0].streamfile) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = vgmstream->ch[0].streamfile;
}
}
/* start me up */
str_ctrl_block_update(0,vgmstream);
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -62,6 +62,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
init_vgmstream_ps2_bmdx, init_vgmstream_ps2_bmdx,
init_vgmstream_wsi, init_vgmstream_wsi,
init_vgmstream_aifc, init_vgmstream_aifc,
init_vgmstream_str_ctrl,
}; };
#define INIT_VGMSTREAM_FCNS (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0])) #define INIT_VGMSTREAM_FCNS (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0]))
@ -271,6 +272,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
case layout_ea_blocked: case layout_ea_blocked:
case layout_caf_blocked: case layout_caf_blocked:
case layout_wsi_blocked: case layout_wsi_blocked:
case layout_str_ctrl_blocked:
render_vgmstream_blocked(buffer,sample_count,vgmstream); render_vgmstream_blocked(buffer,sample_count,vgmstream);
break; break;
} }
@ -725,6 +727,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
snprintf(temp,TEMPSIZE,"Ogg"); snprintf(temp,TEMPSIZE,"Ogg");
break; break;
#endif #endif
case layout_str_ctrl_blocked:
snprintf(temp,TEMPSIZE,".str CTRL blocked");
break;
default: default:
snprintf(temp,TEMPSIZE,"INCONCEIVABLE"); snprintf(temp,TEMPSIZE,"INCONCEIVABLE");
} }
@ -922,6 +927,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case meta_AIFF: case meta_AIFF:
snprintf(temp,TEMPSIZE,"Audio Interchange File Format"); snprintf(temp,TEMPSIZE,"Audio Interchange File Format");
break; break;
case meta_STR_CTRL:
snprintf(temp,TEMPSIZE,".str CTRL SHDR chunk");
break;
default: default:
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET"); snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");
} }

View File

@ -56,6 +56,7 @@ typedef enum {
layout_ea_blocked, layout_ea_blocked,
layout_caf_blocked, layout_caf_blocked,
layout_wsi_blocked, layout_wsi_blocked,
layout_str_ctrl_blocked,
#if 0 #if 0
layout_strm_blocked, /* */ layout_strm_blocked, /* */
#endif #endif
@ -142,6 +143,7 @@ typedef enum {
meta_AIFC, /* Audio Interchange File Format AIFF-C */ meta_AIFC, /* Audio Interchange File Format AIFF-C */
meta_AIFF, /* Audio Interchange File Format */ meta_AIFF, /* Audio Interchange File Format */
meta_STR_CTRL, /* .str with CTRL header */
} meta_t; } meta_t;
typedef struct { typedef struct {