mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-12-24 04:14:50 +01:00
79 lines
2.7 KiB
C
79 lines
2.7 KiB
C
#include "meta.h"
|
|
#include "../coding/coding.h"
|
|
|
|
typedef struct {
|
|
int loop_flag;
|
|
int32_t loop_start;
|
|
int32_t loop_end;
|
|
uint32_t file_size;
|
|
#ifdef VGM_USE_FFMPEG
|
|
mp4_custom_t mp4;
|
|
#endif
|
|
int type;
|
|
} ktac_header_t;
|
|
|
|
|
|
/* KTAC - Koei Tecmo custom AAC [Kin'iro no Corda 3 (Vita), Shingeki no Kyojin: Shichi kara no Dasshutsu (3DS), Dynasty Warriors (PS4)] */
|
|
VGMSTREAM* init_vgmstream_ktac(STREAMFILE* sf) {
|
|
#ifdef VGM_USE_FFMPEG
|
|
VGMSTREAM* vgmstream = NULL;
|
|
ktac_header_t ktac = {0};
|
|
|
|
/* checks */
|
|
/* .ktac: header id */
|
|
if (!check_extensions(sf,"ktac"))
|
|
goto fail;
|
|
if (!is_id32be(0x00,sf, "KTAC"))
|
|
goto fail;
|
|
|
|
/* 0x04: version? (always 1) */
|
|
ktac.file_size = read_u32le(0x08,sf);
|
|
if (ktac.file_size != get_streamfile_size(sf))
|
|
goto fail;
|
|
ktac.mp4.stream_offset = read_u32le(0x0c,sf);
|
|
ktac.mp4.stream_size = read_u32le(0x10,sf);
|
|
ktac.type = read_u32le(0x14,sf);
|
|
ktac.mp4.sample_rate = read_u32le(0x18,sf);
|
|
ktac.mp4.num_samples = read_u32le(0x1c,sf); /* full samples */
|
|
ktac.mp4.channels = read_u16le(0x20,sf);
|
|
ktac.mp4.frame_samples = read_u16le(0x22,sf);
|
|
ktac.mp4.encoder_delay = read_u16le(0x24,sf);
|
|
ktac.mp4.end_padding = read_u16le(0x26,sf);
|
|
ktac.loop_start = read_u32le(0x28,sf);
|
|
ktac.loop_end = read_u32le(0x2c,sf);
|
|
/* 0x30: ? (big, related to loops) */
|
|
/* 0x34: ? (always null) */
|
|
ktac.mp4.table_offset = read_u32le(0x38,sf);
|
|
ktac.mp4.table_entries = read_u32le(0x3c,sf);
|
|
|
|
ktac.loop_flag = (ktac.loop_end > 0);
|
|
|
|
/* type 1 files crash during sample_copy, wrong fake header/esds?
|
|
* (0=AoT, KnC3 bgm, 1=KnC3 1ch voices, 2=DW4, Atelier Ryza) */
|
|
if (ktac.type == 1)
|
|
goto fail;
|
|
|
|
/* build the VGMSTREAM */
|
|
vgmstream = allocate_vgmstream(ktac.mp4.channels, ktac.loop_flag);
|
|
if (!vgmstream) goto fail;
|
|
|
|
vgmstream->meta_type = meta_KTAC;
|
|
vgmstream->sample_rate = ktac.mp4.sample_rate;
|
|
vgmstream->num_samples = ktac.mp4.num_samples - ktac.mp4.encoder_delay - ktac.mp4.end_padding;
|
|
vgmstream->loop_start_sample = ktac.loop_start * ktac.mp4.frame_samples - ktac.mp4.encoder_delay;
|
|
vgmstream->loop_end_sample = ktac.loop_end * ktac.mp4.frame_samples - ktac.mp4.encoder_delay;
|
|
|
|
/* KTAC uses AAC, but not type found in .aac (that has headered frames, like mp3) but raw
|
|
* packets + frame size table (similar to .mp4/m4a). We set config for FFmpeg's fake M4A header */
|
|
vgmstream->codec_data = init_ffmpeg_mp4_custom_std(sf, &ktac.mp4);
|
|
if (!vgmstream->codec_data) goto fail;
|
|
vgmstream->coding_type = coding_FFmpeg;
|
|
vgmstream->layout_type = layout_none;
|
|
|
|
return vgmstream;
|
|
fail:
|
|
close_vgmstream(vgmstream);
|
|
#endif
|
|
return NULL;
|
|
}
|