mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-17 23:36:41 +01:00
Fix RIFF even-sized chunks, PCM GUID and add channel layout
This commit is contained in:
parent
d9296c6693
commit
78d1af6f35
108
src/meta/riff.c
108
src/meta/riff.c
@ -87,6 +87,8 @@ typedef struct {
|
||||
int channel_count;
|
||||
uint32_t block_size;
|
||||
int bps;
|
||||
off_t extra_size;
|
||||
uint32_t channel_layout;
|
||||
|
||||
int coding_type;
|
||||
int interleave;
|
||||
@ -99,12 +101,24 @@ static int read_fmt(int big_endian, STREAMFILE * streamFile, off_t current_chunk
|
||||
fmt->offset = current_chunk;
|
||||
fmt->size = read_32bit(current_chunk+0x04,streamFile);
|
||||
|
||||
fmt->codec = (uint16_t)read_16bit(current_chunk+0x08,streamFile);
|
||||
fmt->sample_rate = read_32bit(current_chunk+0x0c,streamFile);
|
||||
fmt->channel_count = read_16bit(current_chunk+0x0a,streamFile);
|
||||
fmt->block_size = read_16bit(current_chunk+0x14,streamFile);
|
||||
fmt->bps = read_16bit(current_chunk+0x16,streamFile);
|
||||
fmt->interleave = 0;
|
||||
/* WAVEFORMAT */
|
||||
fmt->codec = (uint16_t)read_16bit(current_chunk+0x08,streamFile);
|
||||
fmt->channel_count = read_16bit(current_chunk+0x0a,streamFile);
|
||||
fmt->sample_rate = read_32bit(current_chunk+0x0c,streamFile);
|
||||
//fmt->avg_bps = read_32bit(current_chunk+0x10,streamFile);
|
||||
fmt->block_size = read_16bit(current_chunk+0x14,streamFile);
|
||||
fmt->bps = read_16bit(current_chunk+0x16,streamFile);
|
||||
/* WAVEFORMATEX */
|
||||
if (fmt->size >= 0x10) {
|
||||
fmt->extra_size = read_16bit(current_chunk+0x18,streamFile);
|
||||
/* 0x1a+ depends on codec (ex. coef table for MSADPCM, samples_per_frame in MS-IMA, etc) */
|
||||
}
|
||||
/* WAVEFORMATEXTENSIBLE */
|
||||
if (fmt->codec == 0xFFFE && fmt->extra_size >= 0x16) {
|
||||
//fmt->extra_samples = read_16bit(current_chunk+0x1a,streamFile); /* valid_bits_per_sample or samples_per_block */
|
||||
fmt->channel_layout = read_32bit(current_chunk+0x1c,streamFile);
|
||||
/* 0x10 guid at 0x20 */
|
||||
}
|
||||
|
||||
switch (fmt->codec) {
|
||||
case 0x00: /* Yamaha ADPCM (raw) [Headhunter (DC), Bomber hehhe (DC)] (unofficial) */
|
||||
@ -191,19 +205,34 @@ static int read_fmt(int big_endian, STREAMFILE * streamFile, off_t current_chunk
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
case 0xFFFE: /* WAVEFORMATEXTENSIBLE */
|
||||
case 0xFFFE: { /* WAVEFORMATEXTENSIBLE (see ksmedia.h for known GUIDs)*/
|
||||
uint32_t guid1 = (uint32_t)read_32bit (current_chunk+0x20,streamFile);
|
||||
uint32_t guid2 = ((uint16_t)read_16bit (current_chunk+0x24,streamFile) << 16u) |
|
||||
((uint16_t)read_16bit(current_chunk+0x26,streamFile));
|
||||
uint32_t guid3 = (uint32_t)read_32bitBE(current_chunk+0x28,streamFile);
|
||||
uint32_t guid4 = (uint32_t)read_32bitBE(current_chunk+0x2c,streamFile);
|
||||
//;VGM_LOG("RIFF: guid %08x %08x %08x %08x\n", guid1, guid2, guid3, guid4);
|
||||
|
||||
/* ATRAC3plus GUID (0xBFAA23E9 58CB7144 A119FFFA 01E4CE62) */
|
||||
if (read_32bit(current_chunk+0x20,streamFile) == 0xE923AABF &&
|
||||
read_16bit(current_chunk+0x24,streamFile) == (int16_t)0xCB58 &&
|
||||
read_16bit(current_chunk+0x26,streamFile) == 0x4471 &&
|
||||
read_32bitLE(current_chunk+0x28,streamFile) == 0xFAFF19A1 &&
|
||||
read_32bitLE(current_chunk+0x2C,streamFile) == 0x62CEE401) {
|
||||
/* PCM GUID (0x00000001,0000,0010,80,00,00,AA,00,38,9B,71) */
|
||||
if (guid1 == 0x00000001 && guid2 == 0x00000010 && guid3 == 0x800000AA && guid4 == 0x00389B71) {
|
||||
switch (fmt->bps) {
|
||||
case 16:
|
||||
fmt->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE;
|
||||
fmt->interleave = 0x02;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* ATRAC3plus GUID (0xE923AABF,CB58,4471,A1,19,FF,FA,01,E4,CE,62) */
|
||||
if (guid1 == 0xE923AABF && guid2 == 0xCB584471 && guid3 == 0xA119FFFA && guid4 == 0x01E4CE62) {
|
||||
#ifdef VGM_USE_MAIATRAC3PLUS
|
||||
uint16_t bztmp = read_16bit(current_chunk+0x32,streamFile);
|
||||
bztmp = (bztmp >> 8) | (bztmp << 8);
|
||||
fmt->coding_type = coding_AT3plus;
|
||||
fmt->block_size = (bztmp & 0x3FF) * 8 + 8; //should match fmt->block_size
|
||||
fmt->block_size = (bztmp & 0x3FF) * 8 + 8; /* should match fmt->block_size */
|
||||
#elif defined(VGM_USE_FFMPEG)
|
||||
fmt->coding_type = coding_FFmpeg;
|
||||
break;
|
||||
@ -212,11 +241,8 @@ static int read_fmt(int big_endian, STREAMFILE * streamFile, off_t current_chunk
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ATRAC9 GUID 47E142D2-36BA-4d8d-88FC-61654F8C836C (D242E147 BA368D4D 88FC6165 4F8C836C) */
|
||||
if (read_32bitBE(current_chunk+0x20,streamFile) == 0xD242E147 &&
|
||||
read_32bitBE(current_chunk+0x24,streamFile) == 0xBA368D4D &&
|
||||
read_32bitBE(current_chunk+0x28,streamFile) == 0x88FC6165 &&
|
||||
read_32bitBE(current_chunk+0x2c,streamFile) == 0x4F8C836C) {
|
||||
/* ATRAC9 GUID (0x47E142D2,36BA,4D8D,88,FC,61,65,4F,8C,83,6C) */
|
||||
if (guid1 == 0x47E142D2 && guid2 == 0x36BA4D8D && guid3 == 0x88FC6165 && guid4 == 0x4F8C836C) {
|
||||
#ifdef VGM_USE_ATRAC9
|
||||
fmt->coding_type = coding_ATRAC9;
|
||||
break;
|
||||
@ -226,15 +252,16 @@ static int read_fmt(int big_endian, STREAMFILE * streamFile, off_t current_chunk
|
||||
}
|
||||
|
||||
goto fail; /* unknown GUID */
|
||||
}
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_ue4_msadpcm(VGMSTREAM* vgmstream, STREAMFILE* streamFile, riff_fmt_chunk* fmt, int fact_sample_count, off_t start_offset);
|
||||
@ -283,7 +310,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
||||
* (extensionless): Myst III (Xbox)
|
||||
* .sbv: Spongebob Squarepants - The Movie (PC)
|
||||
* .wvx: Godzilla - Destroy All Monsters Melee (Xbox) */
|
||||
if ( check_extensions(streamFile, "wav,lwav,xwav,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv") ) {
|
||||
if ( check_extensions(streamFile, "wav,lwav,xwav,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv,wvx") ) {
|
||||
;
|
||||
}
|
||||
else if ( check_extensions(streamFile, "mwv") ) {
|
||||
@ -330,27 +357,21 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
||||
|
||||
/* read through chunks to verify format and find metadata */
|
||||
{
|
||||
off_t current_chunk = 0xc; /* start with first chunk */
|
||||
off_t current_chunk = 0x0c; /* start with first chunk */
|
||||
|
||||
while (current_chunk < file_size && current_chunk < riff_size+8) {
|
||||
uint32_t chunk_type = read_32bitBE(current_chunk,streamFile);
|
||||
size_t chunk_size = read_32bitLE(current_chunk+4,streamFile);
|
||||
uint32_t chunk_id = read_32bitBE(current_chunk + 0x00,streamFile); /* FOURCC */
|
||||
size_t chunk_size = read_32bitLE(current_chunk + 0x04,streamFile);
|
||||
|
||||
if (fmt.codec == 0x6771 && chunk_type == 0x64617461) /* Liar-soft again */
|
||||
chunk_size += (chunk_size%2) ? 0x01 : 0x00;
|
||||
if (current_chunk + 0x08 + chunk_size > file_size)
|
||||
goto fail;
|
||||
|
||||
if (current_chunk+0x08+chunk_size > file_size) goto fail;
|
||||
|
||||
switch(chunk_type) {
|
||||
switch(chunk_id) {
|
||||
case 0x666d7420: /* "fmt " */
|
||||
if (FormatChunkFound) goto fail; /* only one per file */
|
||||
FormatChunkFound = 1;
|
||||
|
||||
if (-1 == read_fmt(0, /* big endian == false*/
|
||||
streamFile,
|
||||
current_chunk,
|
||||
&fmt,
|
||||
mwv))
|
||||
if (!read_fmt(0, streamFile, current_chunk, &fmt, mwv))
|
||||
goto fail;
|
||||
|
||||
/* some Dreamcast/Naomi games again [Headhunter (DC), Bomber hehhe (DC)] */
|
||||
@ -367,7 +388,6 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
||||
break;
|
||||
|
||||
case 0x4C495354: /* "LIST" */
|
||||
/* what lurks within?? */
|
||||
switch (read_32bitBE(current_chunk+0x08, streamFile)) {
|
||||
case 0x6164746C: /* "adtl" */
|
||||
/* yay, atdl is its own little world */
|
||||
@ -430,6 +450,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
||||
if (!mwv) break; /* ignore if not in an mwv */
|
||||
mwv_pflt_offset = current_chunk; /* predictor filters */
|
||||
break;
|
||||
|
||||
case 0x6374726c: /* "ctrl" (.mwv extension) */
|
||||
if (!mwv) break;
|
||||
loop_flag = read_32bitLE(current_chunk+0x08, streamFile);
|
||||
@ -457,7 +478,13 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
||||
break;
|
||||
}
|
||||
|
||||
current_chunk += 8+chunk_size;
|
||||
/* chunks are even-sized with padding byte (for 16b reads) as per spec (normally
|
||||
* pre-adjusted except for a few like Liar-soft's), at end may not have padding though
|
||||
* (done *after* chunk parsing since size without padding is needed) */
|
||||
if (chunk_size % 0x02 && current_chunk + 0x08 + chunk_size+0x01 <= file_size)
|
||||
chunk_size += 0x01;
|
||||
|
||||
current_chunk += 0x08 + chunk_size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,6 +522,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = fmt.sample_rate;
|
||||
vgmstream->channel_layout = fmt.channel_layout;
|
||||
|
||||
/* init, samples */
|
||||
switch (fmt.coding_type) {
|
||||
@ -803,11 +831,7 @@ VGMSTREAM * init_vgmstream_rifx(STREAMFILE *streamFile) {
|
||||
if (FormatChunkFound) goto fail;
|
||||
FormatChunkFound = 1;
|
||||
|
||||
if (-1 == read_fmt(1, /* big endian == true */
|
||||
streamFile,
|
||||
current_chunk,
|
||||
&fmt,
|
||||
0)) /* mwv == false */
|
||||
if (!read_fmt(1, streamFile, current_chunk, &fmt, 0))
|
||||
goto fail;
|
||||
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user