Merge pull request #155 from bnnm/code-misc

Code, misc
This commit is contained in:
Christopher Snowhill 2017-12-09 14:08:31 -08:00 committed by GitHub
commit 44a48fcad6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 1691 additions and 1745 deletions

View File

@ -59,6 +59,7 @@ VGMSTREAM_DECLARE_FILE_TYPE("BAKA", baka);
VGMSTREAM_DECLARE_FILE_TYPE("BAR", bar);
VGMSTREAM_DECLARE_FILE_TYPE("BCSTM", bcstm);
VGMSTREAM_DECLARE_FILE_TYPE("BCWAV", bcwav);
VGMSTREAM_DECLARE_FILE_TYPE("BD3", bd3);
VGMSTREAM_DECLARE_FILE_TYPE("BDSP", bdsp);
VGMSTREAM_DECLARE_FILE_TYPE("BFSTM", bfstm);
VGMSTREAM_DECLARE_FILE_TYPE("BFWAV", bfwav);
@ -238,6 +239,7 @@ VGMSTREAM_DECLARE_FILE_TYPE("RND", rnd);
VGMSTREAM_DECLARE_FILE_TYPE("RRDS", rrds);
VGMSTREAM_DECLARE_FILE_TYPE("RSD", rsd);
VGMSTREAM_DECLARE_FILE_TYPE("RSF", rsf);
VGMSTREAM_DECLARE_FILE_TYPE("RSM", rsm);
VGMSTREAM_DECLARE_FILE_TYPE("RSTM", rstm);
VGMSTREAM_DECLARE_FILE_TYPE("RVWS", rvws);
VGMSTREAM_DECLARE_FILE_TYPE("RWAR", rwar);
@ -263,6 +265,7 @@ VGMSTREAM_DECLARE_FILE_TYPE("SC", sc);
VGMSTREAM_DECLARE_FILE_TYPE("SCD", scd);
VGMSTREAM_DECLARE_FILE_TYPE("SCK", sck);
VGMSTREAM_DECLARE_FILE_TYPE("SD9", sd9);
VGMSTREAM_DECLARE_FILE_TYPE("SDF", sdf);
VGMSTREAM_DECLARE_FILE_TYPE("SDT", sdt);
VGMSTREAM_DECLARE_FILE_TYPE("SEG", seg);
VGMSTREAM_DECLARE_FILE_TYPE("SF0", sf0);

View File

@ -38,7 +38,7 @@ size_t ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFi
/* ngc_dsp_decoder */
void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem);
void decode_ngc_dsp_subint(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int interleave);
size_t dsp_bytes_to_samples(size_t bytes, int channels);
int32_t dsp_nibbles_to_samples(int32_t nibbles);
void dsp_read_coefs_be(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t offset, off_t spacing);
@ -276,4 +276,19 @@ void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * cha
size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align);
size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align);
/* An internal struct to pass around and simulate a bitstream. */
typedef enum { BITSTREAM_MSF, BITSTREAM_VORBIS } vgm_bitstream_t;
typedef struct {
uint8_t * buf; /* buffer to read/write*/
size_t bufsize; /* max size of the buffer */
off_t b_off; /* current offset in bits inside the buffer */
off_t info_offset; /* for logging */
vgm_bitstream_t mode; /* read/write modes */
} vgm_bitstream;
int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value);
int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value);
#endif /*_CODING_H*/

View File

@ -835,3 +835,149 @@ size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align) {
* so (full_block_align / channels) DOESN'T give the size of a single channel (common in ATRAC3plus) */
return (bytes / full_block_align) * 2048;
}
/* ******************************************** */
/* BITSTREAM */
/* ******************************************** */
/* Read bits (max 32) from buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
* (ex. from 2 bytes 00100111 00000001 we can could read 4b=0111 and 6b=010010, 6b=remainder (second value is split into the 2nd byte) */
static int r_bits_vorbis(vgm_bitstream * ib, int num_bits, uint32_t * value) {
off_t off, pos;
int i, bit_buf, bit_val;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || ib->b_off + num_bits > ib->bufsize*8) goto fail;
*value = 0; /* set all bits to 0 */
off = ib->b_off / 8; /* byte offset */
pos = ib->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_buf = (1U << pos) & 0xFF; /* bit check for buf */
bit_val = (1U << i); /* bit to set in value */
if (ib->buf[off] & bit_buf) /* is bit in buf set? */
*value |= bit_val; /* set bit */
pos++; /* new byte starts */
if (pos%8 == 0) {
pos = 0;
off++;
}
}
ib->b_off += num_bits;
return 1;
fail:
return 0;
}
/* Write bits (max 32) to buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
* (ex. writing 1101011010 from b_off 2 we get 01101011 00001101 (value split, and 11 in the first byte skipped)*/
static int w_bits_vorbis(vgm_bitstream * ob, int num_bits, uint32_t value) {
off_t off, pos;
int i, bit_val, bit_buf;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || ob->b_off + num_bits > ob->bufsize*8) goto fail;
off = ob->b_off / 8; /* byte offset */
pos = ob->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_val = (1U << i); /* bit check for value */
bit_buf = (1U << pos) & 0xFF; /* bit to set in buf */
if (value & bit_val) /* is bit in val set? */
ob->buf[off] |= bit_buf; /* set bit */
else
ob->buf[off] &= ~bit_buf; /* unset bit */
pos++; /* new byte starts */
if (pos%8 == 0) {
pos = 0;
off++;
}
}
ob->b_off += num_bits;
return 1;
fail:
return 0;
}
/* Read bits (max 32) from buf and update the bit offset. Order is BE (MSF). */
static int r_bits_msf(vgm_bitstream * ib, int num_bits, uint32_t * value) {
off_t off, pos;
int i, bit_buf, bit_val;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || ib->b_off + num_bits > ib->bufsize*8) goto fail;
*value = 0; /* set all bits to 0 */
off = ib->b_off / 8; /* byte offset */
pos = ib->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit check for buf */
bit_val = (1U << (num_bits-1-i)); /* bit to set in value */
if (ib->buf[off] & bit_buf) /* is bit in buf set? */
*value |= bit_val; /* set bit */
pos++;
if (pos%8 == 0) { /* new byte starts */
pos = 0;
off++;
}
}
ib->b_off += num_bits;
return 1;
fail:
return 0;
}
/* Write bits (max 32) to buf and update the bit offset. Order is BE (MSF). */
static int w_bits_msf(vgm_bitstream * ob, int num_bits, uint32_t value) {
off_t off, pos;
int i, bit_val, bit_buf;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || ob->b_off + num_bits > ob->bufsize*8) goto fail;
off = ob->b_off / 8; /* byte offset */
pos = ob->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_val = (1U << (num_bits-1-i)); /* bit check for value */
bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit to set in buf */
if (value & bit_val) /* is bit in val set? */
ob->buf[off] |= bit_buf; /* set bit */
else
ob->buf[off] &= ~bit_buf; /* unset bit */
pos++;
if (pos%8 == 0) { /* new byte starts */
pos = 0;
off++;
}
}
ob->b_off += num_bits;
return 1;
fail:
return 0;
}
int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value) {
if (ib->mode == BITSTREAM_VORBIS)
return r_bits_vorbis(ib,num_bits,value);
else
return r_bits_msf(ib,num_bits,value);
}
int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value) {
if (ob->mode == BITSTREAM_VORBIS)
return w_bits_vorbis(ob,num_bits,value);
else
return w_bits_msf(ob,num_bits,value);
}

View File

@ -18,8 +18,7 @@
* Officially defined in "Microsoft Multimedia Standards Update" doc (RIFFNEW.pdf).
*/
static const int32_t ADPCMTable[89] =
{
static const int ADPCMTable[89] = {
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66,
@ -34,8 +33,7 @@ static const int32_t ADPCMTable[89] =
32767
};
static const int IMA_IndexTable[16] =
{
static const int IMA_IndexTable[16] = {
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
@ -45,17 +43,22 @@ static const int IMA_IndexTable[16] =
static void std_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
int sample_nibble, sample_decoded, step, delta;
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
sample_decoded = *hist1;
step = ADPCMTable[*step_index];
/* calculate diff = [signed] (step / 8) + (step / 4) + (step / 2) + (step) [when code = 4+2+1]
* simplified through math, using bitwise ops to avoid rounding:
* diff = (code + 1/2) * (step / 4)
* > diff = (step * nibble / 4) + (step / 8)
* > diff = (((step * nibble) + (step / 2)) / 4) */
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; /* ADPCM code */
sample_decoded = *hist1; /* predictor value */
step = ADPCMTable[*step_index]; /* current step */
delta = step >> 3;
if (sample_nibble & 1) delta += step >> 2;
if (sample_nibble & 2) delta += step >> 1;
if (sample_nibble & 4) delta += step;
if (sample_nibble & 8)
sample_decoded -= delta;
else
sample_decoded += delta;
if (sample_nibble & 8) delta = -delta;
sample_decoded += delta;
*hist1 = clamp16(sample_decoded);
*step_index += IMA_IndexTable[sample_nibble];
@ -63,21 +66,20 @@ static void std_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset,
if (*step_index > 88) *step_index=88;
}
/* Apple's IMA variation. Exactly the same except it uses 16b history (probably more sensitive to overflow/sign extend) */
/* Apple's IMA variation. Exactly the same except it uses 16b history (probably more sensitive to overflow/sign extend?) */
static void std_ima_expand_nibble_16(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int16_t * hist1, int32_t * step_index) {
int sample_nibble, sample_decoded, step, delta;
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
sample_decoded = *hist1;
step = ADPCMTable[*step_index];
delta = step >> 3;
if (sample_nibble & 1) delta += step >> 2;
if (sample_nibble & 2) delta += step >> 1;
if (sample_nibble & 4) delta += step;
if (sample_nibble & 8)
sample_decoded -= delta;
else
sample_decoded += delta;
if (sample_nibble & 8) delta = -delta;
sample_decoded += delta;
*hist1 = clamp16(sample_decoded); //no need for this actually
*step_index += IMA_IndexTable[sample_nibble];
@ -91,14 +93,12 @@ static void n3ds_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset,
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
sample_decoded = *hist1;
step = ADPCMTable[*step_index];
sample_decoded = sample_decoded << 3;
step = ADPCMTable[*step_index];
delta = step * (sample_nibble & 7) * 2 + step;
if (sample_nibble & 8)
sample_decoded -= delta;
else
sample_decoded += delta;
delta = step * (sample_nibble & 7) * 2 + step; /* custom */
if (sample_nibble & 8) delta = -delta;
sample_decoded += delta;
sample_decoded = sample_decoded >> 3;
*hist1 = clamp16(sample_decoded);
@ -107,41 +107,41 @@ static void n3ds_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset,
if (*step_index > 88) *step_index=88;
}
/* update step_index before doing current sample */
/* The Incredibles PC, updates step_index before doing current sample */
static void snds_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
int sample_nibble, sample_decoded, step, delta;
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
sample_decoded = *hist1;
*step_index += IMA_IndexTable[sample_nibble];
if (*step_index < 0) *step_index=0;
if (*step_index > 88) *step_index=88;
step = ADPCMTable[*step_index];
delta = (sample_nibble & 7) * step / 4 + step / 8;
if (sample_nibble & 8)
delta = -delta;
sample_decoded = *hist1 + delta;
delta = (sample_nibble & 7) * step / 4 + step / 8; /* standard IMA */
if (sample_nibble & 8) delta = -delta;
sample_decoded += delta;
*hist1 = clamp16(sample_decoded);
}
/* algorithm by aluigi, unsure if it's a known IMA variation */
/* Omikron: The Nomad Soul, algorithm by aluigi */
static void otns_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
int sample_nibble, sample_decoded, step, delta;
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
sample_decoded = *hist1;
step = ADPCMTable[*step_index];
delta = 0;
if(sample_nibble & 4) delta = step << 2;
if(sample_nibble & 2) delta += step << 1;
if(sample_nibble & 1) delta += step;
delta >>= 2;
if(sample_nibble & 8)
sample_decoded -= delta;
else
sample_decoded += delta;
if (sample_nibble & 8) delta = -delta;
sample_decoded += delta;
*hist1 = clamp16(sample_decoded);
*step_index += IMA_IndexTable[sample_nibble];
@ -149,23 +149,22 @@ static void otns_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset,
if (*step_index > 88) *step_index=88;
}
/* algorithm by Zench (https://bitbucket.org/Zenchreal/decubisnd) */
/* Ubisoft games, algorithm by Zench (https://bitbucket.org/Zenchreal/decubisnd) */
static void ubi_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
int sample_nibble, sample_decoded, step, delta;
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
sample_decoded = *hist1;
step = ADPCMTable[*step_index];
delta = (((sample_nibble & 7) * 2 + 1) * step) >> 3; /* custom */
if (sample_nibble & 8) delta = -delta;
sample_decoded += delta;
*hist1 = clamp16(sample_decoded);
*step_index += IMA_IndexTable[sample_nibble];
if (*step_index < 0) *step_index=0;
if (*step_index > 88) *step_index=88;
delta = (((sample_nibble & 7) * 2 + 1) * step) >> 3;
if (sample_nibble & 8)
delta = -delta;
sample_decoded = *hist1 + delta;
*hist1 = clamp16(sample_decoded);
}
/* ************************************ */

View File

@ -25,14 +25,6 @@
#define EALAYER3_MAX_GRANULES 2
#define EALAYER3_MAX_CHANNELS 2
/* helper to simulate a bitstream */
typedef struct {
uint8_t * buf; /* buffer to read/write*/
size_t bufsize; /* max size of the buffer */
off_t b_off; /* current offset in bits inside the buffer */
off_t info_offset; /* for logs */
} ealayer3_bitstream;
/* parsed info from a single EALayer3 frame */
typedef struct {
/* EALayer3 v1 header */
@ -81,18 +73,14 @@ typedef struct {
} ealayer3_frame_info;
static int ealayer3_parse_frame(mpeg_codec_data *data, ealayer3_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_parse_frame_v1(ealayer3_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b);
static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_parse_frame_common(ealayer3_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_rebuild_mpeg_frame(ealayer3_bitstream* is_0, ealayer3_frame_info* eaf_0, ealayer3_bitstream* is_1, ealayer3_frame_info* eaf_1, ealayer3_bitstream* os);
static int ealayer3_parse_frame(mpeg_codec_data *data, vgm_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_parse_frame_v1(vgm_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b);
static int ealayer3_parse_frame_v2(vgm_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_parse_frame_common(vgm_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_rebuild_mpeg_frame(vgm_bitstream* is_0, ealayer3_frame_info* eaf_0, vgm_bitstream* is_1, ealayer3_frame_info* eaf_1, vgm_bitstream* os);
static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, ealayer3_frame_info * eaf);
static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start);
static int r_bits(ealayer3_bitstream * iw, int num_bits, uint32_t * value);
static int w_bits(ealayer3_bitstream * ow, int num_bits, uint32_t value);
/* **************************************************************************** */
/* EXTERNAL API */
/* **************************************************************************** */
@ -101,7 +89,7 @@ static int w_bits(ealayer3_bitstream * ow, int num_bits, uint32_t value);
int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type) {
int ok;
ealayer3_frame_info eaf;
ealayer3_bitstream is = {0};
vgm_bitstream is = {0};
uint8_t ibuf[EALAYER3_EA_FRAME_BUFFER_SIZE];
//;VGM_LOG("init at %lx\n", start_offset);
@ -135,7 +123,7 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *
off_t info_offset = stream->offset;
ealayer3_frame_info eaf_0, eaf_1;
ealayer3_bitstream is_0 = {0}, is_1 = {0}, os = {0};
vgm_bitstream is_0 = {0}, is_1 = {0}, os = {0};
uint8_t ibuf_0[EALAYER3_EA_FRAME_BUFFER_SIZE], ibuf_1[EALAYER3_EA_FRAME_BUFFER_SIZE];
/* read first frame/granule, or PCM-only frame (found alone at the end of SCHl streams) */
@ -213,7 +201,7 @@ fail:
/* INTERNAL HELPERS */
/* **************************************************************************** */
static int ealayer3_parse_frame(mpeg_codec_data *data, ealayer3_bitstream *is, ealayer3_frame_info * eaf) {
static int ealayer3_parse_frame(mpeg_codec_data *data, vgm_bitstream *is, ealayer3_frame_info * eaf) {
int ok;
/* make sure as there is re-parsing in loops */
@ -235,7 +223,7 @@ fail:
/* read V1"a" (in SCHl) and V1"b" (in SNS) EALayer3 frame */
static int ealayer3_parse_frame_v1(ealayer3_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b) {
static int ealayer3_parse_frame_v1(vgm_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b) {
int ok;
/* read EA-frame V1 header */
@ -282,7 +270,7 @@ fail:
/* read V2"PCM" and V2"Spike" EALayer3 frame (exactly the same but V2P seems to have bigger
* PCM blocks and maybe smaller frames) */
static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info * eaf) {
static int ealayer3_parse_frame_v2(vgm_bitstream *is, ealayer3_frame_info * eaf) {
int ok;
/* read EA-frame V2 header */
@ -328,7 +316,7 @@ fail:
/* parses an EALayer3 frame (common part) */
static int ealayer3_parse_frame_common(ealayer3_bitstream *is, ealayer3_frame_info * eaf) {
static int ealayer3_parse_frame_common(vgm_bitstream *is, ealayer3_frame_info * eaf) {
/* index tables */
static const int versions[4] = { /* MPEG 2.5 */ 3, /* reserved */ -1, /* MPEG 2 */ 2, /* MPEG 1 */ 1 };
static const int sample_rates[4][4] = { /* [version_index][sample rate index] */
@ -412,7 +400,7 @@ fail:
/* converts an EALAYER3 frame to a standard MPEG frame from pre-parsed info */
static int ealayer3_rebuild_mpeg_frame(ealayer3_bitstream* is_0, ealayer3_frame_info* eaf_0, ealayer3_bitstream* is_1, ealayer3_frame_info* eaf_1, ealayer3_bitstream* os) {
static int ealayer3_rebuild_mpeg_frame(vgm_bitstream* is_0, ealayer3_frame_info* eaf_0, vgm_bitstream* is_1, ealayer3_frame_info* eaf_1, vgm_bitstream* os) {
uint32_t c = 0;
int i,j;
int expected_bitrate_index, expected_frame_size;
@ -663,7 +651,7 @@ fail:
static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start) {
int ok, i;
ealayer3_frame_info eaf;
ealayer3_bitstream is = {0};
vgm_bitstream is = {0};
uint8_t ibuf[EALAYER3_EA_FRAME_BUFFER_SIZE];
int skips = at_start ? num_stream : data->streams_size - 1 - num_stream;
@ -685,68 +673,4 @@ fail:
return 0;
}
/* ********************************************* */
/* Read bits (max 32) from buf and update the bit offset. Order is BE (MSF). */
static int r_bits(ealayer3_bitstream * is, int num_bits, uint32_t * value) {
off_t off, pos;
int i, bit_buf, bit_val;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || is->b_off + num_bits > is->bufsize*8) goto fail;
*value = 0; /* set all bits to 0 */
off = is->b_off / 8; /* byte offset */
pos = is->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit check for buf */
bit_val = (1U << (num_bits-1-i)); /* bit to set in value */
if (is->buf[off] & bit_buf) /* is bit in buf set? */
*value |= bit_val; /* set bit */
pos++;
if (pos%8 == 0) { /* new byte starts */
pos = 0;
off++;
}
}
is->b_off += num_bits;
return 1;
fail:
return 0;
}
/* Write bits (max 32) to buf and update the bit offset. Order is BE (MSF). */
static int w_bits(ealayer3_bitstream * os, int num_bits, uint32_t value) {
off_t off, pos;
int i, bit_val, bit_buf;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || os->b_off + num_bits > os->bufsize*8) goto fail;
off = os->b_off / 8; /* byte offset */
pos = os->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_val = (1U << (num_bits-1-i)); /* bit check for value */
bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit to set in buf */
if (value & bit_val) /* is bit in val set? */
os->buf[off] |= bit_buf; /* set bit */
else
os->buf[off] &= ~bit_buf; /* unset bit */
pos++;
if (pos%8 == 0) { /* new byte starts */
pos = 0;
off++;
}
}
os->b_off += num_bits;
return 1;
fail:
return 0;
}
#endif

View File

@ -2,6 +2,7 @@
#define _MPEG_DECODER_H_
#include "../vgmstream.h"
#include "../coding/coding.h"
/* used by mpeg_decoder.c, but scattered in other .c files */
#ifdef VGM_USE_MPEG

View File

@ -37,13 +37,11 @@ void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
}
/* read from memory rather than a file */
void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem) {
static void decode_ngc_dsp_subint_internal(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem) {
int i=first_sample;
int32_t sample_count;
int framesin = first_sample/14;
int8_t header = mem[framesin*8];
int8_t header = mem[0];
int32_t scale = 1 << (header & 0xf);
int coef_index = (header >> 4) & 0xf;
int32_t hist1 = stream->adpcm_history1_16;
@ -54,7 +52,7 @@ void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels
first_sample = first_sample%14;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = mem[framesin*8+1+i/2];
int sample_byte = mem[1 + i/2];
outbuf[sample_count] = clamp16((
(((i&1?
@ -72,6 +70,27 @@ void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channels
stream->adpcm_history2_16 = hist2;
}
/* decode DSP with byte-interleaved frames (ex. 0x08: 1122112211221122) */
void decode_ngc_dsp_subint(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int interleave) {
uint8_t sample_data[0x08];
int i;
int framesin = first_sample/14;
for (i=0; i < 0x08; i++) {
/* base + current frame + subint section + subint byte + channel adjust */
sample_data[i] = read_8bit(
stream->offset
+ framesin*(0x08*channelspacing)
+ i/interleave * interleave * channelspacing
+ i%interleave
+ interleave * channel, stream->streamfile);
}
decode_ngc_dsp_subint_internal(stream, outbuf, channelspacing, first_sample, samples_to_do, sample_data);
}
/*
* The original DSP spec uses nibble counts for loop points, and some
* variants don't have a proper sample count, so we (who are interested

View File

@ -2,6 +2,7 @@
#define _VORBIS_CUSTOM_DECODER_H_
#include "../vgmstream.h"
#include "../coding/coding.h"
/* used by vorbis_custom_decoder.c, but scattered in other .c files */
#ifdef VGM_USE_VORBIS

View File

@ -8,15 +8,6 @@
/* DEFS */
/* **************************************************************************** */
/* An internal struct to pass around and simulate a bitstream. */
typedef struct {
uint8_t * buf; /* buffer to read/write*/
size_t bufsize; /* max size of the buffer */
off_t b_off; /* current offset in bits inside the buffer */
} vgm_bitstream;
static int r_bits(vgm_bitstream * iw, int num_bits, uint32_t * value);
static int get_packet_header(STREAMFILE *streamFile, off_t *offset, size_t *size);
static int build_header_comment(uint8_t * buf, size_t bufsize);
@ -137,6 +128,7 @@ static int get_packet_header(STREAMFILE *streamFile, off_t *offset, size_t *size
ib.buf = ibuf;
ib.bufsize = ibufsize;
ib.b_off = 0;
ib.mode = BITSTREAM_VORBIS;
/* read using Vorbis weird LSF */
r_bits(&ib, 4,&size_bits);
@ -157,35 +149,4 @@ fail:
return 0;
}
/* Read bits (max 32) from buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
* (ex. from 2 bytes 00100111 00000001 we can could read 4b=0111 and 6b=010010, 6b=remainder (second value is split into the 2nd byte) */
static int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value) {
off_t off, pos;
int i, bit_buf, bit_val;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || ib->b_off + num_bits > ib->bufsize*8) goto fail;
*value = 0; /* set all bits to 0 */
off = ib->b_off / 8; /* byte offset */
pos = ib->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_buf = (1U << pos) & 0xFF; /* bit check for buf */
bit_val = (1U << i); /* bit to set in value */
if (ib->buf[off] & bit_buf) /* is bit in buf set? */
*value |= bit_val; /* set bit */
pos++; /* new byte starts */
if (pos%8 == 0) {
pos = 0;
off++;
}
}
ib->b_off += num_bits;
return 1;
fail:
return 0;
}
#endif

View File

@ -13,25 +13,17 @@
/* DEFS */
/* **************************************************************************** */
/* An internal struct to pass around and simulate a bitstream.
* Mainly to keep code cleaner and somewhat closer to ww2ogg */
typedef struct {
uint8_t * buf; /* buffer to read/write*/
size_t bufsize; /* max size of the buffer */
off_t b_off; /* current offset in bits inside the buffer */
} ww_bitstream;
static int build_header_identification(uint8_t * buf, size_t bufsize, int channels, int sample_rate, int blocksize_short, int blocksize_long);
static int build_header_comment(uint8_t * buf, size_t bufsize);
static int get_packet_header(STREAMFILE *streamFile, off_t offset, wwise_header_t header_type, int * granulepos, size_t * packet_size, int big_endian);
static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian);
static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian, int channels);
static int ww2ogg_generate_vorbis_packet(ww_bitstream * ow, ww_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian);
static int ww2ogg_generate_vorbis_setup(ww_bitstream * ow, ww_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile);
static int ww2ogg_codebook_library_copy(ww_bitstream * ow, ww_bitstream * iw);
static int ww2ogg_codebook_library_rebuild(ww_bitstream * ow, ww_bitstream * iw, size_t cb_size, STREAMFILE *streamFile);
static int ww2ogg_codebook_library_rebuild_by_id(ww_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile);
static int ww2ogg_generate_vorbis_packet(vgm_bitstream * ow, vgm_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian);
static int ww2ogg_generate_vorbis_setup(vgm_bitstream * ow, vgm_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile);
static int ww2ogg_codebook_library_copy(vgm_bitstream * ow, vgm_bitstream * iw);
static int ww2ogg_codebook_library_rebuild(vgm_bitstream * ow, vgm_bitstream * iw, size_t cb_size, STREAMFILE *streamFile);
static int ww2ogg_codebook_library_rebuild_by_id(vgm_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile);
static int ww2ogg_tremor_ilog(unsigned int v);
static unsigned int ww2ogg_tremor_book_maptype1_quantvals(unsigned int entries, unsigned int dimensions);
@ -39,9 +31,6 @@ static int load_wvc(uint8_t * ibuf, size_t ibufsize, uint32_t codebook_id, wwise
static int load_wvc_file(uint8_t * buf, size_t bufsize, uint32_t codebook_id, STREAMFILE *streamFile);
static int load_wvc_array(uint8_t * buf, size_t bufsize, uint32_t codebook_id, wwise_setup_t setup_type);
static int r_bits(ww_bitstream * iw, int num_bits, uint32_t * value);
static int w_bits(ww_bitstream * ow, int num_bits, uint32_t value);
/* **************************************************************************** */
/* EXTERNAL API */
@ -165,7 +154,7 @@ static int get_packet_header(STREAMFILE *streamFile, off_t offset, wwise_header_
/* Transforms a Wwise data packet into a real Vorbis one (depending on config) */
static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) {
ww_bitstream ow, iw;
vgm_bitstream ow, iw;
int rc, granulepos;
size_t header_size, packet_size;
@ -183,11 +172,13 @@ static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFil
/* prepare helper structs */
ow.buf = obuf;
ow.bufsize = obufsize;
ow.b_off = 0 ;
ow.b_off = 0;
ow.mode = BITSTREAM_VORBIS;
iw.buf = ibuf;
iw.bufsize = ibufsize;
iw.b_off = 0;
iw.mode = BITSTREAM_VORBIS;
rc = ww2ogg_generate_vorbis_packet(&ow,&iw, streamFile,offset, data, big_endian);
if (!rc) goto fail;
@ -206,7 +197,7 @@ fail:
/* Transforms a Wwise setup packet into a real Vorbis one (depending on config). */
static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian, int channels) {
ww_bitstream ow, iw;
vgm_bitstream ow, iw;
int rc, granulepos;
size_t header_size, packet_size;
@ -226,10 +217,12 @@ static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile
ow.buf = obuf;
ow.bufsize = obufsize;
ow.b_off = 0;
ow.mode = BITSTREAM_VORBIS;
iw.buf = ibuf;
iw.bufsize = ibufsize;
iw.b_off = 0;
iw.mode = BITSTREAM_VORBIS;
rc = ww2ogg_generate_vorbis_setup(&ow,&iw, data, channels, packet_size, streamFile);
if (!rc) goto fail;
@ -295,7 +288,7 @@ static int build_header_comment(uint8_t * buf, size_t bufsize) {
/* Copy packet as-is or rebuild first byte if mod_packets is used.
* (ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-720004.3) */
static int ww2ogg_generate_vorbis_packet(ww_bitstream * ow, ww_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) {
static int ww2ogg_generate_vorbis_packet(vgm_bitstream * ow, vgm_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) {
int i,granule;
size_t header_size, packet_size, data_size;
@ -350,10 +343,13 @@ static int ww2ogg_generate_vorbis_packet(ww_bitstream * ow, ww_bitstream * iw, S
/* get next first byte to read next_mode_number */
uint32_t next_mode_number;
uint8_t nbuf[1];
ww_bitstream nw;
vgm_bitstream nw;
nw.buf = nbuf;
nw.bufsize = 1;
nw.b_off = 0;
nw.mode = BITSTREAM_VORBIS;
if (read_streamfile(nw.buf, next_offset + next_header_size, nw.bufsize, streamFile) != nw.bufsize)
goto fail;
@ -409,7 +405,7 @@ fail:
/* Rebuild a Wwise setup (simplified with removed stuff), recreating all six setup parts.
* (ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-650004.2.4) */
static int ww2ogg_generate_vorbis_setup(ww_bitstream * ow, ww_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile) {
static int ww2ogg_generate_vorbis_setup(vgm_bitstream * ow, vgm_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile) {
int i,j,k;
uint32_t codebook_count = 0, floor_count = 0, residue_count = 0;
uint32_t codebook_count_less1 = 0;
@ -798,7 +794,7 @@ fail:
/* copies Vorbis codebooks (untouched, but size uncertain) */
static int ww2ogg_codebook_library_copy(ww_bitstream * ow, ww_bitstream * iw) {
static int ww2ogg_codebook_library_copy(vgm_bitstream * ow, vgm_bitstream * iw) {
int i;
uint32_t id = 0, dimensions = 0, entries = 0;
uint32_t ordered = 0, lookup_type = 0;
@ -914,7 +910,7 @@ fail:
/* rebuilds a Wwise codebook into a Vorbis codebook */
static int ww2ogg_codebook_library_rebuild(ww_bitstream * ow, ww_bitstream * iw, size_t cb_size, STREAMFILE *streamFile) {
static int ww2ogg_codebook_library_rebuild(vgm_bitstream * ow, vgm_bitstream * iw, size_t cb_size, STREAMFILE *streamFile) {
int i;
uint32_t id = 0, dimensions = 0, entries = 0;
uint32_t ordered = 0, lookup_type = 0;
@ -1038,11 +1034,11 @@ fail:
}
/* rebuilds an external Wwise codebook referenced by id to a Vorbis codebook */
static int ww2ogg_codebook_library_rebuild_by_id(ww_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile) {
static int ww2ogg_codebook_library_rebuild_by_id(vgm_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile) {
size_t ibufsize = 0x8000; /* arbitrary max size of a codebook */
uint8_t ibuf[0x8000]; /* Wwise codebook buffer */
size_t cb_size;
ww_bitstream iw;
vgm_bitstream iw;
cb_size = load_wvc(ibuf,ibufsize, codebook_id, setup_type, streamFile);
if (cb_size == 0) goto fail;
@ -1050,6 +1046,7 @@ static int ww2ogg_codebook_library_rebuild_by_id(ww_bitstream * ow, uint32_t cod
iw.buf = ibuf;
iw.bufsize = ibufsize;
iw.b_off = 0;
iw.mode = BITSTREAM_VORBIS;
return ww2ogg_codebook_library_rebuild(ow, &iw, cb_size, streamFile);
fail:
@ -1228,70 +1225,4 @@ fail:
return 0;
}
/* ********************************************* */
/* Read bits (max 32) from buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
* (ex. from 2 bytes 00100111 00000001 we can could read 4b=0111 and 6b=010010, 6b=remainder (second value is split into the 2nd byte) */
static int r_bits(ww_bitstream * iw, int num_bits, uint32_t * value) {
off_t off, pos;
int i, bit_buf, bit_val;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || iw->b_off + num_bits > iw->bufsize*8) goto fail;
*value = 0; /* set all bits to 0 */
off = iw->b_off / 8; /* byte offset */
pos = iw->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_buf = (1U << pos) & 0xFF; /* bit check for buf */
bit_val = (1U << i); /* bit to set in value */
if (iw->buf[off] & bit_buf) /* is bit in buf set? */
*value |= bit_val; /* set bit */
pos++; /* new byte starts */
if (pos%8 == 0) {
pos = 0;
off++;
}
}
iw->b_off += num_bits;
return 1;
fail:
return 0;
}
/* Write bits (max 32) to buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
* (ex. writing 1101011010 from b_off 2 we get 01101011 00001101 (value split, and 11 in the first byte skipped)*/
static int w_bits(ww_bitstream * ow, int num_bits, uint32_t value) {
off_t off, pos;
int i, bit_val, bit_buf;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || ow->b_off + num_bits > ow->bufsize*8) goto fail;
off = ow->b_off / 8; /* byte offset */
pos = ow->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_val = (1U << i); /* bit check for value */
bit_buf = (1U << pos) & 0xFF; /* bit to set in buf */
if (value & bit_val) /* is bit in val set? */
ow->buf[off] |= bit_buf; /* set bit */
else
ow->buf[off] &= ~bit_buf; /* unset bit */
pos++; /* new byte starts */
if (pos%8 == 0) {
pos = 0;
off++;
}
}
ow->b_off += num_bits;
return 1;
fail:
return 0;
}
#endif

View File

@ -52,6 +52,7 @@ static const char* extension_list[] = {
"bar",
"bcstm",
"bcwav",
"bd3", //txth/reserved [Elevator Action Deluxe (PS3)]
"bdsp",
"bfstm",
"bfwav",
@ -233,7 +234,8 @@ static const char* extension_list[] = {
"rrds",
"rsd",
"rsf",
"rstm",
"rsm",
"rstm", //rsm header id
"rvws",
"rwar",
"rwav",
@ -258,6 +260,7 @@ static const char* extension_list[] = {
"scd",
"sck",
"sd9",
"sdf",
"sdt",
"seg",
"sf0",
@ -382,6 +385,7 @@ static const char* extension_list[] = {
//, NULL //end mark
};
/* List supported formats and return elements in the list, for plugins that need to know. */
const char ** vgmstream_get_formats(size_t * size) {
*size = sizeof(extension_list) / sizeof(char*);
return extension_list;
@ -427,6 +431,7 @@ static const coding_info coding_info_list[] = {
{coding_CRI_ADX_enc_9, "CRI ADX 4-bit ADPCM (type 9 encryption)"},
{coding_NGC_DSP, "Nintendo DSP 4-bit ADPCM"},
{coding_NGC_DSP_subint, "Nintendo DSP 4-bit ADPCM (subinterleave)"},
{coding_NGC_DTK, "Nintendo DTK 4-bit ADPCM"},
{coding_NGC_AFC, "Nintendo AFC 4-bit ADPCM"},
@ -523,7 +528,6 @@ static const layout_info layout_info_list[] = {
{layout_none, "flat (no layout)"},
{layout_interleave, "interleave"},
{layout_interleave_shortblock, "interleave with short last block"},
{layout_interleave_byte, "sub-frame interleave"},
{layout_mxch_blocked, "MxCh blocked"},
{layout_ast_blocked, "AST blocked"},
{layout_halpst_blocked, "HALPST blocked"},
@ -560,6 +564,7 @@ static const layout_info layout_info_list[] = {
{layout_blocked_ea_sns, "blocked (EA SNS)"},
{layout_blocked_awc, "blocked (AWC)"},
{layout_blocked_vgs, "blocked (VGS)"},
{layout_blocked_vawx, "blocked (VAWX)"},
#ifdef VGM_USE_VORBIS
{layout_ogg_vorbis, "Ogg"},
#endif

View File

@ -161,6 +161,9 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
case layout_blocked_vgs:
block_update_vgs(vgmstream->next_block_offset,vgmstream);
break;
case layout_blocked_vawx:
block_update_vawx(vgmstream->next_block_offset,vgmstream);
break;
default:
break;
}

25
src/layout/blocked_vawx.c Normal file
View File

@ -0,0 +1,25 @@
#include "layout.h"
#include "../vgmstream.h"
/* pseudo-blocks that must skip last 0x20 every 0x8000 */
void block_update_vawx(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
size_t block_size;
/* no header */
block_size = vgmstream->channels * 0x10;
vgmstream->current_block_offset = block_offset;
vgmstream->next_block_offset = block_offset + block_size;
vgmstream->current_block_size = block_size / vgmstream->channels;
if ((vgmstream->next_block_offset - 0x800) > 0
&& ((vgmstream->next_block_offset - 0x800 + 0x20) % 0x8000) == 0) {
vgmstream->next_block_offset += 0x20;
}
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = block_offset + 0x10*i;
}
}

View File

@ -1,62 +0,0 @@
#include "layout.h"
#include "../vgmstream.h"
/* for formats where the interleave is smaller than a frame, so we need to
* deinterleave in memory before passing it along to a specialized decoder which
* reads from memory
*/
/* just do one frame at a time */
void render_vgmstream_interleave_byte(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
/* frame sizes are much smaller than this */
uint8_t sample_data[0x400];
int samples_written=0;
int frame_size = get_vgmstream_frame_size(vgmstream);
int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
int samples_this_block;
samples_this_block = samples_per_frame;
while (samples_written<sample_count) {
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
continue;
}
samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_written+samples_to_do > sample_count)
samples_to_do=sample_count-samples_written;
{
int i,j;
for (j=0;j<vgmstream->channels;j++) {
for (i=0;i<frame_size;i++) {
sample_data[i] = read_8bit(vgmstream->ch[j].offset+
i/vgmstream->interleave_block_size*
vgmstream->interleave_block_size*
vgmstream->channels+
i%vgmstream->interleave_block_size,
vgmstream->ch[j].streamfile);
}
decode_vgmstream_mem(vgmstream, samples_written,
samples_to_do, buffer, sample_data, j);
}
}
samples_written += samples_to_do;
vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block+=samples_to_do;
if (vgmstream->samples_into_block==samples_this_block) {
int chan;
for (chan=0;chan<vgmstream->channels;chan++)
vgmstream->ch[chan].offset+=frame_size*vgmstream->channels;
vgmstream->samples_into_block=0;
}
}
}

View File

@ -5,18 +5,17 @@
#include "../vgmstream.h"
/* blocked layouts */
void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void ast_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
void mxch_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void halpst_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ea_1snh(off_t block_offset, VGMSTREAM * vgmstream);
void caf_block_update(off_t block_offset, VGMSTREAM * vgmstream);
@ -66,14 +65,13 @@ void hwas_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ea_sns(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_awc(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_vgs(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_vawx(off_t block_offset, VGMSTREAM * vgmstream);
/* other layouts */
void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_nolayout(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_interleave_byte(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_mus_acm(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_aix(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);

View File

@ -12,8 +12,8 @@ void thp_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
nextFrameSize=read_32bitBE(vgmstream->current_block_offset,streamFile);
vgmstream->next_block_offset = vgmstream->current_block_offset
+ vgmstream->thpNextFrameSize;
vgmstream->thpNextFrameSize=nextFrameSize;
+ vgmstream->full_block_size;
vgmstream->full_block_size = nextFrameSize;
start_offset=vgmstream->current_block_offset
+ read_32bitBE(vgmstream->current_block_offset+0x08,streamFile)+0x10;

View File

@ -203,6 +203,22 @@
<File
RelativePath=".\meta\hca_keys.h"
>
</File>
<File
RelativePath=".\meta\aax_streamfile.h"
>
</File>
<File
RelativePath=".\meta\aix_streamfile.h"
>
</File>
<File
RelativePath=".\meta\bar_streamfile.h"
>
</File>
<File
RelativePath=".\meta\sqex_scd_streamfile.h"
>
</File>
</Filter>
<Filter
@ -229,7 +245,7 @@
>
</File>
<File
RelativePath=".\meta\afc_header.c"
RelativePath=".\meta\afc.c"
>
</File>
<File
@ -413,7 +429,7 @@
>
</File>
<File
RelativePath=".\meta\gh3_bar.c"
RelativePath=".\meta\bar.c"
>
</File>
<File
@ -661,6 +677,10 @@
<File
RelativePath=".\meta\ogl.c"
>
</File>
<File
RelativePath=".\meta\omu.c"
>
</File>
<File
RelativePath=".\meta\otm.c"
@ -1002,6 +1022,10 @@
RelativePath=".\meta\ps2_xa2.c"
>
</File>
<File
RelativePath=".\meta\ps2_xa2_rrp.c"
>
</File>
<File
RelativePath=".\meta\ps2_xa30.c"
>
@ -1206,6 +1230,10 @@
RelativePath=".\meta\vsf.c"
>
</File>
<File
RelativePath=".\meta\vsf_tta.c"
>
</File>
<File
RelativePath=".\meta\vxn.c"
>
@ -1622,6 +1650,10 @@
RelativePath=".\layout\blocked_ea_1snh.c"
>
</File>
<File
RelativePath=".\layout\blocked_vawx.c"
>
</File>
<File
RelativePath=".\layout\blocked_vgs.c"
>
@ -1666,10 +1698,6 @@
RelativePath=".\layout\interleave.c"
>
</File>
<File
RelativePath=".\layout\interleave_byte.c"
>
</File>
<File
RelativePath=".\layout\blocked_ivaud.c"
>

View File

@ -118,6 +118,10 @@
<ClInclude Include="util.h" />
<ClInclude Include="vgmstream.h" />
<ClInclude Include="meta\adx_keys.h" />
<ClInclude Include="meta\aax_streamfile.h" />
<ClInclude Include="meta\aix_streamfile.h" />
<ClInclude Include="meta\bar_streamfile.h" />
<ClInclude Include="meta\sqex_scd_streamfile.h" />
<ClInclude Include="meta\meta.h" />
<ClInclude Include="meta\hca_keys.h" />
<ClInclude Include="coding\acm_decoder.h" />
@ -197,7 +201,7 @@
<ClCompile Include="meta\acm.c" />
<ClCompile Include="meta\ads.c" />
<ClCompile Include="meta\adx.c" />
<ClCompile Include="meta\afc_header.c" />
<ClCompile Include="meta\afc.c" />
<ClCompile Include="meta\agsc.c" />
<ClCompile Include="meta\ahx.c" />
<ClCompile Include="meta\aifc.c" />
@ -235,7 +239,7 @@
<ClCompile Include="meta\gca.c" />
<ClCompile Include="meta\gcsw.c" />
<ClCompile Include="meta\genh.c" />
<ClCompile Include="meta\gh3_bar.c" />
<ClCompile Include="meta\bar.c" />
<ClCompile Include="meta\gsp_gsb.c" />
<ClCompile Include="meta\gtd.c" />
<ClCompile Include="meta\halpst.c" />
@ -293,6 +297,7 @@
<ClCompile Include="meta\nwa.c" />
<ClCompile Include="meta\ogg_vorbis_file.c" />
<ClCompile Include="meta\ogl.c" />
<ClCompile Include="meta\omu.c" />
<ClCompile Include="meta\otm.c" />
<ClCompile Include="meta\p3d.c" />
<ClCompile Include="meta\pc_al2.c" />
@ -366,6 +371,7 @@
<ClCompile Include="meta\ps2_wad.c" />
<ClCompile Include="meta\ps2_wb.c" />
<ClCompile Include="meta\ps2_xa2.c" />
<ClCompile Include="meta\ps2_xa2_rrp.c" />
<ClCompile Include="meta\ps2_xa30.c" />
<ClCompile Include="meta\ps3_cps.c" />
<ClCompile Include="meta\ps3_msf.c" />
@ -407,6 +413,7 @@
<ClCompile Include="meta\ubi_sb.c" />
<ClCompile Include="meta\vs.c" />
<ClCompile Include="meta\vsf.c" />
<ClCompile Include="meta\vsf_tta.c" />
<ClCompile Include="meta\vxn.c" />
<ClCompile Include="meta\waa_wac_wad_wam.c" />
<ClCompile Include="meta\wii_04sw.c" />
@ -480,6 +487,7 @@
<ClCompile Include="layout\blocked_awc.c" />
<ClCompile Include="layout\blocked_ea_1snh.c" />
<ClCompile Include="layout\blocked_vgs.c" />
<ClCompile Include="layout\blocked_vawx.c" />
<ClCompile Include="layout\caf_blocked.c" />
<ClCompile Include="layout\blocked_dec.c" />
<ClCompile Include="layout\blocked_ea_schl.c" />
@ -490,7 +498,6 @@
<ClCompile Include="layout\halpst_blocked.c" />
<ClCompile Include="layout\ims_block.c" />
<ClCompile Include="layout\interleave.c" />
<ClCompile Include="layout\interleave_byte.c" />
<ClCompile Include="layout\blocked_ivaud.c" />
<ClCompile Include="layout\mus_acm_layout.c" />
<ClCompile Include="layout\mxch_blocked.c" />

View File

@ -62,6 +62,18 @@
<ClInclude Include="meta\adx_keys.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
<ClInclude Include="meta\aax_streamfile.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
<ClInclude Include="meta\aix_streamfile.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
<ClInclude Include="meta\bar_streamfile.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
<ClInclude Include="meta\sqex_scd_streamfile.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
<ClInclude Include="meta\meta.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
@ -133,7 +145,7 @@
<ClCompile Include="meta\adx.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\afc_header.c">
<ClCompile Include="meta\afc.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\agsc.c">
@ -241,7 +253,7 @@
<ClCompile Include="meta\genh.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\gh3_bar.c">
<ClCompile Include="meta\bar.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\gsp_gsb.c">
@ -394,6 +406,9 @@
<ClCompile Include="meta\ogl.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\omu.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\otm.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
@ -613,6 +628,9 @@
<ClCompile Include="meta\ps2_xa2.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ps2_xa2_rrp.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ps2_xa30.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
@ -736,6 +754,9 @@
<ClCompile Include="meta\vsf.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\vsf_tta.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\vxn.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
@ -949,6 +970,9 @@
<ClCompile Include="layout\blocked_vgs.c">
<Filter>layout\Source Files</Filter>
</ClCompile>
<ClCompile Include="layout\blocked_vawx.c">
<Filter>layout\Source Files</Filter>
</ClCompile>
<ClCompile Include="layout\caf_blocked.c">
<Filter>layout\Source Files</Filter>
</ClCompile>
@ -982,9 +1006,6 @@
<ClCompile Include="layout\interleave.c">
<Filter>layout\Source Files</Filter>
</ClCompile>
<ClCompile Include="layout\interleave_byte.c">
<Filter>layout\Source Files</Filter>
</ClCompile>
<ClCompile Include="layout\blocked_ivaud.c">
<Filter>layout\Source Files</Filter>
</ClCompile>

View File

@ -1,16 +1,5 @@
#include "../vgmstream.h"
#include "meta.h"
#include "../util.h"
typedef struct _AAXSTREAMFILE
{
STREAMFILE sf;
STREAMFILE *real_file;
off_t start_physical_offset;
size_t file_size;
} AAXSTREAMFILE;
static STREAMFILE *open_aax_with_STREAMFILE(STREAMFILE *file,off_t start_offset,size_t file_size);
#include "aax_streamfile.h"
struct utf_query
{
@ -107,10 +96,9 @@ struct utf_table_info
};
/* Actual AAX init fcn */
/* AAX - segmented ADX [Padora's Tower (Wii)] */
VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamFileAAX = NULL;
STREAMFILE * streamFileADX = NULL;
char filename[PATH_LIMIT];
@ -131,7 +119,7 @@ VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) {
int channel_count = 0, segment_count;
int sample_rate = 0;
int i;
int i;
long aax_data_offset;
@ -297,91 +285,6 @@ fail:
return NULL;
}
/* virtual file, a piece of the overall file */
static size_t read_aax(AAXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length)
{
/* truncate at end of logical file */
if (offset+length > streamfile->file_size)
{
long signed_length = length;
signed_length = streamfile->file_size - offset;
if (signed_length < 0) signed_length = 0;
length = signed_length;
}
return read_streamfile(dest,
streamfile->start_physical_offset+offset,
length,streamfile->real_file);
}
static void close_aax(AAXSTREAMFILE *streamfile)
{
free(streamfile);
return;
}
static size_t get_size_aax(AAXSTREAMFILE *streamfile)
{
return 0;
}
static size_t get_offset_aax(AAXSTREAMFILE *streamfile)
{
long offset = streamfile->real_file->get_offset(streamfile->real_file);
offset -= streamfile->start_physical_offset;
if (offset < 0) offset = 0;
if (offset > streamfile->file_size) offset = streamfile->file_size;
return offset;
}
static void get_name_aax(AAXSTREAMFILE *streamfile,char *buffer,size_t length)
{
strncpy(buffer,"ARBITRARY.ADX",length);
buffer[length-1]='\0';
}
static STREAMFILE *open_aax_impl(AAXSTREAMFILE *streamfile,const char * const filename,size_t buffersize)
{
AAXSTREAMFILE *newfile;
if (strcmp(filename,"ARBITRARY.ADX"))
return NULL;
newfile = malloc(sizeof(AAXSTREAMFILE));
if (!newfile)
return NULL;
memcpy(newfile,streamfile,sizeof(AAXSTREAMFILE));
return &newfile->sf;
}
static STREAMFILE *open_aax_with_STREAMFILE(STREAMFILE *file,off_t start_offset,size_t file_size)
{
AAXSTREAMFILE *streamfile = malloc(sizeof(AAXSTREAMFILE));
if (!streamfile)
return NULL;
/* success, set our pointers */
streamfile->sf.read = (void*)read_aax;
streamfile->sf.get_size = (void*)get_size_aax;
streamfile->sf.get_offset = (void*)get_offset_aax;
streamfile->sf.get_name = (void*)get_name_aax;
streamfile->sf.get_realname = (void*)get_name_aax;
streamfile->sf.open = (void*)open_aax_impl;
streamfile->sf.close = (void*)close_aax;
#ifdef PROFILE_STREAMFILE
streamfile->sf.get_bytes_read = NULL;
streamfile->sf.get_error_count = NULL;
#endif
streamfile->real_file = file;
streamfile->start_physical_offset = start_offset;
streamfile->file_size = file_size;
return &streamfile->sf;
}
/* @UTF table reading, abridged */
static struct utf_query_result analyze_utf(STREAMFILE *infile, const long offset, const struct utf_query *query)
{
@ -744,8 +647,7 @@ static struct offset_size_pair query_utf_data(STREAMFILE *infile, const long off
/* CRI's UTF wrapper around DSP */
VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int table_error = 0;
@ -843,4 +745,3 @@ fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

87
src/meta/aax_streamfile.h Normal file
View File

@ -0,0 +1,87 @@
#ifndef _AAX_STREAMFILE_H_
#define _AAX_STREAMFILE_H_
#include "../streamfile.h"
/* a streamfile representing a subfile inside another */
typedef struct _AAXSTREAMFILE {
STREAMFILE sf;
STREAMFILE *real_file;
off_t start_physical_offset;
size_t file_size;
} AAXSTREAMFILE;
static size_t read_aax(AAXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length) {
/* truncate at end of logical file */
if (offset+length > streamfile->file_size) {
long signed_length = length;
signed_length = streamfile->file_size - offset;
if (signed_length < 0) signed_length = 0;
length = signed_length;
}
return read_streamfile(dest, streamfile->start_physical_offset+offset, length,streamfile->real_file);
}
static void close_aax(AAXSTREAMFILE *streamfile) {
free(streamfile);
return;
}
static size_t get_size_aax(AAXSTREAMFILE *streamfile) {
return 0;
}
static size_t get_offset_aax(AAXSTREAMFILE *streamfile) {
long offset = streamfile->real_file->get_offset(streamfile->real_file);
offset -= streamfile->start_physical_offset;
if (offset < 0) offset = 0;
if (offset > streamfile->file_size) offset = streamfile->file_size;
return offset;
}
static void get_name_aax(AAXSTREAMFILE *streamfile,char *buffer,size_t length) {
strncpy(buffer,"ARBITRARY.ADX",length);
buffer[length-1]='\0';
}
static STREAMFILE *open_aax_impl(AAXSTREAMFILE *streamfile,const char * const filename,size_t buffersize) {
AAXSTREAMFILE *newfile;
if (strcmp(filename,"ARBITRARY.ADX"))
return NULL;
newfile = malloc(sizeof(AAXSTREAMFILE));
if (!newfile)
return NULL;
memcpy(newfile,streamfile,sizeof(AAXSTREAMFILE));
return &newfile->sf;
}
static STREAMFILE *open_aax_with_STREAMFILE(STREAMFILE *file,off_t start_offset,size_t file_size) {
AAXSTREAMFILE *streamfile = malloc(sizeof(AAXSTREAMFILE));
if (!streamfile)
return NULL;
/* success, set our pointers */
streamfile->sf.read = (void*)read_aax;
streamfile->sf.get_size = (void*)get_size_aax;
streamfile->sf.get_offset = (void*)get_offset_aax;
streamfile->sf.get_name = (void*)get_name_aax;
streamfile->sf.get_realname = (void*)get_name_aax;
streamfile->sf.open = (void*)open_aax_impl;
streamfile->sf.close = (void*)close_aax;
#ifdef PROFILE_STREAMFILE
streamfile->sf.get_bytes_read = NULL;
streamfile->sf.get_error_count = NULL;
#endif
streamfile->real_file = file;
streamfile->start_physical_offset = start_offset;
streamfile->file_size = file_size;
return &streamfile->sf;
}
#endif /* _AAX_STREAMFILE_H_ */

View File

@ -47,17 +47,17 @@ static const adxkey_info adxkey8_list[] = {
/* unknown source */
{0x586d,0x5d65,0x63eb, NULL,0}, // from guessadx (unique?)
/* Navel (Shuffle! On the Stage) */
{0x4969,0x5deb,0x467f, NULL,0}, // 2nd key from guessadx
/* Navel (Shuffle! On the Stage (PS2)) */
{0x4969,0x5deb,0x467f, "SHUF",0},
/* Success (Aoishiro) */
{0x4d65,0x5eb7,0x5dfd, NULL,0}, // 1st key from guessadx
/* Success (Aoishiro (PS2)) */
{0x4d65,0x5eb7,0x5dfd, "wakasugi",0},
/* Sonic Team 2 (Sonic and the Black Knight) */
{0x55b7,0x6191,0x5a77, "morio",0},
/* Enterbrain (Amagami) */
{0x5a17,0x509f,0x5bfd, "mituba",0},
{0x5a17,0x509f,0x5bfd, "mituba",0}, /* also AHX key */
/* Yamasa (Yamasa Digi Portable: Matsuri no Tatsujin) */
{0x4c01,0x549d,0x676f, NULL,0}, // confirmed unique with guessadx
@ -171,7 +171,7 @@ static const adxkey_info adxkey8_list[] = {
/* Suzumiya Haruhi-chan no Mahjong (2011-07-07)(-)(Kadokawa Shoten)[PSP] */
{0x5c33,0x4133,0x4ce7, NULL,0}, // ?
/* Storm Lover Natsu Koi!! (2011-08-04)(Vridge)(D3 Publisher) */
/* Storm Lover Natsu Koi!! (2011-08-04)(Vridge)(D3 Publisher)[PSP] */
{0x4133,0x5a01,0x5723, NULL,0}, // ?
};

View File

@ -1,20 +1,7 @@
#include "../vgmstream.h"
#include "meta.h"
#include "../util.h"
typedef struct _AIXSTREAMFILE
{
STREAMFILE sf;
STREAMFILE *real_file;
off_t start_physical_offset;
off_t current_physical_offset;
off_t current_logical_offset;
off_t current_block_size;
int stream_id;
} AIXSTREAMFILE;
static STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file,off_t start_offset,int stream_id);
#include "aix_streamfile.h"
/* AIX - interleaved AAX, N segments per channels [SoulCalibur IV (PS3)] */
VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
@ -228,190 +215,3 @@ fail:
}
return NULL;
}
static size_t read_aix(AIXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length)
{
size_t sz = 0;
/*printf("trying to read %x bytes from %x (str%d)\n",length,offset,streamfile->stream_id);*/
while (length > 0)
{
int read_something = 0;
/* read the beginning of the requested block, if we can */
if (offset >= streamfile->current_logical_offset)
{
off_t to_read;
off_t length_available;
length_available =
(streamfile->current_logical_offset+
streamfile->current_block_size) -
offset;
if (length < length_available)
{
to_read = length;
}
else
{
to_read = length_available;
}
if (to_read > 0)
{
size_t bytes_read;
bytes_read = read_streamfile(dest,
streamfile->current_physical_offset+0x10+
(offset-streamfile->current_logical_offset),
to_read,streamfile->real_file);
sz += bytes_read;
if (bytes_read != to_read)
{
/* an error which we will not attempt to handle here */
return sz;
}
read_something = 1;
dest += bytes_read;
offset += bytes_read;
length -= bytes_read;
}
}
if (!read_something)
{
/* couldn't read anything, must seek */
int found_block = 0;
/* as we have no memory we must start seeking from the beginning */
if (offset < streamfile->current_logical_offset)
{
streamfile->current_logical_offset = 0;
streamfile->current_block_size = 0;
streamfile->current_physical_offset =
streamfile->start_physical_offset;
}
/* seek ye forwards */
while (!found_block) {
/*printf("seek looks at %x\n",streamfile->current_physical_offset);*/
switch (read_32bitBE(streamfile->current_physical_offset,
streamfile->real_file))
{
case 0x41495850: /* AIXP */
if (read_8bit(
streamfile->current_physical_offset+8,
streamfile->real_file) ==
streamfile->stream_id)
{
streamfile->current_block_size =
(uint16_t)read_16bitBE(
streamfile->current_physical_offset+0x0a,
streamfile->real_file);
if (offset >= streamfile->current_logical_offset+
streamfile->current_block_size)
{
streamfile->current_logical_offset +=
streamfile->current_block_size;
}
else
{
found_block = 1;
}
}
if (!found_block)
{
streamfile->current_physical_offset +=
read_32bitBE(
streamfile->current_physical_offset+0x04,
streamfile->real_file
) + 8;
}
break;
case 0x41495846: /* AIXF */
/* shouldn't ever see this */
case 0x41495845: /* AIXE */
/* shouldn't have reached the end o' the line... */
default:
return sz;
break;
} /* end block/chunk type select */
} /* end while !found_block */
} /* end if !read_something */
} /* end while length > 0 */
return sz;
}
static void close_aix(AIXSTREAMFILE *streamfile)
{
free(streamfile);
return;
}
static size_t get_size_aix(AIXSTREAMFILE *streamfile)
{
return 0;
}
static size_t get_offset_aix(AIXSTREAMFILE *streamfile)
{
return streamfile->current_logical_offset;
}
static void get_name_aix(AIXSTREAMFILE *streamfile,char *buffer,size_t length)
{
strncpy(buffer,"ARBITRARY.ADX",length);
buffer[length-1]='\0';
}
static STREAMFILE *open_aix_impl(AIXSTREAMFILE *streamfile,const char * const filename,size_t buffersize)
{
AIXSTREAMFILE *newfile;
if (strcmp(filename,"ARBITRARY.ADX"))
return NULL;
newfile = malloc(sizeof(AIXSTREAMFILE));
if (!newfile)
return NULL;
memcpy(newfile,streamfile,sizeof(AIXSTREAMFILE));
return &newfile->sf;
}
static STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file,off_t start_offset,int stream_id)
{
AIXSTREAMFILE *streamfile = malloc(sizeof(AIXSTREAMFILE));
if (!streamfile)
return NULL;
/* success, set our pointers */
streamfile->sf.read = (void*)read_aix;
streamfile->sf.get_size = (void*)get_size_aix;
streamfile->sf.get_offset = (void*)get_offset_aix;
streamfile->sf.get_name = (void*)get_name_aix;
streamfile->sf.get_realname = (void*)get_name_aix;
streamfile->sf.open = (void*)open_aix_impl;
streamfile->sf.close = (void*)close_aix;
#ifdef PROFILE_STREAMFILE
streamfile->sf.get_bytes_read = NULL;
streamfile->sf.get_error_count = NULL;
#endif
streamfile->real_file = file;
streamfile->current_physical_offset =
streamfile->start_physical_offset = start_offset;
streamfile->current_logical_offset = 0;
streamfile->current_block_size = 0;
streamfile->stream_id = stream_id;
return &streamfile->sf;
}

169
src/meta/aix_streamfile.h Normal file
View File

@ -0,0 +1,169 @@
#ifndef _AIX_STREAMFILE_H_
#define _AIX_STREAMFILE_H_
#include "../streamfile.h"
/* a streamfile representing a subfile inside another, in blocked AIX format */
typedef struct _AIXSTREAMFILE {
STREAMFILE sf;
STREAMFILE *real_file;
off_t start_physical_offset;
off_t current_physical_offset;
off_t current_logical_offset;
off_t current_block_size;
int stream_id;
} AIXSTREAMFILE;
/*static*/ STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file, off_t start_offset, int stream_id);
static size_t read_aix(AIXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length) {
size_t sz = 0;
/*printf("trying to read %x bytes from %x (str%d)\n",length,offset,streamfile->stream_id);*/
while (length > 0) {
int read_something = 0;
/* read the beginning of the requested block, if we can */
if (offset >= streamfile->current_logical_offset) {
off_t to_read;
off_t length_available;
length_available = (streamfile->current_logical_offset + streamfile->current_block_size) - offset;
if (length < length_available) {
to_read = length;
}
else {
to_read = length_available;
}
if (to_read > 0) {
size_t bytes_read;
bytes_read = read_streamfile(dest,
streamfile->current_physical_offset+0x10 + (offset-streamfile->current_logical_offset),
to_read,streamfile->real_file);
sz += bytes_read;
if (bytes_read != to_read) {
return sz; /* an error which we will not attempt to handle here */
}
read_something = 1;
dest += bytes_read;
offset += bytes_read;
length -= bytes_read;
}
}
if (!read_something) {
/* couldn't read anything, must seek */
int found_block = 0;
/* as we have no memory we must start seeking from the beginning */
if (offset < streamfile->current_logical_offset) {
streamfile->current_logical_offset = 0;
streamfile->current_block_size = 0;
streamfile->current_physical_offset = streamfile->start_physical_offset;
}
/* seek ye forwards */
while (!found_block) {
/*printf("seek looks at %x\n",streamfile->current_physical_offset);*/
switch (read_32bitBE(streamfile->current_physical_offset, streamfile->real_file)) {
case 0x41495850: /* AIXP */
if (read_8bit(streamfile->current_physical_offset+8, streamfile->real_file) == streamfile->stream_id) {
streamfile->current_block_size = (uint16_t)read_16bitBE(streamfile->current_physical_offset+0x0a, streamfile->real_file);
if (offset >= streamfile->current_logical_offset+ streamfile->current_block_size) {
streamfile->current_logical_offset += streamfile->current_block_size;
}
else {
found_block = 1;
}
}
if (!found_block) {
streamfile->current_physical_offset += read_32bitBE(streamfile->current_physical_offset+0x04, streamfile->real_file) + 8;
}
break;
case 0x41495846: /* AIXF */
/* shouldn't ever see this */
case 0x41495845: /* AIXE */
/* shouldn't have reached the end o' the line... */
default:
return sz;
break;
} /* end block/chunk type select */
} /* end while !found_block */
} /* end if !read_something */
} /* end while length > 0 */
return sz;
}
static void close_aix(AIXSTREAMFILE *streamfile) {
free(streamfile);
return;
}
static size_t get_size_aix(AIXSTREAMFILE *streamfile) {
return 0;
}
static size_t get_offset_aix(AIXSTREAMFILE *streamfile) {
return streamfile->current_logical_offset;
}
static void get_name_aix(AIXSTREAMFILE *streamfile,char *buffer,size_t length) {
strncpy(buffer,"ARBITRARY.ADX",length);
buffer[length-1]='\0';
}
static STREAMFILE *open_aix_impl(AIXSTREAMFILE *streamfile,const char * const filename,size_t buffersize) {
AIXSTREAMFILE *newfile;
if (strcmp(filename,"ARBITRARY.ADX"))
return NULL;
newfile = malloc(sizeof(AIXSTREAMFILE));
if (!newfile)
return NULL;
memcpy(newfile,streamfile,sizeof(AIXSTREAMFILE));
return &newfile->sf;
}
/*static*/ STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file, off_t start_offset, int stream_id) {
AIXSTREAMFILE *streamfile = malloc(sizeof(AIXSTREAMFILE));
if (!streamfile)
return NULL;
/* success, set our pointers */
streamfile->sf.read = (void*)read_aix;
streamfile->sf.get_size = (void*)get_size_aix;
streamfile->sf.get_offset = (void*)get_offset_aix;
streamfile->sf.get_name = (void*)get_name_aix;
streamfile->sf.get_realname = (void*)get_name_aix;
streamfile->sf.open = (void*)open_aix_impl;
streamfile->sf.close = (void*)close_aix;
#ifdef PROFILE_STREAMFILE
streamfile->sf.get_bytes_read = NULL;
streamfile->sf.get_error_count = NULL;
#endif
streamfile->real_file = file;
streamfile->current_physical_offset = start_offset;
streamfile->start_physical_offset = start_offset;
streamfile->current_logical_offset = 0;
streamfile->current_block_size = 0;
streamfile->stream_id = stream_id;
return &streamfile->sf;
}
#endif /* _AIX_STREAMFILE_H_ */

77
src/meta/bar.c Normal file
View File

@ -0,0 +1,77 @@
#include "meta.h"
#include "bar_streamfile.h"
/* Guitar Hero III Mobile .bar */
VGMSTREAM * init_vgmstream_bar(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE* streamFileBAR = NULL; // don't close, this is just the source streamFile wrapped
char filename[PATH_LIMIT];
off_t start_offset;
off_t ch2_start_offset;
int loop_flag;
int channel_count;
long file_size;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("bar",filename_extension(filename))) goto fail;
/* decryption wrapper for header reading */
streamFileBAR = wrap_bar_STREAMFILE(streamFile);
if (!streamFileBAR) goto fail;
file_size = get_streamfile_size(streamFileBAR);
/* check header */
if (read_32bitBE(0x00,streamFileBAR) != 0x11000100 ||
read_32bitBE(0x04,streamFileBAR) != 0x01000200) goto fail;
if (read_32bitLE(0x50,streamFileBAR) != file_size) goto fail;
start_offset = read_32bitLE(0x18,streamFileBAR);
if (0x54 != start_offset) goto fail;
ch2_start_offset = read_32bitLE(0x48,streamFileBAR);
if (ch2_start_offset >= file_size) goto fail;
/* build the VGMSTREAM */
channel_count = 2;
loop_flag = 0;
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = 11025;
vgmstream->coding_type = coding_IMA;
vgmstream->num_samples = (file_size-ch2_start_offset)*2;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_GH3_BAR;
{
STREAMFILE *file1, *file2;
file1 = streamFileBAR->open(streamFileBAR,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file1) goto fail;
file2 = streamFileBAR->open(streamFileBAR,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file2)
{
close_streamfile(file1);
goto fail;
}
vgmstream->ch[0].streamfile = file1;
vgmstream->ch[1].streamfile = file2;
vgmstream->ch[0].channel_start_offset=
vgmstream->ch[0].offset=start_offset;
vgmstream->ch[1].channel_start_offset=
vgmstream->ch[1].offset=ch2_start_offset;
}
// discard our decrypt wrapper, without closing the original streamfile
free(streamFileBAR);
return vgmstream;
fail:
if (streamFileBAR)
free(streamFileBAR);
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

100
src/meta/bar_streamfile.h Normal file
View File

@ -0,0 +1,100 @@
#ifndef _BAR_STREAMFILE_H_
#define _BAR_STREAMFILE_H_
#include "../streamfile.h"
/* a streamfile wrapping another for decryption */
enum {BAR_KEY_LENGTH = 16};
// don't know if this is unique, but seems accurate
static const uint8_t bar_key[BAR_KEY_LENGTH] = {
0xbd,0x14,0x0e,0x0a,0x91,0xeb,0xaa,0xf6,
0x11,0x44,0x17,0xc2,0x1c,0xe4,0x66,0x80
};
typedef struct _BARSTREAMFILE {
STREAMFILE sf;
STREAMFILE *real_file;
} BARSTREAMFILE;
/*static*/ STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file);
static size_t read_bar(BARSTREAMFILE *streamFile, uint8_t *dest, off_t offset, size_t length) {
off_t i;
size_t read_length = streamFile->real_file->read(streamFile->real_file, dest, offset, length);
for (i = 0; i < read_length; i++) {
dest[i] = dest[i] ^ bar_key[(i+offset)%BAR_KEY_LENGTH];
}
return read_length;
}
static size_t get_size_bar(BARSTREAMFILE *streamFile) {
return streamFile->real_file->get_size(streamFile->real_file);
}
static size_t get_offset_bar(BARSTREAMFILE *streamFile) {
return streamFile->real_file->get_offset(streamFile->real_file);
}
static void get_name_bar(BARSTREAMFILE *streamFile, char *name, size_t length) {
return streamFile->real_file->get_name(streamFile->real_file, name, length);
}
static void get_realname_bar(BARSTREAMFILE *streamFile, char *name, size_t length) {
return streamFile->real_file->get_realname(streamFile->real_file, name, length);
}
STREAMFILE *open_bar(BARSTREAMFILE *streamFile, const char * const filename, size_t buffersize) {
STREAMFILE *newfile = streamFile->real_file->open(streamFile->real_file,filename,buffersize);
if (!newfile)
return NULL;
return wrap_bar_STREAMFILE(newfile);
}
static void close_bar(BARSTREAMFILE *streamFile) {
streamFile->real_file->close(streamFile->real_file);
free(streamFile);
return;
}
#ifdef PROFILE_STREAMFILE
size_t get_bytes_read_bar(BARSTREAMFILE *streamFile) {
return streamFile->real_file->get_bytes_read(streamFile->real_file);
}
int (*get_error_count)(BARSTREAMFILE *streamFile) {
return streamFile->real_file->get_error_count(streamFile->real_file);
}
#endif
/*static*/ STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file) {
BARSTREAMFILE *streamfile = malloc(sizeof(BARSTREAMFILE));
if (!streamfile)
return NULL;
memset(streamfile, 0, sizeof(BARSTREAMFILE));
streamfile->sf.read = (void*)read_bar;
streamfile->sf.get_size = (void*)get_size_bar;
streamfile->sf.get_offset = (void*)get_offset_bar;
streamfile->sf.get_name = (void*)get_name_bar;
streamfile->sf.get_realname = (void*)get_realname_bar;
streamfile->sf.open = (void*)open_bar;
streamfile->sf.close = (void*)close_bar;
#ifdef PROFILE_STREAMFILE
streamfile->sf.get_bytes_read = get_bytes_read_bar;
streamfile->sf.get_error_count = get_error_count_bar;
#endif
streamfile->real_file = file;
return &streamfile->sf;
}
#endif /* _BAR_STREAMFILE_H_ */

View File

@ -17,8 +17,8 @@ VGMSTREAM * init_vgmstream_ea_snr_sns(STREAMFILE * streamFile) {
/* SNR headers normally need an external SNS file, but some have data */
if (get_streamfile_size(streamFile) > 0x10) {
/* for Burnout Paradise has this, not sure if extension */
off_t start_offset = (read_32bitBE(0x0c, streamFile) == 0) ? 0x0c : 0x08;
/* SNR with data (flag 0x40 not set), seen in Burnout Paradise, NFL2013 iOS */
off_t start_offset = (read_32bitBE(0x08, streamFile) == 0) ? 0x0c : 0x08;
vgmstream = init_vgmstream_eaaudiocore_header(streamFile, streamFile, 0x00, start_offset, meta_EA_SNR_SNS);
if (!vgmstream) goto fail;

View File

@ -353,8 +353,8 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) {
}
else if (fsbh.mode & FSOUND_GCADPCM) {
/* FSB3: ?; FSB4: de Blob (Wii), Night at the Museum, M. Night Shyamalan Avatar: The Last Airbender */
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave_byte;
vgmstream->coding_type = coding_NGC_DSP_subint;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = 0x2;
dsp_read_coefs_be(vgmstream, streamFile, custom_data_offset, 0x2e);
}
@ -380,6 +380,8 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) {
/* full channel interleave, used in short streams (ex. de Blob Wii SFXs) */
if (fsbh.numchannels > 1 && (fsbh.flags & FMOD_FSB_SOURCE_NOTINTERLEAVED)) {
if (vgmstream->coding_type == coding_NGC_DSP_subint)
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = fsbh.lengthcompressedbytes / fsbh.numchannels;
}

View File

@ -193,27 +193,22 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
goto fail;
case 0x01: /* FMOD_SOUND_FORMAT_PCM8 [Anima - Gate of Memories (PC)] */
vgmstream->coding_type = coding_PCM8_U;
vgmstream->layout_type = ChannelCount == 1 ? layout_none : layout_interleave;
vgmstream->interleave_block_size = 0x01;
vgmstream->coding_type = coding_PCM8_U;
break;
case 0x02: /* FMOD_SOUND_FORMAT_PCM16 */
if (ChannelCount == 1) {
vgmstream->layout_type = layout_none;
} else {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02;
}
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = ChannelCount == 1 ? layout_none : layout_interleave;
vgmstream->interleave_block_size = 0x02;
break;
case 0x03: /* FMOD_SOUND_FORMAT_PCM24 */
goto fail;
goto fail; /* not used */
case 0x04: /* FMOD_SOUND_FORMAT_PCM32 */
goto fail;
goto fail; /* not used */
case 0x05: /* FMOD_SOUND_FORMAT_PCMFLOAT [Anima - Gate of Memories (PC)] */
vgmstream->coding_type = coding_PCMFLOAT;
@ -222,31 +217,25 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
break;
case 0x06: /* FMOD_SOUND_FORMAT_GCADPCM [Sonic Boom - Fire and Ice (3DS)] */
if (ChannelCount == 1) {
vgmstream->layout_type = layout_none;
} else {
vgmstream->layout_type = layout_interleave_byte;
vgmstream->interleave_block_size = 0x02;
}
vgmstream->coding_type = coding_NGC_DSP_subint;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = 0x02;
dsp_read_coefs_be(vgmstream,streamFile,DSPInfoStart,0x2E);
vgmstream->coding_type = coding_NGC_DSP;
break;
case 0x07: /* FMOD_SOUND_FORMAT_IMAADPCM */
vgmstream->coding_type = (vgmstream->channels > 2) ? coding_FSB_IMA : coding_XBOX;
vgmstream->layout_type = layout_none;
vgmstream->coding_type = coding_XBOX;
if (vgmstream->channels > 2) /* multichannel FSB IMA (interleaved header) */
vgmstream->coding_type = coding_FSB_IMA;
break;
case 0x08: /* FMOD_SOUND_FORMAT_VAG */
goto fail;
goto fail; /* not used */
case 0x09: /* FMOD_SOUND_FORMAT_HEVAG */
vgmstream->coding_type = coding_HEVAG;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10;
vgmstream->coding_type = coding_HEVAG;
break;
#ifdef VGM_USE_FFMPEG
@ -270,9 +259,8 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
#ifdef VGM_USE_MPEG
case 0x0B: {/* FMOD_SOUND_FORMAT_MPEG */
mpeg_custom_config cfg;
mpeg_custom_config cfg = {0};
memset(&cfg, 0, sizeof(mpeg_custom_config));
cfg.fsb_padding = (vgmstream->channels > 2 ? 16 : 4); /* observed default */
vgmstream->codec_data = init_mpeg_custom_codec_data(streamFile, StartOffset, &vgmstream->coding_type, vgmstream->channels, MPEG_FSB, &cfg);
@ -295,9 +283,8 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
#ifdef VGM_USE_VORBIS
case 0x0F: {/* FMOD_SOUND_FORMAT_VORBIS */
vorbis_custom_config cfg;
vorbis_custom_config cfg = {0};
memset(&cfg, 0, sizeof(vorbis_custom_config));
cfg.channels = vgmstream->channels;
cfg.sample_rate = vgmstream->sample_rate;
cfg.setup_id = VorbisSetupId;

View File

@ -88,11 +88,10 @@ static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t
vgmstream->loop_start_sample = read_32bitBE(offset+0x14, streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave_byte;
vgmstream->meta_type = meta_KT_WIIBGM;
vgmstream->coding_type = coding_NGC_DSP_subint;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = 0x1;
vgmstream->meta_type = meta_KT_WIIBGM;
dsp_read_coefs_be(vgmstream,streamFile, offset+0x5C, 0x60);
start_offset = offset+0x800;
@ -101,7 +100,7 @@ static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -208,8 +208,9 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = genh.interleave;
} else if (genh.coef_interleave_type == 1) {
if (!genh.interleave) goto fail;
vgmstream->layout_type = layout_interleave_byte;
coding = coding_NGC_DSP_subint;
vgmstream->interleave_block_size = genh.interleave;
vgmstream->layout_type = layout_none;
} else if (genh.coef_interleave_type == 2) {
vgmstream->layout_type = layout_none;
}// else {

View File

@ -1,182 +0,0 @@
#include "meta.h"
// Guitar Hero III Mobile .bar
enum {BAR_KEY_LENGTH = 16};
// don't know if this is unique, but seems accurate
static const uint8_t bar_key[BAR_KEY_LENGTH] =
{0xbd,0x14,0x0e,0x0a,0x91,0xeb,0xaa,0xf6,
0x11,0x44,0x17,0xc2,0x1c,0xe4,0x66,0x80};
typedef struct _BARSTREAM
{
STREAMFILE sf;
STREAMFILE *real_file;
} BARSTREAM;
STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file);
VGMSTREAM * init_vgmstream_gh3_bar(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
// don't close, this is just the source streamFile wrapped
STREAMFILE* streamFileBAR = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
off_t ch2_start_offset;
int loop_flag;
int channel_count;
long file_size;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("bar",filename_extension(filename))) goto fail;
/* decryption wrapper for header reading */
streamFileBAR = wrap_bar_STREAMFILE(streamFile);
if (!streamFileBAR) goto fail;
file_size = get_streamfile_size(streamFileBAR);
/* check header */
if (read_32bitBE(0x00,streamFileBAR) != 0x11000100 ||
read_32bitBE(0x04,streamFileBAR) != 0x01000200) goto fail;
if (read_32bitLE(0x50,streamFileBAR) != file_size) goto fail;
start_offset = read_32bitLE(0x18,streamFileBAR);
if (0x54 != start_offset) goto fail;
ch2_start_offset = read_32bitLE(0x48,streamFileBAR);
if (ch2_start_offset >= file_size) goto fail;
/* build the VGMSTREAM */
channel_count = 2;
loop_flag = 0;
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = 11025;
vgmstream->coding_type = coding_IMA;
vgmstream->num_samples = (file_size-ch2_start_offset)*2;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_GH3_BAR;
{
STREAMFILE *file1, *file2;
file1 = streamFileBAR->open(streamFileBAR,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file1) goto fail;
file2 = streamFileBAR->open(streamFileBAR,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file2)
{
close_streamfile(file1);
goto fail;
}
vgmstream->ch[0].streamfile = file1;
vgmstream->ch[1].streamfile = file2;
vgmstream->ch[0].channel_start_offset=
vgmstream->ch[0].offset=start_offset;
vgmstream->ch[1].channel_start_offset=
vgmstream->ch[1].offset=ch2_start_offset;
}
// discard our decrypt wrapper, without closing the original streamfile
free(streamFileBAR);
return vgmstream;
fail:
if (streamFileBAR)
free(streamFileBAR);
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}
static size_t read_bar(BARSTREAM *streamFile, uint8_t *dest, off_t offset, size_t length)
{
off_t i;
size_t read_length =
streamFile->real_file->read(streamFile->real_file, dest, offset, length);
for (i = 0; i < read_length; i++)
{
dest[i] = dest[i] ^ bar_key[(i+offset)%BAR_KEY_LENGTH];
}
return read_length;
}
static size_t get_size_bar(BARSTREAM *streamFile)
{
return streamFile->real_file->get_size(streamFile->real_file);
}
static size_t get_offset_bar(BARSTREAM *streamFile)
{
return streamFile->real_file->get_offset(streamFile->real_file);
}
static void get_name_bar(BARSTREAM *streamFile, char *name, size_t length)
{
return streamFile->real_file->get_name(streamFile->real_file, name, length);
}
static void get_realname_bar(BARSTREAM *streamFile, char *name, size_t length)
{
return streamFile->real_file->get_realname(streamFile->real_file, name, length);
}
STREAMFILE *open_bar(BARSTREAM *streamFile, const char * const filename, size_t buffersize)
{
STREAMFILE *newfile = streamFile->real_file->open(
streamFile->real_file,filename,buffersize);
if (!newfile)
return NULL;
return wrap_bar_STREAMFILE(newfile);
}
static void close_bar(BARSTREAM *streamFile)
{
streamFile->real_file->close(streamFile->real_file);
free(streamFile);
return;
}
#ifdef PROFILE_STREAMFILE
size_t get_bytes_read_bar(BARSTREAM *streamFile)
{
return streamFile->real_file->get_bytes_read(streamFile->real_file);
}
int (*get_error_count)(BARSTREAM *streamFile)
{
return streamFile->real_file->get_error_count(streamFile->real_file);
}
#endif
STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file)
{
BARSTREAM *streamfile = malloc(sizeof(BARSTREAM));
if (!streamfile)
return NULL;
memset(streamfile, 0, sizeof(BARSTREAM));
streamfile->sf.read = (void*)read_bar;
streamfile->sf.get_size = (void*)get_size_bar;
streamfile->sf.get_offset = (void*)get_offset_bar;
streamfile->sf.get_name = (void*)get_name_bar;
streamfile->sf.get_realname = (void*)get_realname_bar;
streamfile->sf.open = (void*)open_bar;
streamfile->sf.close = (void*)close_bar;
#ifdef PROFILE_STREAMFILE
streamfile->sf.get_bytes_read = get_bytes_read_bar;
streamfile->sf.get_error_count = get_error_count_bar;
#endif
streamfile->real_file = file;
return &streamfile->sf;
}

View File

@ -80,8 +80,6 @@ VGMSTREAM * init_vgmstream_xbox_xwav(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile);
@ -173,7 +171,6 @@ VGMSTREAM * init_vgmstream_aus(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_rws(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_fsb(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_fsb4_wav(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_fsb5(STREAMFILE * streamFile);
@ -243,11 +240,9 @@ VGMSTREAM * init_vgmstream_ngc_swd(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_capdsp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_xbox_wvs(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_dc_str(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_dc_str_v2(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_xbox_matx(STREAMFILE *streamFile);
@ -276,12 +271,8 @@ VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_xa2(STREAMFILE * streamFile);
//VGMSTREAM * init_vgmstream_idsp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_idsp2(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_idsp3(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_idsp4(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ngc_ymf(STREAMFILE * streamFile);
@ -321,7 +312,6 @@ VGMSTREAM * init_vgmstream_dc_asd(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_bgw(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_spw(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ps2_ass(STREAMFILE * streamFile);
@ -359,7 +349,6 @@ VGMSTREAM * init_vgmstream_dc_dcsw_dcs(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_wii_smp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_emff_ps2(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_emff_ngc(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_thp(STREAMFILE *streamFile);
@ -387,6 +376,7 @@ VGMSTREAM * init_vgmstream_ps2_vsf(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_nds_rrds(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile);
@ -447,7 +437,6 @@ VGMSTREAM * init_vgmstream_wii_bns(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_wii_was(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pona_3do(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pona_psx(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_xbox_hlwav(STREAMFILE* streamFile);
@ -492,8 +481,6 @@ VGMSTREAM * init_vgmstream_dsp_ddsp(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_p3d(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_adsc(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE* streamFile);
@ -503,9 +490,7 @@ VGMSTREAM * init_vgmstream_dsp_str_ig(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_psx_mgav(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str1(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str2(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str3(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_b1s(STREAMFILE* streamFile);
@ -526,7 +511,7 @@ VGMSTREAM * init_vgmstream_ps2_vms(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_xau(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_gh3_bar(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_bar(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ffw(STREAMFILE* streamFile);
@ -583,7 +568,6 @@ VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_eb_sfx(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_eb_sf0(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps3_klbs(STREAMFILE* streamFile);
@ -669,6 +653,7 @@ VGMSTREAM * init_vgmstream_wii_04sw(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_txth(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE * streamFile);
@ -677,8 +662,6 @@ VGMSTREAM * init_vgmstream_sk_aud(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_stm(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_nsw_opus(STREAMFILE * streamFile);
@ -695,8 +678,8 @@ VGMSTREAM * init_vgmstream_ezw(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_vxn(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ea_snr_sns(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ea_sps(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ngc_vid1(STREAMFILE * streamFile);

View File

@ -2070,8 +2070,8 @@ VGMSTREAM * init_vgmstream_wii_ndp(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = dsp_nibbles_to_samples(
ch0_header.loop_end_offset)+1;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave_byte;
vgmstream->coding_type = coding_NGC_DSP_subint;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = 0x4;
vgmstream->meta_type = meta_WII_NDP;
@ -2089,22 +2089,12 @@ VGMSTREAM * init_vgmstream_wii_ndp(STREAMFILE *streamFile) {
vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2;
/* open the file for reading */
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[0].streamfile)
goto fail;
vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start;
vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[1].streamfile)
goto fail;
vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset=ch2_start;
if (!vgmstream_open_stream(vgmstream,streamFile,ch1_start))
goto fail;
return vgmstream;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

45
src/meta/omu.c Normal file
View File

@ -0,0 +1,45 @@
#include "meta.h"
/* IMU - found in Alter Echo (PS2) */
VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
/* check extension */
if ( !check_extensions(streamFile,"omu") )
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x4F4D5520 && /* "OMU " */
read_32bitBE(0x08,streamFile) != 0x46524D54) /* "FRMT" */
goto fail;
loop_flag = 1;
channel_count = (int)read_8bit(0x14,streamFile);
start_offset = 0x40;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->num_samples = (int32_t)(read_32bitLE(0x3C,streamFile)/(vgmstream->channels*2));
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x200;
vgmstream->meta_type = meta_PS2_OMU;
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -27,6 +27,10 @@ VGMSTREAM * init_vgmstream_ps2_int(STREAMFILE *streamFile) {
else
channel_count = 4;
/* ignore A2M .int */
if (read_32bitBE(0x00,streamFile) == 0x41324D00) /* "A2M\0" */
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,0);
if (!vgmstream) goto fail;
@ -59,57 +63,3 @@ fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}
// OMU is a PS2 .INT file with header ...
// found in Alter Echo
VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int i,channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("omu",filename_extension(filename))) goto fail;
/* check header */
if((read_32bitBE(0,streamFile)!=0x4F4D5520) && (read_32bitBE(0x08,streamFile)!=0x46524D54))
goto fail;
channel_count = (int)read_8bit(0x14,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,1);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels=channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = (int32_t)(read_32bitLE(0x3C,streamFile)/(vgmstream->channels*2));
vgmstream->interleave_block_size = 0x200;
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_PS2_OMU;
vgmstream->loop_start_sample=0;
vgmstream->loop_end_sample=vgmstream->num_samples;
/* open the file for reading by each channel */
{
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=0x40+(i*vgmstream->interleave_block_size);
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,17 +1,15 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/* RSTM (from Midnight Club 3, Bully - Canis Canim Edit) */
/* RSTM - from Rockstar games [Midnight Club 3, Bully - Canis Canim Edit (PS2)] */
VGMSTREAM * init_vgmstream_ps2_rstm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
int loop_flag, channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("rstm",filename_extension(filename))) goto fail;
/* check extension (.rsm: in filelist, .rstm: renamed to header id) */
if ( !check_extensions(streamFile,"rsm,rstm") )
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x5253544D) /* "RSTM" */
@ -19,46 +17,28 @@ VGMSTREAM * init_vgmstream_ps2_rstm(STREAMFILE *streamFile) {
loop_flag = (read_32bitLE(0x24,streamFile)!=0xFFFFFFFF);
channel_count = read_32bitLE(0x0C,streamFile);
start_offset = 0x800;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitLE(0x20,streamFile)*28/16/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x24,streamFile)*28/16/channel_count;
vgmstream->loop_end_sample = read_32bitLE(0x20,streamFile)*28/16/channel_count;
}
vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x20,streamFile),channel_count);
vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitLE(0x24,streamFile),channel_count);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10;
vgmstream->meta_type = meta_PS2_RSTM;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -17,8 +17,8 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) {
int channel_count = 0;
int is_swag = 0;
/* check extension, case insensitive */
if ( !check_extensions(streamFile,"vag,swag,str") )
/* check extension (.swag: Frantix PSP, .str: Ben10 Galactic Racing, .vig: MX vs. ATV Untamed PS2) */
if ( !check_extensions(streamFile,"vag,swag,str,vig") )
goto fail;
/* check VAG Header */
@ -63,7 +63,11 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) {
break;
case 'p': /* "VAGp" (extended) [most common, ex Ratchet & Clank] */
if (read_32bitBE(0x6000,streamFile) == 0x56414770) { /* "VAGp" */
if (check_extensions(streamFile,"vig")) { /* MX vs. ATV Untamed PS2 */
channel_count = 2; /* normal interleave */
loop_flag = 0;
}
else if (read_32bitBE(0x6000,streamFile) == 0x56414770) { /* "VAGp" */
channel_count = 2; /* The Simpsons Wrestling PSX interleave */
loop_flag = 0;
}
@ -136,7 +140,14 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) {
case 'p': // VAGp
interleave=0x10;
if (read_32bitBE(0x6000,streamFile) == 0x56414770) { /* "VAGp" */
if (check_extensions(streamFile,"vig")) { /* MX vs. ATV Untamed PS2 */
vgmstream->layout_type=layout_interleave;
vgmstream->meta_type=meta_PS2_VAGp;
vgmstream->num_samples = (datasize - 0x10*channel_count) / 16 * 28;
start_offset = 0x800;
}
else if (read_32bitBE(0x6000,streamFile) == 0x56414770) { /* interleaved "VAGp" */
interleave = 0x6000; /* The Simpsons Wrestling PSX interleave, includes header */
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_PS2_VAGs;

View File

@ -58,61 +58,3 @@ fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}
/* XA2 (RC Revenge Pro) */
VGMSTREAM * init_vgmstream_ps2_xa2_rrp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("xa2",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0xC,streamFile) != 0x00000000)
goto fail;
loop_flag = 0;
channel_count = read_32bitLE(0x0,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 44100;
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x1000;
vgmstream->meta_type = meta_PS2_XA2_RRP;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

59
src/meta/ps2_xa2_rrp.c Normal file
View File

@ -0,0 +1,59 @@
#include "meta.h"
/* XA2 (RC Revenge Pro) */
VGMSTREAM * init_vgmstream_ps2_xa2_rrp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("xa2",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0xC,streamFile) != 0x00000000)
goto fail;
loop_flag = 0;
channel_count = read_32bitLE(0x0,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 44100;
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x1000;
vgmstream->meta_type = meta_PS2_XA2_RRP;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -11,8 +11,8 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) {
int loop_flag = 0, channel_count;
/* check extension, case insensitive */
if (!check_extensions(streamFile,"msf,at3")) goto fail; /* .at3: Silent Hill HD Collection */
/* check extension, case insensitive (.at3: Silent Hill HD Collection, .mp3: Darkstalkers Resurrection) */
if (!check_extensions(streamFile,"msf,at3,mp3")) goto fail;
/* "WMSF" variation with a mini header over the MSFC header, same extension */
if (read_32bitBE(0x00,streamFile) == 0x574D5346) {

View File

@ -888,15 +888,12 @@ fail:
/* RSD6WADP */
VGMSTREAM * init_vgmstream_rsd6wadp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
int loop_flag, channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("rsd",filename_extension(filename))) goto fail;
if (!check_extensions(streamFile,"rsd"))
goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */
@ -906,54 +903,25 @@ VGMSTREAM * init_vgmstream_rsd6wadp(STREAMFILE *streamFile) {
loop_flag = 0;
channel_count = read_32bitLE(0x8,streamFile);
start_offset = 0x800;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = loop_flag;
vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count;
}
vgmstream->layout_type = layout_interleave_byte; //layout_interleave;
vgmstream->interleave_block_size = 2; //read_32bitLE(0xC,streamFile);
vgmstream->coding_type = coding_NGC_DSP_subint;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = 0x02; //read_32bitLE(0xC,streamFile);
vgmstream->meta_type = meta_RSD6WADP;
if (vgmstream->coding_type == coding_NGC_DSP) {
int i;
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x1A4+i*2,streamFile);
}
if (vgmstream->channels) {
for (i=0;i<16;i++) {
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x1CC+i*2,streamFile);
}
}
}
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
dsp_read_coefs_be(vgmstream,streamFile,0x1a4,0x28);
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:

View File

@ -1,31 +1,14 @@
#include "meta.h"
#include "../coding/coding.h"
#include "sqex_scd_streamfile.h"
/* Square-Enix SCD (FF XIII, XIV) */
/* special streamfile type to handle deinterleaving of complete files,
(based heavily on AIXSTREAMFILE */
typedef struct _SCDINTSTREAMFILE
{
STREAMFILE sf;
STREAMFILE *real_file;
const char * filename;
off_t start_physical_offset;
off_t current_logical_offset;
off_t interleave_block_size;
off_t stride_size;
size_t total_size;
} SCDINTSTREAMFILE;
static STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size);
#ifdef VGM_USE_VORBIS
static void scd_ogg_decrypt_v2_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read);
static void scd_ogg_decrypt_v3_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read);
#endif
/* SCD - Square-Enix console games (FF XIII, XIV) */
VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
@ -34,39 +17,39 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
int32_t loop_start, loop_end;
int target_stream = streamFile->stream_index;
int loop_flag = 0, channel_count, codec_id;
int loop_flag = 0, channel_count, codec_id, sample_rate;
int aux_chunk_count;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
/* check extension, case insensitive */
if ( !check_extensions(streamFile, "scd") ) goto fail;
streamFile->get_name(streamFile,filename,sizeof(filename));
/* SEDB */
if (read_32bitBE(0,streamFile) != 0x53454442) goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53454442) goto fail;
/* SSCF */
if (read_32bitBE(4,streamFile) != 0x53534346) goto fail;
if (read_32bitBE(0x04,streamFile) != 0x53534346) goto fail;
/** main header section **/
if (read_32bitBE(8,streamFile) == 2 || /* version 2 BE, as seen in FFXIII demo for PS3 */
read_32bitBE(8,streamFile) == 3) { /* version 3 BE, as seen in FFXIII for PS3 */
if (read_32bitBE(0x08,streamFile) == 2 || /* version 2 BE, as seen in FFXIII demo for PS3 */
read_32bitBE(0x08,streamFile) == 3) { /* version 3 BE, as seen in FFXIII for PS3 */
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
//size_offset = 0x14;
} else if (read_32bitLE(8,streamFile) == 3 || /* version 2/3 LE, as seen in FFXIV for PC (and others?) */
read_32bitLE(8,streamFile) == 2) {
} else if (read_32bitLE(0x08,streamFile) == 3 || /* version 2/3 LE, as seen in FFXIV for PC (and others?) */
read_32bitLE(0x08,streamFile) == 2) {
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
//size_offset = 0x10;
} else goto fail;
/* 0xc: probably 00=LE, 01=BE */
/* 0xd: unk (always 0x04) */
/* 0x0c: probably 0=LE, 1=BE */
/* 0x0d: unk (always 0x04) */
tables_offset = read_16bit(0xe,streamFile);
#if 0
@ -97,14 +80,14 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
meta_offset = read_32bit(headers_offset + (target_stream-1)*4,streamFile);
/** stream header **/
stream_size = read_32bit(meta_offset + 0x0, streamFile);
channel_count = read_32bit(meta_offset+4,streamFile);
/* 0x8 sample rate */
codec_id = read_32bit(meta_offset+0xc,streamFile);
stream_size = read_32bit(meta_offset+0x00, streamFile);
channel_count = read_32bit(meta_offset+0x04,streamFile);
sample_rate = read_32bit(meta_offset+0x08,streamFile);
codec_id = read_32bit(meta_offset+0x0c,streamFile);
loop_start = read_32bit(meta_offset+0x10,streamFile);
loop_end = read_32bit(meta_offset+0x14,streamFile);
loop_flag = (loop_end > 0);
loop_start = read_32bit(meta_offset+0x10,streamFile);
loop_end = read_32bit(meta_offset+0x14,streamFile);
loop_flag = (loop_end > 0);
post_meta_offset = meta_offset + 0x20;
start_offset = post_meta_offset + read_32bit(meta_offset+0x18,streamFile);
@ -123,18 +106,14 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
}
#ifdef VGM_USE_VORBIS
/* special case using init_vgmstream_ogg_vorbis with callbacks */
if (codec_id == 0x6)
{
if (codec_id == 0x06) {
VGMSTREAM * result = NULL;
uint32_t seek_table_size, vorb_header_size;
uint8_t xor_version, xor_byte;
vgm_vorbis_info_t inf;
vgm_vorbis_info_t inf = {0};
memset(&inf, 0, sizeof(inf));
inf.loop_start = loop_start;
inf.loop_end = loop_end;
inf.loop_flag = loop_flag;
@ -205,13 +184,12 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bit(meta_offset+8,streamFile);
vgmstream->sample_rate = sample_rate;
vgmstream->num_streams = headers_entries;
vgmstream->meta_type = meta_SQEX_SCD;
switch (codec_id) {
case 0x1:
/* PCM */
case 0x01: /* PCM */
vgmstream->coding_type = coding_PCM16_int;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = stream_size / 2 / channel_count;
@ -221,124 +199,111 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = loop_end / 2 / channel_count;
}
break;
case 0x06: /* OGG [Final Fantasy XIII-2 (PS3), Final Fantasy XIV (PC)] */
goto fail; /* handled above */
#ifdef VGM_USE_MPEG
case 0x7:
/* MPEG */
{
mpeg_codec_data *mpeg_data = NULL;
coding_t ct;
case 0x07: { /* MPEG [Final Fantasy XIII (PS3)] */
mpeg_codec_data *mpeg_data = NULL;
/* Drakengard 3, some Kingdom Hearts */
if (vgmstream->sample_rate == 47999)
vgmstream->sample_rate = 48000;
if (vgmstream->sample_rate == 44099)
vgmstream->sample_rate = 44100;
/* Drakengard 3, some Kingdom Hearts */
if (vgmstream->sample_rate == 47999)
vgmstream->sample_rate = 48000;
if (vgmstream->sample_rate == 44099)
vgmstream->sample_rate = 44100;
mpeg_data = init_mpeg_codec_data(streamFile, start_offset, &ct, vgmstream->channels);
if (!mpeg_data) goto fail;
vgmstream->codec_data = mpeg_data;
mpeg_data = init_mpeg_codec_data(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels);
if (!mpeg_data) goto fail;
vgmstream->codec_data = mpeg_data;
vgmstream->layout_type = layout_none;
vgmstream->coding_type = ct;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, mpeg_data);
vgmstream->num_samples -= vgmstream->num_samples%576;
if (loop_flag) {
vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data);
vgmstream->loop_start_sample -= vgmstream->loop_start_sample%576;
vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data);
vgmstream->loop_end_sample -= vgmstream->loop_end_sample%576;
}
vgmstream->interleave_block_size = 0;
vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, mpeg_data);
vgmstream->num_samples -= vgmstream->num_samples%576;
if (loop_flag) {
vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, mpeg_data);
vgmstream->loop_start_sample -= vgmstream->loop_start_sample%576;
vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, mpeg_data);
vgmstream->loop_end_sample -= vgmstream->loop_end_sample%576;
}
vgmstream->interleave_block_size = 0;
break;
}
#endif
case 0xC:
/* MS ADPCM */
case 0x0C: /* MS ADPCM [Final Fantasy XIV (PC) sfx] */
vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = read_16bit(post_meta_offset+0xc,streamFile);
vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->interleave_block_size, vgmstream->channels);
vgmstream->interleave_block_size = read_16bit(post_meta_offset+0x0c,streamFile);
vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->interleave_block_size, vgmstream->channels);
if (loop_flag) {
vgmstream->loop_start_sample = msadpcm_bytes_to_samples(loop_start, vgmstream->interleave_block_size, vgmstream->channels);
vgmstream->loop_end_sample = msadpcm_bytes_to_samples(loop_end, vgmstream->interleave_block_size, vgmstream->channels);
}
break;
case 0xA: /* Dragon Quest X (Wii) */
case 0x15: /* Dragon Quest X (Wii U) (no apparent differences except higher sample rate) */
/* GC/Wii DSP ADPCM */
{
STREAMFILE * file;
int i;
const off_t interleave_size = 0x800;
const off_t stride_size = interleave_size * channel_count;
case 0x0A: /* DSP ADPCM [Dragon Quest X (Wii)] */
case 0x15: { /* DSP ADPCM [Dragon Quest X (Wii U)] (no apparent differences except higher sample rate) */
STREAMFILE * file;
int i;
const off_t interleave_size = 0x800;
const off_t stride_size = interleave_size * channel_count;
size_t total_size;
scd_int_codec_data * data = NULL;
size_t total_size;
scd_int_codec_data * data = NULL;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_scd_int;
/* a normal DSP header... */
vgmstream->num_samples = read_32bitBE(start_offset+0,streamFile);
total_size = (read_32bitBE(start_offset+4,streamFile)+1)/2;
if (loop_flag) {
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end+1;
}
/* verify other channel headers */
for (i = 1; i < channel_count; i++) {
if (read_32bitBE(start_offset+interleave_size*i+0,streamFile) != vgmstream->num_samples ||
(read_32bitBE(start_offset+4,streamFile)+1)/2 != total_size) {
goto fail;
}
}
/* the primary streamfile we'll be using */
file = streamFile->open(streamFile,filename,stride_size);
if (!file)
goto fail;
vgmstream->ch[0].streamfile = file;
data = malloc(sizeof(scd_int_codec_data));
data->substream_count = channel_count;
data->substreams = calloc(channel_count, sizeof(VGMSTREAM *));
data->intfiles = calloc(channel_count, sizeof(STREAMFILE *));
vgmstream->codec_data = data;
for (i=0;i<channel_count;i++) {
STREAMFILE * intfile =
open_scdint_with_STREAMFILE(file, "ARBITRARY.DSP", start_offset+interleave_size*i, interleave_size, stride_size, total_size);
if (!intfile)
goto fail;
data->substreams[i] = init_vgmstream_ngc_dsp_std(intfile);
data->intfiles[i] = intfile;
if (!data->substreams[i])
goto fail;
/* TODO: only handles mono substreams, though that's all we have with DSP */
/* save start things so we can restart for seeking/looping */
/* copy the channels */
memcpy(data->substreams[i]->start_ch,data->substreams[i]->ch,sizeof(VGMSTREAMCHANNEL)*1);
/* copy the whole VGMSTREAM */
memcpy(data->substreams[i]->start_vgmstream,data->substreams[i],sizeof(VGMSTREAM));
}
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_scd_int;
/* a normal DSP header... */
total_size = (read_32bitBE(start_offset+0x04,streamFile)+1)/2;
vgmstream->num_samples = read_32bitBE(start_offset+0x00,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end+1;
}
/* verify other channel headers */
for (i = 1; i < channel_count; i++) {
if (read_32bitBE(start_offset+interleave_size*i+0,streamFile) != vgmstream->num_samples ||
(read_32bitBE(start_offset+4,streamFile)+1)/2 != total_size) {
goto fail;
}
}
/* the primary streamfile we'll be using */
file = streamFile->open(streamFile,filename,stride_size);
if (!file) goto fail;
vgmstream->ch[0].streamfile = file;
data = malloc(sizeof(scd_int_codec_data));
data->substream_count = channel_count;
data->substreams = calloc(channel_count, sizeof(VGMSTREAM *));
data->intfiles = calloc(channel_count, sizeof(STREAMFILE *));
vgmstream->codec_data = data;
for (i=0;i<channel_count;i++) {
STREAMFILE * intfile =
open_scdint_with_STREAMFILE(file, "ARBITRARY.DSP", start_offset+interleave_size*i, interleave_size, stride_size, total_size);
if (!intfile) goto fail;
data->substreams[i] = init_vgmstream_ngc_dsp_std(intfile);
data->intfiles[i] = intfile;
if (!data->substreams[i]) goto fail;
/* TODO: only handles mono substreams, though that's all we have with DSP */
/* save start things so we can restart for seeking/looping */
memcpy(data->substreams[i]->start_ch,data->substreams[i]->ch,sizeof(VGMSTREAMCHANNEL)*1);
memcpy(data->substreams[i]->start_vgmstream,data->substreams[i],sizeof(VGMSTREAM));
}
break;
}
#ifdef VGM_USE_FFMPEG
case 0xB:
/* XMA2 */ /* Lightning Returns SFX, FFXIII (X360) */
{
case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx] */
ffmpeg_codec_data *ffmpeg_data = NULL;
uint8_t buf[200];
int32_t bytes;
@ -356,44 +321,42 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
vgmstream->num_samples = ffmpeg_data->totalSamples;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
}
break;
}
case 0xE:
/* ATRAC3plus */ /* Lord of Arcana (PSP) */
{
ffmpeg_codec_data *ffmpeg_data = NULL;
case 0x0E: { /* ATRAC3plus [Lord of Arcana (PSP)] */
ffmpeg_codec_data *ffmpeg_data = NULL;
/* full RIFF header at start_offset/post_meta_offset (same) */
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* full RIFF header at start_offset/post_meta_offset (same) */
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = ffmpeg_data->totalSamples; /* fact samples */
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
vgmstream->num_samples = ffmpeg_data->totalSamples; /* fact samples */
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
/* manually read skip_samples if FFmpeg didn't do it */
if (ffmpeg_data->skipSamples <= 0) {
off_t chunk_offset;
size_t chunk_size, fact_skip_samples = 0;
if (!find_chunk_le(streamFile, 0x66616374,start_offset+0xc,0, &chunk_offset,&chunk_size)) /* find "fact" */
goto fail;
if (chunk_size == 0x8) {
fact_skip_samples = read_32bitLE(chunk_offset+0x4, streamFile);
} else if (chunk_size == 0xc) {
fact_skip_samples = read_32bitLE(chunk_offset+0x8, streamFile);
}
ffmpeg_set_skip_samples(ffmpeg_data, fact_skip_samples);
/* manually read skip_samples if FFmpeg didn't do it */
if (ffmpeg_data->skipSamples <= 0) {
off_t chunk_offset;
size_t chunk_size, fact_skip_samples = 0;
if (!find_chunk_le(streamFile, 0x66616374,start_offset+0xc,0, &chunk_offset,&chunk_size)) /* find "fact" */
goto fail;
if (chunk_size == 0x8) {
fact_skip_samples = read_32bitLE(chunk_offset+0x4, streamFile);
} else if (chunk_size == 0xc) {
fact_skip_samples = read_32bitLE(chunk_offset+0x8, streamFile);
}
/* SCD loop/sample values are relative (without skip samples) vs RIFF (with skip samples), no need to adjust */
ffmpeg_set_skip_samples(ffmpeg_data, fact_skip_samples);
}
break;
/* SCD loop/sample values are relative (without skip samples) vs RIFF (with skip samples), no need to adjust */
break;
}
#endif
default:
VGM_LOG("SCD: unknown codec_id 0x%x\n", codec_id);
goto fail;
@ -410,131 +373,6 @@ fail:
return NULL;
}
static STREAMFILE *open_scdint_impl(SCDINTSTREAMFILE *streamfile,const char * const filename,size_t buffersize)
{
SCDINTSTREAMFILE *newfile;
if (strcmp(filename, streamfile->filename))
return NULL;
newfile = malloc(sizeof(SCDINTSTREAMFILE));
if (!newfile)
return NULL;
memcpy(newfile,streamfile,sizeof(SCDINTSTREAMFILE));
return &newfile->sf;
}
static void close_scdint(SCDINTSTREAMFILE *streamfile)
{
free(streamfile);
return;
}
static size_t get_size_scdint(SCDINTSTREAMFILE *streamfile)
{
return streamfile->total_size;
}
static size_t get_offset_scdint(SCDINTSTREAMFILE *streamfile)
{
return streamfile->current_logical_offset;
}
static void get_name_scdint(SCDINTSTREAMFILE *streamfile, char *buffer, size_t length)
{
strncpy(buffer,streamfile->filename,length);
buffer[length-1]='\0';
}
static size_t read_scdint(SCDINTSTREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length)
{
size_t sz = 0;
while (length > 0)
{
off_t to_read;
off_t length_available;
off_t block_num;
off_t intrablock_offset;
off_t physical_offset;
block_num = offset / streamfile->interleave_block_size;
intrablock_offset = offset % streamfile->interleave_block_size;
streamfile->current_logical_offset = offset;
physical_offset = streamfile->start_physical_offset + block_num * streamfile->stride_size + intrablock_offset;
length_available =
streamfile->interleave_block_size - intrablock_offset;
if (length < length_available)
{
to_read = length;
}
else
{
to_read = length_available;
}
if (to_read > 0)
{
size_t bytes_read;
bytes_read = read_streamfile(dest,
physical_offset,
to_read, streamfile->real_file);
sz += bytes_read;
streamfile->current_logical_offset = offset + bytes_read;
if (bytes_read != to_read)
{
/* an error which we will not attempt to handle here */
return sz;
}
dest += bytes_read;
offset += bytes_read;
length -= bytes_read;
}
}
return sz;
}
/* start_offset is for *this* interleaved stream */
static STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size)
{
SCDINTSTREAMFILE * scd = NULL;
/* _scdint funcs can't handle this case */
if (start_offset + total_size > file->get_size(file))
return NULL;
scd = malloc(sizeof(SCDINTSTREAMFILE));
if (!scd)
return NULL;
scd->sf.read = (void*)read_scdint;
scd->sf.get_size = (void*)get_size_scdint;
scd->sf.get_offset = (void*)get_offset_scdint;
scd->sf.get_name = (void*)get_name_scdint;
scd->sf.get_realname = (void*)get_name_scdint;
scd->sf.open = (void*)open_scdint_impl;
scd->sf.close = (void*)close_scdint;
scd->real_file = file;
scd->filename = filename;
scd->start_physical_offset = start_offset;
scd->current_logical_offset = 0;
scd->interleave_block_size = interleave_block_size;
scd->stride_size = stride_size;
scd->total_size = total_size;
return &scd->sf;
}
#ifdef VGM_USE_VORBIS
static void scd_ogg_decrypt_v2_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read) {

View File

@ -0,0 +1,134 @@
#ifndef _SQEX_SCD_STREAMFILE_H_
#define _SQEX_SCD_STREAMFILE_H_
#include "../streamfile.h"
/* special streamfile type to handle deinterleaving of complete files (based heavily on AIXSTREAMFILE */
typedef struct _SCDINTSTREAMFILE {
STREAMFILE sf;
STREAMFILE *real_file;
const char * filename;
off_t start_physical_offset;
off_t current_logical_offset;
off_t interleave_block_size;
off_t stride_size;
size_t total_size;
} SCDINTSTREAMFILE;
/*static*/ STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size);
static STREAMFILE *open_scdint_impl(SCDINTSTREAMFILE *streamfile,const char * const filename,size_t buffersize) {
SCDINTSTREAMFILE *newfile;
if (strcmp(filename, streamfile->filename))
return NULL;
newfile = malloc(sizeof(SCDINTSTREAMFILE));
if (!newfile)
return NULL;
memcpy(newfile,streamfile,sizeof(SCDINTSTREAMFILE));
return &newfile->sf;
}
static void close_scdint(SCDINTSTREAMFILE *streamfile) {
free(streamfile);
return;
}
static size_t get_size_scdint(SCDINTSTREAMFILE *streamfile) {
return streamfile->total_size;
}
static size_t get_offset_scdint(SCDINTSTREAMFILE *streamfile) {
return streamfile->current_logical_offset;
}
static void get_name_scdint(SCDINTSTREAMFILE *streamfile, char *buffer, size_t length) {
strncpy(buffer,streamfile->filename,length);
buffer[length-1]='\0';
}
static size_t read_scdint(SCDINTSTREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length) {
size_t sz = 0;
while (length > 0) {
off_t to_read;
off_t length_available;
off_t block_num;
off_t intrablock_offset;
off_t physical_offset;
block_num = offset / streamfile->interleave_block_size;
intrablock_offset = offset % streamfile->interleave_block_size;
streamfile->current_logical_offset = offset;
physical_offset = streamfile->start_physical_offset + block_num * streamfile->stride_size + intrablock_offset;
length_available = streamfile->interleave_block_size - intrablock_offset;
if (length < length_available) {
to_read = length;
}
else {
to_read = length_available;
}
if (to_read > 0) {
size_t bytes_read;
bytes_read = read_streamfile(dest,
physical_offset,
to_read, streamfile->real_file);
sz += bytes_read;
streamfile->current_logical_offset = offset + bytes_read;
if (bytes_read != to_read) {
return sz; /* an error which we will not attempt to handle here */
}
dest += bytes_read;
offset += bytes_read;
length -= bytes_read;
}
}
return sz;
}
/* start_offset is for *this* interleaved stream */
/*static*/ STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size) {
SCDINTSTREAMFILE * scd = NULL;
/* _scdint funcs can't handle this case */
if (start_offset + total_size > file->get_size(file))
return NULL;
scd = malloc(sizeof(SCDINTSTREAMFILE));
if (!scd)
return NULL;
scd->sf.read = (void*)read_scdint;
scd->sf.get_size = (void*)get_size_scdint;
scd->sf.get_offset = (void*)get_offset_scdint;
scd->sf.get_name = (void*)get_name_scdint;
scd->sf.get_realname = (void*)get_name_scdint;
scd->sf.open = (void*)open_scdint_impl;
scd->sf.close = (void*)close_scdint;
scd->real_file = file;
scd->filename = filename;
scd->start_physical_offset = start_offset;
scd->current_logical_offset = 0;
scd->interleave_block_size = interleave_block_size;
scd->stride_size = stride_size;
scd->total_size = total_size;
return &scd->sf;
}
#endif /* _SCD_STREAMFILE_H_ */

View File

@ -87,7 +87,7 @@ VGMSTREAM * init_vgmstream_thp(STREAMFILE *streamFile) {
}
}
vgmstream->thpNextFrameSize=read_32bitBE(0x18,streamFile);
vgmstream->full_block_size = read_32bitBE(0x18,streamFile); /* block size of current block, changes every time */
thp_block_update(start_offset,vgmstream);
vgmstream->coding_type = coding_NGC_DSP;

View File

@ -219,7 +219,8 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = txth.interleave;
} else if (txth.channels > 1 && txth.codec_mode == 1) {
if (!txth.interleave) goto fail;
vgmstream->layout_type = layout_interleave_byte;
coding = coding_NGC_DSP_subint;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = txth.interleave;
} else if (txth.channels == 1 || txth.codec_mode == 2) {
vgmstream->layout_type = layout_none;
@ -471,7 +472,13 @@ static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_h
if (!parse_num(streamFile,val, &txth->codec_mode)) goto fail;
}
else if (0==strcmp(key,"interleave")) {
if (!parse_num(streamFile,val, &txth->interleave)) goto fail;
if (0==strcmp(val,"half_size")) {
txth->interleave = txth->data_size / txth->channels;
VGM_LOG("int=%x, ds=%x\n", txth->interleave, txth->data_size);
}
else {
if (!parse_num(streamFile,val, &txth->interleave)) goto fail;
}
}
else if (0==strcmp(key,"id_value")) {
if (!parse_num(streamFile,val, &txth->id_value)) goto fail;

View File

@ -70,10 +70,11 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
switch(((uint64_t)platform << 32) | type) {
case 0x57696E2070636D20: /* "Win pcm " */
case 0x4F72626970636D20: /* "Orbipcm " (Orbis = PS4)*/
/* chunks: "data" */
vgmstream->coding_type = little_endian ? coding_PCM16LE : coding_PCM16BE;
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = block_align;
vgmstream->interleave_block_size = block_align; /* usually 0x04 */
vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, bits_per_sample);
break;
@ -88,7 +89,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
break;
case 0x5769692061647063: /* "Wii adpc" */
case 0x4361666561647063: /* "Cafeadpc" (WiiU) */
case 0x4361666561647063: /* "Cafeadpc" (Cafe = WiiU) */
/* chunks: "datS" (stereo), "datL" (mono or full interleave), "datR" (full interleave), "data" equivalents */
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = channel_count==1 ? layout_none : layout_interleave;

View File

@ -184,13 +184,18 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = sb.stream_size / sb.channels;
vgmstream->num_samples = ps_bytes_to_samples(sb.stream_size, sb.channels);
if (sb.channels > 1) { VGM_LOG("UBI SB: >1 channel\n"); goto fail; } //todo
break;
#ifdef VGM_USE_FFMPEG
case FMT_AT3: {
ffmpeg_codec_data *ffmpeg_data;
/* skip weird value (3, 4) in Brothers in Arms: D-Day (PSP) */
if (read_32bitBE(start_offset+0x04,streamData) == 0x52494646) {
start_offset += 0x04;
sb.stream_size -= 0x04;
}
ffmpeg_data = init_ffmpeg_offset(streamData, start_offset, sb.stream_size);
if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data;
@ -480,6 +485,7 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
int is_sb5 = check_extensions(streamFile, "sb5"); /* PSP, 3DS? */
//int is_sb6 = check_extensions(streamFile, "sb6"); /* PS3? */
int is_sb7 = check_extensions(streamFile, "sb7"); /* Wii */
int is_biadd_psp = 0;
/* The format varies with almost every game + platform (some kind of class serialization?),
@ -554,6 +560,21 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
return 1;
}
/* Tom Clancy's Rainbow Six 3 (2003)(PS2) */
if (sb->version == 0x000A0007 && is_sb1) {
sb->section1_entry_size = 0x48;
sb->section2_entry_size = 0x6c;
sb->external_flag_offset = 0; /* no apparent flag */
sb->channels_offset = 0x20;
sb->sample_rate_offset = 0x24;
sb->num_samples_offset = 0x30;
sb->stream_name_offset = 0x40;
sb->stream_type_offset = 0x68;
return 1;
}
/* Prince of Persia: Sands of Time (2003)(GC) */
if ((sb->version == 0x000A0002 && is_sb3) || /* Prince of Persia 1 port */
(sb->version == 0x000A0004 && is_sb3)) { /* main game */
@ -649,8 +670,17 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
return 1;
}
/* Prince of Persia: Revelations (2005)(PSP) */
/* two games with same id; use project file as identifier */
if (sb->version == 0x0012000C && is_sb4) {
STREAMFILE * streamTest = open_stream_name(streamFile, "BIAAUDIO.SP4");
if (streamTest) {
is_biadd_psp = 1;
close_streamfile(streamTest);
}
}
/* Prince of Persia: Revelations (2005)(PSP) */
if (sb->version == 0x0012000C && is_sb4 && !is_biadd_psp) {
sb->section1_entry_size = 0x68;
sb->section2_entry_size = 0x84;
@ -665,6 +695,23 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
return 1;
}
/* Brothers in Arms - D-Day (2006)(PSP) */
if (sb->version == 0x0012000C && is_sb4 && is_biadd_psp) {
sb->section1_entry_size = 0x80;
sb->section2_entry_size = 0x94;
sb->stream_id_offset = 0x0; //todo 0x1C or 0x20? table seems problematic
sb->external_flag_offset = 0x24;
sb->num_samples_offset = 0; /* variable? */
sb->sample_rate_offset = 0x44;
sb->channels_offset = 0x4c;
sb->stream_type_offset = 0x50;
sb->stream_name_offset = 0x54;
sb->has_internal_names = 1;
return 1;
}
/* Prince of Persia: The Two Thrones (2005)(PC) */
if (sb->version == 0x00150000 && is_sb0) {
sb->section1_entry_size = 0x68;
@ -731,21 +778,6 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
return 1;
}
/* Red Steel (2006)(Wii) */
if (sb->version == 0x00180006 && is_sb7) { /* same as 0x00150000 */
sb->section1_entry_size = 0x68;
sb->section2_entry_size = 0x6c;
sb->external_flag_offset = 0x28; /* maybe 0x2c */
sb->num_samples_offset = 0x3c;
sb->sample_rate_offset = 0x50;
sb->channels_offset = 0x58;
sb->stream_type_offset = 0x5c;
sb->extra_name_offset = 0x60;
return 1;
}
/* Prince of Persia: Rival Swords (2007)(PSP) */
if (sb->version == 0x00180005 && is_sb5) {
sb->section1_entry_size = 0x48;
@ -762,6 +794,51 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
return 1;
}
#if 0
/* Rainbow Six Vegas (2007)(PSP) */
if (sb->version == 0x00180006 && is_sb5) {
sb->section1_entry_size = 0x48;
sb->section2_entry_size = 0x54;
sb->external_flag_offset = 0;
sb->channels_offset = 0x28;
sb->sample_rate_offset = 0x2c;
//sb->num_samples_offset = 0x34 or 0x3c /* varies */
sb->extra_name_offset = 0x44;
sb->stream_type_offset = 0x48;
sb->has_extra_name_flag = 1;
sb->has_rotating_ids = 1;
return 1;
}
/* todo Rainbow Six Vegas changes:
* some streams use type 0x06 instead of 0x01, known values:
* 0x0c: header offset in extra table?
* 0x2c: stream size
* 0x30: stream offset
* most other fields are fixed, comparing different files
* header is in the extra table, after the stream name (repeated?)
* (0x04: sample rate, 0x0c: channels, etc)
* stream data may be newer Ubi ADPCM (see DecUbiSnd)
*/
#endif
/* Red Steel (2006)(Wii) */
if (sb->version == 0x00180006 && is_sb7) { /* same as 0x00150000 */
sb->section1_entry_size = 0x68;
sb->section2_entry_size = 0x6c;
sb->external_flag_offset = 0x28; /* maybe 0x2c */
sb->num_samples_offset = 0x3c;
sb->sample_rate_offset = 0x50;
sb->channels_offset = 0x58;
sb->stream_type_offset = 0x5c;
sb->extra_name_offset = 0x60;
return 1;
}
/* Prince of Persia: Rival Swords (2007)(Wii) */
if (sb->version == 0x00190003 && is_sb7) {
sb->section1_entry_size = 0x68;

View File

@ -1,4 +1,5 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
@ -37,12 +38,11 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
switch(type) {
case 2: /* VAG */
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->layout_type = channel_count == 6 ? layout_blocked_vawx : layout_interleave ;
vgmstream->interleave_block_size = 0x10;
vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile);
/* todo 6ch has 0x8000 blocks and must skip last 0x20 each block (or, skip 0x20 every 0x1550*6 */
break;
@ -110,6 +110,9 @@ VGMSTREAM * init_vgmstream_vawx(STREAMFILE *streamFile) {
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
if (vgmstream->layout_type == layout_blocked_vawx)
block_update_vawx(start_offset,vgmstream);
return vgmstream;
fail:

View File

@ -66,67 +66,3 @@ fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}
/* VSF with SMSS header (from Tiny Toon Adventures: Defenders of the Universe */
VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("vsf",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x534D5353) /* "SMSS" */
goto fail;
loop_flag = read_32bitLE(0x18,streamFile);
channel_count = read_32bitLE(0x0c,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*2)*28/16/channel_count;
vgmstream->loop_end_sample = (read_32bitLE(0x1c,streamFile)*2)*28/16/channel_count;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x8,streamFile);
vgmstream->meta_type = meta_PS2_VSF_TTA;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

66
src/meta/vsf_tta.c Normal file
View File

@ -0,0 +1,66 @@
#include "meta.h"
/* VSF with SMSS header (from Tiny Toon Adventures: Defenders of the Universe) */
VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("vsf",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x534D5353) /* "SMSS" */
goto fail;
loop_flag = read_32bitLE(0x18,streamFile);
channel_count = read_32bitLE(0x0c,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*2)*28/16/channel_count;
vgmstream->loop_end_sample = (read_32bitLE(0x1c,streamFile)*2)*28/16/channel_count;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x8,streamFile);
vgmstream->meta_type = meta_PS2_VSF_TTA;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -55,6 +55,13 @@ VGMSTREAM * init_vgmstream_vxn(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_VXN;
switch (codec) {
case 0x0001: /* PCM */
if (bits != 16) goto fail;
vgmstream->coding_type = coding_PCM16LE;
vgmstream->interleave_block_size = block_align;
vgmstream->layout_type = layout_interleave;
break;
case 0x0002: /* MSADPCM (ex. Asphalt 7) */
if (bits != 4) goto fail;

View File

@ -61,17 +61,16 @@ static inline int get_low_nibble_signed(uint8_t n) {
return nibble_to_int[n&0xf];
}
/* return a file's extension (a pointer to the first character of the
* extension in the original filename or the ending null byte if no extension
*/
const char * filename_extension(const char * filename);
static inline int clamp16(int32_t val) {
if (val>32767) return 32767;
if (val<-32768) return -32768;
return val;
if (val>32767) return 32767;
if (val<-32768) return -32768;
return val;
}
/* return a file's extension (a pointer to the first character of the
* extension in the original filename or the ending null byte if no extension */
const char * filename_extension(const char * filename);
void swap_samples_le(sample *buf, int count);
void concatn(int length, char * dst, const char * src);

View File

@ -147,7 +147,6 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_kraw,
init_vgmstream_ps2_omu,
init_vgmstream_ps2_xa2,
//init_vgmstream_idsp,
init_vgmstream_idsp2,
init_vgmstream_idsp3,
init_vgmstream_idsp4,
@ -279,7 +278,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_dsp_bdsp,
init_vgmstream_ps2_vms,
init_vgmstream_xau,
init_vgmstream_gh3_bar,
init_vgmstream_bar,
init_vgmstream_ffw,
init_vgmstream_dsp_dspw,
init_vgmstream_ps2_jstm,
@ -440,21 +439,6 @@ static VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile) {
}
#ifdef VGM_DEBUG_OUTPUT
#ifdef VGM_USE_FFMPEG
/* debug fun */
if (vgmstream->coding_type != coding_FFmpeg){
int i = 0;
/* probable segfault but some layouts/codecs can ignore these */
for (i = 0; i < vgmstream->channels; i++) {
VGM_ASSERT(vgmstream->ch[i].streamfile == NULL, "VGMSTREAM: null streamfile in ch%i\n",i);
}
}
#endif
#endif/*VGM_DEBUG_OUTPUT*/
#ifdef VGM_USE_FFMPEG
/* check FFmpeg streams here, for lack of a better place */
if (vgmstream->coding_type == coding_FFmpeg) {
@ -577,28 +561,6 @@ void reset_vgmstream(VGMSTREAM * vgmstream) {
}
}
if (vgmstream->layout_type==layout_aix) {
aix_codec_data *data = vgmstream->codec_data;
int i;
data->current_segment = 0;
for (i=0;i<data->segment_count*data->stream_count;i++)
{
reset_vgmstream(data->adxs[i]);
}
}
if (vgmstream->layout_type==layout_aax) {
aax_codec_data *data = vgmstream->codec_data;
int i;
data->current_segment = 0;
for (i=0;i<data->segment_count;i++)
{
reset_vgmstream(data->adxs[i]);
}
}
if (
vgmstream->coding_type == coding_NWA0 ||
vgmstream->coding_type == coding_NWA1 ||
@ -611,19 +573,38 @@ void reset_vgmstream(VGMSTREAM * vgmstream) {
reset_nwa(data->nwa);
}
if (vgmstream->layout_type==layout_aix) {
aix_codec_data *data = vgmstream->codec_data;
int i;
data->current_segment = 0;
for (i=0;i<data->segment_count*data->stream_count;i++) {
reset_vgmstream(data->adxs[i]);
}
}
if (vgmstream->layout_type==layout_aax) {
aax_codec_data *data = vgmstream->codec_data;
int i;
data->current_segment = 0;
for (i=0;i<data->segment_count;i++) {
reset_vgmstream(data->adxs[i]);
}
}
if (vgmstream->layout_type==layout_scd_int) {
scd_int_codec_data *data = vgmstream->codec_data;
int i;
for (i=0;i<data->substream_count;i++)
{
for (i=0;i<data->substream_count;i++) {
reset_vgmstream(data->substreams[i]);
}
}
}
/* simply allocate memory for the VGMSTREAM and its channels */
/* Allocate memory and setup a VGMSTREAM */
VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
VGMSTREAM * vgmstream;
VGMSTREAM * start_vgmstream;
@ -705,7 +686,7 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
free_hca(vgmstream->codec_data);
vgmstream->codec_data = NULL;
}
if (vgmstream->coding_type==coding_EA_MT) {
free_ea_mt(vgmstream->codec_data);
vgmstream->codec_data = NULL;
@ -780,53 +761,6 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
}
}
if (vgmstream->layout_type==layout_aix) {
aix_codec_data *data = (aix_codec_data *) vgmstream->codec_data;
if (data) {
if (data->adxs) {
int i;
for (i=0;i<data->segment_count*data->stream_count;i++) {
/* note that the AIX close_streamfile won't do anything but
* deallocate itself, there is only one open file and that
* is in vgmstream->ch[0].streamfile */
close_vgmstream(data->adxs[i]);
}
free(data->adxs);
}
if (data->sample_counts) {
free(data->sample_counts);
}
free(data);
}
vgmstream->codec_data = NULL;
}
if (vgmstream->layout_type==layout_aax) {
aax_codec_data *data = (aax_codec_data *) vgmstream->codec_data;
if (data) {
if (data->adxs) {
int i;
for (i=0;i<data->segment_count;i++) {
/* note that the AAX close_streamfile won't do anything but
* deallocate itself, there is only one open file and that
* is in vgmstream->ch[0].streamfile */
close_vgmstream(data->adxs[i]);
}
free(data->adxs);
}
if (data->sample_counts) {
free(data->sample_counts);
}
free(data);
}
vgmstream->codec_data = NULL;
}
if (
vgmstream->coding_type == coding_NWA0 ||
vgmstream->coding_type == coding_NWA1 ||
@ -842,6 +776,51 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
vgmstream->codec_data = NULL;
}
if (vgmstream->layout_type==layout_aix) {
aix_codec_data *data = (aix_codec_data *) vgmstream->codec_data;
if (data) {
if (data->adxs) {
int i;
for (i=0;i<data->segment_count*data->stream_count;i++) {
/* note that the close_streamfile won't do anything but deallocate itself,
* there is only one open file in vgmstream->ch[0].streamfile */
close_vgmstream(data->adxs[i]);
}
free(data->adxs);
}
if (data->sample_counts) {
free(data->sample_counts);
}
free(data);
}
vgmstream->codec_data = NULL;
}
if (vgmstream->layout_type==layout_aax) {
aax_codec_data *data = (aax_codec_data *) vgmstream->codec_data;
if (data) {
if (data->adxs) {
int i;
for (i=0;i<data->segment_count;i++) {
/* note that the close_streamfile won't do anything but deallocate itself,
* there is only one open file in vgmstream->ch[0].streamfile */
close_vgmstream(data->adxs[i]);
}
free(data->adxs);
}
if (data->sample_counts) {
free(data->sample_counts);
}
free(data);
}
vgmstream->codec_data = NULL;
}
if (vgmstream->layout_type==layout_scd_int) {
scd_int_codec_data *data = (scd_int_codec_data *) vgmstream->codec_data;
@ -849,10 +828,8 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
if (data->substreams) {
int i;
for (i=0;i<data->substream_count;i++) {
/* note that the scd_int close_streamfile won't do anything
* but deallocate itself, there is only one open file and
* that is in vgmstream->ch[0].streamfile */
/* note that the close_streamfile won't do anything but deallocate itself,
* there is only one open file in vgmstream->ch[0].streamfile */
close_vgmstream(data->substreams[i]);
if(data->intfiles[i]) close_streamfile(data->intfiles[i]);
}
@ -865,6 +842,7 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
vgmstream->codec_data = NULL;
}
/* now that the special cases have had their chance, clean up the standard items */
{
int i,j;
@ -919,7 +897,22 @@ int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double
}
}
/* decode data into sample buffer */
void vgmstream_force_loop(VGMSTREAM* vgmstream, int loop_flag, int loop_start_sample, int loop_end_sample) {
if (!vgmstream) return;
/* this requires a bit more messing with the VGMSTREAM than I'm comfortable with... */
if (loop_flag && !vgmstream->loop_flag && !vgmstream->loop_ch) {
vgmstream->loop_ch = calloc(vgmstream->channels,sizeof(VGMSTREAMCHANNEL));
/* loop_ch will be populated when decoded samples reach loop start */
}
vgmstream->loop_flag = loop_flag;
if (loop_flag) {
vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample;
}
}
/* Decode data into sample buffer */
void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
switch (vgmstream->layout_type) {
case layout_interleave:
@ -966,11 +959,9 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
case layout_blocked_ea_sns:
case layout_blocked_awc:
case layout_blocked_vgs:
case layout_blocked_vawx:
render_vgmstream_blocked(buffer,sample_count,vgmstream);
break;
case layout_interleave_byte:
render_vgmstream_interleave_byte(buffer,sample_count,vgmstream);
break;
case layout_acm:
case layout_mus_acm:
render_vgmstream_mus_acm(buffer,sample_count,vgmstream);
@ -989,7 +980,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
}
}
/* get the size in samples of a single frame (1 or N channels), for interleaved/blocked layouts */
/* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */
int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
switch (vgmstream->coding_type) {
case coding_CRI_ADX:
@ -1001,6 +992,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_L5_555:
return 32;
case coding_NGC_DSP:
case coding_NGC_DSP_subint:
return 14;
case coding_PCM16LE:
case coding_PCM16LE_XOR_int:
@ -1141,16 +1133,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
}
}
int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) {
switch (vgmstream->coding_type) {
case coding_NDS_IMA:
return (vgmstream->interleave_smallblock_size-4)*2;
default:
return get_vgmstream_samples_per_frame(vgmstream);
}
}
/* get the data size of a single frame (1 or N channels), for interleaved/blocked layouts */
/* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */
int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
switch (vgmstream->coding_type) {
case coding_CRI_ADX:
@ -1162,7 +1145,9 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_L5_555:
return 18;
case coding_NGC_DSP:
return 8;
return 0x08;
case coding_NGC_DSP_subint:
return 0x08 * vgmstream->channels;
case coding_PCM16LE:
case coding_PCM16LE_XOR_int:
case coding_PCM16BE:
@ -1275,6 +1260,15 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
}
}
/* In NDS IMA the frame size is the block size, so the last one is short */
int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) {
switch (vgmstream->coding_type) {
case coding_NDS_IMA:
return (vgmstream->interleave_smallblock_size-4)*2;
default:
return get_vgmstream_samples_per_frame(vgmstream);
}
}
int get_vgmstream_shortframe_size(VGMSTREAM * vgmstream) {
switch (vgmstream->coding_type) {
case coding_NDS_IMA:
@ -1284,20 +1278,8 @@ int get_vgmstream_shortframe_size(VGMSTREAM * vgmstream) {
}
}
void decode_vgmstream_mem(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer, uint8_t * data, int channel) {
switch (vgmstream->coding_type) {
case coding_NGC_DSP:
decode_ngc_dsp_mem(&vgmstream->ch[channel],
buffer+samples_written*vgmstream->channels+channel,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do, data);
break;
default:
break;
}
}
/* Decode samples into the buffer. Assume that we have written samples_written into the
* buffer already, and we have samples_to_do consecutive samples ahead of us. */
void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer) {
int chan;
@ -1346,6 +1328,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do);
}
break;
case coding_NGC_DSP_subint:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_ngc_dsp_subint(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do,
chan, vgmstream->interleave_block_size);
}
break;
case coding_PCM16LE:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_pcm16LE(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
@ -1873,6 +1863,7 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
}
}
/* Calculate number of consecutive samples to do (taking into account stopping for loop start and end) */
int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM * vgmstream) {
int samples_to_do;
int samples_left_this_block;
@ -1904,7 +1895,7 @@ int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMST
return samples_to_do;
}
/* loop if end sample is reached, and return 1 if we did loop */
/* Detect loop start and save values, or detect loop end and restore (loop back). Returns 1 if loop was done. */
int vgmstream_do_loop(VGMSTREAM * vgmstream) {
/*if (!vgmstream->loop_flag) return 0;*/
@ -2026,7 +2017,8 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream) {
return 0; /* not looped */
}
/* build a descriptive string */
/* Write a description of the stream into array pointed by desc, which must be length bytes long.
* Will always be null-terminated if length > 0 */
void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
#define TEMPSIZE 256
char temp[TEMPSIZE];
@ -2111,8 +2103,7 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
concatn(length,desc,temp);
if (vgmstream->layout_type == layout_interleave
|| vgmstream->layout_type == layout_interleave_shortblock
|| vgmstream->layout_type == layout_interleave_byte) {
|| vgmstream->layout_type == layout_interleave_shortblock) {
snprintf(temp,TEMPSIZE,
"interleave: %#x bytes\n",
(int32_t)vgmstream->interleave_block_size);
@ -2337,67 +2328,45 @@ fail:
return;
}
static int get_vgmstream_channel_count(VGMSTREAM * vgmstream)
/* average bitrate helper */
static int get_vgmstream_average_bitrate_channel_count(VGMSTREAM * vgmstream)
{
//AAX, AIX, ACM?
if (vgmstream->layout_type==layout_scd_int) {
scd_int_codec_data *data = (scd_int_codec_data *) vgmstream->codec_data;
if (data) {
return data->substream_count;
}
else {
return 0;
}
return (data) ? data->substream_count : 0;
}
#ifdef VGM_USE_VORBIS
if (vgmstream->coding_type==coding_ogg_vorbis) {
ogg_vorbis_codec_data *data = (ogg_vorbis_codec_data *) vgmstream->codec_data;
if (data) {
return 1;
}
else {
return 0;
}
return (data) ? 1 : 0;
}
#endif
if (vgmstream->coding_type==coding_CRI_HCA) {
hca_codec_data *data = (hca_codec_data *) vgmstream->codec_data;
if (data) {
return 1;
}
else {
return 0;
}
return (data) ? 1 : 0;
}
#ifdef VGM_USE_FFMPEG
if (vgmstream->coding_type==coding_FFmpeg) {
ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data;
if (data) {
return 1;
}
else {
return 0;
}
return (data) ? 1 : 0;
}
#endif
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
if (vgmstream->coding_type==coding_MP4_AAC) {
mp4_aac_codec_data *data = (mp4_aac_codec_data *) vgmstream->codec_data;
if (data) {
return 1;
}
else {
return 0;
}
return (data) ? 1 : 0;
}
#endif
return vgmstream->channels;
}
static STREAMFILE * get_vgmstream_streamfile(VGMSTREAM * vgmstream, int channel)
/* average bitrate helper */
static STREAMFILE * get_vgmstream_average_bitrate_channel_streamfile(VGMSTREAM * vgmstream, int channel)
{
//AAX, AIX, ACM?
if (vgmstream->layout_type==layout_scd_int) {
scd_int_codec_data *data = (scd_int_codec_data *) vgmstream->codec_data;
return data->intfiles[channel];
@ -2405,19 +2374,16 @@ static STREAMFILE * get_vgmstream_streamfile(VGMSTREAM * vgmstream, int channel)
#ifdef VGM_USE_VORBIS
if (vgmstream->coding_type==coding_ogg_vorbis) {
ogg_vorbis_codec_data *data = (ogg_vorbis_codec_data *) vgmstream->codec_data;
return data->ov_streamfile.streamfile;
}
#endif
if (vgmstream->coding_type==coding_CRI_HCA) {
hca_codec_data *data = (hca_codec_data *) vgmstream->codec_data;
return data->streamfile;
}
#ifdef VGM_USE_FFMPEG
if (vgmstream->coding_type==coding_FFmpeg) {
ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data;
return data->streamfile;
}
#endif
@ -2430,42 +2396,41 @@ static STREAMFILE * get_vgmstream_streamfile(VGMSTREAM * vgmstream, int channel)
return vgmstream->ch[channel].streamfile;
}
static int get_vgmstream_channel_average_bitrate(STREAMFILE * streamfile, int sample_rate, int length_samples)
{
static int get_vgmstream_average_bitrate_from_streamfile(STREAMFILE * streamfile, int sample_rate, int length_samples) {
// todo: not correct in subsongs or formats which only use part of the data
return (int)((int64_t)get_streamfile_size(streamfile) * 8 * sample_rate / length_samples);
}
int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream)
{
/* Return the average bitrate in bps of all unique files contained within this stream. */
int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream) {
char path_current[PATH_LIMIT];
char path_compare[PATH_LIMIT];
unsigned int i, j;
int bitrate = 0;
int sample_rate = vgmstream->sample_rate;
int length_samples = vgmstream->num_samples;
int channels = get_vgmstream_channel_count(vgmstream);
int channels = get_vgmstream_average_bitrate_channel_count(vgmstream);
STREAMFILE * streamFile;
if (!sample_rate || !channels || !length_samples)
return 0;
if (channels >= 1) {
streamFile = get_vgmstream_streamfile(vgmstream, 0);
streamFile = get_vgmstream_average_bitrate_channel_streamfile(vgmstream, 0);
if (streamFile) {
bitrate += get_vgmstream_channel_average_bitrate(streamFile, sample_rate, length_samples);
bitrate += get_vgmstream_average_bitrate_from_streamfile(streamFile, sample_rate, length_samples);
}
}
for (i = 1; i < channels; ++i)
{
streamFile = get_vgmstream_streamfile(vgmstream, i);
/* Compares files by absolute paths, so bitrate doesn't multiply when the same STREAMFILE is reopened per channel */
for (i = 1; i < channels; ++i) {
streamFile = get_vgmstream_average_bitrate_channel_streamfile(vgmstream, i);
if (!streamFile)
continue;
streamFile->get_name(streamFile, path_current, sizeof(path_current));
for (j = 0; j < i; ++j)
{
STREAMFILE * compareFile = get_vgmstream_streamfile(vgmstream, j);
for (j = 0; j < i; ++j) {
STREAMFILE * compareFile = get_vgmstream_average_bitrate_channel_streamfile(vgmstream, j);
if (!compareFile)
continue;
streamFile->get_name(compareFile, path_compare, sizeof(path_compare));
@ -2473,9 +2438,9 @@ int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream)
break;
}
if (j == i)
bitrate += get_vgmstream_channel_average_bitrate(streamFile, sample_rate, length_samples);
bitrate += get_vgmstream_average_bitrate_from_streamfile(streamFile, sample_rate, length_samples);
}
return bitrate;
}
@ -2494,8 +2459,10 @@ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t s
int use_same_offset_per_channel = 0;
/* stream/offsets not needed, scd manages itself */
if (vgmstream->layout_type == layout_scd_int)
/* stream/offsets not needed, manages themselves */
if (vgmstream->layout_type == layout_aix ||
vgmstream->layout_type == layout_aax ||
vgmstream->layout_type == layout_scd_int)
return 1;
#ifdef VGM_USE_FFMPEG

View File

@ -98,6 +98,7 @@ typedef enum {
coding_CRI_ADX_enc_9, /* CRI ADX, type 9 encryption (PSO2) */
coding_NGC_DSP, /* Nintendo DSP ADPCM */
coding_NGC_DSP_subint, /* Nintendo DSP ADPCM with frame subinterframe */
coding_NGC_DTK, /* Nintendo DTK ADPCM (hardware disc), also called TRK or ADP */
coding_NGC_AFC, /* Nintendo AFC ADPCM */
@ -208,7 +209,6 @@ typedef enum {
/* interleave */
layout_interleave, /* equal interleave throughout the stream */
layout_interleave_shortblock, /* interleave with a short last block */
layout_interleave_byte, /* full byte interleave */
/* headered blocks */
layout_ast_blocked,
@ -242,6 +242,7 @@ typedef enum {
layout_blocked_ea_sns, /* newest Electronic Arts blocks, found in SNS/SNU/SPS/etc formats */
layout_blocked_awc, /* Rockstar AWC */
layout_blocked_vgs, /* Guitar Hero II (PS2) */
layout_blocked_vawx, /* No More Heroes 6ch (PS3) */
/* otherwise odd */
layout_acm, /* libacm layout */
@ -730,9 +731,8 @@ typedef struct {
int32_t loop_end_sample; /* last sample of the loop (not included in the loop) */
/* layouts/block */
size_t interleave_block_size; /* interleave for this file */
size_t interleave_block_size; /* interleave, or block/frame size (depending on the codec) */
size_t interleave_smallblock_size; /* smaller interleave for last block */
size_t full_block_size; /* fixed data size, from header (may include padding and other unusable data) */
/* channel state */
VGMSTREAMCHANNEL * ch; /* pointer to array of channels */
@ -740,6 +740,7 @@ typedef struct {
VGMSTREAMCHANNEL * loop_ch; /* copies of channel status as they were at the loop point */
/* layout/block state */
size_t full_block_size; /* actual data size of an entire block (ie. may be fixed, include padding/headers, etc) */
int32_t current_sample; /* number of samples we've passed */
int32_t samples_into_block; /* number of samples into the current block */
off_t current_block_offset; /* start of this block (offset of block header) */
@ -771,8 +772,6 @@ typedef struct {
int32_t ws_output_size; /* WS ADPCM: output bytes for this block */
int32_t thpNextFrameSize; /* THP */
void * start_vgmstream; /* a copy of the VGMSTREAM as it was at the beginning of the stream (for AAX/AIX/SCD) */
/* Data the codec needs for the whole stream. This is for codecs too
@ -1155,6 +1154,45 @@ typedef struct {
} ea_mt_codec_data;
#if 0
//possible future public/opaque API
/* define standard C param call and name mangling (to avoid __stdcall / .defs) */
#define VGMSTREAM_CALL __cdecl //needed?
/* define external function types (during compilation) */
#if defined(VGMSTREAM_EXPORT)
#define VGMSTREAM_API __declspec(dllexport) /* when exporting/creating vgmstream DLL */
#elif defined(VGMSTREAM_IMPORT)
#define VGMSTREAM_API __declspec(dllimport) /* when importing/linking vgmstream DLL */
#else
#define VGMSTREAM_API /* nothing, internal/default */
#endif
//VGMSTREAM_API void VGMSTREAM_CALL vgmstream_function(void);
//info for opaque VGMSTREAM
typedef struct {
int channels;
int sample_rate;
int num_samples;
int loop_start_sample;
int loop_end_sample;
int loop_flag;
int num_streams;
int current_sample;
int average_bitrate;
} VGMSTREAM_INFO;
void vgmstream_get_info(VGMSTREAM* vgmstream, VGMSTREAM_INFO *vgmstream_info);
//or maybe
enum vgmstream_value_t { VGMSTREAM_CHANNELS, VGMSTREAM_CURRENT_SAMPLE, ... };
int vgmstream_get_info(VGMSTREAM* vgmstream, vgmstream_value_t type);
// or
int vgmstream_get_current_sample(VGMSTREAM* vgmstream);
#endif
/* -------------------------------------------------------------------------*/
/* vgmstream "public" API */
/* -------------------------------------------------------------------------*/
@ -1174,48 +1212,46 @@ void close_vgmstream(VGMSTREAM * vgmstream);
/* calculate the number of samples to be played based on looping parameters */
int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM * vgmstream);
/* render! */
/* Decode data into sample buffer */
void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
/* Write a description of the stream into array pointed by desc,
* which must be length bytes long. Will always be null-terminated if length > 0 */
/* Write a description of the stream into array pointed by desc, which must be length bytes long.
* Will always be null-terminated if length > 0 */
void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length);
/* Return the average bitrate in bps of all unique files contained within this
* stream. Compares files by absolute paths. */
/* Return the average bitrate in bps of all unique files contained within this stream. */
int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream);
/* List of supported formats and elements in the list, for plugins that need to know. */
/* List supported formats and return elements in the list, for plugins that need to know. */
const char ** vgmstream_get_formats(size_t * size);
/* Force enable/disable internal looping. Should be done before playing anything,
* and not all codecs support arbitrary loop values ATM. */
void vgmstream_force_loop(VGMSTREAM* vgmstream, int loop_flag, int loop_start_sample, int loop_end_sample);
/* -------------------------------------------------------------------------*/
/* vgmstream "private" API */
/* -------------------------------------------------------------------------*/
/* allocate a VGMSTREAM and channel stuff */
/* Allocate memory and setup a VGMSTREAM */
VGMSTREAM * allocate_vgmstream(int channel_count, int looped);
/* smallest self-contained group of samples is a frame */
/* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */
int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream);
/* number of bytes per frame */
/* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */
int get_vgmstream_frame_size(VGMSTREAM * vgmstream);
/* in NDS IMA the frame size is the block size, so the last one is short */
/* In NDS IMA the frame size is the block size, so the last one is short */
int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream);
int get_vgmstream_shortframe_size(VGMSTREAM * vgmstream);
/* Assume that we have written samples_written into the buffer already, and we have samples_to_do consecutive
* samples ahead of us. Decode those samples into the buffer. */
/* Decode samples into the buffer. Assume that we have written samples_written into the
* buffer already, and we have samples_to_do consecutive samples ahead of us. */
void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer);
/* Assume additionally that we have samples_to_do consecutive samples in "data",
* and this this is for channel number "channel" */
void decode_vgmstream_mem(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer, uint8_t * data, int channel);
/* calculate number of consecutive samples to do (taking into account stopping for loop start and end) */
/* Calculate number of consecutive samples to do (taking into account stopping for loop start and end) */
int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM * vgmstream);
/* Detect start and save values, also detect end and restore values. Only works on exact sample values.
* Returns 1 if loop was done. */
/* Detect loop start and save values, or detect loop end and restore (loop back). Returns 1 if loop was done. */
int vgmstream_do_loop(VGMSTREAM * vgmstream);
/* Open the stream for reading at offset (standarized taking into account layouts, channels and so on).

View File

@ -208,26 +208,16 @@ int main(int argc, char ** argv) {
}
}
/* force only if there aren't already loop points */
if (force_loop && !vgmstream->loop_flag) {
/* this requires a bit more messing with the VGMSTREAM than I'm comfortable with... */
vgmstream->loop_flag=1;
vgmstream->loop_start_sample=0;
vgmstream->loop_end_sample=vgmstream->num_samples;
vgmstream->loop_ch=calloc(vgmstream->channels,sizeof(VGMSTREAMCHANNEL));
vgmstream_force_loop(vgmstream, 1, 0,vgmstream->num_samples);
}
/* force even if there are loop points */
if (really_force_loop) {
if (!vgmstream->loop_flag)
vgmstream->loop_ch=calloc(vgmstream->channels,sizeof(VGMSTREAMCHANNEL));
vgmstream->loop_flag=1;
vgmstream->loop_start_sample=0;
vgmstream->loop_end_sample=vgmstream->num_samples;
vgmstream_force_loop(vgmstream, 1, 0,vgmstream->num_samples);
}
if (ignore_loop) {
vgmstream->loop_flag=0;
vgmstream_force_loop(vgmstream, 0, 0,0);
}
if (play_sdtout) {
@ -379,7 +369,8 @@ int main(int argc, char ** argv) {
}
}
if (write_lwav && vgmstream->loop_flag) { // Writing smpl chuck
/* Writing "smpl" chunck at the end */
if (write_lwav && vgmstream->loop_flag) {
make_smpl_chunk((uint8_t*)buf, vgmstream->loop_start_sample, vgmstream->loop_end_sample);
fwrite(buf,1,0x44,outfile);
}
@ -426,26 +417,16 @@ int main(int argc, char ** argv) {
/* these manipulations are undone by reset */
/* force only if there aren't already loop points */
if (force_loop && !vgmstream->loop_flag) {
/* this requires a bit more messing with the VGMSTREAM than I'm comfortable with... */
vgmstream->loop_flag=1;
vgmstream->loop_start_sample=0;
vgmstream->loop_end_sample=vgmstream->num_samples;
vgmstream->loop_ch=calloc(vgmstream->channels,sizeof(VGMSTREAMCHANNEL));
vgmstream_force_loop(vgmstream, 1, 0,vgmstream->num_samples);
}
/* force even if there are loop points */
if (really_force_loop) {
if (!vgmstream->loop_flag)
vgmstream->loop_ch=calloc(vgmstream->channels,sizeof(VGMSTREAMCHANNEL));
vgmstream->loop_flag=1;
vgmstream->loop_start_sample=0;
vgmstream->loop_end_sample=vgmstream->num_samples;
vgmstream_force_loop(vgmstream, 1, 0,vgmstream->num_samples);
}
if (ignore_loop) {
vgmstream->loop_flag=0;
vgmstream_force_loop(vgmstream, 0, 0,0);
}
/* decode */
@ -521,7 +502,7 @@ static void make_wav_header(uint8_t * buf, int32_t sample_count, int32_t sample_
}
static void make_smpl_chunk(uint8_t * buf, int32_t loop_start, int32_t loop_end) {
int i;
int i;
memcpy(buf+0, "smpl", 4);/* header */
put_32bitLE(buf+4, 0x3c);/* size */