mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-17 23:36:41 +01:00
Clean AIX meta a bit
This commit is contained in:
parent
a273d9d9a2
commit
496d2ba534
262
src/meta/aix.c
262
src/meta/aix.c
@ -1,166 +1,150 @@
|
|||||||
#include "meta.h"
|
#include "meta.h"
|
||||||
#include "aix_streamfile.h"
|
#include "aix_streamfile.h"
|
||||||
|
|
||||||
/* AIX - interleaved AAX, N segments per channels [SoulCalibur IV (PS3)] */
|
/* AIX - interleaved AAX, N segments with M layers (1/2ch) inside [SoulCalibur IV (PS3), Dragon Ball Z: Burst Limit (PS3)] */
|
||||||
VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) {
|
VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM * vgmstream = NULL;
|
||||||
VGMSTREAM * vgmstream = NULL;
|
|
||||||
STREAMFILE * streamFileAIX = NULL;
|
STREAMFILE * streamFileAIX = NULL;
|
||||||
STREAMFILE * streamFileADX = NULL;
|
int loop_flag = 0, channel_count, sample_rate;
|
||||||
char filename[PATH_LIMIT];
|
int32_t sample_count, loop_start_sample = 0, loop_end_sample = 0;
|
||||||
|
|
||||||
off_t *segment_offset = NULL;
|
off_t *segment_offset = NULL;
|
||||||
int32_t *samples_in_segment = NULL;
|
int32_t *segment_samples = NULL;
|
||||||
int32_t sample_count;
|
|
||||||
|
|
||||||
int loop_flag = 0;
|
|
||||||
int32_t loop_start_sample=0;
|
|
||||||
int32_t loop_end_sample=0;
|
|
||||||
|
|
||||||
aix_codec_data *data = NULL;
|
aix_codec_data *data = NULL;
|
||||||
|
off_t data_offset;
|
||||||
off_t first_AIXP;
|
off_t layer_list_offset;
|
||||||
off_t stream_list_offset;
|
off_t layer_list_end;
|
||||||
off_t stream_list_end;
|
|
||||||
const int segment_list_entry_size = 0x10;
|
|
||||||
const off_t segment_list_offset = 0x20;
|
const off_t segment_list_offset = 0x20;
|
||||||
|
const size_t segment_list_entry_size = 0x10;
|
||||||
|
const size_t layer_list_entry_size = 0x08;
|
||||||
|
|
||||||
int stream_count,channel_count,segment_count;
|
int segment_count, layer_count;
|
||||||
int sample_rate;
|
int i, j;
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* check extension, case insensitive */
|
/* checks */
|
||||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
if (!check_extensions(streamFile, "aix"))
|
||||||
if (strcasecmp("aix",filename_extension(filename))) goto fail;
|
goto fail;
|
||||||
|
if (read_32bitBE(0x00,streamFile) != 0x41495846 || /* "AIXF" */
|
||||||
if (read_32bitBE(0x0,streamFile) != 0x41495846 || /* "AIXF" */
|
read_32bitBE(0x08,streamFile) != 0x01000014 || /* version? */
|
||||||
read_32bitBE(0x08,streamFile) != 0x01000014 ||
|
read_32bitBE(0x0c,streamFile) != 0x00000800)
|
||||||
read_32bitBE(0x0c,streamFile) != 0x00000800)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
first_AIXP = read_32bitBE(0x4,streamFile)+8;
|
/* base segment header */
|
||||||
|
data_offset = read_32bitBE(0x04,streamFile)+0x08;
|
||||||
|
|
||||||
segment_count = (uint16_t)read_16bitBE(0x18,streamFile);
|
segment_count = (uint16_t)read_16bitBE(0x18,streamFile);
|
||||||
stream_list_offset = segment_list_offset+segment_list_entry_size*segment_count+0x10;
|
if (segment_count < 1) goto fail;
|
||||||
|
|
||||||
if (stream_list_offset >= first_AIXP)
|
layer_list_offset = segment_list_offset + segment_count*segment_list_entry_size + 0x10;
|
||||||
goto fail;
|
if (layer_list_offset >= data_offset) goto fail;
|
||||||
if (segment_count < 1)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
sample_rate = read_32bitBE(stream_list_offset+8,streamFile);
|
segment_samples = calloc(segment_count,sizeof(int32_t));
|
||||||
if (sample_rate < 300 || sample_rate > 96000)
|
if (!segment_samples) goto fail;
|
||||||
goto fail;
|
|
||||||
|
|
||||||
samples_in_segment = calloc(segment_count,sizeof(int32_t));
|
|
||||||
if (!samples_in_segment)
|
|
||||||
goto fail;
|
|
||||||
segment_offset = calloc(segment_count,sizeof(off_t));
|
segment_offset = calloc(segment_count,sizeof(off_t));
|
||||||
if (!segment_offset)
|
if (!segment_offset) goto fail;
|
||||||
goto fail;
|
|
||||||
|
|
||||||
for (i = 0; i < segment_count; i++)
|
/* parse segments table */
|
||||||
{
|
{
|
||||||
segment_offset[i] = read_32bitBE(segment_list_offset+segment_list_entry_size*i+0,streamFile);
|
sample_rate = read_32bitBE(layer_list_offset+0x08,streamFile); /* first layer's sample rate */
|
||||||
samples_in_segment[i] = read_32bitBE(segment_list_offset+segment_list_entry_size*i+0x08,streamFile);
|
|
||||||
/*printf("samples_in_segment[%d]=%d\n",i,samples_in_segment[i]);*/
|
for (i = 0; i < segment_count; i++) {
|
||||||
/* all segments must have equal sample rate */
|
segment_offset[i] = read_32bitBE(segment_list_offset + segment_list_entry_size*i + 0x00,streamFile);
|
||||||
if (read_32bitBE(segment_list_offset+segment_list_entry_size*i+0x0c,streamFile) != sample_rate)
|
/* 0x04: segment size */
|
||||||
{
|
segment_samples[i] = read_32bitBE(segment_list_offset + segment_list_entry_size*i + 0x08,streamFile);
|
||||||
/* segments > 0 can have 0 sample rate (Ryu ga gotoku: Kenzan! tenkei_sng1.aix),
|
|
||||||
seems to indicate same sample rate as first */
|
/* all segments must have equal sample rate */
|
||||||
if (!(i > 0 && read_32bitBE(segment_list_offset+segment_list_entry_size*i+0x0c,streamFile) == 0))
|
if (read_32bitBE(segment_list_offset + segment_list_entry_size*i + 0x0c,streamFile) != sample_rate) {
|
||||||
goto fail;
|
/* segments > 0 can have 0 sample rate (Ryu ga gotoku: Kenzan! tenkei_sng1.aix),
|
||||||
|
seems to indicate same sample rate as first */
|
||||||
|
if (!(i > 0 && read_32bitBE(segment_list_offset + segment_list_entry_size*i + 0x0c,streamFile) == 0))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (segment_offset[0] != data_offset)
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (segment_offset[0] != first_AIXP)
|
/* base layer header */
|
||||||
goto fail;
|
layer_count = (uint8_t)read_8bit(layer_list_offset,streamFile);
|
||||||
|
if (layer_count < 1) goto fail;
|
||||||
|
|
||||||
stream_count = (uint8_t)read_8bit(stream_list_offset,streamFile);
|
layer_list_end = layer_list_offset + 0x08 + layer_count*layer_list_entry_size;
|
||||||
if (stream_count < 1)
|
if (layer_list_end >= data_offset) goto fail;
|
||||||
goto fail;
|
|
||||||
stream_list_end = stream_list_offset + 0x8 + stream_count * 8;
|
|
||||||
|
|
||||||
if (stream_list_end >= first_AIXP)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
|
/* parse layers table */
|
||||||
channel_count = 0;
|
channel_count = 0;
|
||||||
for (i = 0; i < stream_count; i++)
|
for (i = 0; i < layer_count; i++) {
|
||||||
{
|
|
||||||
/* all streams must have same samplerate as segments */
|
/* all streams must have same samplerate as segments */
|
||||||
if (read_32bitBE(stream_list_offset+8+i*8,streamFile)!=sample_rate)
|
if (read_32bitBE(layer_list_offset + 0x08 + i*layer_list_entry_size + 0x00,streamFile) != sample_rate)
|
||||||
goto fail;
|
goto fail;
|
||||||
channel_count += read_8bit(stream_list_offset+8+i*8+4,streamFile);
|
channel_count += read_8bit(layer_list_offset + 0x08 + i*layer_list_entry_size + 0x04,streamFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for existence of segments */
|
/* check for existence of segments */
|
||||||
for (i = 0; i < segment_count; i++)
|
for (i = 0; i < segment_count; i++) {
|
||||||
{
|
off_t aixp_offset = segment_offset[i];
|
||||||
int j;
|
for (j = 0; j < layer_count; j++) {
|
||||||
off_t AIXP_offset = segment_offset[i];
|
if (read_32bitBE(aixp_offset,streamFile) != 0x41495850) /* "AIXP" */
|
||||||
for (j = 0; j < stream_count; j++)
|
|
||||||
{
|
|
||||||
if (read_32bitBE(AIXP_offset,streamFile)!=0x41495850) /* "AIXP" */
|
|
||||||
goto fail;
|
goto fail;
|
||||||
if (read_8bit(AIXP_offset+8,streamFile)!=j)
|
if (read_8bit(aixp_offset+0x08,streamFile) != j)
|
||||||
goto fail;
|
goto fail;
|
||||||
AIXP_offset += read_32bitBE(AIXP_offset+4,streamFile)+8;
|
aixp_offset += read_32bitBE(aixp_offset+0x04,streamFile) + 0x08;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
streamFileAIX = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
/* open base streamfile, that will be shared by all open_aix_with_STREAMFILE */
|
||||||
if (!streamFileAIX) goto fail;
|
|
||||||
|
|
||||||
data = malloc(sizeof(aix_codec_data));
|
|
||||||
if (!data) goto fail;
|
|
||||||
data->segment_count = segment_count;
|
|
||||||
data->stream_count = stream_count;
|
|
||||||
data->adxs = malloc(sizeof(STREAMFILE *)*segment_count*stream_count);
|
|
||||||
if (!data->adxs) goto fail;
|
|
||||||
for (i=0;i<segment_count*stream_count;i++) {
|
|
||||||
data->adxs[i] = NULL;
|
|
||||||
}
|
|
||||||
data->sample_counts = calloc(segment_count,sizeof(int32_t));
|
|
||||||
if (!data->sample_counts) goto fail;
|
|
||||||
memcpy(data->sample_counts,samples_in_segment,segment_count*sizeof(int32_t));
|
|
||||||
|
|
||||||
/* for each segment */
|
|
||||||
for (i = 0; i < segment_count; i++)
|
|
||||||
{
|
{
|
||||||
int j;
|
char filename[PATH_LIMIT];
|
||||||
/* for each stream */
|
|
||||||
for (j = 0; j < stream_count; j++)
|
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||||
{
|
streamFileAIX = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); //todo simplify
|
||||||
VGMSTREAM *adx;
|
if (!streamFileAIX) goto fail;
|
||||||
/*printf("try opening segment %d/%d stream %d/%d %x\n",i,segment_count,j,stream_count,segment_offset[i]);*/
|
}
|
||||||
streamFileADX = open_aix_with_STREAMFILE(streamFileAIX,segment_offset[i],j);
|
|
||||||
if (!streamFileADX) goto fail;
|
/* init layout */
|
||||||
adx = data->adxs[i*stream_count+j] = init_vgmstream_adx(streamFileADX);
|
{
|
||||||
if (!adx)
|
data = malloc(sizeof(aix_codec_data));
|
||||||
|
if (!data) goto fail;
|
||||||
|
|
||||||
|
data->segment_count = segment_count;
|
||||||
|
data->stream_count = layer_count;
|
||||||
|
data->adxs = calloc(segment_count * layer_count, sizeof(VGMSTREAM*));
|
||||||
|
if (!data->adxs) goto fail;
|
||||||
|
|
||||||
|
data->sample_counts = calloc(segment_count,sizeof(int32_t));
|
||||||
|
if (!data->sample_counts) goto fail;
|
||||||
|
|
||||||
|
memcpy(data->sample_counts,segment_samples,segment_count*sizeof(int32_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* open each segment / layer subfile */
|
||||||
|
for (i = 0; i < segment_count; i++) {
|
||||||
|
for (j = 0; j < layer_count; j++) {
|
||||||
|
//;VGM_LOG("AIX: opening segment %d/%d stream %d/%d %x\n",i,segment_count,j,stream_count,segment_offset[i]);
|
||||||
|
VGMSTREAM *temp_vgmstream;
|
||||||
|
STREAMFILE * temp_streamFile = open_aix_with_STREAMFILE(streamFileAIX,segment_offset[i],j);
|
||||||
|
if (!temp_streamFile) goto fail;
|
||||||
|
|
||||||
|
temp_vgmstream = data->adxs[i*layer_count+j] = init_vgmstream_adx(temp_streamFile);
|
||||||
|
|
||||||
|
close_streamfile(temp_streamFile);
|
||||||
|
|
||||||
|
if (!temp_vgmstream) goto fail;
|
||||||
|
|
||||||
|
/* setup layers */
|
||||||
|
if (temp_vgmstream->num_samples != data->sample_counts[i] || temp_vgmstream->loop_flag != 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
close_streamfile(streamFileADX); streamFileADX = NULL;
|
memcpy(temp_vgmstream->start_ch,temp_vgmstream->ch,sizeof(VGMSTREAMCHANNEL)*temp_vgmstream->channels);
|
||||||
|
memcpy(temp_vgmstream->start_vgmstream,temp_vgmstream,sizeof(VGMSTREAM));
|
||||||
if (adx->num_samples != data->sample_counts[i] ||
|
|
||||||
adx->loop_flag != 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* save start things so we can restart for seeking/looping */
|
|
||||||
/* copy the channels */
|
|
||||||
memcpy(adx->start_ch,adx->ch,sizeof(VGMSTREAMCHANNEL)*adx->channels);
|
|
||||||
/* copy the whole VGMSTREAM */
|
|
||||||
memcpy(adx->start_vgmstream,adx,sizeof(VGMSTREAM));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (segment_count > 1)
|
/* get looping and samples */
|
||||||
{
|
|
||||||
loop_flag = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sample_count = 0;
|
sample_count = 0;
|
||||||
for (i = 0; i < segment_count; i++)
|
loop_flag = (segment_count > 1);
|
||||||
{
|
for (i = 0; i < segment_count; i++) {
|
||||||
sample_count += data->sample_counts[i];
|
sample_count += data->sample_counts[i];
|
||||||
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
@ -169,45 +153,45 @@ VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) {
|
|||||||
loop_end_sample = sample_count;
|
loop_end_sample = sample_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
vgmstream->num_samples = sample_count;
|
|
||||||
vgmstream->sample_rate = sample_rate;
|
vgmstream->sample_rate = sample_rate;
|
||||||
|
vgmstream->num_samples = sample_count;
|
||||||
vgmstream->loop_start_sample = loop_start_sample;
|
vgmstream->loop_start_sample = loop_start_sample;
|
||||||
vgmstream->loop_end_sample = loop_end_sample;
|
vgmstream->loop_end_sample = loop_end_sample;
|
||||||
|
|
||||||
|
vgmstream->meta_type = meta_AIX;
|
||||||
vgmstream->coding_type = data->adxs[0]->coding_type;
|
vgmstream->coding_type = data->adxs[0]->coding_type;
|
||||||
vgmstream->layout_type = layout_aix;
|
vgmstream->layout_type = layout_aix;
|
||||||
vgmstream->meta_type = meta_AIX;
|
|
||||||
|
|
||||||
vgmstream->ch[0].streamfile = streamFileAIX;
|
vgmstream->ch[0].streamfile = streamFileAIX;
|
||||||
data->current_segment = 0;
|
data->current_segment = 0;
|
||||||
|
|
||||||
vgmstream->codec_data = data;
|
vgmstream->codec_data = data;
|
||||||
free(segment_offset);
|
free(segment_offset);
|
||||||
free(samples_in_segment);
|
free(segment_samples);
|
||||||
|
|
||||||
return vgmstream;
|
return vgmstream;
|
||||||
|
|
||||||
/* clean up anything we may have opened */
|
|
||||||
fail:
|
fail:
|
||||||
if (streamFileAIX) close_streamfile(streamFileAIX);
|
close_streamfile(streamFileAIX);
|
||||||
if (streamFileADX) close_streamfile(streamFileADX);
|
close_vgmstream(vgmstream);
|
||||||
if (vgmstream) close_vgmstream(vgmstream);
|
free(segment_samples);
|
||||||
if (samples_in_segment) free(samples_in_segment);
|
free(segment_offset);
|
||||||
if (segment_offset) free(segment_offset);
|
|
||||||
|
/* free aix layout */
|
||||||
if (data) {
|
if (data) {
|
||||||
if (data->adxs)
|
if (data->adxs) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
for (i=0;i<data->segment_count*data->stream_count;i++)
|
for (i = 0; i < data->segment_count*data->stream_count; i++) {
|
||||||
if (data->adxs)
|
close_vgmstream(data->adxs[i]);
|
||||||
close_vgmstream(data->adxs[i]);
|
}
|
||||||
free(data->adxs);
|
free(data->adxs);
|
||||||
}
|
}
|
||||||
if (data->sample_counts)
|
if (data->sample_counts) {
|
||||||
{
|
|
||||||
free(data->sample_counts);
|
free(data->sample_counts);
|
||||||
}
|
}
|
||||||
free(data);
|
free(data);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user