mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-17 23:36:41 +01:00
Add AAC codec for TXTH and bytes-to-samples
This commit is contained in:
parent
c114dc3ba1
commit
2b4570395a
10
doc/TXTH.md
10
doc/TXTH.md
@ -101,26 +101,31 @@ A text file with the above commands must be saved as ".vag.txth" or ".txth", not
|
||||
# - MSADPCM Microsoft ADPCM (mono/stereo)
|
||||
# * For some PC games
|
||||
# * Interleave (frame size) varies, often multiple of 0x100 [required]
|
||||
# - SDX2 Squareroot-delta-exact 8-bit DPCM (3DO games)
|
||||
# - SDX2 Squareroot-delta-exact 8-bit DPCM
|
||||
# * For many 3DO games
|
||||
# - MPEG MPEG Audio Layer file (MP1/2/3)
|
||||
# * For some games (usually PC/PS3)
|
||||
# * May set skip_samples
|
||||
# - ATRAC3 Sony ATRAC3
|
||||
# * For some PS2 and PS3 games
|
||||
# * Interleave (frame size) can be 0x60/0x98/0xC0 * channels [required]
|
||||
# * Should set skip_samples (more than 1024 but varies)
|
||||
# - ATRAC3PLUS Sony ATRAC3plus
|
||||
# * For many PSP games and rare PS3 games
|
||||
# * Interleave (frame size) can be: [required]
|
||||
# Mono: 0x0118|0178|0230|02E8
|
||||
# Stereo: 0x0118|0178|0230|02E8|03A8|0460|05D0|0748|0800
|
||||
# * Should set skip_samples (more than 2048 but varies)
|
||||
# - XMA1 Microsoft XMA1
|
||||
# * For early X360 games
|
||||
# - XMA2 Microsoft XMA2
|
||||
# * For later X360 games
|
||||
# - FFMPEG Any headered FFmpeg format
|
||||
# * For uncommon games
|
||||
# * May set skip_samples
|
||||
# - AC3 AC3/SPDIF
|
||||
# * For few PS2 games
|
||||
# * Should set skip_samples (around 256 but varies)
|
||||
# - PCFX PC-FX ADPCM
|
||||
# * For many PC-FX games
|
||||
# * Interleave is multiple of 0x1, often +0x8000
|
||||
@ -131,6 +136,9 @@ A text file with the above commands must be saved as ".vag.txth" or ".txth", not
|
||||
# * Variation with modified encoding
|
||||
# - OKI16 OKI ADPCM with 16-bit output (not VOX/Dialogic 12-bit)
|
||||
# * For few PS2 games (Sweet Legacy, Hooligan)
|
||||
# - AAC Advanced Audio Coding (raw without .mp4)
|
||||
# * For some 3DS games and many iOS games
|
||||
# * Should set skip_samples (around 1024 but varies)
|
||||
codec = (codec string)
|
||||
|
||||
# Codec variations [OPTIONAL, depends on codec]
|
||||
|
@ -353,6 +353,7 @@ int riff_get_fact_skip_samples(STREAMFILE * streamFile, off_t start_offset);
|
||||
|
||||
size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align);
|
||||
size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align);
|
||||
size_t aac_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes);
|
||||
|
||||
|
||||
|
||||
|
@ -1017,6 +1017,38 @@ size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align) {
|
||||
return (bytes / full_block_align) * 2048;
|
||||
}
|
||||
|
||||
size_t aac_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes) {
|
||||
const int samples_per_frame = 1024; /* theoretically 960 exists in .MP4 so may need a flag */
|
||||
int frames = 0;
|
||||
off_t offset = start_offset;
|
||||
off_t max_offset = start_offset + bytes;
|
||||
if (max_offset > get_streamfile_size(streamFile))
|
||||
max_offset = get_streamfile_size(streamFile);
|
||||
|
||||
/* AAC sometimes comes with an "ADIF" header right before data but probably not in games,
|
||||
* while standard raw frame headers are called "ADTS" and are similar to MPEG's:
|
||||
* (see https://wiki.multimedia.cx/index.php/ADTS) */
|
||||
|
||||
/* AAC uses VBR so must read all frames */
|
||||
while (offset < max_offset) {
|
||||
uint16_t frame_sync = read_u16be(offset+0x00, streamFile);
|
||||
uint32_t frame_size = read_u32be(offset+0x02, streamFile);
|
||||
|
||||
frame_sync = (frame_sync >> 4) & 0x0FFF; /* 12b */
|
||||
frame_size = (frame_size >> 5) & 0x1FFF; /* 13b */
|
||||
|
||||
if (frame_sync != 0xFFF)
|
||||
break;
|
||||
if (frame_size <= 0x08)
|
||||
break;
|
||||
|
||||
frames++;
|
||||
offset += frame_size;
|
||||
}
|
||||
|
||||
return frames * samples_per_frame;
|
||||
}
|
||||
|
||||
|
||||
/* ******************************************** */
|
||||
/* BITSTREAM */
|
||||
|
@ -33,7 +33,8 @@ typedef enum {
|
||||
PCFX = 24, /* PC-FX ADPCM */
|
||||
PCM4 = 25, /* 4-bit signed PCM (3rd and 4th gen games) */
|
||||
PCM4_U = 26, /* 4-bit unsigned PCM (3rd and 4th gen games) */
|
||||
OKI16 = 27, /* OKI ADPCM with 16-bit output (unlike OKI/VOX/Dialogic ADPCM's 12-bit) */
|
||||
OKI16 = 27, /* OKI ADPCM with 16-bit output (unlike OKI/VOX/Dialogic ADPCM's 12-bit) */
|
||||
AAC = 28, /* Advanced Audio Coding (raw without .mp4) */
|
||||
} genh_type;
|
||||
|
||||
typedef struct {
|
||||
@ -115,6 +116,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
||||
case XMA1:
|
||||
case XMA2:
|
||||
case AC3:
|
||||
case AAC:
|
||||
case FFMPEG: coding = coding_FFmpeg; break;
|
||||
#endif
|
||||
case PCFX: coding = coding_PCFX; break;
|
||||
@ -293,7 +295,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
|
||||
case coding_FFmpeg: {
|
||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
||||
|
||||
if (genh.codec == FFMPEG || genh.codec == AC3) {
|
||||
if (genh.codec == FFMPEG || genh.codec == AC3 || genh.codec == AAC) {
|
||||
/* default FFmpeg */
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, genh.start_offset,genh.data_size);
|
||||
if ( !ffmpeg_data ) goto fail;
|
||||
|
@ -34,6 +34,7 @@ typedef enum {
|
||||
PCM4 = 25, /* 4-bit signed PCM (3rd and 4th gen games) */
|
||||
PCM4_U = 26, /* 4-bit unsigned PCM (3rd and 4th gen games) */
|
||||
OKI16 = 27, /* OKI ADPCM with 16-bit output (unlike OKI/VOX/Dialogic ADPCM's 12-bit) */
|
||||
AAC = 28, /* Advanced Audio Coding (raw without .mp4) */
|
||||
} txth_type;
|
||||
|
||||
typedef struct {
|
||||
@ -177,6 +178,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
|
||||
case XMA1:
|
||||
case XMA2:
|
||||
case AC3:
|
||||
case AAC:
|
||||
case FFMPEG: coding = coding_FFmpeg; break;
|
||||
#endif
|
||||
case PCFX: coding = coding_PCFX; break;
|
||||
@ -375,7 +377,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
|
||||
case coding_FFmpeg: {
|
||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
||||
|
||||
if (txth.codec == FFMPEG || txth.codec == AC3) {
|
||||
if (txth.codec == FFMPEG || txth.codec == AC3 || txth.codec == AAC) {
|
||||
/* default FFmpeg */
|
||||
ffmpeg_data = init_ffmpeg_offset(txth.streamBody, txth.start_offset,txth.data_size);
|
||||
if ( !ffmpeg_data ) goto fail;
|
||||
@ -631,6 +633,7 @@ static int parse_keyval(STREAMFILE * streamFile_, txth_header * txth, const char
|
||||
else if (0==strcmp(val,"PCM4")) txth->codec = PCM4;
|
||||
else if (0==strcmp(val,"PCM4_U")) txth->codec = PCM4_U;
|
||||
else if (0==strcmp(val,"OKI16")) txth->codec = OKI16;
|
||||
else if (0==strcmp(val,"AAC")) txth->codec = AAC;
|
||||
else goto fail;
|
||||
|
||||
/* set common interleaves to simplify usage
|
||||
@ -998,6 +1001,9 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) {
|
||||
case ATRAC3PLUS:
|
||||
if (!txth->interleave) return 0;
|
||||
return atrac3plus_bytes_to_samples(bytes, txth->interleave);
|
||||
case AAC:
|
||||
if (!txth->streamBody) return 0;
|
||||
return aac_get_samples(txth->streamBody, txth->start_offset, bytes);
|
||||
|
||||
/* XMA bytes-to-samples is done at the end as the value meanings are a bit different */
|
||||
case XMA1:
|
||||
|
Loading…
x
Reference in New Issue
Block a user