From 383d27fdff8b0957348d8292f3ab92e318c79042 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Fri, 7 May 2021 18:21:19 -0700 Subject: [PATCH] Updated VGMStream to r1050-3706-gdcdc1950 --- .../vgmstream/src/coding/coding_utils.c | 197 +++++++++--------- Frameworks/vgmstream/vgmstream/src/formats.c | 1 + .../vgmstream/vgmstream/src/meta/ea_schl.c | 2 +- .../vgmstream/vgmstream/src/meta/hca_keys.h | 29 +-- .../vgmstream/vgmstream/src/meta/maxis_xa.c | 6 +- .../vgmstream/vgmstream/src/meta/ogg_vorbis.c | 4 +- .../vgmstream/vgmstream/src/meta/raw_int.c | 88 ++++---- .../vgmstream/vgmstream/src/meta/riff.c | 6 +- .../vgmstream/vgmstream/src/meta/xma_ue3.c | 3 +- Frameworks/vgmstream/vgmstream/src/meta/xwb.c | 13 +- 10 files changed, 185 insertions(+), 164 deletions(-) diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c b/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c index faddd023e..e2621067d 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding_utils.c @@ -19,11 +19,11 @@ * read num_bits (up to 25) from a bit offset. * 25 since we read a 32 bit int, and need to adjust up to 7 bits from the byte-rounded fseek (32-7=25) */ -static uint32_t read_bitsBE_b(int64_t bit_offset, int num_bits, STREAMFILE *streamFile) { +static uint32_t read_bitsBE_b(int64_t bit_offset, int num_bits, STREAMFILE* sf) { uint32_t num, mask; if (num_bits > 25) return -1; //??? - num = read_32bitBE(bit_offset / 8, streamFile); /* fseek rounded to 8 */ + num = read_32bitBE(bit_offset / 8, sf); /* fseek rounded to 8 */ num = num << (bit_offset % 8); /* offset adjust (up to 7) */ num = num >> (32 - num_bits); mask = 0xffffffff >> (32 - num_bits); @@ -37,7 +37,7 @@ static uint32_t read_bitsBE_b(int64_t bit_offset, int num_bits, STREAMFILE *stre /* ******************************************** */ /* All helpers copy a RIFF header to buf and returns the number of bytes in buf or -1 when buf is not big enough */ -int ffmpeg_make_riff_atrac3plus(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int encoder_delay) { +int ffmpeg_make_riff_atrac3plus(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int encoder_delay) { uint16_t codec_ATRAC3plus = 0xfffe; /* wave format extensible */ size_t riff_size = 4+4+ 4 + 0x3c + 0x14 + 4+4; @@ -80,7 +80,7 @@ int ffmpeg_make_riff_atrac3plus(uint8_t * buf, size_t buf_size, size_t sample_co return riff_size; } -int ffmpeg_make_riff_xma1(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int stream_mode) { +int ffmpeg_make_riff_xma1(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int stream_mode) { uint16_t codec_XMA1 = 0x0165; size_t riff_size; int streams, i; @@ -164,7 +164,7 @@ int ffmpeg_make_riff_xma1(uint8_t * buf, size_t buf_size, size_t sample_count, s return riff_size; } -int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size) { +int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size) { uint16_t codec_XMA2 = 0x0166; size_t riff_size = 4+4+ 4 + 0x3c + 4+4; size_t bytecount; @@ -225,17 +225,17 @@ int ffmpeg_make_riff_xma2(uint8_t * buf, size_t buf_size, size_t sample_count, s /* Makes a XMA1/2 RIFF header for FFmpeg using a "fmt " chunk (XMAWAVEFORMAT or XMA2WAVEFORMATEX) as a base: * Useful to preserve the stream layout */ -int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t * buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE *streamFile, int big_endian) { +int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t* buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE* sf, int big_endian) { size_t riff_size = 4+4+ 4 + 4+4+fmt_size + 4+4; uint8_t chunk[0x100]; if (buf_size < riff_size || fmt_size > 0x100) goto fail; - if (read_streamfile(chunk,fmt_offset,fmt_size, streamFile) != fmt_size) + if (read_streamfile(chunk,fmt_offset,fmt_size, sf) != fmt_size) goto fail; if (big_endian) { - int codec = read_16bitBE(fmt_offset,streamFile); + int codec = read_16bitBE(fmt_offset,sf); ffmpeg_fmt_chunk_swap_endian(chunk, fmt_size, codec); } @@ -258,14 +258,14 @@ fail: /* Makes a XMA2 RIFF header for FFmpeg using a "XMA2" chunk (XMA2WAVEFORMAT) as a base. * Useful to preserve the stream layout */ -int ffmpeg_make_riff_xma2_from_xma2_chunk(uint8_t * buf, size_t buf_size, off_t xma2_offset, size_t xma2_size, size_t data_size, STREAMFILE *streamFile) { +int ffmpeg_make_riff_xma2_from_xma2_chunk(uint8_t* buf, size_t buf_size, off_t xma2_offset, size_t xma2_size, size_t data_size, STREAMFILE* sf) { uint8_t chunk[0x100]; size_t riff_size; riff_size = 4+4+ 4 + 4+4+xma2_size + 4+4; if (buf_size < riff_size || xma2_size > 0x100) goto fail; - if (read_streamfile(chunk,xma2_offset,xma2_size, streamFile) != xma2_size) + if (read_streamfile(chunk,xma2_offset,xma2_size, sf) != xma2_size) goto fail; @@ -286,7 +286,7 @@ fail: return -1; } -int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align) { +int ffmpeg_make_riff_xwma(uint8_t* buf, size_t buf_size, int codec, size_t data_size, int channels, int sample_rate, int avg_bps, int block_align) { size_t riff_size = 4+4+ 4 + 0x1a + 4+4; if (buf_size < riff_size) @@ -343,7 +343,7 @@ int ffmpeg_make_riff_xwma(uint8_t * buf, size_t buf_size, int codec, size_t data } -int ffmpeg_fmt_chunk_swap_endian(uint8_t * chunk, size_t chunk_size, uint16_t codec) { +int ffmpeg_fmt_chunk_swap_endian(uint8_t* chunk, size_t chunk_size, uint16_t codec) { int i; /* swap from LE to BE or the other way around, doesn't matter */ switch(codec) { @@ -403,23 +403,24 @@ fail: /* XMA PARSING */ /* ******************************************** */ -static void ms_audio_parse_header(STREAMFILE *streamFile, int xma_version, int64_t offset_b, int bits_frame_size, size_t *first_frame_b, size_t *packet_skip_count, size_t *header_size_b) { +static void ms_audio_parse_header(STREAMFILE* sf, int xma_version, int64_t offset_b, int bits_frame_size, size_t *first_frame_b, size_t *packet_skip_count, size_t *header_size_b) { + if (xma_version == 1) { /* XMA1 */ - //packet_sequence = read_bitsBE_b(offset_b+0, 4, streamFile); /* numbered from 0 to N */ - //unknown = read_bitsBE_b(offset_b+4, 2, streamFile); /* packet_metadata? (always 2) */ - *first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside the packet */ - *packet_skip_count = read_bitsBE_b(offset_b+21, 11, streamFile); /* packets to skip for next packet of this stream */ + //packet_sequence = read_bitsBE_b(offset_b+0, 4, sf); /* numbered from 0 to N */ + //unknown = read_bitsBE_b(offset_b+4, 2, sf); /* packet_metadata? (always 2) */ + *first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, sf); /* offset in bits inside the packet */ + *packet_skip_count = read_bitsBE_b(offset_b+21, 11, sf); /* packets to skip for next packet of this stream */ *header_size_b = 32; } else if (xma_version == 2) { /* XMA2 */ - //frame_count = read_bitsBE_b(offset_b+0, 6, streamFile); /* frames that begin in this packet */ - *first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside this packet */ - //packet_metadata = read_bitsBE_b(offset_b+21, 3, streamFile); /* packet_metadata (always 1) */ - *packet_skip_count = read_bitsBE_b(offset_b+24, 8, streamFile); /* packets to skip for next packet of this stream */ + //frame_count = read_bitsBE_b(offset_b+0, 6, sf); /* frames that begin in this packet */ + *first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, sf); /* offset in bits inside this packet */ + //packet_metadata = read_bitsBE_b(offset_b+21, 3, sf); /* packet_metadata (always 1) */ + *packet_skip_count = read_bitsBE_b(offset_b+24, 8, sf); /* packets to skip for next packet of this stream */ *header_size_b = 32; } else { /* WMAPRO(v3) */ - //packet_sequence = read_bitsBE_b(offset_b+0, 4, streamFile); /* numbered from 0 to N */ - //unknown = read_bitsBE_b(offset_b+4, 2, streamFile); /* packet_metadata? (always 2) */ - *first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, streamFile); /* offset in bits inside the packet */ + //packet_sequence = read_bitsBE_b(offset_b+0, 4, sf); /* numbered from 0 to N */ + //unknown = read_bitsBE_b(offset_b+4, 2, sf); /* packet_metadata? (always 2) */ + *first_frame_b = read_bitsBE_b(offset_b+6, bits_frame_size, sf); /* offset in bits inside the packet */ *packet_skip_count = 0; /* xwma has no need to skip packets since it uses real multichannel audio */ *header_size_b = 4+2+bits_frame_size; /* variable-sized header */ } @@ -457,7 +458,7 @@ static void ms_audio_parse_header(STREAMFILE *streamFile, int xma_version, int64 * * XMA1/XMA2/WMAPRO data only differs in the packet headers. */ -static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int channels_per_packet, int bytes_per_packet, int samples_per_frame, int samples_per_subframe, int bits_frame_size) { +static void ms_audio_get_samples(ms_sample_data* msd, STREAMFILE* sf, int channels_per_packet, int bytes_per_packet, int samples_per_frame, int samples_per_subframe, int bits_frame_size) { int frames = 0, samples = 0, loop_start_frame = 0, loop_end_frame = 0; size_t first_frame_b, packet_skip_count, header_size_b, frame_size_b; @@ -465,9 +466,9 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i size_t packet_size = bytes_per_packet; size_t packet_size_b = packet_size * 8; - off_t offset = msd->data_offset; - off_t max_offset = msd->data_offset + msd->data_size; - off_t stream_offset_b = msd->data_offset * 8; + int64_t offset = msd->data_offset; + int64_t max_offset = msd->data_offset + msd->data_size; + int64_t stream_offset_b = msd->data_offset * 8; /* read packets */ while (offset < max_offset) { @@ -475,7 +476,7 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i offset += packet_size; /* global offset in bytes */ /* packet header */ - ms_audio_parse_header(streamFile, msd->xma_version, offset_b, bits_frame_size, &first_frame_b, &packet_skip_count, &header_size_b); + ms_audio_parse_header(sf, msd->xma_version, offset_b, bits_frame_size, &first_frame_b, &packet_skip_count, &header_size_b); if (packet_skip_count > 0x7FF) { continue; /* full skip */ } @@ -496,7 +497,7 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i loop_end_frame = frames; /* frame header */ - frame_size_b = read_bitsBE_b(frame_offset_b, bits_frame_size, streamFile); + frame_size_b = read_bitsBE_b(frame_offset_b, bits_frame_size, sf); frame_offset_b += bits_frame_size; /* stop when packet padding starts (0x00 for XMA1 or 0xFF in XMA2) */ @@ -511,7 +512,7 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i /* last bit in frame = more frames flag, end packet to avoid reading garbage in some cases * (last frame spilling to other packets also has this flag, though it's ignored here) */ - if (packet_offset_b < packet_size_b && !read_bitsBE_b(offset_b + packet_offset_b - 1, 1, streamFile)) { + if (packet_offset_b < packet_size_b && !read_bitsBE_b(offset_b + packet_offset_b - 1, 1, sf)) { break; } } @@ -534,7 +535,7 @@ static void ms_audio_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, i } /* simlar to the above but only gets skips */ -static void ms_audio_get_skips(STREAMFILE *streamFile, int xma_version, off_t data_offset, int channels_per_packet, int bytes_per_packet, int samples_per_frame, int bits_frame_size, int *out_start_skip, int *out_end_skip) { +static void ms_audio_get_skips(STREAMFILE* sf, int xma_version, off_t data_offset, int channels_per_packet, int bytes_per_packet, int samples_per_frame, int bits_frame_size, int *out_start_skip, int *out_end_skip) { int start_skip = 0, end_skip = 0; size_t first_frame_b, packet_skip_count, header_size_b, frame_size_b; @@ -550,7 +551,7 @@ static void ms_audio_get_skips(STREAMFILE *streamFile, int xma_version, off_t da offset += packet_size; /* global offset in bytes */ /* packet header */ - ms_audio_parse_header(streamFile, 2, offset_b, bits_frame_size, &first_frame_b, &packet_skip_count, &header_size_b); + ms_audio_parse_header(sf, 2, offset_b, bits_frame_size, &first_frame_b, &packet_skip_count, &header_size_b); if (packet_skip_count > 0x7FF) { return; /* full skip */ } @@ -562,7 +563,7 @@ static void ms_audio_get_skips(STREAMFILE *streamFile, int xma_version, off_t da frame_offset_b = offset_b + packet_offset_b; /* in bits for aligment stuff */ /* frame header */ - frame_size_b = read_bitsBE_b(frame_offset_b, bits_frame_size, streamFile); + frame_size_b = read_bitsBE_b(frame_offset_b, bits_frame_size, sf); frame_offset_b += bits_frame_size; /* stop when packet padding starts (0x00 for XMA1 or 0xFF in XMA2) */ @@ -580,10 +581,10 @@ static void ms_audio_get_skips(STREAMFILE *streamFile, int xma_version, off_t da /* ignore "postproc transform" */ if (channels_per_packet > 1) { - flag = read_bitsBE_b(frame_offset_b, 1, streamFile); + flag = read_bitsBE_b(frame_offset_b, 1, sf); frame_offset_b += 1; if (flag) { - flag = read_bitsBE_b(frame_offset_b, 1, streamFile); + flag = read_bitsBE_b(frame_offset_b, 1, sf); frame_offset_b += 1; if (flag) { frame_offset_b += 1 + 4 * channels_per_packet*channels_per_packet; /* 4-something per double channel? */ @@ -592,14 +593,14 @@ static void ms_audio_get_skips(STREAMFILE *streamFile, int xma_version, off_t da } /* get start/end skips to get the proper number of samples (both can be 0) */ - flag = read_bitsBE_b(frame_offset_b, 1, streamFile); + flag = read_bitsBE_b(frame_offset_b, 1, sf); frame_offset_b += 1; if (flag) { /* get start skip */ - flag = read_bitsBE_b(frame_offset_b, 1, streamFile); + flag = read_bitsBE_b(frame_offset_b, 1, sf); frame_offset_b += 1; if (flag) { - int new_skip = read_bitsBE_b(frame_offset_b, 10, streamFile); + int new_skip = read_bitsBE_b(frame_offset_b, 10, sf); //;VGM_LOG("MS_SAMPLES: start_skip %i at 0x%x (bit 0x%x)\n", new_skip, (uint32_t)frame_offset_b/8, (uint32_t)frame_offset_b); frame_offset_b += 10; @@ -611,10 +612,10 @@ static void ms_audio_get_skips(STREAMFILE *streamFile, int xma_version, off_t da } /* get end skip */ - flag = read_bitsBE_b(frame_offset_b, 1, streamFile); + flag = read_bitsBE_b(frame_offset_b, 1, sf); frame_offset_b += 1; if (flag) { - int new_skip = read_bitsBE_b(frame_offset_b, 10, streamFile); + int new_skip = read_bitsBE_b(frame_offset_b, 10, sf); //;VGM_LOG("MS_SAMPLES: end_skip %i at 0x%x (bit 0x%x)\n", new_skip, (uint32_t)frame_offset_b/8, (uint32_t)frame_offset_b); frame_offset_b += 10; @@ -661,20 +662,20 @@ static int wma_get_samples_per_frame(int version, int sample_rate, uint32_t deco return 1 << frame_len_bits; } -static int xma_get_channels_per_stream(STREAMFILE* streamFile, off_t chunk_offset, int channels) { +static int xma_get_channels_per_stream(STREAMFILE* sf, off_t chunk_offset, int channels) { int start_stream = 0; int channels_per_stream = 0; /* get from stream config (needed to find skips) */ if (chunk_offset) { - int format = read_16bitLE(chunk_offset,streamFile); + int format = read_16bitLE(chunk_offset,sf); if (format == 0x0165 || format == 0x6501) { /* XMA1 */ - channels_per_stream = read_8bit(chunk_offset + 0x0C + 0x14*start_stream + 0x11,streamFile); + channels_per_stream = read_8bit(chunk_offset + 0x0C + 0x14*start_stream + 0x11,sf); } else if (format == 0x0166 || format == 0x6601) { /* new XMA2 */ channels_per_stream = channels > 1 ? 2 : 1; } else { /* old XMA2 */ - int version = read_8bit(chunk_offset,streamFile); - channels_per_stream = read_8bit(chunk_offset + 0x20 + (version==3 ? 0x00 : 0x08) + 0x4*start_stream + 0x00,streamFile); + int version = read_8bit(chunk_offset,sf); + channels_per_stream = read_8bit(chunk_offset + 0x20 + (version==3 ? 0x00 : 0x08) + 0x4*start_stream + 0x00,sf); } } else if (channels) { @@ -687,17 +688,17 @@ static int xma_get_channels_per_stream(STREAMFILE* streamFile, off_t chunk_offse return channels_per_stream; } -void xma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile) { +void xma_get_samples(ms_sample_data* msd, STREAMFILE* sf) { const int bytes_per_packet = 2048; const int samples_per_frame = 512; const int samples_per_subframe = 128; const int bits_frame_size = 15; - int channels_per_stream = xma_get_channels_per_stream(streamFile, msd->chunk_offset, msd->channels); + int channels_per_stream = xma_get_channels_per_stream(sf, msd->chunk_offset, msd->channels); - ms_audio_get_samples(msd, streamFile, channels_per_stream, bytes_per_packet, samples_per_frame, samples_per_subframe, bits_frame_size); + ms_audio_get_samples(msd, sf, channels_per_stream, bytes_per_packet, samples_per_frame, samples_per_subframe, bits_frame_size); } -void wmapro_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags) { +void wmapro_get_samples(ms_sample_data* msd, STREAMFILE* sf, int block_align, int sample_rate, uint32_t decode_flags) { const int version = 3; /* WMAPRO = WMAv3 */ int bytes_per_packet = block_align; int samples_per_frame = 0; @@ -715,10 +716,10 @@ void wmapro_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_ samples_per_subframe = 0; /* not needed as WMAPro can't use loop subframes (complex subframe lengths) */ msd->xma_version = 0; /* signal it's not XMA */ - ms_audio_get_samples(msd, streamFile, channels_per_stream, bytes_per_packet, samples_per_frame, samples_per_subframe, bits_frame_size); + ms_audio_get_samples(msd, sf, channels_per_stream, bytes_per_packet, samples_per_frame, samples_per_subframe, bits_frame_size); } -void wma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_align, int sample_rate, uint32_t decode_flags) { +void wma_get_samples(ms_sample_data* msd, STREAMFILE* sf, int block_align, int sample_rate, uint32_t decode_flags) { const int version = 2; /* WMAv1 rarely used */ int use_bit_reservoir = 0; /* last packet frame can spill into the next packet */ int samples_per_frame = 0; @@ -741,7 +742,7 @@ void wma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_ali off_t max_offset = msd->data_offset + msd->data_size; while (offset < max_offset) { /* read packets (superframes) */ int packet_frames; - uint8_t header = read_8bit(offset, streamFile); /* upper nibble: index; lower nibble: frames */ + uint8_t header = read_8bit(offset, sf); /* upper nibble: index; lower nibble: frames */ /* frames starting in this packet (ie. counts frames that spill due to bit_reservoir) */ packet_frames = (header & 0xf); @@ -763,7 +764,7 @@ void wma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_ali /* XMA hell for precise looping and gapless support, fixes raw sample values from headers * that don't count XMA's final subframe/encoder delay/encoder padding, and FFmpeg stuff. * Configurable since different headers vary for maximum annoyance. */ -void xma_fix_raw_samples_ch(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stream_offset, size_t stream_size, int channels_per_stream, int fix_num_samples, int fix_loop_samples) { +void xma_fix_raw_samples_ch(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t stream_offset, size_t stream_size, int channels_per_stream, int fix_num_samples, int fix_loop_samples) { const int bytes_per_packet = 2048; const int samples_per_frame = 512; const int samples_per_subframe = 128; @@ -774,7 +775,7 @@ void xma_fix_raw_samples_ch(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t s off_t last_packet = stream_offset + stream_size - bytes_per_packet; int32_t start_skip = 0, end_skip = 0; - if (stream_offset + stream_size > get_streamfile_size(streamFile)) { + if (stream_offset + stream_size > get_streamfile_size(sf)) { VGM_LOG("XMA SKIPS: ignoring bad stream offset+size vs real size\n"); return; } @@ -782,8 +783,8 @@ void xma_fix_raw_samples_ch(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t s /* find delay/padding values in the bitstream (should be safe even w/ multistreams * as every stream repeats them). Theoretically every packet could contain skips, * doesn't happen in practice though. */ - ms_audio_get_skips(streamFile, xma_version, first_packet, channels_per_stream, bytes_per_packet, samples_per_frame, bits_frame_size, &start_skip, NULL); - ms_audio_get_skips(streamFile, xma_version, last_packet, channels_per_stream, bytes_per_packet, samples_per_frame, bits_frame_size, NULL, &end_skip); + ms_audio_get_skips(sf, xma_version, first_packet, channels_per_stream, bytes_per_packet, samples_per_frame, bits_frame_size, &start_skip, NULL); + ms_audio_get_skips(sf, xma_version, last_packet, channels_per_stream, bytes_per_packet, samples_per_frame, bits_frame_size, NULL, &end_skip); //;VGM_LOG("XMA SKIPS: apply start=%i, end=%i\n", start_skip, end_skip); VGM_ASSERT(start_skip < samples_per_frame, "XMA SKIPS: small start skip\n"); @@ -835,14 +836,14 @@ void xma_fix_raw_samples_ch(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t s #endif } -void xma_fix_raw_samples_hb(VGMSTREAM *vgmstream, STREAMFILE *headerFile, STREAMFILE *bodyFile, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples) { - int channels_per_stream = xma_get_channels_per_stream(headerFile, chunk_offset, vgmstream->channels); - xma_fix_raw_samples_ch(vgmstream, bodyFile, stream_offset, stream_size, channels_per_stream, fix_num_samples, fix_loop_samples); +void xma_fix_raw_samples_hb(VGMSTREAM* vgmstream, STREAMFILE* sf_head, STREAMFILE* sf_body, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples) { + int channels_per_stream = xma_get_channels_per_stream(sf_head, chunk_offset, vgmstream->channels); + xma_fix_raw_samples_ch(vgmstream, sf_body, stream_offset, stream_size, channels_per_stream, fix_num_samples, fix_loop_samples); } -void xma_fix_raw_samples(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples) { - int channels_per_stream = xma_get_channels_per_stream(streamFile, chunk_offset, vgmstream->channels); - xma_fix_raw_samples_ch(vgmstream, streamFile, stream_offset, stream_size, channels_per_stream, fix_num_samples, fix_loop_samples); +void xma_fix_raw_samples(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples) { + int channels_per_stream = xma_get_channels_per_stream(sf, chunk_offset, vgmstream->channels); + xma_fix_raw_samples_ch(vgmstream, sf, stream_offset, stream_size, channels_per_stream, fix_num_samples, fix_loop_samples); } @@ -852,46 +853,46 @@ void xma_fix_raw_samples(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stre /* Read values from a XMA1 RIFF "fmt" chunk (XMAWAVEFORMAT), starting from an offset *after* chunk type+size. * Useful as custom X360 headers commonly have it lurking inside. */ -void xma1_parse_fmt_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * channels, int * sample_rate, int * loop_flag, int32_t * loop_start_b, int32_t * loop_end_b, int32_t * loop_subframe, int be) { +void xma1_parse_fmt_chunk(STREAMFILE* sf, off_t chunk_offset, int * channels, int* sample_rate, int* loop_flag, int32_t * loop_start_b, int32_t * loop_end_b, int32_t * loop_subframe, int be) { int16_t (*read_16bit)(off_t,STREAMFILE*) = be ? read_16bitBE : read_16bitLE; int32_t (*read_32bit)(off_t,STREAMFILE*) = be ? read_32bitBE : read_32bitLE; int i, num_streams, total_channels = 0; - if (read_16bit(chunk_offset+0x00,streamFile) != 0x165) + if (read_16bit(chunk_offset+0x00,sf) != 0x165) return; - num_streams = read_16bit(chunk_offset+0x08,streamFile); - if(loop_flag) *loop_flag = (uint8_t)read_8bit(chunk_offset+0xA,streamFile) > 0; + num_streams = read_16bit(chunk_offset+0x08,sf); + if(loop_flag) *loop_flag = (uint8_t)read_8bit(chunk_offset+0xA,sf) > 0; /* sample rate and loop bit offsets are defined per stream, but the first is enough */ - if(sample_rate) *sample_rate = read_32bit(chunk_offset+0x10,streamFile); - if(loop_start_b) *loop_start_b = read_32bit(chunk_offset+0x14,streamFile); - if(loop_end_b) *loop_end_b = read_32bit(chunk_offset+0x18,streamFile); - if(loop_subframe) *loop_subframe = (uint8_t)read_8bit(chunk_offset+0x1C,streamFile); + if(sample_rate) *sample_rate = read_32bit(chunk_offset+0x10,sf); + if(loop_start_b) *loop_start_b = read_32bit(chunk_offset+0x14,sf); + if(loop_end_b) *loop_end_b = read_32bit(chunk_offset+0x18,sf); + if(loop_subframe) *loop_subframe = (uint8_t)read_8bit(chunk_offset+0x1C,sf); /* channels is the sum of all streams */ for (i = 0; i < num_streams; i++) { - total_channels += read_8bit(chunk_offset+0x0C+0x14*i+0x11,streamFile); + total_channels += read_8bit(chunk_offset+0x0C+0x14*i+0x11,sf); } if(channels) *channels = total_channels; } /* Read values from a 'new' XMA2 RIFF "fmt" chunk (XMA2WAVEFORMATEX), starting from an offset *after* chunk type+size. * Useful as custom X360 headers commonly have it lurking inside. Only parses the extra data (before is a normal WAVEFORMATEX). */ -void xma2_parse_fmt_chunk_extra(STREAMFILE *streamFile, off_t chunk_offset, int * out_loop_flag, int32_t * out_num_samples, int32_t * out_loop_start_sample, int32_t * out_loop_end_sample, int be) { +void xma2_parse_fmt_chunk_extra(STREAMFILE* sf, off_t chunk_offset, int* out_loop_flag, int32_t* out_num_samples, int32_t* out_loop_start_sample, int32_t* out_loop_end_sample, int be) { int16_t (*read_16bit)(off_t,STREAMFILE*) = be ? read_16bitBE : read_16bitLE; int32_t (*read_32bit)(off_t,STREAMFILE*) = be ? read_32bitBE : read_32bitLE; int num_samples, loop_start_sample, loop_end_sample, loop_flag; - if (read_16bit(chunk_offset+0x00,streamFile) != 0x166) + if (read_16bit(chunk_offset+0x00,sf) != 0x166) return; - if (read_16bit(chunk_offset+0x10,streamFile) < 0x22) + if (read_16bit(chunk_offset+0x10,sf) < 0x22) return; /* expected extra data size */ - num_samples = read_32bit(chunk_offset+0x18,streamFile); - loop_start_sample = read_32bit(chunk_offset+0x28,streamFile); - loop_end_sample = loop_start_sample + read_32bit(chunk_offset+0x2C,streamFile); - loop_flag = (uint8_t)read_8bit(chunk_offset+0x30,streamFile) != 0; + num_samples = read_32bit(chunk_offset+0x18,sf); + loop_start_sample = read_32bit(chunk_offset+0x28,sf); + loop_end_sample = loop_start_sample + read_32bit(chunk_offset+0x2C,sf); + loop_flag = (uint8_t)read_8bit(chunk_offset+0x30,sf) != 0; /* may need loop end +1, though some header doesn't need it (ex.- Sonic and Sega All Stars Racing .str) */ /* flag rarely set, use loop_end as marker */ @@ -912,35 +913,35 @@ void xma2_parse_fmt_chunk_extra(STREAMFILE *streamFile, off_t chunk_offset, int if(out_loop_flag) *out_loop_flag = loop_flag; /* play_begin+end = pcm_samples in original sample rate (not usable as file may be resampled) */ - /* int32_t play_begin_sample = read_32bit(xma->chunk_offset+0x20,streamFile); */ - /* int32_t play_end_sample = play_begin_sample + read_32bit(xma->chunk_offset+0x24,streamFile); */ + /* int32_t play_begin_sample = read_32bit(xma->chunk_offset+0x20,sf); */ + /* int32_t play_end_sample = play_begin_sample + read_32bit(xma->chunk_offset+0x24,sf); */ } /* Read values from an 'old' XMA2 RIFF "XMA2" chunk (XMA2WAVEFORMAT), starting from an offset *after* chunk type+size. * Useful as custom X360 headers commonly have it lurking inside. */ -void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * out_channels, int * out_sample_rate, int * out_loop_flag, int32_t * out_num_samples, int32_t * out_loop_start_sample, int32_t * out_loop_end_sample) { +void xma2_parse_xma2_chunk(STREAMFILE* sf, off_t chunk_offset, int* out_channels, int* out_sample_rate, int* out_loop_flag, int32_t* out_num_samples, int32_t* out_loop_start_sample, int32_t* out_loop_end_sample) { int32_t (*read_32bit)(off_t,STREAMFILE*) = read_32bitBE; /* XMA2WAVEFORMAT is always big endian */ int i, xma2_chunk_version, num_streams; int channels, sample_rate, loop_flag, num_samples, loop_start_sample, loop_end_sample; off_t offset; - xma2_chunk_version = read_8bit(chunk_offset+0x00,streamFile); - num_streams = read_8bit(chunk_offset+0x01,streamFile); - loop_start_sample = read_32bit(chunk_offset+0x04,streamFile); - loop_end_sample = read_32bit(chunk_offset+0x08,streamFile); - loop_flag = (uint8_t)read_8bit(chunk_offset+0x03,streamFile) > 0 || loop_end_sample; /* rarely not set, encoder default */ - sample_rate = read_32bit(chunk_offset+0x0c,streamFile); + xma2_chunk_version = read_8bit(chunk_offset+0x00,sf); + num_streams = read_8bit(chunk_offset+0x01,sf); + loop_start_sample = read_32bit(chunk_offset+0x04,sf); + loop_end_sample = read_32bit(chunk_offset+0x08,sf); + loop_flag = (uint8_t)read_8bit(chunk_offset+0x03,sf) > 0 || loop_end_sample; /* rarely not set, encoder default */ + sample_rate = read_32bit(chunk_offset+0x0c,sf); /* may need loop end +1 */ offset = xma2_chunk_version == 3 ? 0x14 : 0x1C; - num_samples = read_32bit(chunk_offset+offset+0x00,streamFile); + num_samples = read_32bit(chunk_offset+offset+0x00,sf); /* pcm_samples in original sample rate (not usable as file may be resampled) */ - /* pcm_samples = read_32bitBE(chunk_offset+offset+0x04,streamFile)*/ + /* pcm_samples = read_32bitBE(chunk_offset+offset+0x04,sf)*/ offset = xma2_chunk_version == 3 ? 0x20 : 0x28; channels = 0; /* channels is the sum of all streams */ for (i = 0; i < num_streams; i++) { - channels += read_8bit(chunk_offset+offset+i*0x04,streamFile); + channels += read_8bit(chunk_offset+offset+i*0x04,sf); } /* samples are "raw" values, must be fixed externally (see xma_fix_raw_samples) */ @@ -976,17 +977,17 @@ size_t ac3_bytes_to_samples(size_t bytes, int full_block_align, int channels) { } -size_t aac_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes) { +size_t aac_get_samples(STREAMFILE* sf, 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 (!streamFile) + if (!sf) return 0; - if (max_offset > get_streamfile_size(streamFile)) - max_offset = get_streamfile_size(streamFile); + if (max_offset > get_streamfile_size(sf)) + max_offset = get_streamfile_size(sf); /* 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: @@ -994,8 +995,8 @@ size_t aac_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes) /* 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); + uint16_t frame_sync = read_u16be(offset+0x00, sf); + uint32_t frame_size = read_u32be(offset+0x02, sf); frame_sync = (frame_sync >> 4) & 0x0FFF; /* 12b */ frame_size = (frame_size >> 5) & 0x1FFF; /* 13b */ @@ -1016,7 +1017,7 @@ size_t aac_get_samples(STREAMFILE *streamFile, off_t start_offset, size_t bytes) /* CUSTOM STREAMFILES */ /* ******************************************** */ -STREAMFILE* setup_subfile_streamfile(STREAMFILE *sf, off_t subfile_offset, size_t subfile_size, const char* extension) { +STREAMFILE* setup_subfile_streamfile(STREAMFILE* sf, off_t subfile_offset, size_t subfile_size, const char* extension) { STREAMFILE *new_sf = NULL; new_sf = open_wrap_streamfile(sf); diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index dcb8c3603..1eb4585ac 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -595,6 +595,7 @@ static const char* extension_list[] = { "wvx", "x", + "x360audio", //fake extension for Unreal Engine 3 XMA (real extension unknown) "xa", "xa2", "xa30", diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c index 0b44bcedc..25d8fb79e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c @@ -23,7 +23,7 @@ #define EA_PLATFORM_X360 0x09 #define EA_PLATFORM_PSP 0x0A #define EA_PLATFORM_PS3 0x0E /* very rare [Need for Speed: Carbon (PS3)] */ -#define EA_PLATFORM_WII 0x10 +#define EA_PLATFORM_WII 0x10 /* not seen so far */ #define EA_PLATFORM_3DS 0x14 /* codec constants (undefined are probably reserved, ie.- sx.exe encodes PCM24/DVI but no platform decodes them) */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h index 49b6ed8f8..5e1dba0d0 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h @@ -394,10 +394,13 @@ static const hcakey_info hcakey_list[] = { /* Fantasia Re: Build (Android) */ {8430978314079461325}, // 7500DA1B7FBA5FCD - - /* SaGa Frontier Remastered */ + + /* SaGa Frontier Remastered (multi) */ {5935495141785029458}, // 525F1D6244274B52 + /* Mushoku Tensei: Game ni Nattemo Honki Dasu (Android) */ + {12281329554827291428u}, // AA700C292CFCAB24 + /* D4DJ Groovy Mix (Android) [base files] */ {393410674916959300}, // 0575ACECA945A444 /* D4DJ Groovy Mix (Android) [music_* files, per-song later mixed with subkey] */ @@ -602,7 +605,6 @@ static const hcakey_info hcakey_list[] = { {0xa691936caf4d91d0}, {0x94466db0d3c10f4b}, {0x47f52330df2ead11}, - {0x33848be13a2884a3}, {0xc9f159f60b065f91}, {0xdd9ca800a7123d6f}, {0xa090c8ebf8463d05}, @@ -612,15 +614,18 @@ static const hcakey_info hcakey_list[] = { {0x1980271cfe0da9bd}, {0x945cdb3cf1f29e52}, {0x7f0feac6be7def5b}, - {0xc9f159f60b065f91}, - {0xdd9ca800a7123d6f}, - {0x0a90c8ebf8463d05}, - {0xa5c1adeb7919845f}, - {0x58d97e6f3d1aee86}, - {0x71b5fa3761d6726d}, - {0x1980271cfe0da9bd}, - {0x945cdb3cf1f29e52}, - {0x7f0feac6be7def5b}, + {0xe35d52b6d2c094fb}, + {0xd45e8ba374b45ff7}, + {0x09e68da734cc472f}, + {0xfc3fa77fc33460d4}, + {0xa2c543b227b8e5e2}, + {0xe6d1fd6effa46736}, + {0x75859a7a2b1ed37d}, + {0x358adfd1bbd3a95e}, + {0xc86f8564e0b9078c}, + {0x2e107d849959c430}, + {0xb96786621e27daf3}, + {0x1111d6c10e509824}, /* Dragalia Lost (iOS/Android) */ {2967411924141, subkeys_dgl, sizeof(subkeys_dgl) / sizeof(subkeys_dgl[0]) }, // 000002B2E7889CAD diff --git a/Frameworks/vgmstream/vgmstream/src/meta/maxis_xa.c b/Frameworks/vgmstream/vgmstream/src/meta/maxis_xa.c index 955aca458..b0c3a5cbb 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/maxis_xa.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/maxis_xa.c @@ -12,8 +12,10 @@ VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) { goto fail; /* check header */ - if ((read_32bitBE(0x00,streamFile) != 0x58414900) && /* "XAI\0" */ - (read_32bitBE(0x00,streamFile) != 0x58414A00)) /* "XAJ\0" (some odd song uses this, no apparent diffs) */ + if ((read_32bitBE(0x00,streamFile) != 0x58414900) && /* "XAI\0" (sound/speech) */ + (read_32bitBE(0x00,streamFile) != 0x58414A00) && /* "XAJ\0" (music, no apparent diffs) */ + (read_32bitBE(0x00,streamFile) != 0x58410000) && /* "XA\0\0" (sound/speech from The Sims 2, no apparent diffs) */ + (read_32bitBE(0x00,streamFile) != 0x58411200)) /* "XA\x12\0" (music from The Sims 2, no apparent diffs) */ goto fail; loop_flag = 0; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c index e852508cd..ce33cc876 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c @@ -472,7 +472,7 @@ VGMSTREAM* init_vgmstream_ogg_vorbis_callbacks(STREAMFILE* sf, ov_callbacks* cal strstr(comment,"LOOP_BEGIN=") == comment || /* Hatsune Miku: Project Diva F (PS3) */ strstr(comment,"LoopStart=") == comment || /* Devil May Cry 4 (PC) */ strstr(comment,"LOOP=") == comment || /* Duke Nukem 3D: 20th Anniversary World Tour */ - strstr(comment,"XIPH_CUE_LOOPSTART=") == comment) { /* Super Mario Run (Android) */ + strstr(comment,"XIPH_CUE_LOOPSTART=") == comment) { /* DeNa games [Super Mario Run (Android), FF Record Keeper (Android)] */ loop_start = atol(strrchr(comment,'=')+1); loop_flag = (loop_start >= 0); } @@ -546,7 +546,7 @@ VGMSTREAM* init_vgmstream_ogg_vorbis_callbacks(STREAMFILE* sf, ov_callbacks* cal } else if (strstr(comment,"COMMENT=- loopTime ") == comment || /* Aristear Remain (PC) */ strstr(comment,"COMMENT=-loopTime ") == comment) { /* Hyakki Ryouran no Yakata x Kawarazaki-ke no Ichizoku (PC) */ - loop_start = atol(strrchr(comment,'l')) / 1000.0f * sample_rate; /* ms to samples */ + loop_start = atol(strrchr(comment,' ')) / 1000.0f * sample_rate; /* ms to samples */ loop_flag = (loop_start >= 0); /* files have all page granule positions -1 except a few close to loop. This throws off diff --git a/Frameworks/vgmstream/vgmstream/src/meta/raw_int.c b/Frameworks/vgmstream/vgmstream/src/meta/raw_int.c index d0ba9719b..a2e851cf9 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/raw_int.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/raw_int.c @@ -1,44 +1,44 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* raw PCM file assumed by extension [PaRappa The Rapper 2 (PS2)? , Amplitude (PS2)?] */ -VGMSTREAM * init_vgmstream_raw_int(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int channel_count; - - /* checks */ - if (!check_extensions(streamFile, "int,wp2")) - goto fail; - - if (check_extensions(streamFile, "int")) - channel_count = 2; - else - channel_count = 4; - - /* ignore .int PS-ADPCM */ - if (ps_check_format(streamFile, 0x00, 0x10000)) - goto fail; - - start_offset = 0x00; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,0); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_RAW_INT; - vgmstream->sample_rate = 48000; - vgmstream->num_samples = pcm_bytes_to_samples(get_streamfile_size(streamFile), vgmstream->channels, 16); - vgmstream->coding_type = coding_PCM16LE; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x200; - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* raw PCM file assumed by extension [PaRappa The Rapper 2 (PS2), Amplitude (PS2), R-Type Final (PS2)] */ +VGMSTREAM* init_vgmstream_raw_int(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + int channel_count; + + /* checks */ + if (!check_extensions(sf, "int,wp2")) + goto fail; + + if (check_extensions(sf, "wp2")) + channel_count = 4; + else + channel_count = 2; + + /* ignore .int PS-ADPCM (some files start with silence so up a bit) */ + if (ps_check_format(sf, 0x00, 0x100000)) + goto fail; + + start_offset = 0x00; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, 0); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_RAW_INT; + vgmstream->sample_rate = 48000; + vgmstream->num_samples = pcm_bytes_to_samples(get_streamfile_size(sf), vgmstream->channels, 16); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x200; + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/riff.c b/Frameworks/vgmstream/vgmstream/src/meta/riff.c index 6bc9275a3..6efa2fa0f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/riff.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/riff.c @@ -537,11 +537,13 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { break; case 0x63756520: /* "cue " (used in Source Engine for storing loop points) */ - if (fmt.coding_type == coding_PCM16LE || fmt.coding_type == coding_MSADPCM) { + if (fmt.coding_type == coding_PCM8_U || + fmt.coding_type == coding_PCM16LE || + fmt.coding_type == coding_MSADPCM) { uint32_t num_cues = read_32bitLE(current_chunk + 0x08, sf); if (num_cues > 0) { - /* The second cue sets loop end point but it's not actually used by the engine. */ + /* the second cue sets loop end point but it's not actually used by the engine */ loop_flag = 1; loop_start_cue = read_32bitLE(current_chunk + 0x20, sf); } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xma_ue3.c b/Frameworks/vgmstream/vgmstream/src/meta/xma_ue3.c index 197259416..324457cd6 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xma_ue3.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xma_ue3.c @@ -12,7 +12,8 @@ VGMSTREAM* init_vgmstream_xma_ue3(STREAMFILE *sf) { /* checks */ /* .xma: assumed */ - if (!check_extensions(sf, "xma,")) + /* .x360audio: fake produced by UE Viewer */ + if (!check_extensions(sf, "xma,x360audio,")) goto fail; /* UE3 uses class-like chunks called "SoundNodeWave" to store info and (rarely multi) raw audio data. Other diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c index 3383ce844..3447371c6 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c @@ -241,10 +241,12 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) { uint32_t entry_info = read_u32(offset+0x00, sf); if (xwb.version <= XACT1_1_MAX) { xwb.entry_flags = entry_info; - } else { + } + else { xwb.entry_flags = (entry_info) & 0xF; /*4b*/ xwb.num_samples = (entry_info >> 4) & 0x0FFFFFFF; /*28b*/ } + xwb.format = read_u32(offset+0x04, sf); xwb.stream_offset = xwb.data_offset + read_u32(offset+0x08, sf); xwb.stream_size = read_u32(offset+0x0c, sf); @@ -397,7 +399,8 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) { xwb.loop_start_sample = msadpcm_bytes_to_samples(xwb.loop_start, block_size, xwb.channels); xwb.loop_end_sample = msadpcm_bytes_to_samples(xwb.loop_start + xwb.loop_end, block_size, xwb.channels); } - else if (xwb.version <= XACT2_1_MAX && (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) { + else if ((xwb.version <= XACT2_1_MAX && (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) + || (xwb.version == XACT_TECHLAND && xwb.codec == XMA2)) { /* v38: byte offset, v40+: sample offset, v39: ? */ /* need to manually find sample offsets, thanks to Microsoft's dumb headers */ ms_sample_data msd = {0}; @@ -421,6 +424,12 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) { xwb.fix_xma_loop_samples = 1; xwb.fix_xma_num_samples = 0; + /* Techland's XMA in tool_version 0x2a (not 0x2c?) seems to use (entry_info >> 1) num_samples + * for music banks, but not sfx [Nail'd (X360)-0x2a, Dead Island (X360)-0x2c] */ + if (xwb.version == XACT_TECHLAND) { + xwb.num_samples = 0; + } + /* for XWB v22 (and below?) this seems normal [Project Gotham Racing (X360)] */ if (xwb.num_samples == 0) { xwb.num_samples = msd.num_samples;