rwav and improved rwar support in rwsd

git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@563 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
halleyscometsw 2009-01-20 01:03:33 +00:00
parent 85d14007c7
commit 48075dedd6
6 changed files with 86 additions and 26 deletions

View File

@ -186,7 +186,7 @@ multi:
- .genh (lots)
- .nwa (16 bit PCM, NWA DPCM)
- .psw (PSX ADPCM, GC DSP ADPCM)
- .rwar (GC DSP ADPCM, 8/16 bit PCM)
- .rwar,.rwav (GC DSP ADPCM, 8/16 bit PCM)
- .rwsd (GC DSP ADPCM, 8/16 bit PCM)
- .rsd (PSX ADPCM, 16 bit PCM, GC DSP ADPCM, Xbox IMA ADPCM)
- .sad (GC DSP ADPCM, NDS IMA ADPCM, Procyon Studios NDS ADPCM)

View File

@ -2,27 +2,46 @@
#include "../coding/coding.h"
#include "../util.h"
static off_t read_rwar(off_t offset, int *version, STREAMFILE *streamFile)
static off_t read_rwav(off_t offset, int *version, off_t *start_offset, off_t *info_chunkp, STREAMFILE *streamFile)
{
off_t info_chunk;
off_t data_chunk;
off_t wave_offset;
if ((uint32_t)read_32bitBE(offset,streamFile)!=0x52574156) /* "RWAV" */
goto fail;
if ((uint32_t)read_32bitBE(offset+4,streamFile)!=0xFEFF0102) /* version 2 */
goto fail;
info_chunk = offset+read_32bitBE(offset+0x10,streamFile);
if ((uint32_t)read_32bitBE(info_chunk,streamFile)!=0x494e464f) /* "INFO" */
goto fail;
data_chunk = offset+read_32bitBE(offset+0x18,streamFile);
if ((uint32_t)read_32bitBE(data_chunk,streamFile)!=0x44415441) /* "DATA" */
goto fail;
*start_offset = data_chunk + 8;
*info_chunkp = info_chunk + 8;
*version = 2;
wave_offset = info_chunk - 8;
return wave_offset;
fail:
return -1;
}
static off_t read_rwar(off_t offset, int *version, off_t *start_offset, off_t *info_chunk, STREAMFILE *streamFile)
{
off_t wave_offset;
if ((uint32_t)read_32bitBE(offset,streamFile)!=0x52574152) /* "RWAR" */
goto fail;
if ((uint32_t)read_32bitBE(offset+4,streamFile)!=0xFEFF0100) /* version 0 */
goto fail;
switch (read_32bitBE(offset+4,streamFile))
{
case 0xFEFF0100:
if ((uint32_t)read_32bitBE(offset+0x60,streamFile)!=0x52574156) /* "RWAV" */
goto fail;
wave_offset = offset+0x78;
*version = 0;
break;
default:
goto fail;
}
wave_offset = read_rwav(offset+0x60,version,start_offset,info_chunk,streamFile);
*version = 0;
return wave_offset;
fail:
return -1;
}
@ -36,12 +55,14 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) {
coding_t coding_type;
off_t info_chunk;
off_t wave_offset;
size_t wave_length;
int codec_number;
int channel_count;
int loop_flag;
int rwar = 0;
int rwav = 0;
int version = -1;
off_t start_offset = 0;
@ -52,15 +73,31 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) {
if (strcasecmp("rwsd",filename_extension(filename)))
{
if (strcasecmp("rwar",filename_extension(filename)))
goto fail;
{
if (strcasecmp("rwav",filename_extension(filename)))
{
goto fail;
}
else
{
rwav = 1;
}
}
else
{
rwar = 1;
}
}
/* check header */
if (rwar)
{
wave_offset = read_rwar(0,&version,streamFile);
wave_offset = read_rwar(0,&version,&start_offset,&info_chunk,streamFile);
if (wave_offset < 0) goto fail;
}
else if (rwav)
{
wave_offset = read_rwav(0,&version,&start_offset,&info_chunk,streamFile);
if (wave_offset < 0) goto fail;
}
else
@ -90,7 +127,7 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) {
break;
case 0xFEFF0103:
wave_offset = read_rwar(0xe0,&version,streamFile);
wave_offset = read_rwar(0xe0,&version,&start_offset,&info_chunk,streamFile);
if (wave_offset < 0) goto fail;
rwar = 1;
@ -139,6 +176,8 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) {
if (rwar)
vgmstream->meta_type = meta_RWAR;
else if (rwav)
vgmstream->meta_type = meta_RWAV;
else
vgmstream->meta_type = meta_RWSD;
@ -146,19 +185,34 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) {
off_t coef_offset;
int i,j;
coef_offset=0x6c;
for (j=0;j<vgmstream->channels;j++) {
if (rwar || rwav)
{
/* This is pretty nasty, so an explaination is in order.
* At 0x10 in the info_chunk is the offset of a table with
* one entry per channel. Each entry in this table is itself
* an offset to a set of information for the channel. The
* first element in the set is the offset into DATA of the
* channel. The stream_size read far below just happens to
* hit on this properly for stereo. The second element is the
* offset of the coefficient table for the channel. */
coef_offset = info_chunk +
read_32bitBE(info_chunk +
read_32bitBE(info_chunk+
read_32bitBE(info_chunk+0x10,streamFile)+j*4,
streamFile) + 4, streamFile);
} else {
coef_offset=wave_offset+0x6c+j*0x30;
}
for (i=0;i<16;i++) {
vgmstream->ch[j].adpcm_coef[i]=read_16bitBE(wave_offset+coef_offset+j*0x30+i*2,streamFile);
vgmstream->ch[j].adpcm_coef[i]=read_16bitBE(coef_offset+i*2,streamFile);
}
}
}
if (rwar)
if (rwar || rwav)
{
if (version == 0)
start_offset = wave_offset + 0xF0;
/* */
}
else
{

View File

@ -1565,7 +1565,10 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
snprintf(temp,TEMPSIZE,"Nintendo RWSD header (single stream)");
break;
case meta_RWAR:
snprintf(temp,TEMPSIZE,"Nintendo RWAR header (single stream)");
snprintf(temp,TEMPSIZE,"Nintendo RWAR header (single RWAV stream)");
break;
case meta_RWAV:
snprintf(temp,TEMPSIZE,"Nintendo RWAV header");
break;
case meta_PSX_XA:
snprintf(temp,TEMPSIZE,"RIFF/CDXA header");

View File

@ -174,6 +174,7 @@ typedef enum {
meta_AST, /* AST */
meta_RWSD, /* single-stream RWSD */
meta_RWAR, /* single-stream RWAR */
meta_RWAV, /* contents of RWAR */
meta_RSTM_SPM, /* RSTM with 44->22khz hack */
meta_THP,
meta_RSTM_shrunken, /* Atlus' mutant shortened RSTM */

View File

@ -160,6 +160,7 @@ gchar *vgmstream_exts [] = {
"mwv",
"gbts",
"p2bt",
"rwav",
/* terminator */
NULL
};

View File

@ -222,6 +222,7 @@ char * extension_list[] = {
"gbts\0GBTS Audio File (*.GBTS)\0",
"aax\0AAX Audio File (*.AAX)\0",
"mwv\0MWV Audio File (*.MWV)\0",
"rwav\0RWAV Audio File (*.RWAV)\0",
};
void about(HWND hwndParent) {