diff --git a/src/layout/blocked_ea_schl.c b/src/layout/blocked_ea_schl.c index bfa07412..a55c960c 100644 --- a/src/layout/blocked_ea_schl.c +++ b/src/layout/blocked_ea_schl.c @@ -6,7 +6,6 @@ void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) { STREAMFILE* streamFile = vgmstream->ch[0].streamfile; int i; - int new_schl = 0; size_t block_size, block_samples; int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE; @@ -49,24 +48,11 @@ void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) { break; } - /* "SCHl" start block (movie "SHxx" shouldn't use multi files) */ - if (block_id == 0x5343486C) - new_schl = 1; - - /* padding between "SCEl" and next "SCHl" (when subfiles exist) */ - if (block_id == 0x00000000) - block_size = 0x04; - /* guard against errors (happens in bad rips/endianness, observed max is vid ~0x20000) */ if (block_size == 0x00 || block_size > 0xFFFFF || block_samples > 0xFFFF) { block_size = 0x04; block_samples = 0; } - - /* "SCEl" end chunk should be 32b-aligned, fixes some multi-SCHl [ex. Need for Speed 2 (PC) .eam] */ - if (((block_offset + block_size) % 0x04) && block_id == 0x5343456C) { - block_size += 0x04 - ((block_offset + block_size) % 0x04); - } } @@ -165,11 +151,6 @@ void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) { vgmstream->ch[i].offset = block_offset + 0x0C + (0x04*vgmstream->channels) + channel_start; } - /* SCHl with multiple SCHl need to reset their MPEG decoder as there are trailing samples in the buffers */ - if (new_schl) { - flush_mpeg(vgmstream->codec_data); - } - break; #endif /* id, size, samples, offsets-per-channel, interleaved data (w/ optional hist per channel) */ diff --git a/src/meta/ea_schl.c b/src/meta/ea_schl.c index 709a5f9b..5e5b6c32 100644 --- a/src/meta/ea_schl.c +++ b/src/meta/ea_schl.c @@ -97,13 +97,12 @@ typedef struct { int codec_config; } ea_header; -static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int total_streams); -static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int total_streams); +static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset); +static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int is_embedded); static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t begin_offset, int max_length, int bnk_version); static uint32_t read_patch(STREAMFILE* streamFile, off_t* offset); -static int get_ea_stream_total_samples(STREAMFILE* streamFile, off_t start_offset, VGMSTREAM* vgmstream); static off_t get_ea_stream_mpeg_start_offset(STREAMFILE* streamFile, off_t start_offset, const ea_header* ea); -static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_header *ea, off_t start_offset, int is_bnk, int total_streams); +static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_header *ea, off_t start_offset, int is_bnk); /* EA SCHl with variable header - from EA games (roughly 1997~2010); generated by EA Canada's sx.exe/Sound eXchange */ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) { @@ -126,7 +125,7 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) { /* Stream is divided into blocks/chunks: SCHl=audio header, SCCl=count of SCDl, SCDl=data xN, SCLl=loop end, SCEl=end. * Video uses picture blocks (MVhd/MV0K/etc) and sometimes multiaudio blocks (SHxx/SCxx/SDxx/SExx where xx=language=EN/FR/GE/IT/SP/RU/JA). * The number/size is affected by: block rate setting, sample rate, channels, CPU location (SPU/main/DSP/others), etc */ - return parse_schl_block(streamFile, 0x00, 0); + return parse_schl_block(streamFile, 0x00); fail: return NULL; @@ -261,7 +260,7 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) { goto fail; bnk_target_stream = read_32bit(target_entry_offset + 0x04, streamFile) + 1; - vgmstream = parse_bnk_header(streamFile, bnk_offset, bnk_target_stream, total_sounds); + vgmstream = parse_bnk_header(streamFile, bnk_offset, bnk_target_stream, 1); if (!vgmstream) goto fail; break; @@ -280,7 +279,7 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) { if (read_32bitBE(schl_offset, astData) != EA_BLOCKID_HEADER) goto fail; - vgmstream = parse_schl_block(astData, schl_offset, total_sounds); + vgmstream = parse_schl_block(astData, schl_offset); if (!vgmstream) goto fail; break; @@ -290,6 +289,7 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) { break; } + vgmstream->num_streams = total_sounds; close_streamfile(astData); return vgmstream; @@ -339,10 +339,11 @@ VGMSTREAM * init_vgmstream_ea_hdr_dat(STREAMFILE *streamFile) { if (read_32bitBE(schl_offset, datFile) != EA_BLOCKID_HEADER) goto fail; - vgmstream = parse_schl_block(datFile, schl_offset, total_sounds); + vgmstream = parse_schl_block(datFile, schl_offset); if (!vgmstream) goto fail; + vgmstream->num_streams = total_sounds; close_streamfile(datFile); return vgmstream; @@ -398,10 +399,11 @@ VGMSTREAM * init_vgmstream_ea_map_mus(STREAMFILE *streamFile) { if (read_32bitBE(schl_offset, musFile) != EA_BLOCKID_HEADER) goto fail; - vgmstream = parse_schl_block(musFile, schl_offset, num_sounds); + vgmstream = parse_schl_block(musFile, schl_offset); if (!vgmstream) goto fail; + vgmstream->num_streams = num_sounds; close_streamfile(musFile); return vgmstream; @@ -485,10 +487,11 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE *streamFile) { if (read_32bitBE(schl_offset, musFile) != EA_BLOCKID_HEADER) goto fail; - vgmstream = parse_schl_block(musFile, schl_offset, total_streams); + vgmstream = parse_schl_block(musFile, schl_offset); if (!vgmstream) goto fail; + vgmstream->num_streams = total_streams; close_streamfile(musFile); return vgmstream; @@ -498,7 +501,7 @@ fail: } /* EA SCHl with variable header - from EA games (roughly 1997~2010); generated by EA Canada's sx.exe/Sound eXchange */ -static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int total_streams) { +static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset) { off_t start_offset, header_offset; size_t header_size; ea_header ea = { 0 }; @@ -519,19 +522,20 @@ static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int to start_offset = offset + header_size; /* starts in "SCCl" (skipped in block layout) or very rarely "SCDl" and maybe movie blocks */ /* rest is common */ - return init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, 0, total_streams); + return init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, 0); fail: return NULL; } /* EA BNK with variable header - from EA games SFXs; also created by sx.exe */ -static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int total_streams) { +static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int is_embedded) { off_t header_offset, start_offset, test_offset, table_offset; size_t header_size; ea_header ea = {0}; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + VGMSTREAM *vgmstream = NULL; int i, bnk_version; int total_bnk_sounds, real_bnk_sounds = 0; @@ -582,7 +586,7 @@ static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int ta real_bnk_sounds++; /* ABK points at absolute indexes, i.e. with dummies included */ - if (total_streams != 0) { + if (is_embedded != 0) { if (target_stream - 1 == i) header_offset = offset + table_offset + 0x04 * i + test_offset; } @@ -609,14 +613,20 @@ static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int ta start_offset = ea.offsets[0]; /* first channel, presumably needed for MPEG */ /* rest is common */ - return init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, bnk_version, total_streams ? total_streams : real_bnk_sounds); + vgmstream = init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, bnk_version); + if (!vgmstream) goto fail; + if (!is_embedded) { + vgmstream->num_streams = real_bnk_sounds; + } + + return vgmstream; fail: return NULL; } /* inits VGMSTREAM from a EA header */ -static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_header * ea, off_t start_offset, int bnk_version, int total_streams) { +static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_header * ea, off_t start_offset, int bnk_version) { VGMSTREAM * vgmstream = NULL; int i, ch; int is_bnk = bnk_version; @@ -663,7 +673,6 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_ vgmstream->layout_type = layout_blocked_ea_schl; } - vgmstream->num_streams = total_streams; //vgmstream->stream_size = ; //todo needed for kbps info /* EA usually implements their codecs in all platforms (PS2/WII do EAXA/MT/EALAYER3) and @@ -848,15 +857,6 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_ } } } - else if (vgmstream->layout_type == layout_blocked_ea_schl) { - /* regular SCHls, except ATRAC3plus */ - if (total_streams == 0) { - /* HACK: fix num_samples for streams with multiple SCHl. Need to eventually get rid of this */ - int total_samples = get_ea_stream_total_samples(streamFile, start_offset, vgmstream); - if (total_samples > vgmstream->num_samples) - vgmstream->num_samples = total_samples; - } - } return vgmstream; @@ -1245,40 +1245,6 @@ fail: return 0; } -/* Get total samples by parsing block headers, needed when multiple files are stitched together. - * Some EA files (.mus/eam/sng/etc) concat many small subfiles, used for interactive/mapped - * music (.map/lin). Subfiles always share header, except num_samples. */ -static int get_ea_stream_total_samples(STREAMFILE* streamFile, off_t start_offset, VGMSTREAM* vgmstream) { - int num_samples = 0; - int multiple_schl = 0; - - /* calc num_samples as playable data size varies between files/blocks */ - { - vgmstream->next_block_offset = start_offset; - do { - uint32_t block_id = read_32bitBE(vgmstream->next_block_offset+0x00,streamFile); - if (block_id == EA_BLOCKID_HEADER) /* "SCHl" start block (movie "SHxx" shouldn't use multi files) */ - multiple_schl = 1; - - block_update_ea_schl(vgmstream->next_block_offset,vgmstream); - num_samples += vgmstream->current_block_samples; - } - while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); - - /* reset after getting samples */ - block_update(start_offset,vgmstream); - } - - /* only use calculated samples with multiple subfiles (rarely header samples may be less due to padding) */ - if (multiple_schl) { - ;VGM_LOG("EA SCHl: multiple SCHl found\n"); - return num_samples; - } - else { - return 0; - } -} - /* find data start offset inside the first SCDl; not very elegant but oh well */ static off_t get_ea_stream_mpeg_start_offset(STREAMFILE* streamFile, off_t start_offset, const ea_header* ea) { size_t file_size = get_streamfile_size(streamFile);