Merge pull request #853 from bnnm/xwb2

- Fix XMA sample counting in big files [Dead Island (X360)]
- Tweak .int validations
This commit is contained in:
bnnm 2021-05-05 23:56:37 +02:00 committed by GitHub
commit 7e3e15c12b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 153 additions and 148 deletions

View File

@ -466,7 +466,9 @@ a perfectly valid *!tags.m3u*:
# @ARTIST Various Artists
```
### Non-English filenames and tags
### Compatibility and non-English filenames and tags
For best compatibility save `!tags.m3u` as *"ANSI"* or *"UTF-8" (with BOM)*.
Tags and filenames using extended characters (like Japanese) should work, as long
as `!tags.m3u` is saved as *"UTF-8 with BOM"* (UTF-8 is a way to define non-English
characters, and BOM is a helper "byte-order" mark). Windows' *notepad* creates files

View File

@ -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);

View File

@ -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;
}

View File

@ -242,10 +242,6 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) {
if (xwb.version <= XACT1_1_MAX) {
xwb.entry_flags = entry_info;
}
else if (xwb.version == XACT_TECHLAND) { /* Nail'd (X360) */
xwb.entry_flags = 0;
xwb.num_samples = 0;//(entry_info >> 1) & 0x7FFFFFFF; /* seems ok for music banks but not sfx, fixed later */
}
else {
xwb.entry_flags = (entry_info) & 0xF; /*4b*/
xwb.num_samples = (entry_info >> 4) & 0x0FFFFFFF; /*28b*/
@ -428,7 +424,13 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) {
xwb.fix_xma_loop_samples = 1;
xwb.fix_xma_num_samples = 0;
/* for XWB v22 (and below?) this seems normal, also techland [Project Gotham Racing (X360)] */
/* 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;
xwb.fix_xma_num_samples = 1;