diff --git a/src/coding/mpeg_custom_utils.c b/src/coding/mpeg_custom_utils.c index dd481741..f225f931 100644 --- a/src/coding/mpeg_custom_utils.c +++ b/src/coding/mpeg_custom_utils.c @@ -18,6 +18,8 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m } data->channels_per_frame = info.channels; data->samples_per_frame = info.frame_samples; + data->bitrate_per_frame = info.bit_rate; + data->sample_rate_per_frame = info.sample_rate; /* extra checks per type */ @@ -50,6 +52,7 @@ int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, m break; case MPEG_P3D: + case MPEG_SCD: if (data->config.interleave <= 0) goto fail; /* needs external fixed size */ break; @@ -94,7 +97,9 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d mpeg_frame_info info; size_t current_data_size = 0; size_t current_padding = 0; - size_t current_interleave = 0; + size_t current_interleave_pre = 0; /* interleaved data size before current stream */ + size_t current_interleave_post = 0; /* interleaved data size after current stream */ + size_t current_interleave = 0; /* interleave in this block (usually this + pre + post = interleave*streams = block) */ /* Get data size to give to the decoder, per stream. Usually 1 frame at a time, @@ -102,11 +107,18 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d switch(data->type) { case MPEG_XVAG: /* frames of fixed size (though we could read frame info too) */ - current_data_size = data->config.chunk_size; current_interleave = data->config.interleave; /* big interleave */ + current_interleave_pre = current_interleave*num_stream; + current_interleave_post = current_interleave*(data->streams_size-1) - current_interleave_pre; + + current_data_size = data->config.chunk_size; break; case MPEG_FSB: /* frames with padding + interleave */ + current_interleave = data->config.interleave; /* constant for multi-stream FSbs (1 frame + padding) */ + current_interleave_pre = current_interleave*num_stream; + current_interleave_post = current_interleave*(data->streams_size-1) - current_interleave_pre; + if ( !mpeg_get_frame_info(stream->streamfile, stream->offset, &info) ) goto fail; current_data_size = info.frame_size; @@ -119,17 +131,28 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d : 0; } - /* frame interleave (ie. read 1 data-frame, skip 1 data-frame per stream) */ - current_interleave = data->config.interleave; /* constant for multi-stream FSbs */ - VGM_ASSERT(data->streams_size > 1 && current_interleave != current_data_size+current_padding, "MPEG FSB: %i streams with non-constant interleave found @ 0x%08lx\n", data->streams_size, stream->offset); break; case MPEG_P3D: /* fixed interleave, not frame-aligned (ie. blocks may end/start in part of a frame) */ - current_data_size = data->config.interleave / 4; /* to ensure we don't feed mpg123 too much */ - current_interleave = data->config.interleave; /* fixed interleave (0x400) */ - //todo: last block is smaller that interleave, not sure how it's divided + case MPEG_SCD: + current_interleave = data->config.interleave; + +#if 1 + /* check if current interleave block is short */ + { + off_t block_offset = stream->offset - stream->channel_start_offset; + size_t next_block = data->streams_size*data->config.interleave; + + if (data->config.data_size && block_offset + next_block >= data->config.data_size) + current_interleave = (data->config.data_size % next_block) / data->streams_size; /* short_interleave*/ + } +#endif + current_interleave_pre = current_interleave*num_stream; + current_interleave_post = current_interleave*(data->streams_size-1) - current_interleave_pre; + + current_data_size = current_interleave; break; default: /* standard frames (CBR or VBR) */ @@ -143,19 +166,26 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *d goto fail; } + /* This assumes all streams' offsets start in the first stream, and advances + * the 'full interleaved block' at once, ex: + * start at s0=0x00, s1=0x00, interleave=0x40 (block = 0x40*2=0x80) + * @0x00 read 0x40 of s0, skip 0x40 of s1 (block of 0x80 done) > new offset = 0x80 + * @0x00 skip 0x40 of s0, read 0x40 of s1 (block of 0x80 done) > new offset = 0x800 + */ - /* read single frame */ - ms->bytes_in_buffer = read_streamfile(ms->buffer,stream->offset, current_data_size, stream->streamfile); + /* read chunk (skipping other interleaves if needed) */ + ms->bytes_in_buffer = read_streamfile(ms->buffer,stream->offset + current_interleave_pre, current_data_size, stream->streamfile); - /* update offsets */ + /* update offsets and skip other streams */ stream->offset += current_data_size + current_padding; - /* skip interleave once block is done, if defined */ - if (current_interleave && ((stream->offset - stream->channel_start_offset) % current_interleave == 0)) { - stream->offset += current_interleave * (data->streams_size-1); /* skip a block each stream */ + /* skip rest of block (interleave per stream) once this stream's interleaved data is done, if defined */ + if (current_interleave && ((stream->offset - stream->channel_start_offset + current_interleave_pre + current_interleave_post) % current_interleave == 0)) { + stream->offset += current_interleave_pre + current_interleave_post; } + return 1; fail: return 0; diff --git a/src/coding/mpeg_custom_utils_ealayer3.c b/src/coding/mpeg_custom_utils_ealayer3.c index 84f6cc74..c50f6d85 100644 --- a/src/coding/mpeg_custom_utils_ealayer3.c +++ b/src/coding/mpeg_custom_utils_ealayer3.c @@ -150,6 +150,8 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data * } + // todo rarely there is a block between granules (ex. EAL3 v2P in FIFA 2016) + /* get second frame/granule (MPEG1 only) if first granule was found */ granule_found = 0; while (eaf_0.common_size && eaf_0.mpeg1 && !granule_found) { @@ -665,6 +667,7 @@ static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, i if (!ok) goto fail; stream->offset += eaf.eaframe_size; + //;VGM_LOG("s%i: skipping %x, now at %lx\n", num_stream,eaf.eaframe_size,stream->offset); } //;VGM_LOG("s%i: skipped %i frames, now at %lx\n", num_stream,skips,stream->offset); diff --git a/src/coding/mpeg_decoder.c b/src/coding/mpeg_decoder.c index dcfeede1..ba8aeea9 100644 --- a/src/coding/mpeg_decoder.c +++ b/src/coding/mpeg_decoder.c @@ -167,9 +167,6 @@ mpeg_codec_data *init_mpeg_custom_codec_data(STREAMFILE *streamFile, off_t start } - /* write output */ - config->interleave = data->config.interleave; /* for FSB */ - return data; fail: @@ -383,7 +380,7 @@ static void decode_mpeg_custom_stream(VGMSTREAMCHANNEL *stream, mpeg_codec_data /* extra EOF check for edge cases when the caller tries to read more samples than possible */ if (!ms->buffer_full && stream->offset >= stream_size) { - VGM_LOG("MPEG: EOF found but more data is requested\n"); + VGM_LOG("MPEG: EOF found but more data is requested in stream %i\n", num_stream); goto decode_fail; } @@ -603,7 +600,12 @@ long mpeg_bytes_to_samples(long bytes, const mpeg_codec_data *data) { return (int64_t)bytes * data->mi.rate * 8 / (data->mi.bitrate * 1000); } else { - return 0; /* a bit too complex for what is worth */ + /* needed for SCD */ + if (data->streams_size && data->bitrate_per_frame) { + return (int64_t)(bytes / data->streams_size) * data->sample_rate_per_frame * 8 / (data->bitrate_per_frame * 1000); + } + + return 0; } } diff --git a/src/formats.c b/src/formats.c index 37e5e0bf..f3572d48 100644 --- a/src/formats.c +++ b/src/formats.c @@ -162,6 +162,7 @@ static const char* extension_list[] = { "leg", "lmp4", //fake extension, for MP4s "logg", //fake extension, for OGGs + "lopus", //fake extension, for OPUS "lpcm", "lps", "lsf", @@ -569,9 +570,6 @@ static const layout_info layout_info_list[] = { #ifdef VGM_USE_VORBIS {layout_ogg_vorbis, "Ogg"}, #endif -#ifdef VGM_USE_MPEG - {layout_mpeg_custom, "Custom MPEG Audio"}, -#endif }; static const meta_info meta_info_list[] = { diff --git a/src/layout/blocked_ea_sns.c b/src/layout/blocked_ea_sns.c index 827ecc93..12afab00 100644 --- a/src/layout/blocked_ea_sns.c +++ b/src/layout/blocked_ea_sns.c @@ -2,7 +2,7 @@ #include "../coding/coding.h" #include "../vgmstream.h" -/* EA "SNS "blocks (most common in .SNS) */ +/* 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; @@ -21,16 +21,10 @@ void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream) { return; } - /* 0x80: last block - * 0x40: new block for some codecs? - * 0x08: ? - * 0x04: new block for some codecs? - * 0x01: last block for some codecs? - * 0x00: none? */ - if (block_size & 0xFF000000) { - //VGM_ASSERT(!(block_size & 0x80000000), "EA SNS: unknown flag found at %lx\n", block_offset); - block_size &= 0x00FFFFFF; - } + /* 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_size &= 0x00FFFFFF; for (i = 0; i < vgmstream->channels; i++) { off_t channel_start = 0x00; diff --git a/src/meta/adx_keys.h b/src/meta/adx_keys.h index 1cb41d1f..29cdbbcd 100644 --- a/src/meta/adx_keys.h +++ b/src/meta/adx_keys.h @@ -3,7 +3,9 @@ /* Tests each start/mult/add vs derived key8/9 (if provided), as most where brute forced. - * Mainly for debugging purposes (info from VGAudio / ADX_Decoder) */ + * Ie. uncommenting this and adding a new key8/key9 + compiling with VGM_DEBUG_OUTPUT + * will print its derived key (useful as games often use the same key for hca and adx type 9). + * Mainly for debugging purposes (info from VGAudio / ADX_Decoder). */ //#define ADX_VERIFY_DERIVED_KEYS 1 @@ -199,6 +201,9 @@ static const adxkey_info adxkey9_list[] = { /* Yuuki Yuuna wa Yuusha de aru - Hanayui no Kirameki / Yuyuyui (iOS/Android) */ {0x3f10,0x3651,0x6d31, NULL,4867249871962584729}, // 438BF1F883653699 + // Super Robot Wars X-Omega (voices) [iOS/Android] + {0x5152,0x7979,0x152b, NULL,165521992944278}, // 0000968A97978A96 + }; static const int adxkey8_list_count = sizeof(adxkey8_list) / sizeof(adxkey8_list[0]); diff --git a/src/meta/ea_eaac.c b/src/meta/ea_eaac.c index 2f77004e..03eb0ebd 100644 --- a/src/meta/ea_eaac.c +++ b/src/meta/ea_eaac.c @@ -48,12 +48,10 @@ VGMSTREAM * init_vgmstream_ea_sps(STREAMFILE * streamFile) { if (!check_extensions(streamFile,"sps")) goto fail; - /* Very hacky but the original check for 0x48000000 rejected some playable files */ - if (((read_16bitBE(0x00,streamFile) & 0xFFFFFF00) != 0x4800) && - ((read_8bit(0x00, streamFile) & 0xFFFFFF00) != 0x00)) + /* SPS block start: 0x00(1): block flag (header=0x48); 0x01(3): block size (usually 0x0c-0x14) */ + if (read_8bit(0x00, streamFile) != 0x48) goto fail; - - start_offset = read_8bit(0x03, streamFile); + start_offset = read_32bitBE(0x00, streamFile) & 0x00FFFFFF; vgmstream = init_vgmstream_eaaudiocore_header(streamFile, streamFile, 0x04, start_offset, meta_EA_SPS); if (!vgmstream) goto fail; diff --git a/src/meta/fsb.c b/src/meta/fsb.c index cdce31cb..388cad2e 100644 --- a/src/meta/fsb.c +++ b/src/meta/fsb.c @@ -287,9 +287,8 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) { if (fsbh.mode & FSOUND_MPEG) { /* FSB3: ?; FSB4: Shatter, Way of the Samurai 3/4, Forza Horizon 1/2, Dragon Age Origins */ #if defined(VGM_USE_MPEG) - mpeg_custom_config cfg; + mpeg_custom_config cfg = {0}; - memset(&cfg, 0, sizeof(mpeg_custom_config)); cfg.fsb_padding = (vgmstream->channels > 2 ? 16 : (fsbh.flags & FMOD_FSB_SOURCE_MPEG_PADDED4 ? 4 : (fsbh.flags & FMOD_FSB_SOURCE_MPEG_PADDED ? 2 : 0))); @@ -299,10 +298,7 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) { vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_FSB, &cfg); if (!vgmstream->codec_data) goto fail; - - /* both to setup initial interleave in vgmstream_open_stream */ - vgmstream->interleave_block_size = cfg.interleave; - vgmstream->layout_type = layout_mpeg_custom; + vgmstream->layout_type = layout_none; #else goto fail; /* FFmpeg can't properly read FSB4 or FMOD's 0-padded MPEG data @ start_offset */ diff --git a/src/meta/fsb5.c b/src/meta/fsb5.c index eb8f0d37..c648db71 100644 --- a/src/meta/fsb5.c +++ b/src/meta/fsb5.c @@ -265,10 +265,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) { vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, StartOffset, &vgmstream->coding_type, vgmstream->channels, MPEG_FSB, &cfg); if (!vgmstream->codec_data) goto fail; - - /* both to setup initial interleave in vgmstream_open_stream */ - vgmstream->interleave_block_size = cfg.interleave; - vgmstream->layout_type = layout_mpeg_custom; + vgmstream->layout_type = layout_none; break; } #endif diff --git a/src/meta/hca_keys.h b/src/meta/hca_keys.h index 21c9ef92..31af3f24 100644 --- a/src/meta/hca_keys.h +++ b/src/meta/hca_keys.h @@ -144,6 +144,9 @@ static const hcakey_info hcakey_list[] = { // Pro Evolution Soccer 2018 / Winning Eleven 2018 (Android) {14121473}, // 0000000000D77A01 + // Kirara Fantasia (Android/iOS) + {51408295487268137}, // 00B6A3928706E529 + }; diff --git a/src/meta/nsw_opus.c b/src/meta/nsw_opus.c index a0e8ca07..a95a18f1 100644 --- a/src/meta/nsw_opus.c +++ b/src/meta/nsw_opus.c @@ -11,7 +11,7 @@ VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE *streamFile) { off_t offset = 0; /* check extension, case insensitive */ - if ( !check_extensions(streamFile,"opus")) /* no relation to Ogg Opus */ + if ( !check_extensions(streamFile,"opus,lopus")) /* no relation to Ogg Opus */ goto fail; /* variations, maybe custom */ diff --git a/src/meta/p3d.c b/src/meta/p3d.c index 5556fc18..752e6014 100644 --- a/src/meta/p3d.c +++ b/src/meta/p3d.c @@ -145,18 +145,15 @@ VGMSTREAM * init_vgmstream_p3d(STREAMFILE *streamFile) { #ifdef VGM_USE_MPEG case 0x6D703300: { /* "mp3\0" (PS3) */ - mpeg_custom_config cfg; + mpeg_custom_config cfg = {0}; - memset(&cfg, 0, sizeof(mpeg_custom_config)); cfg.interleave = 0x400; + cfg.data_size = data_size; /* block_size * 3 = frame size (0x60*3=0x120 or 0x40*3=0xC0) but doesn't seem to have any significance) */ vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_P3D, &cfg); if (!vgmstream->codec_data) goto fail; - - /* both to setup initial interleave in vgmstream_open_stream */ - vgmstream->interleave_block_size = cfg.interleave; - vgmstream->layout_type = layout_mpeg_custom; + vgmstream->layout_type = layout_none; break; } #endif diff --git a/src/meta/sqex_scd.c b/src/meta/sqex_scd.c index 24828187..faffc0a0 100644 --- a/src/meta/sqex_scd.c +++ b/src/meta/sqex_scd.c @@ -12,9 +12,9 @@ static void scd_ogg_decrypt_v3_callback(void *ptr, size_t size, size_t nmemb, vo VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; - off_t start_offset, tables_offset, headers_offset, meta_offset, post_meta_offset, stream_size; + off_t start_offset, tables_offset, headers_offset, meta_offset, post_meta_offset; int headers_entries; - int32_t loop_start, loop_end; + int32_t stream_size, loop_start, loop_end; int target_stream = streamFile->stream_index; int loop_flag = 0, channel_count, codec_id, sample_rate; @@ -80,7 +80,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { meta_offset = read_32bit(headers_offset + (target_stream-1)*4,streamFile); /** stream header **/ - stream_size = read_32bit(meta_offset+0x00, streamFile); + stream_size = read_32bit(meta_offset+0x00,streamFile); channel_count = read_32bit(meta_offset+0x04,streamFile); sample_rate = read_32bit(meta_offset+0x08,streamFile); codec_id = read_32bit(meta_offset+0x0c,streamFile); @@ -200,33 +200,33 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { } break; - case 0x06: /* OGG [Final Fantasy XIII-2 (PS3), Final Fantasy XIV (PC)] */ + case 0x06: /* OGG [Final Fantasy XIII-2 (PC), Final Fantasy XIV (PC)] */ goto fail; /* handled above */ #ifdef VGM_USE_MPEG case 0x07: { /* MPEG [Final Fantasy XIII (PS3)] */ mpeg_codec_data *mpeg_data = NULL; + mpeg_custom_config cfg = {0}; - /* Drakengard 3, some Kingdom Hearts */ - if (vgmstream->sample_rate == 47999) - vgmstream->sample_rate = 48000; - if (vgmstream->sample_rate == 44099) - vgmstream->sample_rate = 44100; + cfg.interleave = 0x800; /* for multistream [Final Fantasy XIII-2 (PS3)], otherwise ignored */ + cfg.data_size = stream_size; - mpeg_data = init_mpeg_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels); + mpeg_data = init_mpeg_custom_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_SCD, &cfg); if (!mpeg_data) goto fail; vgmstream->codec_data = mpeg_data; vgmstream->layout_type = layout_none; + /* some Drakengard 3, Kingdom Hearts HD have adjusted sample rate (47999, 44099), for looping? */ + vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, mpeg_data); + vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data); + vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data); + + //todo find if this actually helps vgmstream->num_samples -= vgmstream->num_samples%576; - if (loop_flag) { - vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data); - vgmstream->loop_start_sample -= vgmstream->loop_start_sample%576; - vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data); - vgmstream->loop_end_sample -= vgmstream->loop_end_sample%576; - } - vgmstream->interleave_block_size = 0; + vgmstream->loop_start_sample -= vgmstream->loop_start_sample%576; + vgmstream->loop_end_sample -= vgmstream->loop_end_sample%576; + break; } #endif diff --git a/src/meta/xvag.c b/src/meta/xvag.c index 987db2f1..c187aebf 100644 --- a/src/meta/xvag.c +++ b/src/meta/xvag.c @@ -82,25 +82,19 @@ VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) { #ifdef VGM_USE_MPEG case 0x08: { /* MPEG: The Last of Us, Uncharted 3, Medieval Moves */ - mpeg_custom_config cfg; - int fixed_frame_size; - - memset(&cfg, 0, sizeof(mpeg_custom_config)); + mpeg_custom_config cfg = {0}; /* "mpin": mpeg info */ /* 0x00/04: mpeg version/layer? other: unknown or repeats of "fmat" */ - if (!find_chunk(streamFile, 0x6D70696E,first_offset,0, &chunk_offset,NULL, !little_endian, 1)) goto fail; /*"mpin"*/ - fixed_frame_size = read_32bit(chunk_offset+0x1c,streamFile); + if (!find_chunk(streamFile, 0x6D70696E,first_offset,0, &chunk_offset,NULL, !little_endian, 1)) + goto fail; /*"mpin"*/ - cfg.chunk_size = fixed_frame_size; - cfg.interleave = fixed_frame_size * multiplier; + cfg.chunk_size = read_32bit(chunk_offset+0x1c,streamFile); /* fixed frame size */ + cfg.interleave = cfg.chunk_size * multiplier; vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_XVAG, &cfg); if (!vgmstream->codec_data) goto fail; - - /* both to setup initial interleave in vgmstream_open_stream */ - vgmstream->interleave_block_size = cfg.interleave; - vgmstream->layout_type = layout_mpeg_custom; + vgmstream->layout_type = layout_none; break; } #endif diff --git a/src/vgmstream.c b/src/vgmstream.c index b5bb594e..c3001d21 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -922,9 +922,6 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre break; #ifdef VGM_USE_VORBIS case layout_ogg_vorbis: -#endif -#ifdef VGM_USE_MPEG - case layout_mpeg_custom: #endif case layout_none: render_vgmstream_nolayout(buffer,sample_count,vgmstream); diff --git a/src/vgmstream.h b/src/vgmstream.h index fdd0318f..4d7d2a6c 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -254,9 +254,6 @@ typedef enum { #ifdef VGM_USE_VORBIS layout_ogg_vorbis, /* ogg vorbis file */ #endif -#ifdef VGM_USE_MPEG - layout_mpeg_custom, /* usually straight data but may setup offset/interleave somehow */ -#endif } layout_t; /* The meta type specifies how we know what we know about the file. @@ -880,6 +877,7 @@ typedef enum { MPEG_XVAG, /* N streams of fixed interleave (frame-aligned, several data-frames of fixed size) */ MPEG_FSB, /* N streams of 1 data-frame+padding (=interleave) */ MPEG_P3D, /* N streams of fixed interleave (not frame-aligned) */ + MPEG_SCD, /* N streams of fixed interleave (not frame-aligned) */ MPEG_EA, /* 1 stream (maybe N streams in absolute offsets?) */ MPEG_EAL31, /* EALayer3 v1 (SCHl), custom frames with v1 header */ MPEG_EAL31b, /* EALayer3 v1 (SNS), custom frames with v1 header + minor changes */ @@ -894,6 +892,7 @@ typedef struct { int channels; /* max channels */ int fsb_padding; /* fsb padding mode */ int chunk_size; /* size of a data portion */ + int data_size; /* playable size */ int interleave; /* size of stream interleave */ int encryption; /* encryption mode */ int big_endian; @@ -939,6 +938,9 @@ typedef struct { /* for internal use, assumed to be constant for all frames */ int channels_per_frame; int samples_per_frame; + /* for some calcs */ + int bitrate_per_frame; + int sample_rate_per_frame; /* custom MPEG internals */ int custom; /* flag */