mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 15:00:11 +01:00
EAAC: Properly calculate stream size for bitrate
This commit is contained in:
parent
8a00c7cd66
commit
519659fd3e
@ -5,38 +5,52 @@
|
||||
/* EA SNS/SPS blocks */
|
||||
void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
|
||||
uint32_t block_size, block_samples;
|
||||
uint32_t block_id, block_size, block_samples;
|
||||
size_t file_size = get_streamfile_size(streamFile);
|
||||
off_t channel_start;
|
||||
size_t channel_interleave;
|
||||
int i;
|
||||
|
||||
/* always BE */
|
||||
block_size = read_32bitBE(block_offset + 0x00,streamFile);
|
||||
block_samples = read_32bitBE(block_offset + 0x04,streamFile);
|
||||
|
||||
/* EOF */
|
||||
if (block_size == 0 || block_offset >= file_size) {
|
||||
vgmstream->current_block_offset = file_size;
|
||||
vgmstream->next_block_offset = file_size + 0x04;
|
||||
vgmstream->current_block_samples = vgmstream->num_samples;
|
||||
/* EOF reads: signal we have nothing and let the layout fail */
|
||||
if (block_offset >= get_streamfile_size(streamFile)) {
|
||||
vgmstream->current_block_offset = block_offset;
|
||||
vgmstream->next_block_offset = block_offset;
|
||||
vgmstream->current_block_samples = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* always BE */
|
||||
block_size = read_32bitBE(block_offset + 0x00,streamFile);
|
||||
|
||||
/* At 0x00(1): block flag
|
||||
* - in SNS: 0x00=normal block, 0x80=last block (not mandatory)
|
||||
* - in SPS: 0x48=header, 0x44=normal block, 0x45=last block (empty) */
|
||||
block_id = (block_size & 0x00FFFFFF) >> 24;
|
||||
block_size &= 0x00FFFFFF;
|
||||
|
||||
switch(vgmstream->coding_type) {
|
||||
if (block_id == 0x00 || block_id == 0x80 || block_id == 0x44) {
|
||||
block_samples = read_32bitBE(block_offset + 0x04, streamFile);
|
||||
} else {
|
||||
block_samples = 0;
|
||||
}
|
||||
|
||||
vgmstream->current_block_offset = block_offset;
|
||||
vgmstream->next_block_offset = block_offset + block_size;
|
||||
vgmstream->current_block_samples = block_samples;
|
||||
|
||||
/* no need to setup offsets (plus could read over filesize near EOF) */
|
||||
if (block_samples == 0)
|
||||
return;
|
||||
|
||||
switch (vgmstream->coding_type) {
|
||||
case coding_NGC_DSP:
|
||||
/* 0x04: unknown (0x00/02), 0x08: some size?, 0x34: null? */
|
||||
channel_start = read_32bitBE(block_offset+0x08+0x00,streamFile);
|
||||
channel_interleave = read_32bitBE(block_offset+0x08+0x0c,streamFile);
|
||||
channel_start = read_32bitBE(block_offset + 0x08 + 0x00, streamFile);
|
||||
channel_interleave = read_32bitBE(block_offset + 0x08 + 0x0c, streamFile);
|
||||
/* guessed as all known EA DSP only have one block with subheader (maybe changes coefs every block?) */
|
||||
if (channel_start >= 0x40) {
|
||||
dsp_read_coefs_be(vgmstream,streamFile, block_offset+0x08+0x10,0x28);
|
||||
dsp_read_hist_be (vgmstream,streamFile, block_offset+0x08+0x30,0x28);//todo guessed and doesn't fix clicks in full loops
|
||||
dsp_read_coefs_be(vgmstream, streamFile, block_offset + 0x08 + 0x10, 0x28);
|
||||
dsp_read_hist_be(vgmstream, streamFile, block_offset + 0x08 + 0x30, 0x28);//todo guessed and doesn't fix clicks in full loops
|
||||
}
|
||||
break;
|
||||
|
||||
@ -47,15 +61,11 @@ void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
}
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
vgmstream->ch[i].offset = block_offset + 0x08 + channel_start + i*channel_interleave;
|
||||
vgmstream->ch[i].offset = block_offset + 0x08 + channel_start + i * channel_interleave;
|
||||
|
||||
/* also fix first offset (for EALayer3) */
|
||||
if (block_offset == vgmstream->ch[i].channel_start_offset) {
|
||||
vgmstream->ch[i].channel_start_offset = vgmstream->ch[i].offset;
|
||||
}
|
||||
}
|
||||
|
||||
vgmstream->current_block_offset = block_offset;
|
||||
vgmstream->next_block_offset = block_offset + block_size;
|
||||
vgmstream->current_block_samples = block_samples;
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ VGMSTREAM * init_vgmstream_ea_sbr(STREAMFILE *streamFile) {
|
||||
|
||||
for (i = 0; i < num_metas; i++) {
|
||||
entry_offset = metas_offset + 0x06 * i;
|
||||
meta_type = read_16bitBE(entry_offset, streamFile);
|
||||
meta_type = read_16bitBE(entry_offset + 0x00, streamFile);
|
||||
data_offset = read_32bitBE(entry_offset + 0x02, streamFile);
|
||||
|
||||
type_desc = read_32bitBE(types_offset + 0x06 * meta_type, streamFile);
|
||||
@ -497,7 +497,7 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus_eaac(STREAMFILE *streamFile) {
|
||||
uint32_t num_sounds;
|
||||
uint8_t version, sub_version, block_id;
|
||||
off_t table_offset, entry_offset, snr_offset, sns_offset;
|
||||
size_t /*snr_size,*/ sns_size;
|
||||
/* size_t snr_size sns_size; */
|
||||
int32_t(*read_32bit)(off_t, STREAMFILE*);
|
||||
STREAMFILE *musFile = NULL;
|
||||
VGMSTREAM *vgmstream = NULL;
|
||||
@ -547,8 +547,10 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus_eaac(STREAMFILE *streamFile) {
|
||||
entry_offset = table_offset + (target_stream - 1) * 0x1c;
|
||||
snr_offset = read_32bit(entry_offset + 0x08, musFile) * 0x10;
|
||||
sns_offset = read_32bit(entry_offset + 0x0c, musFile) * 0x80;
|
||||
//snr_size = read_32bit(entry_offset + 0x10, musFile);
|
||||
/*
|
||||
snr_size = read_32bit(entry_offset + 0x10, musFile);
|
||||
sns_size = read_32bit(entry_offset + 0x14, musFile);
|
||||
*/
|
||||
|
||||
block_id = read_8bit(sns_offset, musFile);
|
||||
if (block_id != EAAC_BLOCKID0_DATA && block_id != EAAC_BLOCKID0_END)
|
||||
@ -559,7 +561,6 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus_eaac(STREAMFILE *streamFile) {
|
||||
goto fail;
|
||||
|
||||
vgmstream->num_streams = num_sounds;
|
||||
vgmstream->stream_size = sns_size;
|
||||
close_streamfile(musFile);
|
||||
return vgmstream;
|
||||
|
||||
@ -764,7 +765,7 @@ typedef struct {
|
||||
|
||||
static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *streamData, eaac_header *eaac);
|
||||
static layered_layout_data* build_layered_eaaudiocore_eaxma(STREAMFILE *streamFile, eaac_header *eaac);
|
||||
|
||||
static size_t calculate_eaac_size(VGMSTREAM *vgmstream, STREAMFILE *streamFile, eaac_header *eaac, off_t start_offset);
|
||||
|
||||
/* EA newest header from RwAudioCore (RenderWare?) / EAAudioCore library (still generated by sx.exe).
|
||||
* Audio "assets" come in separate RAM headers (.SNR/SPH) and raw blocked streams (.SNS/SPS),
|
||||
@ -831,7 +832,7 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
|
||||
eaac.loop_offset = eaac.stream_offset + eaac.loop_offset;
|
||||
}
|
||||
else {
|
||||
/* RAM assets only one block in case in case of full loops */
|
||||
/* RAM assets have only one block in case of full loops */
|
||||
eaac.loop_offset = eaac.stream_offset; /* implicit */
|
||||
}
|
||||
|
||||
@ -1023,9 +1024,13 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,temp_streamFile ? temp_streamFile : streamData,start_offset))
|
||||
if (!vgmstream_open_stream(vgmstream, temp_streamFile ? temp_streamFile : streamData, start_offset))
|
||||
goto fail;
|
||||
|
||||
if (eaac.loop_start == 0) {
|
||||
vgmstream->stream_size = calculate_eaac_size(vgmstream, temp_streamFile ? temp_streamFile : streamData, &eaac, start_offset);
|
||||
}
|
||||
|
||||
close_streamfile(temp_streamFile);
|
||||
return vgmstream;
|
||||
|
||||
@ -1037,12 +1042,50 @@ fail:
|
||||
|
||||
static size_t get_snr_size(STREAMFILE *streamFile, off_t offset) {
|
||||
switch (read_8bit(offset + 0x04, streamFile) >> 4 & 0x0F) { /* flags */
|
||||
case EAAC_FLAG_LOOPED | EAAC_FLAG_STREAMED: return 0x10;
|
||||
case EAAC_FLAG_LOOPED: return 0x0C;
|
||||
default: return 0x08;
|
||||
case EAAC_FLAG_LOOPED | EAAC_FLAG_STREAMED: return 0x10;
|
||||
case EAAC_FLAG_LOOPED: return 0x0C;
|
||||
default: return 0x08;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t calculate_eaac_size(VGMSTREAM *vgmstream, STREAMFILE *streamFile, eaac_header *eaac, off_t start_offset) {
|
||||
uint32_t total_samples;
|
||||
size_t stream_size, file_size;
|
||||
|
||||
switch (eaac->codec) {
|
||||
case EAAC_CODEC_EAXMA:
|
||||
case EAAC_CODEC_EALAYER3_V1:
|
||||
case EAAC_CODEC_EALAYER3_V2_PCM:
|
||||
case EAAC_CODEC_EALAYER3_V2_SPIKE:
|
||||
case EAAC_CODEC_EATRAX:
|
||||
case EAAC_CODEC_EAMP3:
|
||||
case EAAC_CODEC_EAOPUS:
|
||||
stream_size = get_streamfile_size(streamFile);
|
||||
break;
|
||||
default:
|
||||
stream_size = 0;
|
||||
total_samples = 0;
|
||||
file_size = get_streamfile_size(streamFile);
|
||||
vgmstream->next_block_offset = start_offset;
|
||||
|
||||
while (vgmstream->next_block_offset < file_size && total_samples != vgmstream->num_samples) {
|
||||
block_update_ea_sns(vgmstream->next_block_offset, vgmstream);
|
||||
if (vgmstream->current_block_samples == 0)
|
||||
continue;
|
||||
|
||||
/* stream size is almost never provided in bank files so we have to calc it manually */
|
||||
stream_size += vgmstream->next_block_offset - vgmstream->ch[0].offset;
|
||||
total_samples += vgmstream->current_block_samples;
|
||||
}
|
||||
|
||||
/* reset once we're done */
|
||||
block_update(start_offset, vgmstream);
|
||||
break;
|
||||
}
|
||||
|
||||
return stream_size;
|
||||
}
|
||||
|
||||
|
||||
/* Actual looping uses 2 block sections, separated by a block end flag *and* padded.
|
||||
*
|
||||
@ -1108,6 +1151,8 @@ static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *st
|
||||
|
||||
if (!vgmstream_open_stream(data->segments[i],temp_streamFile[i],0x00))
|
||||
goto fail;
|
||||
|
||||
data->segments[i]->stream_size = calculate_eaac_size(data->segments[i], temp_streamFile[i], eaac, 0x00);
|
||||
}
|
||||
|
||||
if (!setup_layout_segmented(data))
|
||||
|
Loading…
Reference in New Issue
Block a user