mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-12-24 20:34:51 +01:00
88 lines
2.9 KiB
C
88 lines
2.9 KiB
C
|
#include "meta.h"
|
||
|
#include "../coding/coding.h"
|
||
|
#include "../layout/layout.h"
|
||
|
#include "xavs_streamfile.h"
|
||
|
|
||
|
/* XAVS - Reflections audio and video+audio container [Stuntman (PS2)] */
|
||
|
VGMSTREAM * init_vgmstream_xavs(STREAMFILE *streamFile) {
|
||
|
VGMSTREAM * vgmstream = NULL;
|
||
|
off_t start_offset;
|
||
|
int loop_flag, channel_count;
|
||
|
int total_subsongs, target_subsong = streamFile->stream_index;
|
||
|
STREAMFILE *temp_streamFile = NULL;
|
||
|
|
||
|
|
||
|
/* checks */
|
||
|
if (!check_extensions(streamFile, "xav"))
|
||
|
goto fail;
|
||
|
if (read_32bitBE(0x00, streamFile) != 0x58415653) /* "XAVS" */
|
||
|
goto fail;
|
||
|
|
||
|
loop_flag = 0;
|
||
|
channel_count = 2;
|
||
|
start_offset = 0x00;
|
||
|
|
||
|
/* 0x04: 16b width + height (0 if file has no video) */
|
||
|
/* 0x08: related to video (0 if file has no video) */
|
||
|
total_subsongs = read_16bitLE(0x0c, streamFile);
|
||
|
/* 0x0c: volume? (0x50, 0x4e) */
|
||
|
/* 0x10: biggest video chunk? (0 if file has no video) */
|
||
|
/* 0x14: biggest audio chunk? */
|
||
|
|
||
|
if (target_subsong == 0) target_subsong = 1;
|
||
|
if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail;
|
||
|
|
||
|
/* could use a blocked layout, but this needs interleaved PCM within blocks which can't be done ATM */
|
||
|
temp_streamFile = setup_xavs_streamfile(streamFile, 0x18, target_subsong - 1);
|
||
|
if (!temp_streamFile) goto fail;
|
||
|
|
||
|
|
||
|
/* build the VGMSTREAM */
|
||
|
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||
|
if (!vgmstream) goto fail;
|
||
|
|
||
|
vgmstream->meta_type = meta_XAVS;
|
||
|
vgmstream->num_streams = total_subsongs;
|
||
|
|
||
|
vgmstream->coding_type = coding_PCM16LE;
|
||
|
vgmstream->layout_type = layout_interleave;
|
||
|
|
||
|
/* no apparent flags, most videos use 0x41 but not all */
|
||
|
{
|
||
|
off_t offset = 0x18;
|
||
|
while (offset < get_streamfile_size(streamFile)) {
|
||
|
uint32_t chunk_id = read_32bitLE(offset+0x00, streamFile) & 0xFF;
|
||
|
uint32_t chunk_size = read_32bitLE(offset+0x00, streamFile) >> 8;
|
||
|
|
||
|
if ((chunk_id & 0xF0) == 0x40) {
|
||
|
vgmstream->sample_rate = 48000;
|
||
|
vgmstream->interleave_block_size = 0x200;
|
||
|
break;
|
||
|
} else if ((chunk_id & 0xF0) == 0x60) {
|
||
|
vgmstream->sample_rate = 24000;
|
||
|
vgmstream->interleave_block_size = 0x100;
|
||
|
break;
|
||
|
} else if (chunk_id == 0x56) {
|
||
|
offset += 0x04 + chunk_size;
|
||
|
} else if (chunk_id == 0x21) {
|
||
|
offset += 0x04;
|
||
|
} else {
|
||
|
goto fail;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
vgmstream->num_samples = pcm_bytes_to_samples(get_streamfile_size(temp_streamFile), channel_count, 16);
|
||
|
|
||
|
if (!vgmstream_open_stream(vgmstream,temp_streamFile,start_offset))
|
||
|
goto fail;
|
||
|
|
||
|
close_streamfile(temp_streamFile);
|
||
|
return vgmstream;
|
||
|
|
||
|
fail:
|
||
|
close_streamfile(temp_streamFile);
|
||
|
close_vgmstream(vgmstream);
|
||
|
return NULL;
|
||
|
}
|