From 3208863d75c14c57ad962094067a636f643511a4 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 3 Nov 2019 22:58:33 +0100 Subject: [PATCH] Minor cleanup/comments --- src/coding/ffmpeg_decoder_utils.c | 379 ++++++++++++++--------------- src/coding/ima_decoder.c | 13 +- src/meta/ps2_2pfs.c | 201 +++++++--------- src/meta/sgxd.c | 380 +++++++++++++++--------------- 4 files changed, 465 insertions(+), 508 deletions(-) diff --git a/src/coding/ffmpeg_decoder_utils.c b/src/coding/ffmpeg_decoder_utils.c index 3b674310..e4d997e1 100644 --- a/src/coding/ffmpeg_decoder_utils.c +++ b/src/coding/ffmpeg_decoder_utils.c @@ -1,189 +1,190 @@ -#include "coding.h" - -#ifdef VGM_USE_FFMPEG - -static int ffmpeg_make_riff_atrac3(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int joint_stereo, int encoder_delay) { - uint16_t codec_ATRAC3 = 0x0270; - size_t riff_size = 4+4+ 4 + 0x28 + 0x10 + 4+4; - - if (buf_size < riff_size) - return -1; - - memcpy(buf+0x00, "RIFF", 4); - put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */ - memcpy(buf+0x08, "WAVE", 4); - - memcpy(buf+0x0c, "fmt ", 4); - put_32bitLE(buf+0x10, 0x20);/*fmt size*/ - put_16bitLE(buf+0x14, codec_ATRAC3); - put_16bitLE(buf+0x16, channels); - put_32bitLE(buf+0x18, sample_rate); - put_32bitLE(buf+0x1c, sample_rate*channels / sizeof(sample)); /* average bytes per second (wrong) */ - put_32bitLE(buf+0x20, (int16_t)(block_align)); /* block align */ - - put_16bitLE(buf+0x24, 0x0e); /* extra data size */ - put_16bitLE(buf+0x26, 1); /* unknown, always 1 */ - put_16bitLE(buf+0x28, 0x0800 * channels); /* unknown (some size? 0x1000=2ch, 0x0800=1ch) */ - put_16bitLE(buf+0x2a, 0); /* unknown, always 0 */ - put_16bitLE(buf+0x2c, joint_stereo ? 0x0001 : 0x0000); - put_16bitLE(buf+0x2e, joint_stereo ? 0x0001 : 0x0000); /* repeated? */ - put_16bitLE(buf+0x30, 1); /* unknown, always 1 (frame_factor?) */ - put_16bitLE(buf+0x32, 0); /* unknown, always 0 */ - - memcpy(buf+0x34, "fact", 4); - put_32bitLE(buf+0x38, 0x8); /* fact size */ - put_32bitLE(buf+0x3c, sample_count); - put_32bitLE(buf+0x40, encoder_delay); - - memcpy(buf+0x44, "data", 4); - put_32bitLE(buf+0x48, data_size); /* data size */ - - return riff_size; -} - -ffmpeg_codec_data * init_ffmpeg_atrac3_raw(STREAMFILE *sf, off_t offset, size_t data_size, int sample_count, int channels, int sample_rate, int block_align, int encoder_delay) { - ffmpeg_codec_data *ffmpeg_data = NULL; - uint8_t buf[0x100]; - int bytes; - int joint_stereo = (block_align == 0x60*channels) && channels > 1; /* only lowest block size does joint stereo */ - int is_at3 = 1; /* could detect using block size */ - - /* create fake header + init ffmpeg + apply fixes to FFmpeg decoding */ - bytes = ffmpeg_make_riff_atrac3(buf,sizeof(buf), sample_count, data_size, channels, sample_rate, block_align, joint_stereo, encoder_delay); - ffmpeg_data = init_ffmpeg_header_offset(sf, buf,bytes, offset,data_size); - if (!ffmpeg_data) goto fail; - - /* unlike with RIFF ATRAC3 we don't set implicit delay, as raw ATRAC3 headers often give loop/samples - * in offsets, so calcs are expected to be handled externally (presumably the game would call raw decoding API - * and any skips would be handled manually) */ - - /* FFmpeg reads this but just in case they fiddle with it in the future */ - ffmpeg_data->totalSamples = sample_count; - - /* encoder delay: encoder introduces some garbage (not always silent) samples to skip at the beginning (at least 1 frame) - * FFmpeg doesn't set this, and even if it ever does it's probably better to force it for the implicit skip. */ - ffmpeg_set_skip_samples(ffmpeg_data, encoder_delay); - - /* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */ - if (is_at3) { - ffmpeg_data->invert_floats_set = 1; - } - - return ffmpeg_data; -fail: - free_ffmpeg(ffmpeg_data); - return NULL; -} - -/* init ATRAC3/plus while adding some fixes */ -ffmpeg_codec_data * init_ffmpeg_atrac3_riff(STREAMFILE *sf, off_t offset, int* out_samples) { - ffmpeg_codec_data *ffmpeg_data = NULL; - int is_at3 = 0, is_at3p = 0, codec; - size_t riff_size; - int fact_samples, skip_samples, implicit_skip; - off_t fact_offset = 0; - size_t fact_size = 0; - - - /* some simplified checks just in case */ - if (read_32bitBE(offset + 0x00,sf) != 0x52494646) /* "RIFF" */ - goto fail; - - riff_size = read_32bitLE(offset + 0x04,sf) + 0x08; - codec = (uint16_t)read_16bitLE(offset + 0x14, sf); - switch(codec) { - case 0x0270: is_at3 = 1; break; - case 0xFFFE: is_at3p = 1; break; - default: goto fail; - } - - - /* init ffmpeg + apply fixes to FFmpeg decoding (with these fixes should be - * sample-accurate vs official tools, except usual +-1 float-to-pcm conversion) */ - ffmpeg_data = init_ffmpeg_offset(sf, offset, riff_size); - if (!ffmpeg_data) goto fail; - - - /* well behaved .at3 define "fact" but official tools accept files without it */ - if (find_chunk_le(sf,0x66616374,offset + 0x0c,0, &fact_offset, &fact_size)) { /* "fact" */ - if (fact_size == 0x08) { /* early AT3 (mainly PSP games) */ - fact_samples = read_32bitLE(fact_offset + 0x00, sf); - skip_samples = read_32bitLE(fact_offset + 0x04, sf); /* base skip samples */ - } - else if (fact_size == 0x0c) { /* late AT3 (mainly PS3 games and few PSP games) */ - fact_samples = read_32bitLE(fact_offset + 0x00, sf); - /* 0x04: base skip samples, ignored by decoder */ - skip_samples = read_32bitLE(fact_offset + 0x08, sf); /* skip samples with implicit skip of 184 added */ - } - else { - VGM_LOG("ATRAC3: unknown fact size\n"); - goto fail; - } - } - else { - fact_samples = 0; /* tools output 0 samples in this case unless loop end is defined */ - if (is_at3) - skip_samples = 1024; /* 1 frame */ - else if (is_at3p) - skip_samples = 2048; /* 1 frame */ - else - skip_samples = 0; - } - - /* implicit skip: official tools skip this even with encoder delay forced to 0. Maybe FFmpeg decodes late, - * but when forcing tools to decode all frame samples it always ends a bit before last frame, so maybe it's - * really an internal skip, since encoder adds extra frames so fact num_samples + encoder delay + implicit skip - * never goes past file. Same for all bitrate/channels, not added to loops. */ - if (is_at3) { - implicit_skip = 69; - } - else if (is_at3p && fact_size == 0x08) { - implicit_skip = 184*2; - } - else if (is_at3p && fact_size == 0x0c) { - implicit_skip = 184; /* first 184 is already added to delay vs field at 0x08 */ - } - else if (is_at3p) { - implicit_skip = 184; /* default for unknown sizes */ - } - else { - implicit_skip = 0; - } - - /* FFmpeg reads this but just in case they fiddle with it in the future */ - ffmpeg_data->totalSamples = fact_samples; - - /* encoder delay: encoder introduces some garbage (not always silent) samples to skip at the beginning (at least 1 frame) - * FFmpeg doesn't set this, and even if it ever does it's probably better to force it for the implicit skip. */ - ffmpeg_set_skip_samples(ffmpeg_data, skip_samples + implicit_skip); - - /* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */ - if (is_at3) { - ffmpeg_data->invert_floats_set = 1; - } - - /* multichannel fix: LFE channel should be reordered on decode (ATRAC3Plus only, only 1/2/6/8ch exist): - * - 6ch: FL FR FC BL BR LFE > FL FR FC LFE BL BR - * - 8ch: FL FR FC BL BR SL SR LFE > FL FR FC LFE BL BR SL SR */ - if (is_at3p && ffmpeg_data->channels == 6) { - /* LFE BR BL > LFE BL BR > same */ - int channel_remap[] = { 0, 1, 2, 5, 5, 5, }; - ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap); - } - else if (is_at3p && ffmpeg_data->channels == 8) { - /* LFE BR SL SR BL > LFE BL SL SR BR > LFE BL BR SR SL > LFE BL BR SL SR > same */ - int channel_remap[] = { 0, 1, 2, 7, 7, 7, 7, 7}; - ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap); - } - - - if (out_samples) - *out_samples = fact_samples; - - return ffmpeg_data; -fail: - free_ffmpeg(ffmpeg_data); - return NULL; -} - -#endif +#include "coding.h" + +#ifdef VGM_USE_FFMPEG + +static int ffmpeg_make_riff_atrac3(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int joint_stereo, int encoder_delay) { + uint16_t codec_ATRAC3 = 0x0270; + size_t riff_size = 4+4+ 4 + 0x28 + 0x10 + 4+4; + + if (buf_size < riff_size) + return -1; + + memcpy(buf+0x00, "RIFF", 4); + put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */ + memcpy(buf+0x08, "WAVE", 4); + + memcpy(buf+0x0c, "fmt ", 4); + put_32bitLE(buf+0x10, 0x20);/*fmt size*/ + put_16bitLE(buf+0x14, codec_ATRAC3); + put_16bitLE(buf+0x16, channels); + put_32bitLE(buf+0x18, sample_rate); + put_32bitLE(buf+0x1c, sample_rate*channels / sizeof(sample)); /* average bytes per second (wrong) */ + put_32bitLE(buf+0x20, (int16_t)(block_align)); /* block align */ + + put_16bitLE(buf+0x24, 0x0e); /* extra data size */ + put_16bitLE(buf+0x26, 1); /* unknown, always 1 */ + put_16bitLE(buf+0x28, 0x0800 * channels); /* unknown (some size? 0x1000=2ch, 0x0800=1ch) */ + put_16bitLE(buf+0x2a, 0); /* unknown, always 0 */ + put_16bitLE(buf+0x2c, joint_stereo ? 0x0001 : 0x0000); + put_16bitLE(buf+0x2e, joint_stereo ? 0x0001 : 0x0000); /* repeated? */ + put_16bitLE(buf+0x30, 1); /* unknown, always 1 (frame_factor?) */ + put_16bitLE(buf+0x32, 0); /* unknown, always 0 */ + + memcpy(buf+0x34, "fact", 4); + put_32bitLE(buf+0x38, 0x8); /* fact size */ + put_32bitLE(buf+0x3c, sample_count); + put_32bitLE(buf+0x40, encoder_delay); + + memcpy(buf+0x44, "data", 4); + put_32bitLE(buf+0x48, data_size); /* data size */ + + return riff_size; +} + +ffmpeg_codec_data * init_ffmpeg_atrac3_raw(STREAMFILE *sf, off_t offset, size_t data_size, int sample_count, int channels, int sample_rate, int block_align, int encoder_delay) { + ffmpeg_codec_data *ffmpeg_data = NULL; + uint8_t buf[0x100]; + int bytes; + int joint_stereo = (block_align == 0x60*channels) && channels > 1; /* only lowest block size does joint stereo */ + int is_at3 = 1; /* could detect using block size */ + + /* create fake header + init ffmpeg + apply fixes to FFmpeg decoding */ + bytes = ffmpeg_make_riff_atrac3(buf,sizeof(buf), sample_count, data_size, channels, sample_rate, block_align, joint_stereo, encoder_delay); + ffmpeg_data = init_ffmpeg_header_offset(sf, buf,bytes, offset,data_size); + if (!ffmpeg_data) goto fail; + + /* unlike with RIFF ATRAC3 we don't set implicit delay, as raw ATRAC3 headers often give loop/samples + * in offsets, so calcs are expected to be handled externally (presumably the game would call raw decoding API + * and any skips would be handled manually) */ + + /* FFmpeg reads this but just in case they fiddle with it in the future */ + ffmpeg_data->totalSamples = sample_count; + + /* encoder delay: encoder introduces some garbage (not always silent) samples to skip at the beginning (at least 1 frame) + * FFmpeg doesn't set this, and even if it ever does it's probably better to force it for the implicit skip. */ + ffmpeg_set_skip_samples(ffmpeg_data, encoder_delay); + + /* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */ + if (is_at3) { + ffmpeg_data->invert_floats_set = 1; + } + + return ffmpeg_data; +fail: + free_ffmpeg(ffmpeg_data); + return NULL; +} + +/* init ATRAC3/plus while adding some fixes */ +ffmpeg_codec_data * init_ffmpeg_atrac3_riff(STREAMFILE *sf, off_t offset, int* out_samples) { + ffmpeg_codec_data *ffmpeg_data = NULL; + int is_at3 = 0, is_at3p = 0, codec; + size_t riff_size; + int fact_samples, skip_samples, implicit_skip; + off_t fact_offset = 0; + size_t fact_size = 0; + + + /* some simplified checks just in case */ + if (read_32bitBE(offset + 0x00,sf) != 0x52494646) /* "RIFF" */ + goto fail; + + riff_size = read_32bitLE(offset + 0x04,sf) + 0x08; + codec = (uint16_t)read_16bitLE(offset + 0x14, sf); + switch(codec) { + case 0x0270: is_at3 = 1; break; + case 0xFFFE: is_at3p = 1; break; + default: goto fail; + } + + + /* init ffmpeg + apply fixes to FFmpeg decoding (with these fixes should be + * sample-accurate vs official tools, except usual +-1 float-to-pcm conversion) */ + ffmpeg_data = init_ffmpeg_offset(sf, offset, riff_size); + if (!ffmpeg_data) goto fail; + + + /* well behaved .at3 define "fact" but official tools accept files without it */ + if (find_chunk_le(sf,0x66616374,offset + 0x0c,0, &fact_offset, &fact_size)) { /* "fact" */ + if (fact_size == 0x08) { /* early AT3 (mainly PSP games) */ + fact_samples = read_32bitLE(fact_offset + 0x00, sf); + skip_samples = read_32bitLE(fact_offset + 0x04, sf); /* base skip samples */ + } + else if (fact_size == 0x0c) { /* late AT3 (mainly PS3 games and few PSP games) */ + fact_samples = read_32bitLE(fact_offset + 0x00, sf); + /* 0x04: base skip samples, ignored by decoder */ + skip_samples = read_32bitLE(fact_offset + 0x08, sf); /* skip samples with implicit skip of 184 added */ + } + else { + VGM_LOG("ATRAC3: unknown fact size\n"); + goto fail; + } + } + else { + fact_samples = 0; /* tools output 0 samples in this case unless loop end is defined */ + if (is_at3) + skip_samples = 1024; /* 1 frame */ + else if (is_at3p) + skip_samples = 2048; /* 1 frame */ + else + skip_samples = 0; + } + + /* implicit skip: official tools skip this even with encoder delay forced to 0. Maybe FFmpeg decodes late, + * but when forcing tools to decode all frame samples it always ends a bit before last frame, so maybe it's + * really an internal skip, since encoder adds extra frames so fact num_samples + encoder delay + implicit skip + * never goes past file. Same for all bitrate/channels, not added to loops. This is probably "decoder delay" + * also seen in codecs like MP3 */ + if (is_at3) { + implicit_skip = 69; + } + else if (is_at3p && fact_size == 0x08) { + implicit_skip = 184*2; + } + else if (is_at3p && fact_size == 0x0c) { + implicit_skip = 184; /* first 184 is already added to delay vs field at 0x08 */ + } + else if (is_at3p) { + implicit_skip = 184; /* default for unknown sizes */ + } + else { + implicit_skip = 0; + } + + /* FFmpeg reads this but just in case they fiddle with it in the future */ + ffmpeg_data->totalSamples = fact_samples; + + /* encoder delay: encoder introduces some garbage (not always silent) samples to skip at the beginning (at least 1 frame) + * FFmpeg doesn't set this, and even if it ever does it's probably better to force it for the implicit skip. */ + ffmpeg_set_skip_samples(ffmpeg_data, skip_samples + implicit_skip); + + /* invert ATRAC3: waveform is inverted vs official tools (not noticeable but for accuracy) */ + if (is_at3) { + ffmpeg_data->invert_floats_set = 1; + } + + /* multichannel fix: LFE channel should be reordered on decode (ATRAC3Plus only, only 1/2/6/8ch exist): + * - 6ch: FL FR FC BL BR LFE > FL FR FC LFE BL BR + * - 8ch: FL FR FC BL BR SL SR LFE > FL FR FC LFE BL BR SL SR */ + if (is_at3p && ffmpeg_data->channels == 6) { + /* LFE BR BL > LFE BL BR > same */ + int channel_remap[] = { 0, 1, 2, 5, 5, 5, }; + ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap); + } + else if (is_at3p && ffmpeg_data->channels == 8) { + /* LFE BR SL SR BL > LFE BL SL SR BR > LFE BL BR SR SL > LFE BL BR SL SR > same */ + int channel_remap[] = { 0, 1, 2, 7, 7, 7, 7, 7}; + ffmpeg_set_channel_remapping(ffmpeg_data, channel_remap); + } + + + if (out_samples) + *out_samples = fact_samples; + + return ffmpeg_data; +fail: + free_ffmpeg(ffmpeg_data); + return NULL; +} + +#endif diff --git a/src/coding/ima_decoder.c b/src/coding/ima_decoder.c index c5832756..1c290e4c 100644 --- a/src/coding/ima_decoder.c +++ b/src/coding/ima_decoder.c @@ -878,7 +878,7 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t * stream->adpcm_step_index = step_index; } -/* mono XBOX-IMA with header endianness and alt nibble expand (per hcs's decompilation) */ +/* mono XBOX-IMA with header endianness and alt nibble expand (verified vs AK test demos) */ void decode_wwise_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { int i, sample_count = 0, num_frame; int32_t hist1 = stream->adpcm_history1_32; @@ -922,17 +922,6 @@ void decode_wwise_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample_t stream->adpcm_history1_32 = hist1; stream->adpcm_step_index = step_index; } -/* from hcs's analysis Wwise IMA expands nibbles slightly different, reducing dbs. Just "MUL" expand? -<_ZN13CAkADPCMCodec12DecodeSampleEiii>: //From Wwise_v2015.1.6_Build5553_SDK.Linux - 10: 83 e0 07 and $0x7,%eax ; sample - 13: 01 c0 add %eax,%eax ; sample*2 - 15: 83 c0 01 add $0x1,%eax ; sample*2+1 - 18: 0f af 45 e4 imul -0x1c(%rbp),%eax ; (sample*2+1)*scale - 1c: 8d 50 07 lea 0x7(%rax),%edx ; result+7 - 1f: 85 c0 test %eax,%eax ; result negative? - 21: 0f 48 c2 cmovs %edx,%eax ; adjust if negative to fix rounding for below division - 24: c1 f8 03 sar $0x3,%eax ; (sample*2+1)*scale/8 -*/ /* MS-IMA with possibly the XBOX-IMA model of even number of samples per block (more tests are needed) */ void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { diff --git a/src/meta/ps2_2pfs.c b/src/meta/ps2_2pfs.c index 24df3335..442c7434 100644 --- a/src/meta/ps2_2pfs.c +++ b/src/meta/ps2_2pfs.c @@ -1,117 +1,84 @@ -#include "meta.h" -#include "../util.h" - -/* 2PFS (Konami) - - Mahoromatic: Moetto - KiraKira Maid-San (PS2) [.2pfs (V1, 2003)] - - GANTZ The Game (PS2) [.sap (V2, 2005)] - - There are two versions of the format, though they use different extensions. - Implemented both versions here in case there are .2pfs with the V2 header out there. - Both loop correctly AFAIK (there is a truncated Mahoromatic rip around, beware). -*/ -VGMSTREAM * init_vgmstream_ps2_2pfs(STREAMFILE *streamFile) -{ - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - - off_t start_offset = 0x800; - int interleave = 0x1000; - - int loop_flag; - int channel_count; - int version; /* v1=1, v2=2 */ - - int loop_start_block; /* block number where the loop starts */ - int loop_end_block; /* usually the last block */ - int loop_start_sample_adjust; /* loops start/end a few samples into the start/end block */ - int loop_end_sample_adjust; - - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if ( strcasecmp("2pfs",filename_extension(filename)) - && strcasecmp("sap",filename_extension(filename)) ) - goto fail; - - /* check header ("2PFS") */ - if (read_32bitBE(0x00,streamFile) != 0x32504653) - goto fail; - - version = read_16bitLE(0x04,streamFile); - if ( version!=0x01 && version!=0x02 ) - goto fail; - - - channel_count = read_8bit(0x40,streamFile); - loop_flag = read_8bit(0x41,streamFile); - /* other header values - * 0x06 (4): unknown, v1=0x0004 v2=0x0001 - * 0x08 (32): unique file id - * 0x0c (32): base header size (v1=0x50, v2=0x60) + datasize (without the 0x800 full header size) - * 0x10-0x30: unknown (v1 differs from v2) - * 0x38-0x40: unknown (v1 same as v2) - * 0x4c (32) in V2: unknown, some kind of total samples? - */ - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = read_32bitLE(0x34,streamFile) * 28 / 16 / channel_count; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; - vgmstream->meta_type = meta_PS2_2PFS; - - if ( version==0x01 ) { - vgmstream->sample_rate = read_32bitLE(0x44,streamFile); - loop_start_sample_adjust = read_16bitLE(0x42,streamFile); - loop_start_block = read_32bitLE(0x48,streamFile); - loop_end_block = read_32bitLE(0x4c,streamFile); - } else { - vgmstream->sample_rate = read_32bitLE(0x48,streamFile); - loop_start_sample_adjust = read_32bitLE(0x44,streamFile); - loop_start_block = read_32bitLE(0x50,streamFile); - loop_end_block = read_32bitLE(0x54,streamFile); - } - loop_end_sample_adjust = interleave; /* loops end after all samples in the end_block AFAIK */ - - if ( loop_flag ) { - /* block to offset > offset to sample + adjust (number of samples into the block) */ - vgmstream->loop_start_sample = ((loop_start_block * channel_count * interleave) - * 28 / 16 / channel_count) - + (loop_start_sample_adjust * 28 / 16); - vgmstream->loop_end_sample = ((loop_end_block * channel_count * interleave) - * 28 / 16 / channel_count) - + (loop_end_sample_adjust * 28 / 16); - } - - - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset = - vgmstream->ch[i].offset = - start_offset + (vgmstream->interleave_block_size * i); - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + + +/* 2PFS - from Konami Games [Mahoromatic: Moetto - KiraKira Maid-San (PS2), GANTZ The Game (PS2)] */ +VGMSTREAM * init_vgmstream_ps2_2pfs(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count, version, interleave; + int loop_start_block, loop_end_block; /* block number */ + int loop_start_adjust, loop_end_adjust; /* loops start/end a few samples into the start/end block */ + + + /* checks */ + /* .sap: standard + * .2psf: header id? (Mahoromatic) */ + if (!check_extensions(streamFile, "sap,2psf")) + goto fail; + + if (read_32bitBE(0x00,streamFile) != 0x32504653) /* "2PFS" */ + goto fail; + + version = read_16bitLE(0x04,streamFile); + if (version != 0x01 && version != 0x02) /* v1: Mahoromatic, v2: Gantz */ + goto fail; + + + channel_count = read_8bit(0x40,streamFile); + loop_flag = read_8bit(0x41,streamFile); + start_offset = 0x800; + interleave = 0x1000; + + /* other header values + * 0x06: unknown, v1=0x0004 v2=0x0001 + * 0x08: unique file id + * 0x0c: base header size (v1=0x50, v2=0x60) + datasize (without the 0x800 full header size) + * 0x10-0x30: unknown (v1 differs from v2) + * 0x38-0x40: unknown (v1 same as v2) + * 0x4c: unknown, some kind of total samples? (v2 only) + */ + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_PS2_2PFS; + vgmstream->num_samples = read_32bitLE(0x34,streamFile) * 28 / 16 / channel_count; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + + if (version == 0x01) { + vgmstream->sample_rate = read_32bitLE(0x44,streamFile); + loop_start_adjust = read_16bitLE(0x42,streamFile); + loop_start_block = read_32bitLE(0x48,streamFile); + loop_end_block = read_32bitLE(0x4c,streamFile); + } + else { + vgmstream->sample_rate = read_32bitLE(0x48,streamFile); + loop_start_adjust = read_32bitLE(0x44,streamFile); + loop_start_block = read_32bitLE(0x50,streamFile); + loop_end_block = read_32bitLE(0x54,streamFile); + } + loop_end_adjust = interleave; /* loops end after all samples in the end_block AFAIK */ + + if (loop_flag) { + /* block to offset > offset to sample + adjust (number of frames into the block) */ + vgmstream->loop_start_sample = + ps_bytes_to_samples(loop_start_block * channel_count * interleave, channel_count) + + ps_bytes_to_samples(loop_start_adjust * channel_count, channel_count); + vgmstream->loop_end_sample = + ps_bytes_to_samples(loop_end_block * channel_count * interleave, channel_count) + + ps_bytes_to_samples(loop_end_adjust * channel_count, channel_count); + } + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/sgxd.c b/src/meta/sgxd.c index cc9c0f36..b37680a5 100644 --- a/src/meta/sgxd.c +++ b/src/meta/sgxd.c @@ -1,190 +1,190 @@ -#include "meta.h" -#include "../coding/coding.h" - - -/* SGXD - Sony/SCEI's format (SGB+SGH / SGD / SGX) */ -VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamHeader = NULL; - off_t start_offset, data_offset, chunk_offset, name_offset = 0; - size_t stream_size; - - int is_sgx, is_sgb = 0; - int loop_flag, channels, type; - int sample_rate, num_samples, loop_start_sample, loop_end_sample; - int total_subsongs, target_subsong = streamFile->stream_index; - - - /* check extension, case insensitive */ - /* .sgx: header+data (Genji), .sgd: header+data, .sgh/sgd: header/data */ - if (!check_extensions(streamFile,"sgx,sgd,sgb")) - goto fail; - is_sgx = check_extensions(streamFile,"sgx"); - is_sgb = check_extensions(streamFile,"sgb"); - - /* SGB+SGH: use SGH as header; otherwise use the current file as header */ - if (is_sgb) { - streamHeader = open_streamfile_by_ext(streamFile, "sgh"); - if (!streamHeader) goto fail; - } else { - streamHeader = streamFile; - } - - - /* SGXD base (size 0x10) */ - if (read_32bitBE(0x00,streamHeader) != 0x53475844) /* "SGXD" */ - goto fail; - /* 0x04 SGX: full header_size; SGD/SGH: unknown header_size (counting from 0x0/0x8/0x10, varies) */ - /* 0x08 SGX: first chunk offset? (0x10); SGD/SGH: full header_size */ - /* 0x0c SGX/SGH: full data size with padding; SGD: full data size + 0x80000000 with padding */ - if (is_sgb) { - data_offset = 0x00; - } else if ( is_sgx ) { - data_offset = read_32bitLE(0x04,streamHeader); - } else { - data_offset = read_32bitLE(0x08,streamHeader); - } - - - /* typical chunks: WAVE, RGND, NAME (strings for WAVE or RGND), SEQD (related to SFX), WSUR, WMKR, BUSS */ - /* WAVE chunk (size 0x10 + files * 0x38 + optional padding) */ - if (is_sgx) { /* position after chunk+size */ - if (read_32bitBE(0x10,streamHeader) != 0x57415645) goto fail; /* "WAVE" */ - chunk_offset = 0x18; - } else { - if (!find_chunk_le(streamHeader, 0x57415645,0x10,0, &chunk_offset,NULL)) goto fail; /* "WAVE" */ - } - /* 0x04 SGX: unknown; SGD/SGH: chunk length, 0x08 null */ - - /* check multi-streams (usually only SE containers; Puppeteer) */ - total_subsongs = read_32bitLE(chunk_offset+0x04,streamHeader); - if (target_subsong == 0) target_subsong = 1; - if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - - /* read stream header */ - { - off_t stream_offset; - chunk_offset += 0x08 + 0x38 * (target_subsong-1); /* position in target header*/ - - /* 0x00 ? (00/01/02) */ - if (!is_sgx) /* meaning unknown in .sgx; offset 0 = not a stream (a RGND sample) */ - name_offset = read_32bitLE(chunk_offset+0x04,streamHeader); - type = read_8bit(chunk_offset+0x08,streamHeader); - channels = read_8bit(chunk_offset+0x09,streamHeader); - /* 0x0a null */ - sample_rate = read_32bitLE(chunk_offset+0x0c,streamHeader); - - /* 0x10 info_type: meaning of the next value - * (00=null, 30/40=data size without padding (ADPCM, ATRAC3plus), 80/A0=block size (AC3) */ - /* 0x14 info_value (see above) */ - /* 0x18 unknown (ex. 0x0008/0010/3307/CC02/etc)x2 */ - /* 0x1c null */ - - num_samples = read_32bitLE(chunk_offset+0x20,streamHeader); - loop_start_sample = read_32bitLE(chunk_offset+0x24,streamHeader); - loop_end_sample = read_32bitLE(chunk_offset+0x28,streamHeader); - stream_size = read_32bitLE(chunk_offset+0x2c,streamHeader); /* stream size (without padding) / interleave (for type3) */ - - if (is_sgx) { - stream_offset = 0x0; - } else{ - stream_offset = read_32bitLE(chunk_offset+0x30,streamHeader); - } - /* 0x34 SGX: unknown; SGD/SGH: stream size (with padding) / interleave */ - - loop_flag = loop_start_sample!=0xffffffff && loop_end_sample!=0xffffffff; - start_offset = data_offset + stream_offset; - } - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channels,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = num_samples; - vgmstream->loop_start_sample = loop_start_sample; - vgmstream->loop_end_sample = loop_end_sample; - vgmstream->num_streams = total_subsongs; - vgmstream->stream_size = stream_size; - vgmstream->meta_type = meta_SGXD; - if (name_offset) - read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamHeader); - - switch (type) { -#ifdef VGM_USE_FFMPEG - case 0x02: /* Ogg Vorbis [Ni no Kuni: Wrath of the White Witch Remastered (PC)] (codec hijack?) */ - vgmstream->codec_data = init_ogg_vorbis(streamFile, start_offset, stream_size, NULL); - if (!vgmstream->codec_data) goto fail; - vgmstream->coding_type = coding_OGG_VORBIS; - vgmstream->layout_type = layout_none; - break; -#endif - case 0x03: /* PS-ADPCM [Genji (PS3), Ape Escape Move (PS3)]*/ - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - if (is_sgx || is_sgb) { - vgmstream->interleave_block_size = 0x10; - } else { /* this only seems to happen with SFX */ - vgmstream->interleave_block_size = stream_size; - } - - break; - -#ifdef VGM_USE_FFMPEG - case 0x04: { /* ATRAC3plus [Kurohyo 1/2 (PSP), BraveStory (PSP)] */ - vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamFile, start_offset, NULL); - if (!vgmstream->codec_data) goto fail; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - - /* SGXD's sample rate has priority over RIFF's sample rate (may not match) */ - /* loop/sample values are relative (without skip) vs RIFF (with skip), matching "smpl" otherwise */ - break; - } -#endif - case 0x05: /* Short PS-ADPCM [Afrika (PS3)] */ - vgmstream->coding_type = coding_PSX_cfg; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x4; - - break; - -#ifdef VGM_USE_FFMPEG - case 0x06: { /* AC3 [Tokyo Jungle (PS3), Afrika (PS3)] */ - ffmpeg_codec_data *ffmpeg_data; - - ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset, stream_size); - if ( !ffmpeg_data ) goto fail; - vgmstream->codec_data = ffmpeg_data; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - - /* manually set skip_samples if FFmpeg didn't do it */ - if (ffmpeg_data->skipSamples <= 0) { - /* PS3 AC3 consistently has 256 encoder delay samples, and there are ~1000-2000 samples after num_samples. - * Skipping them marginally improves full loops in some Tokyo Jungle tracks (ex. a_1.sgd). */ - ffmpeg_set_skip_samples(ffmpeg_data, 256); - } - /* SGXD loop/sample values are relative (without skip samples), no need to adjust */ - - break; - } -#endif - - default: - goto fail; - } - - /* open the file for reading */ - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - - if (is_sgb && streamHeader) close_streamfile(streamHeader); - return vgmstream; - -fail: - if (is_sgb && streamHeader) close_streamfile(streamHeader); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + + +/* SGXD - Sony/SCEI's format (SGB+SGH / SGD / SGX) */ +VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamHeader = NULL; + off_t start_offset, data_offset, chunk_offset, name_offset = 0; + size_t stream_size; + + int is_sgx, is_sgb = 0; + int loop_flag, channels, type; + int sample_rate, num_samples, loop_start_sample, loop_end_sample; + int total_subsongs, target_subsong = streamFile->stream_index; + + + /* check extension, case insensitive */ + /* .sgx: header+data (Genji), .sgd: header+data, .sgh/sgd: header/data */ + if (!check_extensions(streamFile,"sgx,sgd,sgb")) + goto fail; + is_sgx = check_extensions(streamFile,"sgx"); + is_sgb = check_extensions(streamFile,"sgb"); + + /* SGB+SGH: use SGH as header; otherwise use the current file as header */ + if (is_sgb) { + streamHeader = open_streamfile_by_ext(streamFile, "sgh"); + if (!streamHeader) goto fail; + } else { + streamHeader = streamFile; + } + + + /* SGXD base (size 0x10) */ + if (read_32bitBE(0x00,streamHeader) != 0x53475844) /* "SGXD" */ + goto fail; + /* 0x04 SGX: full header_size; SGD/SGH: unknown header_size (counting from 0x0/0x8/0x10, varies) */ + /* 0x08 SGX: first chunk offset? (0x10); SGD/SGH: full header_size */ + /* 0x0c SGX/SGH: full data size with padding; SGD: full data size + 0x80000000 with padding */ + if (is_sgb) { + data_offset = 0x00; + } else if ( is_sgx ) { + data_offset = read_32bitLE(0x04,streamHeader); + } else { + data_offset = read_32bitLE(0x08,streamHeader); + } + + + /* typical chunks: WAVE, RGND, NAME (strings for WAVE or RGND), SEQD (related to SFX), WSUR, WMKR, BUSS */ + /* WAVE chunk (size 0x10 + files * 0x38 + optional padding) */ + if (is_sgx) { /* position after chunk+size */ + if (read_32bitBE(0x10,streamHeader) != 0x57415645) goto fail; /* "WAVE" */ + chunk_offset = 0x18; + } else { + if (!find_chunk_le(streamHeader, 0x57415645,0x10,0, &chunk_offset,NULL)) goto fail; /* "WAVE" */ + } + /* 0x04 SGX: unknown; SGD/SGH: chunk length, 0x08 null */ + + /* check multi-streams (usually only SE containers; Puppeteer) */ + total_subsongs = read_32bitLE(chunk_offset+0x04,streamHeader); + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + /* read stream header */ + { + off_t stream_offset; + chunk_offset += 0x08 + 0x38 * (target_subsong-1); /* position in target header*/ + + /* 0x00 ? (00/01/02) */ + if (!is_sgx) /* meaning unknown in .sgx; offset 0 = not a stream (a RGND sample) */ + name_offset = read_32bitLE(chunk_offset+0x04,streamHeader); + type = read_8bit(chunk_offset+0x08,streamHeader); + channels = read_8bit(chunk_offset+0x09,streamHeader); + /* 0x0a null */ + sample_rate = read_32bitLE(chunk_offset+0x0c,streamHeader); + + /* 0x10 info_type: meaning of the next value + * (00=null, 30/40=data size without padding (ADPCM, ATRAC3plus), 80/A0=block size (AC3) */ + /* 0x14 info_value (see above) */ + /* 0x18 unknown (ex. 0x0008/0010/3307/CC02/etc)x2 */ + /* 0x1c null */ + + num_samples = read_32bitLE(chunk_offset+0x20,streamHeader); + loop_start_sample = read_32bitLE(chunk_offset+0x24,streamHeader); + loop_end_sample = read_32bitLE(chunk_offset+0x28,streamHeader); + stream_size = read_32bitLE(chunk_offset+0x2c,streamHeader); /* stream size (without padding) / interleave (for type3) */ + + if (is_sgx) { + stream_offset = 0x0; + } else{ + stream_offset = read_32bitLE(chunk_offset+0x30,streamHeader); + } + /* 0x34 SGX: unknown; SGD/SGH: stream size (with padding) / interleave */ + + loop_flag = loop_start_sample!=0xffffffff && loop_end_sample!=0xffffffff; + start_offset = data_offset + stream_offset; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start_sample; + vgmstream->loop_end_sample = loop_end_sample; + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + vgmstream->meta_type = meta_SGXD; + if (name_offset) + read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamHeader); + + switch (type) { +#ifdef VGM_USE_VORBIS + case 0x02: /* Ogg Vorbis [Ni no Kuni: Wrath of the White Witch Remastered (PC)] (codec hijack?) */ + vgmstream->codec_data = init_ogg_vorbis(streamFile, start_offset, stream_size, NULL); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_OGG_VORBIS; + vgmstream->layout_type = layout_none; + break; +#endif + case 0x03: /* PS-ADPCM [Genji (PS3), Ape Escape Move (PS3)]*/ + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + if (is_sgx || is_sgb) { + vgmstream->interleave_block_size = 0x10; + } else { /* this only seems to happen with SFX */ + vgmstream->interleave_block_size = stream_size; + } + + break; + +#ifdef VGM_USE_FFMPEG + case 0x04: { /* ATRAC3plus [Kurohyo 1/2 (PSP), BraveStory (PSP)] */ + vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamFile, start_offset, NULL); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + /* SGXD's sample rate has priority over RIFF's sample rate (may not match) */ + /* loop/sample values are relative (without skip) vs RIFF (with skip), matching "smpl" otherwise */ + break; + } +#endif + case 0x05: /* Short PS-ADPCM [Afrika (PS3)] */ + vgmstream->coding_type = coding_PSX_cfg; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x4; + + break; + +#ifdef VGM_USE_FFMPEG + case 0x06: { /* AC3 [Tokyo Jungle (PS3), Afrika (PS3)] */ + ffmpeg_codec_data *ffmpeg_data; + + ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset, stream_size); + if ( !ffmpeg_data ) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + /* manually set skip_samples if FFmpeg didn't do it */ + if (ffmpeg_data->skipSamples <= 0) { + /* PS3 AC3 consistently has 256 encoder delay samples, and there are ~1000-2000 samples after num_samples. + * Skipping them marginally improves full loops in some Tokyo Jungle tracks (ex. a_1.sgd). */ + ffmpeg_set_skip_samples(ffmpeg_data, 256); + } + /* SGXD loop/sample values are relative (without skip samples), no need to adjust */ + + break; + } +#endif + + default: + goto fail; + } + + /* open the file for reading */ + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + + if (is_sgb && streamHeader) close_streamfile(streamHeader); + return vgmstream; + +fail: + if (is_sgb && streamHeader) close_streamfile(streamHeader); + close_vgmstream(vgmstream); + return NULL; +}