mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-31 12:23:44 +01:00
Cleanup
This commit is contained in:
parent
71bee18a06
commit
3e52b1dd0b
1200
src/meta/fsb.c
1200
src/meta/fsb.c
File diff suppressed because it is too large
Load Diff
122
src/meta/fsb5.c
122
src/meta/fsb5.c
@ -33,45 +33,45 @@ typedef struct {
|
||||
|
||||
/* ********************************************************************************** */
|
||||
|
||||
static layered_layout_data* build_layered_fsb5_celt(STREAMFILE *streamFile, fsb5_header* fsb5);
|
||||
static layered_layout_data* build_layered_fsb5_atrac9(STREAMFILE *streamFile, fsb5_header* fsb5, off_t configs_offset, size_t configs_size);
|
||||
static layered_layout_data* build_layered_fsb5_celt(STREAMFILE* sf, fsb5_header* fsb5);
|
||||
static layered_layout_data* build_layered_fsb5_atrac9(STREAMFILE* sf, fsb5_header* fsb5, off_t configs_offset, size_t configs_size);
|
||||
|
||||
/* FSB5 - FMOD Studio multiplatform format */
|
||||
VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
fsb5_header fsb5 = {0};
|
||||
int target_subsong = streamFile->stream_index;
|
||||
int target_subsong = sf->stream_index;
|
||||
int i;
|
||||
|
||||
|
||||
/* checks */
|
||||
/* .fsb: standard
|
||||
* .snd: Alchemy engine (also Unity) */
|
||||
if (!check_extensions(streamFile,"fsb,snd"))
|
||||
if (!check_extensions(sf,"fsb,snd"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x00,streamFile) != 0x46534235) /* "FSB5" */
|
||||
if (read_32bitBE(0x00,sf) != 0x46534235) /* "FSB5" */
|
||||
goto fail;
|
||||
|
||||
/* 0x00 is rare (seen in Tales from Space Vita) */
|
||||
fsb5.version = read_32bitLE(0x04,streamFile);
|
||||
fsb5.version = read_32bitLE(0x04,sf);
|
||||
if (fsb5.version != 0x00 && fsb5.version != 0x01) goto fail;
|
||||
|
||||
fsb5.total_subsongs = read_32bitLE(0x08,streamFile);
|
||||
fsb5.sample_header_size = read_32bitLE(0x0C,streamFile);
|
||||
fsb5.name_table_size = read_32bitLE(0x10,streamFile);
|
||||
fsb5.sample_data_size = read_32bitLE(0x14,streamFile);
|
||||
fsb5.codec = read_32bitLE(0x18,streamFile);
|
||||
fsb5.total_subsongs = read_32bitLE(0x08,sf);
|
||||
fsb5.sample_header_size = read_32bitLE(0x0C,sf);
|
||||
fsb5.name_table_size = read_32bitLE(0x10,sf);
|
||||
fsb5.sample_data_size = read_32bitLE(0x14,sf);
|
||||
fsb5.codec = read_32bitLE(0x18,sf);
|
||||
/* version 0x01 - 0x1c(4): zero, 0x24(16): hash, 0x34(8): unk
|
||||
* version 0x00 has an extra field (always 0?) at 0x1c */
|
||||
if (fsb5.version == 0x01) {
|
||||
/* found by tests and assumed to be flags, no games known */
|
||||
fsb5.flags = read_32bitLE(0x20,streamFile);
|
||||
fsb5.flags = read_32bitLE(0x20,sf);
|
||||
}
|
||||
fsb5.base_header_size = (fsb5.version==0x00) ? 0x40 : 0x3C;
|
||||
|
||||
if ((fsb5.sample_header_size + fsb5.name_table_size + fsb5.sample_data_size + fsb5.base_header_size) != get_streamfile_size(streamFile)) {
|
||||
VGM_LOG("FSB5: bad size (%x + %x + %x + %x != %x)\n", fsb5.sample_header_size, fsb5.name_table_size, fsb5.sample_data_size, fsb5.base_header_size, get_streamfile_size(streamFile));
|
||||
if ((fsb5.sample_header_size + fsb5.name_table_size + fsb5.sample_data_size + fsb5.base_header_size) != get_streamfile_size(sf)) {
|
||||
VGM_LOG("FSB5: bad size (%x + %x + %x + %x != %x)\n", fsb5.sample_header_size, fsb5.name_table_size, fsb5.sample_data_size, fsb5.base_header_size, get_streamfile_size(sf));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -87,8 +87,8 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
off_t data_offset = 0;
|
||||
uint32_t sample_mode1, sample_mode2; /* maybe one uint64? */
|
||||
|
||||
sample_mode1 = (uint32_t)read_32bitLE(fsb5.sample_header_offset+0x00,streamFile);
|
||||
sample_mode2 = (uint32_t)read_32bitLE(fsb5.sample_header_offset+0x04,streamFile);
|
||||
sample_mode1 = (uint32_t)read_32bitLE(fsb5.sample_header_offset+0x00,sf);
|
||||
sample_mode2 = (uint32_t)read_32bitLE(fsb5.sample_header_offset+0x04,sf);
|
||||
stream_header_size += 0x08;
|
||||
|
||||
/* get samples */
|
||||
@ -133,7 +133,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
uint32_t extraflag, extraflag_type, extraflag_size, extraflag_end;
|
||||
|
||||
do {
|
||||
extraflag = read_32bitLE(extraflag_offset,streamFile);
|
||||
extraflag = read_32bitLE(extraflag_offset,sf);
|
||||
extraflag_type = (extraflag >> 25) & 0x7F; /* bits 32..26 (7) */
|
||||
extraflag_size = (extraflag >> 1) & 0xFFFFFF; /* bits 25..1 (24)*/
|
||||
extraflag_end = (extraflag & 0x01); /* bit 0 (1) */
|
||||
@ -142,15 +142,15 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
if (i + 1 == target_subsong) {
|
||||
switch(extraflag_type) {
|
||||
case 0x01: /* channels */
|
||||
fsb5.channels = read_8bit(extraflag_offset+0x04,streamFile);
|
||||
fsb5.channels = read_8bit(extraflag_offset+0x04,sf);
|
||||
break;
|
||||
case 0x02: /* sample rate */
|
||||
fsb5.sample_rate = read_32bitLE(extraflag_offset+0x04,streamFile);
|
||||
fsb5.sample_rate = read_32bitLE(extraflag_offset+0x04,sf);
|
||||
break;
|
||||
case 0x03: /* loop info */
|
||||
fsb5.loop_start = read_32bitLE(extraflag_offset+0x04,streamFile);
|
||||
fsb5.loop_start = read_32bitLE(extraflag_offset+0x04,sf);
|
||||
if (extraflag_size > 0x04) { /* probably not needed */
|
||||
fsb5.loop_end = read_32bitLE(extraflag_offset+0x08,streamFile);
|
||||
fsb5.loop_end = read_32bitLE(extraflag_offset+0x08,sf);
|
||||
fsb5.loop_end += 1; /* correct compared to FMOD's tools */
|
||||
}
|
||||
//;VGM_LOG("FSB5: stream %i loop start=%i, loop end=%i, samples=%i\n", i, fsb5.loop_start, fsb5.loop_end, fsb5.num_samples);
|
||||
@ -183,7 +183,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
case 0x05: /* unknown 32b */
|
||||
/* rare, found in Tearaway (Vita) with value 0 in first stream and
|
||||
* Shantae and the Seven Sirens (Mobile) with value 0x0003bd72 BE in #44 (Arena Town) */
|
||||
VGM_LOG("FSB5: stream %i flag %x with value %08x\n", i, extraflag_type, read_32bitLE(extraflag_offset+0x04,streamFile));
|
||||
VGM_LOG("FSB5: stream %i flag %x with value %08x\n", i, extraflag_type, read_32bitLE(extraflag_offset+0x04,sf));
|
||||
break;
|
||||
case 0x06: /* XMA seek table */
|
||||
/* no need for it */
|
||||
@ -209,7 +209,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
break;
|
||||
case 0x0d: /* unknown 32b (config? usually 0x3fnnnn00 BE and sometimes 0x3dnnnn00 BE) */
|
||||
/* found in some XMA2/Vorbis/FADPCM */
|
||||
VGM_LOG("FSB5: stream %i flag %x with value %08x\n", i, extraflag_type, read_32bitLE(extraflag_offset+0x04,streamFile));
|
||||
VGM_LOG("FSB5: stream %i flag %x with value %08x\n", i, extraflag_type, read_32bitLE(extraflag_offset+0x04,sf));
|
||||
break;
|
||||
default:
|
||||
VGM_LOG("FSB5: stream %i unknown flag 0x%x at %x + 0x04 (size 0x%x)\n", i, extraflag_type, (uint32_t)extraflag_offset, extraflag_size);
|
||||
@ -233,8 +233,8 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
else {
|
||||
off_t next_data_offset;
|
||||
uint32_t next_sample_mode1, next_sample_mode2;
|
||||
next_sample_mode1 = (uint32_t)read_32bitLE(fsb5.sample_header_offset+stream_header_size+0x00,streamFile);
|
||||
next_sample_mode2 = (uint32_t)read_32bitLE(fsb5.sample_header_offset+stream_header_size+0x04,streamFile);
|
||||
next_sample_mode1 = (uint32_t)read_32bitLE(fsb5.sample_header_offset+stream_header_size+0x00,sf);
|
||||
next_sample_mode2 = (uint32_t)read_32bitLE(fsb5.sample_header_offset+stream_header_size+0x04,sf);
|
||||
next_data_offset = (((next_sample_mode2 & 0x03) << 25) | ((next_sample_mode1 >> 7) & 0x1FFFFFF)) << 5;
|
||||
|
||||
fsb5.stream_size = next_data_offset - data_offset;
|
||||
@ -252,7 +252,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
/* get stream name */
|
||||
if (fsb5.name_table_size) {
|
||||
off_t name_suboffset = fsb5.base_header_size + fsb5.sample_header_size + 0x04*(target_subsong-1);
|
||||
fsb5.name_offset = fsb5.base_header_size + fsb5.sample_header_size + read_32bitLE(name_suboffset,streamFile);
|
||||
fsb5.name_offset = fsb5.base_header_size + fsb5.sample_header_size + read_32bitLE(name_suboffset,sf);
|
||||
}
|
||||
|
||||
|
||||
@ -270,7 +270,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
vgmstream->stream_size = fsb5.stream_size;
|
||||
vgmstream->meta_type = meta_FSB5;
|
||||
if (fsb5.name_offset)
|
||||
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, fsb5.name_offset,streamFile);
|
||||
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, fsb5.name_offset,sf);
|
||||
|
||||
switch (fsb5.codec) {
|
||||
case 0x00: /* FMOD_SOUND_FORMAT_NONE */
|
||||
@ -313,7 +313,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = 0x02;
|
||||
}
|
||||
dsp_read_coefs_be(vgmstream,streamFile,fsb5.extradata_offset,0x2E);
|
||||
dsp_read_coefs_be(vgmstream,sf,fsb5.extradata_offset,0x2E);
|
||||
break;
|
||||
|
||||
case 0x07: /* FMOD_SOUND_FORMAT_IMAADPCM [Skylanders] */
|
||||
@ -347,12 +347,12 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
block_count = fsb5.stream_size / block_size + (fsb5.stream_size % block_size ? 1 : 0);
|
||||
|
||||
bytes = ffmpeg_make_riff_xma2(buf, 0x100, vgmstream->num_samples, fsb5.stream_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
|
||||
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, fsb5.stream_offset,fsb5.stream_size);
|
||||
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, fsb5.stream_offset,fsb5.stream_size);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
xma_fix_raw_samples(vgmstream, streamFile, fsb5.stream_offset,fsb5.stream_size, 0, 0,0); /* samples look ok */
|
||||
xma_fix_raw_samples(vgmstream, sf, fsb5.stream_offset,fsb5.stream_size, 0, 0,0); /* samples look ok */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -363,7 +363,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
|
||||
cfg.fsb_padding = (vgmstream->channels > 2 ? 16 : 4); /* observed default */
|
||||
|
||||
vgmstream->codec_data = init_mpeg_custom(streamFile, fsb5.stream_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_FSB, &cfg);
|
||||
vgmstream->codec_data = init_mpeg_custom(sf, fsb5.stream_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_FSB, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
@ -375,7 +375,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
int is_multistream = fsb5.channels > 2;
|
||||
|
||||
if (is_multistream) {
|
||||
vgmstream->layout_data = build_layered_fsb5_celt(streamFile, &fsb5);
|
||||
vgmstream->layout_data = build_layered_fsb5_celt(sf, &fsb5);
|
||||
if (!vgmstream->layout_data) goto fail;
|
||||
vgmstream->coding_type = coding_CELT_FSB;
|
||||
vgmstream->layout_type = layout_layered;
|
||||
@ -398,7 +398,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
|
||||
|
||||
/* skip frame size in newer FSBs [Day of the Tentacle Remastered (Vita), Tearaway Unfolded (PS4)] */
|
||||
if (configs_size >= 0x08 && (uint8_t)read_8bit(configs_offset, streamFile) != 0xFE) { /* ATRAC9 sync */
|
||||
if (configs_size >= 0x08 && (uint8_t)read_8bit(configs_offset, sf) != 0xFE) { /* ATRAC9 sync */
|
||||
configs_offset += 0x04;
|
||||
configs_size -= 0x04;
|
||||
}
|
||||
@ -407,7 +407,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
|
||||
if (is_multistream) {
|
||||
/* multichannel made of various streams [Little Big Planet (Vita)] */
|
||||
vgmstream->layout_data = build_layered_fsb5_atrac9(streamFile, &fsb5, configs_offset, configs_size);
|
||||
vgmstream->layout_data = build_layered_fsb5_atrac9(sf, &fsb5, configs_offset, configs_size);
|
||||
if (!vgmstream->layout_data) goto fail;
|
||||
vgmstream->coding_type = coding_ATRAC9;
|
||||
vgmstream->layout_type = layout_layered;
|
||||
@ -417,7 +417,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
atrac9_config cfg = {0};
|
||||
|
||||
cfg.channels = vgmstream->channels;
|
||||
cfg.config_data = read_32bitBE(configs_offset,streamFile);
|
||||
cfg.config_data = read_32bitBE(configs_offset,sf);
|
||||
//cfg.encoder_delay = 0x100; //todo not used? num_samples seems to count all data
|
||||
|
||||
vgmstream->codec_data = init_atrac9(&cfg);
|
||||
@ -434,14 +434,14 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
uint8_t buf[0x100];
|
||||
int bytes, format, average_bps, block_align;
|
||||
|
||||
format = read_16bitBE(fsb5.extradata_offset+0x00,streamFile);
|
||||
block_align = (uint16_t)read_16bitBE(fsb5.extradata_offset+0x02,streamFile);
|
||||
average_bps = (uint32_t)read_32bitBE(fsb5.extradata_offset+0x04,streamFile);
|
||||
format = read_16bitBE(fsb5.extradata_offset+0x00,sf);
|
||||
block_align = (uint16_t)read_16bitBE(fsb5.extradata_offset+0x02,sf);
|
||||
average_bps = (uint32_t)read_32bitBE(fsb5.extradata_offset+0x04,sf);
|
||||
/* rest: seek entries + mini seek table? */
|
||||
/* XWMA encoder only does up to 6ch (doesn't use FSB multistreams for more) */
|
||||
|
||||
bytes = ffmpeg_make_riff_xwma(buf,0x100, format, fsb5.stream_size, vgmstream->channels, vgmstream->sample_rate, average_bps, block_align);
|
||||
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, fsb5.stream_offset,fsb5.stream_size);
|
||||
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, fsb5.stream_offset,fsb5.stream_size);
|
||||
if ( !vgmstream->codec_data ) goto fail;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
@ -455,11 +455,11 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
|
||||
cfg.channels = vgmstream->channels;
|
||||
cfg.sample_rate = vgmstream->sample_rate;
|
||||
cfg.setup_id = read_32bitLE(fsb5.extradata_offset,streamFile);
|
||||
cfg.setup_id = read_32bitLE(fsb5.extradata_offset,sf);
|
||||
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->coding_type = coding_VORBIS_custom;
|
||||
vgmstream->codec_data = init_vorbis_custom(streamFile, fsb5.stream_offset, VORBIS_FSB, &cfg);
|
||||
vgmstream->codec_data = init_vorbis_custom(sf, fsb5.stream_offset, VORBIS_FSB, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
|
||||
break;
|
||||
@ -477,7 +477,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,fsb5.stream_offset))
|
||||
if (!vgmstream_open_stream(vgmstream,sf,fsb5.stream_offset))
|
||||
goto fail;
|
||||
|
||||
return vgmstream;
|
||||
@ -488,15 +488,15 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
static layered_layout_data* build_layered_fsb5_celt(STREAMFILE *streamFile, fsb5_header* fsb5) {
|
||||
static layered_layout_data* build_layered_fsb5_celt(STREAMFILE* sf, fsb5_header* fsb5) {
|
||||
layered_layout_data* data = NULL;
|
||||
STREAMFILE* temp_streamFile = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
int i, layers = (fsb5->channels+1) / 2;
|
||||
size_t interleave;
|
||||
|
||||
if (read_32bitBE(fsb5->stream_offset+0x00,streamFile) != 0x17C30DF3) /* FSB CELT frame ID */
|
||||
if (read_32bitBE(fsb5->stream_offset+0x00,sf) != 0x17C30DF3) /* FSB CELT frame ID */
|
||||
goto fail;
|
||||
interleave = 0x04+0x04+read_32bitLE(fsb5->stream_offset+0x04,streamFile); /* frame size */
|
||||
interleave = 0x04+0x04+read_32bitLE(fsb5->stream_offset+0x04,sf); /* frame size */
|
||||
|
||||
//todo unknown interleave for max quality odd channel streams (found in test files)
|
||||
/* FSB5 odd channels use 2ch+2ch...+1ch streams, and the last only goes up to 0x17a, and other
|
||||
@ -533,29 +533,29 @@ static layered_layout_data* build_layered_fsb5_celt(STREAMFILE *streamFile, fsb5
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
temp_streamFile = setup_fsb5_streamfile(streamFile, fsb5->stream_offset, fsb5->stream_size, layers, i, interleave);
|
||||
if (!temp_streamFile) goto fail;
|
||||
temp_sf = setup_fsb5_streamfile(sf, fsb5->stream_offset, fsb5->stream_size, layers, i, interleave);
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
if (!vgmstream_open_stream(data->layers[i], temp_streamFile, 0x00))
|
||||
if (!vgmstream_open_stream(data->layers[i], temp_sf, 0x00))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* setup layered VGMSTREAMs */
|
||||
if (!setup_layout_layered(data))
|
||||
goto fail;
|
||||
close_streamfile(temp_streamFile);
|
||||
close_streamfile(temp_sf);
|
||||
return data;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_streamFile);
|
||||
close_streamfile(temp_sf);
|
||||
free_layout_layered(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static layered_layout_data* build_layered_fsb5_atrac9(STREAMFILE *streamFile, fsb5_header* fsb5, off_t configs_offset, size_t configs_size) {
|
||||
static layered_layout_data* build_layered_fsb5_atrac9(STREAMFILE* sf, fsb5_header* fsb5, off_t configs_offset, size_t configs_size) {
|
||||
layered_layout_data* data = NULL;
|
||||
STREAMFILE* temp_streamFile = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
int i, layers = (configs_size / 0x04);
|
||||
size_t interleave = 0;
|
||||
|
||||
@ -566,7 +566,7 @@ static layered_layout_data* build_layered_fsb5_atrac9(STREAMFILE *streamFile, fs
|
||||
|
||||
/* open each layer subfile (2ch+2ch..+1/2ch) */
|
||||
for (i = 0; i < layers; i++) {
|
||||
uint32_t config = read_32bitBE(configs_offset + 0x04*i, streamFile);
|
||||
uint32_t config = read_32bitBE(configs_offset + 0x04*i, sf);
|
||||
int channel_index, layer_channels;
|
||||
size_t frame_size;
|
||||
|
||||
@ -609,21 +609,21 @@ static layered_layout_data* build_layered_fsb5_atrac9(STREAMFILE *streamFile, fs
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
temp_streamFile = setup_fsb5_streamfile(streamFile, fsb5->stream_offset, fsb5->stream_size, layers, i, interleave);
|
||||
if (!temp_streamFile) goto fail;
|
||||
temp_sf = setup_fsb5_streamfile(sf, fsb5->stream_offset, fsb5->stream_size, layers, i, interleave);
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
if (!vgmstream_open_stream(data->layers[i], temp_streamFile, 0x00))
|
||||
if (!vgmstream_open_stream(data->layers[i], temp_sf, 0x00))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* setup layered VGMSTREAMs */
|
||||
if (!setup_layout_layered(data))
|
||||
goto fail;
|
||||
close_streamfile(temp_streamFile);
|
||||
close_streamfile(temp_sf);
|
||||
return data;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_streamFile);
|
||||
close_streamfile(temp_sf);
|
||||
free_layout_layered(data);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,54 +1,54 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* FEV+FSB5 container [Just Cause 3 (PC), Shantae: Half-Genie Hero (Switch)] */
|
||||
VGMSTREAM * init_vgmstream_fsb5_fev_bank(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
STREAMFILE *temp_streamFile = NULL;
|
||||
off_t subfile_offset, chunk_offset, first_offset = 0x0c;
|
||||
size_t subfile_size, chunk_size;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "bank"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x00,streamFile) != 0x52494646) /* "RIFF" */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x08,streamFile) != 0x46455620) /* "FEV " */
|
||||
goto fail;
|
||||
|
||||
/* .fev is an event format referencing various external .fsb, but FMOD can bake .fev and .fsb to
|
||||
* form a .bank, which is the format we support here (regular .fev is complex and not very interesting).
|
||||
* Format is RIFF with FMT (main), LIST (config) and SND (FSB5 data), we want the FSB5 offset inside LIST */
|
||||
if (!find_chunk_le(streamFile, 0x4C495354,first_offset,0, &chunk_offset,NULL)) /* "LIST" */
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(chunk_offset+0x00,streamFile) != 0x50524F4A || /* "PROJ" */
|
||||
read_32bitBE(chunk_offset+0x04,streamFile) != 0x424E4B49) /* "BNKI" */
|
||||
goto fail; /* event .fev has "OBCT" instead of "BNKI" */
|
||||
|
||||
/* inside BNKI is a bunch of LIST each with event subchunks and finally the fsb offset */
|
||||
first_offset = chunk_offset + 0x04;
|
||||
if (!find_chunk_le(streamFile, 0x534E4448,first_offset,0, &chunk_offset,&chunk_size)) /* "SNDH" */
|
||||
goto fail;
|
||||
|
||||
if (chunk_size != 0x0c)
|
||||
goto fail; /* assuming only one FSB5 is possible */
|
||||
subfile_offset = read_32bitLE(chunk_offset+0x04,streamFile);
|
||||
subfile_size = read_32bitLE(chunk_offset+0x08,streamFile);
|
||||
|
||||
|
||||
temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, "fsb");
|
||||
if (!temp_streamFile) goto fail;
|
||||
|
||||
vgmstream = init_vgmstream_fsb5(temp_streamFile);
|
||||
close_streamfile(temp_streamFile);
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_streamFile);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* FEV+FSB5 container [Just Cause 3 (PC), Shantae: Half-Genie Hero (Switch)] */
|
||||
VGMSTREAM* init_vgmstream_fsb5_fev_bank(STREAMFILE* sf) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
STREAMFILE *temp_sf = NULL;
|
||||
off_t subfile_offset, chunk_offset, first_offset = 0x0c;
|
||||
size_t subfile_size, chunk_size;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(sf, "bank"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x00,sf) != 0x52494646) /* "RIFF" */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x08,sf) != 0x46455620) /* "FEV " */
|
||||
goto fail;
|
||||
|
||||
/* .fev is an event format referencing various external .fsb, but FMOD can bake .fev and .fsb to
|
||||
* form a .bank, which is the format we support here (regular .fev is complex and not very interesting).
|
||||
* Format is RIFF with FMT (main), LIST (config) and SND (FSB5 data), we want the FSB5 offset inside LIST */
|
||||
if (!find_chunk_le(sf, 0x4C495354,first_offset,0, &chunk_offset,NULL)) /* "LIST" */
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(chunk_offset+0x00,sf) != 0x50524F4A || /* "PROJ" */
|
||||
read_32bitBE(chunk_offset+0x04,sf) != 0x424E4B49) /* "BNKI" */
|
||||
goto fail; /* event .fev has "OBCT" instead of "BNKI" */
|
||||
|
||||
/* inside BNKI is a bunch of LIST each with event subchunks and finally the fsb offset */
|
||||
first_offset = chunk_offset + 0x04;
|
||||
if (!find_chunk_le(sf, 0x534E4448,first_offset,0, &chunk_offset,&chunk_size)) /* "SNDH" */
|
||||
goto fail;
|
||||
|
||||
if (chunk_size != 0x0c)
|
||||
goto fail; /* assuming only one FSB5 is possible */
|
||||
subfile_offset = read_32bitLE(chunk_offset+0x04,sf);
|
||||
subfile_size = read_32bitLE(chunk_offset+0x08,sf);
|
||||
|
||||
|
||||
temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, "fsb");
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
vgmstream = init_vgmstream_fsb5(temp_sf);
|
||||
close_streamfile(temp_sf);
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_sf);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -24,37 +24,37 @@ typedef struct {
|
||||
off_t stream_offset;
|
||||
} xvag_header;
|
||||
|
||||
static int init_xvag_atrac9(STREAMFILE *streamFile, VGMSTREAM* vgmstream, xvag_header * xvag, off_t chunk_offset);
|
||||
static layered_layout_data* build_layered_xvag(STREAMFILE *streamFile, xvag_header * xvag, off_t chunk_offset, off_t start_offset);
|
||||
static int init_xvag_atrac9(STREAMFILE* sf, VGMSTREAM* vgmstream, xvag_header * xvag, off_t chunk_offset);
|
||||
static layered_layout_data* build_layered_xvag(STREAMFILE* sf, xvag_header * xvag, off_t chunk_offset, off_t start_offset);
|
||||
|
||||
/* XVAG - Sony's Scream Tool/Stream Creator format (God of War III, Ratchet & Clank Future, The Last of Us, Uncharted) */
|
||||
VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
STREAMFILE* temp_streamFile = NULL;
|
||||
VGMSTREAM* init_vgmstream_xvag(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
xvag_header xvag = {0};
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
|
||||
off_t start_offset, chunk_offset, first_offset = 0x20;
|
||||
size_t chunk_size;
|
||||
int total_subsongs = 0, target_subsong = streamFile->stream_index;
|
||||
int total_subsongs = 0, target_subsong = sf->stream_index;
|
||||
|
||||
|
||||
/* checks */
|
||||
/* .xvag: standard
|
||||
* (extensionless): The Last Of Us (PS3) speech files */
|
||||
if (!check_extensions(streamFile,"xvag,"))
|
||||
if (!check_extensions(sf,"xvag,"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x58564147) /* "XVAG" */
|
||||
if (read_32bitBE(0x00,sf) != 0x58564147) /* "XVAG" */
|
||||
goto fail;
|
||||
|
||||
/* endian flag (XVAGs of the same game can use BE or LE, usually when reusing from other platforms) */
|
||||
xvag.big_endian = read_8bit(0x08,streamFile) & 0x01;
|
||||
xvag.big_endian = read_8bit(0x08,sf) & 0x01;
|
||||
if (xvag.big_endian) {
|
||||
read_32bit = read_32bitBE;
|
||||
} else {
|
||||
read_32bit = read_32bitLE;
|
||||
}
|
||||
|
||||
start_offset = read_32bit(0x04,streamFile);
|
||||
start_offset = read_32bit(0x04,sf);
|
||||
/* 0x08: flags? (&0x01=big endian, 0x02=?, 0x06=full RIFF AT9?)
|
||||
* 0x09: flags2? (0x00/0x01/0x04, speaker mode?)
|
||||
* 0x0a: always 0?
|
||||
@ -62,24 +62,24 @@ VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) {
|
||||
|
||||
|
||||
/* "fmat": base format (always first) */
|
||||
if (!find_chunk(streamFile, 0x666D6174,first_offset,0, &chunk_offset,&chunk_size, xvag.big_endian, 1)) /*"fmat"*/
|
||||
if (!find_chunk(sf, 0x666D6174,first_offset,0, &chunk_offset,&chunk_size, xvag.big_endian, 1)) /*"fmat"*/
|
||||
goto fail;
|
||||
xvag.channels = read_32bit(chunk_offset+0x00,streamFile);
|
||||
xvag.codec = read_32bit(chunk_offset+0x04,streamFile);
|
||||
xvag.num_samples = read_32bit(chunk_offset+0x08,streamFile);
|
||||
xvag.channels = read_32bit(chunk_offset+0x00,sf);
|
||||
xvag.codec = read_32bit(chunk_offset+0x04,sf);
|
||||
xvag.num_samples = read_32bit(chunk_offset+0x08,sf);
|
||||
/* 0x0c: samples again? */
|
||||
VGM_ASSERT(xvag.num_samples != read_32bit(chunk_offset+0x0c,streamFile), "XVAG: num_samples values don't match\n");
|
||||
VGM_ASSERT(xvag.num_samples != read_32bit(chunk_offset+0x0c,sf), "XVAG: num_samples values don't match\n");
|
||||
|
||||
xvag.factor = read_32bit(chunk_offset+0x10,streamFile); /* for interleave */
|
||||
xvag.sample_rate = read_32bit(chunk_offset+0x14,streamFile);
|
||||
xvag.data_size = read_32bit(chunk_offset+0x18,streamFile); /* not always accurate */
|
||||
xvag.factor = read_32bit(chunk_offset+0x10,sf); /* for interleave */
|
||||
xvag.sample_rate = read_32bit(chunk_offset+0x14,sf);
|
||||
xvag.data_size = read_32bit(chunk_offset+0x18,sf); /* not always accurate */
|
||||
|
||||
/* extra data, seen in versions 0x61+ */
|
||||
if (chunk_size > 0x1c) {
|
||||
/* number of interleaved subsongs */
|
||||
xvag.subsongs = read_32bit(chunk_offset+0x1c,streamFile);
|
||||
xvag.subsongs = read_32bit(chunk_offset+0x1c,sf);
|
||||
/* number of interleaved layers (layers * channels_per_layer = channels) */
|
||||
xvag.layers = read_32bit(chunk_offset+0x20,streamFile);
|
||||
xvag.layers = read_32bit(chunk_offset+0x20,sf);
|
||||
}
|
||||
else {
|
||||
xvag.subsongs = 1;
|
||||
@ -99,9 +99,9 @@ VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) {
|
||||
|
||||
/* XVAG has no looping, but some PS3 PS-ADPCM seems to do full loops (without data flags) */
|
||||
if (xvag.codec == 0x06 && xvag.subsongs == 1) {
|
||||
size_t file_size = get_streamfile_size(streamFile);
|
||||
size_t file_size = get_streamfile_size(sf);
|
||||
/* simply test if last frame is not empty = may loop */
|
||||
xvag.loop_flag = (read_8bit(file_size - 0x01, streamFile) != 0);
|
||||
xvag.loop_flag = (read_8bit(file_size - 0x01, sf) != 0);
|
||||
xvag.loop_start = 0;
|
||||
xvag.loop_end = ps_bytes_to_samples(file_size - start_offset, xvag.channels);
|
||||
}
|
||||
@ -162,7 +162,7 @@ VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) {
|
||||
if (xvag.layers > 1 && !(xvag.layers*1 == vgmstream->channels || xvag.layers*2 == vgmstream->channels)) goto fail;
|
||||
|
||||
/* "mpin": mpeg info */
|
||||
if (!find_chunk(streamFile, 0x6D70696E,first_offset,0, &chunk_offset,NULL, xvag.big_endian, 1)) /*"mpin"*/
|
||||
if (!find_chunk(sf, 0x6D70696E,first_offset,0, &chunk_offset,NULL, xvag.big_endian, 1)) /*"mpin"*/
|
||||
goto fail;
|
||||
|
||||
/* all layers/subsongs share the same config; not very useful but for posterity:
|
||||
@ -182,18 +182,18 @@ VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) {
|
||||
* - 0x34: data size
|
||||
* (rest is padding)
|
||||
* */
|
||||
cfg.chunk_size = read_32bit(chunk_offset+0x1c,streamFile);
|
||||
cfg.skip_samples = read_32bit(chunk_offset+0x20,streamFile);
|
||||
cfg.chunk_size = read_32bit(chunk_offset+0x1c,sf);
|
||||
cfg.skip_samples = read_32bit(chunk_offset+0x20,sf);
|
||||
cfg.interleave = cfg.chunk_size * xvag.factor;
|
||||
|
||||
vgmstream->codec_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_XVAG, &cfg);
|
||||
vgmstream->codec_data = init_mpeg_custom(sf, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_XVAG, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
/* interleaved subsongs, rarely [Sly Cooper: Thieves in Time (PS3)] */
|
||||
if (xvag.subsongs > 1) {
|
||||
temp_streamFile = setup_xvag_streamfile(streamFile, start_offset, cfg.interleave,cfg.chunk_size, (target_subsong-1), total_subsongs);
|
||||
if (!temp_streamFile) goto fail;
|
||||
temp_sf = setup_xvag_streamfile(sf, start_offset, cfg.interleave,cfg.chunk_size, (target_subsong-1), total_subsongs);
|
||||
if (!temp_sf) goto fail;
|
||||
start_offset = 0;
|
||||
}
|
||||
|
||||
@ -207,13 +207,13 @@ VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) {
|
||||
|
||||
/* "a9in": ATRAC9 info */
|
||||
/* 0x00: frame size, 0x04: samples per frame, 0x0c: fact num_samples (no change), 0x10: encoder delay1 */
|
||||
if (!find_chunk(streamFile, 0x6139696E,first_offset,0, &chunk_offset,NULL, xvag.big_endian, 1)) /*"a9in"*/
|
||||
if (!find_chunk(sf, 0x6139696E,first_offset,0, &chunk_offset,NULL, xvag.big_endian, 1)) /*"a9in"*/
|
||||
goto fail;
|
||||
|
||||
if (xvag.layers > 1) {
|
||||
/* some Vita/PS4 multichannel [flower (Vita), Uncharted Collection (PS4)]. PS4 ATRAC9 also
|
||||
* does single-stream >2ch, but this can do configs ATRAC9 can't, like 5ch/14ch/etc */
|
||||
vgmstream->layout_data = build_layered_xvag(streamFile, &xvag, chunk_offset, start_offset);
|
||||
vgmstream->layout_data = build_layered_xvag(sf, &xvag, chunk_offset, start_offset);
|
||||
if (!vgmstream->layout_data) goto fail;
|
||||
vgmstream->coding_type = coding_ATRAC9;
|
||||
vgmstream->layout_type = layout_layered;
|
||||
@ -222,12 +222,12 @@ VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) {
|
||||
}
|
||||
else {
|
||||
/* interleaved subsongs (section layers) */
|
||||
size_t frame_size = read_32bit(chunk_offset+0x00,streamFile);
|
||||
size_t frame_size = read_32bit(chunk_offset+0x00,sf);
|
||||
|
||||
if (!init_xvag_atrac9(streamFile, vgmstream, &xvag, chunk_offset))
|
||||
if (!init_xvag_atrac9(sf, vgmstream, &xvag, chunk_offset))
|
||||
goto fail;
|
||||
temp_streamFile = setup_xvag_streamfile(streamFile, start_offset, frame_size*xvag.factor,frame_size, (target_subsong-1), total_subsongs);
|
||||
if (!temp_streamFile) goto fail;
|
||||
temp_sf = setup_xvag_streamfile(sf, start_offset, frame_size*xvag.factor,frame_size, (target_subsong-1), total_subsongs);
|
||||
if (!temp_sf) goto fail;
|
||||
start_offset = 0;
|
||||
}
|
||||
|
||||
@ -240,25 +240,25 @@ VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,temp_streamFile ? temp_streamFile : streamFile,start_offset))
|
||||
if (!vgmstream_open_stream(vgmstream,temp_sf ? temp_sf : sf,start_offset))
|
||||
goto fail;
|
||||
close_streamfile(temp_streamFile);
|
||||
close_streamfile(temp_sf);
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_streamFile);
|
||||
close_streamfile(temp_sf);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_ATRAC9
|
||||
static int init_xvag_atrac9(STREAMFILE *streamFile, VGMSTREAM* vgmstream, xvag_header * xvag, off_t chunk_offset) {
|
||||
static int init_xvag_atrac9(STREAMFILE* sf, VGMSTREAM* vgmstream, xvag_header * xvag, off_t chunk_offset) {
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = xvag->big_endian ? read_32bitBE : read_32bitLE;
|
||||
atrac9_config cfg = {0};
|
||||
|
||||
cfg.channels = vgmstream->channels;
|
||||
cfg.config_data = read_32bitBE(chunk_offset+0x08,streamFile);
|
||||
cfg.encoder_delay = read_32bit(chunk_offset+0x14,streamFile);
|
||||
cfg.config_data = read_32bitBE(chunk_offset+0x08,sf);
|
||||
cfg.encoder_delay = read_32bit(chunk_offset+0x14,sf);
|
||||
|
||||
vgmstream->codec_data = init_atrac9(&cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
@ -271,9 +271,9 @@ fail:
|
||||
}
|
||||
#endif
|
||||
|
||||
static layered_layout_data* build_layered_xvag(STREAMFILE *streamFile, xvag_header * xvag, off_t chunk_offset, off_t start_offset) {
|
||||
static layered_layout_data* build_layered_xvag(STREAMFILE* sf, xvag_header * xvag, off_t chunk_offset, off_t start_offset) {
|
||||
layered_layout_data* data = NULL;
|
||||
STREAMFILE* temp_streamFile = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = xvag->big_endian ? read_32bitBE : read_32bitLE;
|
||||
int i, layers = xvag->layers;
|
||||
|
||||
@ -296,12 +296,12 @@ static layered_layout_data* build_layered_xvag(STREAMFILE *streamFile, xvag_head
|
||||
switch(xvag->codec) {
|
||||
#ifdef VGM_USE_ATRAC9
|
||||
case 0x09: {
|
||||
size_t frame_size = read_32bit(chunk_offset+0x00,streamFile);
|
||||
size_t frame_size = read_32bit(chunk_offset+0x00,sf);
|
||||
|
||||
if (!init_xvag_atrac9(streamFile, data->layers[i], xvag, chunk_offset))
|
||||
if (!init_xvag_atrac9(sf, data->layers[i], xvag, chunk_offset))
|
||||
goto fail;
|
||||
temp_streamFile = setup_xvag_streamfile(streamFile, start_offset, frame_size*xvag->factor,frame_size, i, layers);
|
||||
if (!temp_streamFile) goto fail;
|
||||
temp_sf = setup_xvag_streamfile(sf, start_offset, frame_size*xvag->factor,frame_size, i, layers);
|
||||
if (!temp_sf) goto fail;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -309,9 +309,9 @@ static layered_layout_data* build_layered_xvag(STREAMFILE *streamFile, xvag_head
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ( !vgmstream_open_stream(data->layers[i], temp_streamFile, 0x00) )
|
||||
if ( !vgmstream_open_stream(data->layers[i], temp_sf, 0x00) )
|
||||
goto fail;
|
||||
close_streamfile(temp_streamFile);
|
||||
close_streamfile(temp_sf);
|
||||
}
|
||||
|
||||
/* setup layered VGMSTREAMs */
|
||||
@ -320,7 +320,7 @@ static layered_layout_data* build_layered_xvag(STREAMFILE *streamFile, xvag_head
|
||||
return data;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_streamFile);
|
||||
close_streamfile(temp_sf);
|
||||
free_layout_layered(data);
|
||||
return NULL;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user