diff --git a/src/layout/aax_layout.c b/src/layout/aax_layout.c index 9d14dc11..eedcd2e4 100644 --- a/src/layout/aax_layout.c +++ b/src/layout/aax_layout.c @@ -26,7 +26,8 @@ fail: void render_vgmstream_aax(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { int samples_written=0; - aax_codec_data *data = vgmstream->codec_data; + aax_codec_data *data = vgmstream->layout_data; + //int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); while (samples_written sample_count) samples_to_do=sample_count-samples_written; @@ -64,7 +63,6 @@ void render_vgmstream_aax(sample * buffer, int32_t sample_count, VGMSTREAM * vgm { int i; data->current_segment++; - /*printf("advance to %d at %d samples\n",data->current_segment,vgmstream->current_sample);*/ reset_vgmstream(data->segments[data->current_segment]); /* carry over the history from the previous segment */ diff --git a/src/meta/aax.c b/src/meta/aax.c index b61fa57e..28eb3b9c 100644 --- a/src/meta/aax.c +++ b/src/meta/aax.c @@ -1,17 +1,17 @@ #include "meta.h" #include "../layout/layout.h" #include "../coding/coding.h" -#include "aax_streamfile.h" #include "aax_utf.h" +static STREAMFILE* setup_aax_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext); + #define MAX_SEGMENTS 2 /* usually segment0=intro, segment1=loop/main */ /* AAX - segmented ADX [Bayonetta (PS3), Pandora's Tower (Wii), Catherine (X360), Binary Domain (PS3)] */ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - STREAMFILE * streamFileAAX = NULL; + int is_hca; int loop_flag = 0, channel_count = 0; int32_t sample_count, loop_start_sample = 0, loop_end_sample = 0; @@ -51,7 +51,12 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) { if (result.name_offset+0x04 > aax_string_table_size) goto fail; - if (read_32bitBE(aax_string_table_offset + result.name_offset, streamFile) != 0x41415800) /* "AAX\0" */ + + if (read_32bitBE(aax_string_table_offset + result.name_offset, streamFile) == 0x41415800) /* "AAX\0" */ + is_hca = 0; + else if (read_32bitBE(aax_string_table_offset + result.name_offset, streamFile) == 0x48434100) /* "HCA\0" */ + is_hca = 1; + else goto fail; /* get offsets of constituent segments */ @@ -70,17 +75,14 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) { data = init_layout_aax(segment_count); if (!data) goto fail; - /* get temp file */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - streamFileAAX = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!streamFileAAX) goto fail; - /* open each segment subfile */ for (i = 0; i < segment_count; i++) { - STREAMFILE* temp_streamFile = open_aax_with_STREAMFILE(streamFileAAX,segment_offset[i],segment_size[i]); + STREAMFILE* temp_streamFile = setup_aax_streamfile(streamFile, segment_offset[i],segment_size[i], (is_hca ? "hca" : "adx")); if (!temp_streamFile) goto fail; - data->segments[i] = init_vgmstream_adx(temp_streamFile); + data->segments[i] = is_hca ? + init_vgmstream_hca(temp_streamFile) : + init_vgmstream_adx(temp_streamFile); close_streamfile(temp_streamFile); @@ -138,18 +140,40 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) { vgmstream->coding_type = data->segments[0]->coding_type; vgmstream->layout_type = layout_aax; - vgmstream->codec_data = data; + vgmstream->layout_data = data; data->loop_segment = loop_segment; return vgmstream; fail: - close_streamfile(streamFileAAX); close_vgmstream(vgmstream); free_layout_aax(data); return NULL; } +static STREAMFILE* setup_aax_streamfile(STREAMFILE *streamFile, off_t subfile_offset, size_t subfile_size, const char* fake_ext) { + STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; + + /* setup subfile */ + new_streamFile = open_wrap_streamfile(streamFile); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + new_streamFile = open_clamp_streamfile(temp_streamFile, subfile_offset,subfile_size); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,fake_ext); + if (!new_streamFile) goto fail; + temp_streamFile = new_streamFile; + + return temp_streamFile; + +fail: + close_streamfile(temp_streamFile); + return NULL; +} + /* CRI's UTF wrapper around DSP [Sonic Colors sfx (Wii), NiGHTS: Journey of Dreams sfx (Wii)] */ VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) { diff --git a/src/vgmstream.c b/src/vgmstream.c index b8d262c4..6ba1b23c 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -570,10 +570,11 @@ void reset_vgmstream(VGMSTREAM * vgmstream) { if (vgmstream->coding_type==coding_ACM) { mus_acm_codec_data *data = vgmstream->codec_data; int i; - - data->current_file = 0; - for (i=0;ifile_count;i++) { - acm_reset(data->files[i]); + if (data) { + data->current_file = 0; + for (i=0;ifile_count;i++) { + acm_reset(data->files[i]); + } } } @@ -586,7 +587,8 @@ void reset_vgmstream(VGMSTREAM * vgmstream) { vgmstream->coding_type == coding_NWA5 ) { nwa_codec_data *data = vgmstream->codec_data; - reset_nwa(data->nwa); + if (data) + reset_nwa(data->nwa); } @@ -601,7 +603,7 @@ void reset_vgmstream(VGMSTREAM * vgmstream) { } if (vgmstream->layout_type==layout_aax) { - reset_layout_aax(vgmstream->codec_data); + reset_layout_aax(vgmstream->layout_data); } if (vgmstream->layout_type==layout_scd_int) { @@ -819,7 +821,7 @@ void close_vgmstream(VGMSTREAM * vgmstream) { } if (vgmstream->layout_type==layout_aax) { - free_layout_aax(vgmstream->codec_data); + free_layout_aax(vgmstream->layout_data); vgmstream->codec_data = NULL; } @@ -2047,7 +2049,8 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) { vgmstream->coding_type == coding_NWA5) { nwa_codec_data *data = vgmstream->codec_data; - seek_nwa(data->nwa, vgmstream->loop_sample); + if (data) + seek_nwa(data->nwa, vgmstream->loop_sample); } /* restore! */ @@ -2435,11 +2438,6 @@ static STREAMFILE * get_vgmstream_average_bitrate_channel_streamfile(VGMSTREAM * { //AAX, AIX, ACM? - if (vgmstream->layout_type==layout_aax) { - aax_codec_data *data = (aax_codec_data *) vgmstream->codec_data; - return data->segments[0]->ch[channel].streamfile; //todo not correct with multifile segments (ex. .ACM Ogg) - } - if (vgmstream->layout_type==layout_scd_int) { scd_int_codec_data *data = (scd_int_codec_data *) vgmstream->codec_data; return data->intfiles[channel]; @@ -2485,10 +2483,10 @@ int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream) { int bitrate = 0; int sample_rate = vgmstream->sample_rate; int length_samples = vgmstream->num_samples; - int channels = get_vgmstream_average_bitrate_channel_count(vgmstream); + int channels; STREAMFILE * streamFile; - if (!sample_rate || !channels || !length_samples) + if (!sample_rate || !length_samples) return 0; /* subsongs need to report this to properly calculate */ @@ -2496,6 +2494,16 @@ int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream) { return get_vgmstream_average_bitrate_from_size(vgmstream->stream_size, sample_rate, length_samples); } + /* AAX layout is handled differently as it has multiple sub-VGMSTREAMs (may include special codecs) */ + //todo not correct with multifile segments (ex. .ACM Ogg) + if (vgmstream->layout_type==layout_aax) { + aax_codec_data *data = (aax_codec_data *) vgmstream->layout_data; + return get_vgmstream_average_bitrate(data->segments[0]); + } + + channels = get_vgmstream_average_bitrate_channel_count(vgmstream); + if (!channels) return 0; + if (channels >= 1) { streamFile = get_vgmstream_average_bitrate_channel_streamfile(vgmstream, 0); if (streamFile) { diff --git a/src/vgmstream.h b/src/vgmstream.h index 49a1ed75..ebfb1237 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -797,6 +797,10 @@ typedef struct { * Note also that support must be added for resetting, looping and * closing for every codec that uses this, as it will not be handled. */ void * codec_data; + /* Same, for special layouts. + * Reusing the above pointer causes bugs when it's using special layout + codec + * (vgmstream may try to free/loop/etc codec_data). */ + void * layout_data; } VGMSTREAM; #ifdef VGM_USE_VORBIS