Merge pull request #207 from bnnm/yamaha-layouts-fixes

Yamaha, layouts, fixes
This commit is contained in:
Christopher Snowhill 2018-03-25 15:48:45 -07:00 committed by GitHub
commit 16423580a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 1544 additions and 1412 deletions

View File

@ -154,7 +154,7 @@ void input_vgmstream::get_info(t_uint32 p_subsong, file_info & p_info, abort_cal
if (get_description_tag(temp,description,"encoding: ")) p_info.info_set("codec",temp); if (get_description_tag(temp,description,"encoding: ")) p_info.info_set("codec",temp);
if (get_description_tag(temp,description,"layout: ")) p_info.info_set("layout",temp); if (get_description_tag(temp,description,"layout: ")) p_info.info_set("layout",temp);
if (get_description_tag(temp,description,"interleave: ",' ')) p_info.info_set("interleave",temp); if (get_description_tag(temp,description,"interleave: ",' ')) p_info.info_set("interleave",temp);
if (get_description_tag(temp,description,"last block interleave:",' ')) p_info.info_set("interleave_last_block",temp); if (get_description_tag(temp,description,"interleave last block:",' ')) p_info.info_set("interleave_last_block",temp);
if (get_description_tag(temp,description,"block size: ")) p_info.info_set("block_size",temp); if (get_description_tag(temp,description,"block size: ")) p_info.info_set("block_size",temp);
if (get_description_tag(temp,description,"metadata from: ")) p_info.info_set("metadata_source",temp); if (get_description_tag(temp,description,"metadata from: ")) p_info.info_set("metadata_source",temp);

View File

@ -1,50 +0,0 @@
#include "../util.h"
#include "coding.h"
/* fixed point (.8) amount to scale the current step size by */
/* part of the same series as used in MS ADPCM "ADPCMTable" */
static const unsigned int scale_step[16] =
{
230, 230, 230, 230, 307, 409, 512, 614,
230, 230, 230, 230, 307, 409, 512, 614
};
/* expand an unsigned four bit delta to a wider signed range */
static const int scale_delta[16] =
{
1, 3, 5, 7, 9, 11, 13, 15,
-1, -3, -5, -7, -9,-11,-13,-15
};
/* Yamaha AICA ADPCM (as seen in Dreamcast) */
void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
int32_t hist1 = stream->adpcm_history1_16;
uint32_t step_size = stream->adpcm_step_index;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_nibble =
(
(unsigned)read_8bit(stream->offset+i/2,stream->streamfile) >>
(i&1?4:0)
)&0xf;
int32_t sample_delta = (int32_t)step_size * scale_delta[sample_nibble];
int32_t new_sample;
new_sample = hist1 + sample_delta/8;
outbuf[sample_count] = clamp16(new_sample);
hist1 = outbuf[sample_count];
step_size = (step_size * scale_step[sample_nibble])/0x100;
if (step_size < 0x7f) step_size = 0x7f;
if (step_size > 0x6000) step_size = 0x6000;
}
stream->adpcm_history1_16 = hist1;
stream->adpcm_step_index = step_size;
}

View File

@ -17,7 +17,8 @@ void g72x_init_state(struct g72x_state *state_ptr);
/* ima_decoder */ /* ima_decoder */
void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_xbox_ima_mch(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_standard_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo, int is_high_first); void decode_standard_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo, int is_high_first);
@ -116,8 +117,11 @@ void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first
void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do); void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do);
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels); long msadpcm_bytes_to_samples(long bytes, int block_size, int channels);
/* aica_decoder */ /* yamaha_decoder */
void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_yamaha(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_yamaha_nxap(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
size_t yamaha_bytes_to_samples(size_t bytes, int channels);
/* nds_procyon_decoder */ /* nds_procyon_decoder */
void decode_nds_procyon(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_nds_procyon(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);

View File

@ -389,8 +389,9 @@ void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o
/* ************************************ */ /* ************************************ */
/* MS-IMA with fixed frame size, and outputs an even number of samples per frame (skips last nibble). /* MS-IMA with fixed frame size, and outputs an even number of samples per frame (skips last nibble).
* Defined in Xbox's SDK. Multichannel interleaves 2ch*N/2, or 1ch*N with odd num_channels. */ * Defined in Xbox's SDK. Multichannel interleaves 2ch*N/2, or 1ch*N with odd num_channels
void decode_xbox_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { * (seen in some Koei .wav, could be simplified as interleaved stereo) --unsure if official. */
void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count = 0; int i, sample_count = 0;
int32_t hist1 = stream->adpcm_history1_32; int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index; int step_index = stream->adpcm_step_index;
@ -434,7 +435,51 @@ void decode_xbox_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample *
/* internal interleave: increment offset on complete frame */ /* internal interleave: increment offset on complete frame */
if (i == block_samples) { if (i == block_samples) {
stream->offset += 0x24*vgmstream->channels; stream->offset += 0x24*channelspacing;
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}
/* Multichannel XBOX-IMA ADPCM, with all channels mixed in the same block (equivalent to multichannel MS-IMA; seen in .rsd XADP). */
void decode_xbox_ima_mch(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count = 0, num_frame;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
/* external interleave (fixed size), multichannel */
int block_samples = (0x24 - 0x4) * 2;
num_frame = first_sample / block_samples;
first_sample = first_sample % block_samples;
/* normal header (hist+step+reserved), multichannel */
if (first_sample == 0) {
off_t header_offset = stream->offset + 0x24*channelspacing*num_frame + 0x04*channel;
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
step_index = read_8bit(header_offset+0x02,stream->streamfile);
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
/* write header sample (even samples per block, skips last nibble) */
outbuf[sample_count] = (short)(hist1);
sample_count += channelspacing;
first_sample += 1;
samples_to_do -= 1;
}
/* decode nibbles (layout: alternates 4 bytes/4*2 nibbles per channel) */
for (i = first_sample; i < first_sample + samples_to_do; i++) {
off_t byte_offset = (stream->offset + 0x24*channelspacing*num_frame + 0x04*channelspacing) + 0x04*channel + 0x04*channelspacing*((i-1)/8) + ((i-1)%8)/2;
int nibble_shift = ((i-1)&1?4:0); /* low nibble first */
/* must skip last nibble per spec, rarely needed though */
if (i < block_samples) {
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
outbuf[sample_count] = (short)(hist1);
sample_count += channelspacing;
}
} }
stream->adpcm_history1_32 = hist1; stream->adpcm_history1_32 = hist1;
@ -613,6 +658,7 @@ void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channel
stream->adpcm_step_index = step_index; stream->adpcm_step_index = step_index;
} }
/* Apple's IMA4, a.k.a QuickTime IMA. 2 byte header and header sample is not written (setup only). */
void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i, sample_count, num_frame; int i, sample_count, num_frame;
int16_t hist1 = stream->adpcm_history1_16;//todo unneeded 16? int16_t hist1 = stream->adpcm_history1_16;//todo unneeded 16?

149
src/coding/yamaha_decoder.c Normal file
View File

@ -0,0 +1,149 @@
#include "../util.h"
#include "coding.h"
/* fixed point (.8) amount to scale the current step size by */
/* part of the same series as used in MS ADPCM "ADPCMTable" */
static const unsigned int scale_step[16] = {
230, 230, 230, 230, 307, 409, 512, 614,
230, 230, 230, 230, 307, 409, 512, 614
};
/* expand an unsigned four bit delta to a wider signed range */
static const int scale_delta[16] = {
1, 3, 5, 7, 9, 11, 13, 15,
-1, -3, -5, -7, -9,-11,-13,-15
};
/* Yamaha AICA ADPCM, as seen in Dreamcast. Possibly like RIFF codec 0x20 or used in older arcade sound chips. */
void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i, sample_count;
int32_t hist1 = stream->adpcm_history1_16;
int step_size = stream->adpcm_step_index;
/* no header (external setup), pre-clamp for wrong values */
if (step_size < 0x7f) step_size = 0x7f;
if (step_size > 0x6000) step_size = 0x6000;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_nibble, sample_decoded, sample_delta;
off_t byte_offset = (stream->offset) + i/2;
int nibble_shift = (i&1?4:0); /* low nibble first */
/* Yamaha/AICA expand, but same result as IMA's (((delta * 2 + 1) * step) >> 3) */
sample_nibble = ((read_8bit(byte_offset,stream->streamfile) >> nibble_shift))&0xf;
sample_delta = (step_size * scale_delta[sample_nibble]) / 8;
sample_decoded = hist1 + sample_delta;
outbuf[sample_count] = clamp16(sample_decoded);
hist1 = outbuf[sample_count];
step_size = (step_size * scale_step[sample_nibble]) >> 8;
if (step_size < 0x7f) step_size = 0x7f;
if (step_size > 0x6000) step_size = 0x6000;
}
stream->adpcm_history1_16 = hist1;
stream->adpcm_step_index = step_size;
}
/* Yamaha ADPCM, in headered frames like MS-IMA. Possibly originated from Yamaha's SMAF tools
* (Windows ACM encoder/decoder was given in their site). Some info from Rockbox's yamaha_adpcm.c */
void decode_yamaha(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count, num_frame;
int32_t hist1 = stream->adpcm_history1_32;
int step_size = stream->adpcm_step_index;
/* external interleave */
int block_samples = (0x40 - 0x04*channelspacing) * 2 / channelspacing;
num_frame = first_sample / block_samples;
first_sample = first_sample % block_samples;
/* header (hist+step) */
if (first_sample == 0) {
off_t header_offset = stream->offset + 0x40*num_frame + 0x04*channel;
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
step_size = read_16bitLE(header_offset+0x02,stream->streamfile);
if (step_size < 0x7f) step_size = 0x7f;
if (step_size > 0x6000) step_size = 0x6000;
}
/* decode nibbles (layout: varies) */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_nibble, sample_decoded, sample_delta;
off_t byte_offset = (channelspacing == 2) ?
(stream->offset + 0x40*num_frame + 0x04*channelspacing) + i : /* stereo: one nibble per channel */
(stream->offset + 0x40*num_frame + 0x04*channelspacing) + i/2; /* mono: consecutive nibbles */
int nibble_shift = (channelspacing == 2) ?
(!(channel&1) ? 0:4) :
(!(i&1) ? 0:4); /* even = low, odd = high */
/* Yamaha/AICA expand, but same result as IMA's (((delta * 2 + 1) * step) >> 3) */
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
sample_delta = (step_size * scale_delta[sample_nibble]) / 8;
sample_decoded = hist1 + sample_delta;
outbuf[sample_count] = clamp16(sample_decoded);
hist1 = outbuf[sample_count];
step_size = (step_size * scale_step[sample_nibble]) >> 8;
if (step_size < 0x7f) step_size = 0x7f;
if (step_size > 0x6000) step_size = 0x6000;
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_size;
}
/* Yamaha ADPCM with unknown expand variation (noisy), step size is double of normal Yamaha? */
void decode_yamaha_nxap(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i, sample_count, num_frame;
int32_t hist1 = stream->adpcm_history1_32;
int step_size = stream->adpcm_step_index;
/* external interleave */
int block_samples = (0x40 - 0x4) * 2;
num_frame = first_sample / block_samples;
first_sample = first_sample % block_samples;
/* header (hist+step) */
if (first_sample == 0) {
off_t header_offset = stream->offset + 0x40*num_frame;
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
step_size = read_16bitLE(header_offset+0x02,stream->streamfile);
if (step_size < 0x7f) step_size = 0x7f;
if (step_size > 0x6000) step_size = 0x6000;
}
/* decode nibbles (layout: all nibbles from one channel) */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_nibble, sample_decoded, sample_delta;
off_t byte_offset = (stream->offset + 0x40*num_frame + 0x04) + i/2;
int nibble_shift = (i&1?4:0); /* low nibble first */
/* Yamaha expand? */
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
sample_delta = (step_size * scale_delta[sample_nibble] / 4) / 8; //todo not ok
sample_decoded = hist1 + sample_delta;
outbuf[sample_count] = clamp16(sample_decoded);
hist1 = outbuf[sample_count];
step_size = (step_size * scale_step[sample_nibble]) >> 8;
if (step_size < 0x7f) step_size = 0x7f;
if (step_size > 0x6000) step_size = 0x6000;
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_size;
}
size_t yamaha_bytes_to_samples(size_t bytes, int channels) {
int block_align = 0x40;
return (bytes / block_align) * (block_align - 0x04*channels) * 2 / channels
+ ((bytes % block_align) ? ((bytes % block_align) - 0x04*channels) * 2 / channels : 0);
}

View File

@ -166,6 +166,7 @@ static const char* extension_list[] = {
"ktss", "ktss",
"kvs", "kvs",
"l",
"laac", //fake extension, for AAC (tri-Ace/FFmpeg) "laac", //fake extension, for AAC (tri-Ace/FFmpeg)
"lac3", //fake extension, for AC3 "lac3", //fake extension, for AC3
"leg", "leg",
@ -240,6 +241,7 @@ static const char* extension_list[] = {
"psnd", "psnd",
"psw", "psw",
"r",
"rac", //txth/reserved [Manhunt (Xbox)] "rac", //txth/reserved [Manhunt (Xbox)]
"rak", "rak",
"ras", "ras",
@ -291,6 +293,7 @@ static const char* extension_list[] = {
"sli", "sli",
"smp", "smp",
"smpl", //fake extension (to be removed) "smpl", //fake extension (to be removed)
"smv",
"snd", "snd",
"snds", "snds",
"sng", "sng",
@ -479,6 +482,7 @@ static const coding_info coding_info_list[] = {
{coding_3DS_IMA, "3DS IMA 4-bit ADPCM"}, {coding_3DS_IMA, "3DS IMA 4-bit ADPCM"},
{coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"}, {coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"},
{coding_XBOX_IMA, "XBOX 4-bit IMA ADPCM"}, {coding_XBOX_IMA, "XBOX 4-bit IMA ADPCM"},
{coding_XBOX_IMA_mch, "XBOX 4-bit IMA ADPCM (multichannel)"},
{coding_XBOX_IMA_int, "XBOX 4-bit IMA ADPCM (mono/interleave)"}, {coding_XBOX_IMA_int, "XBOX 4-bit IMA ADPCM (mono/interleave)"},
{coding_NDS_IMA, "NDS-style 4-bit IMA ADPCM"}, {coding_NDS_IMA, "NDS-style 4-bit IMA ADPCM"},
{coding_DAT4_IMA, "Eurocom DAT4 4-bit IMA ADPCM"}, {coding_DAT4_IMA, "Eurocom DAT4 4-bit IMA ADPCM"},
@ -496,6 +500,8 @@ static const coding_info coding_info_list[] = {
{coding_MSADPCM, "Microsoft 4-bit ADPCM"}, {coding_MSADPCM, "Microsoft 4-bit ADPCM"},
{coding_WS, "Westwood Studios VBR ADPCM"}, {coding_WS, "Westwood Studios VBR ADPCM"},
{coding_AICA, "Yamaha AICA 4-bit ADPCM"}, {coding_AICA, "Yamaha AICA 4-bit ADPCM"},
{coding_YAMAHA, "Yamaha 4-bit ADPCM"},
{coding_YAMAHA_NXAP, "Yamaha NXAP 4-bit ADPCM"},
{coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"}, {coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"},
{coding_L5_555, "Level-5 0x555 4-bit ADPCM"}, {coding_L5_555, "Level-5 0x555 4-bit ADPCM"},
{coding_SASSC, "Activision / EXAKT SASSC 8-bit DPCM"}, {coding_SASSC, "Activision / EXAKT SASSC 8-bit DPCM"},
@ -548,7 +554,11 @@ static const coding_info coding_info_list[] = {
static const layout_info layout_info_list[] = { static const layout_info layout_info_list[] = {
{layout_none, "flat (no layout)"}, {layout_none, "flat (no layout)"},
{layout_interleave, "interleave"}, {layout_interleave, "interleave"},
{layout_interleave_shortblock, "interleave with short last block"},
{layout_segmented, "segmented"},
{layout_aix, "AIX interleave, internally 18-byte interleaved"},
{layout_scd_int, "SCD multistream interleave"},
{layout_mxch_blocked, "MxCh blocked"}, {layout_mxch_blocked, "MxCh blocked"},
{layout_ast_blocked, "AST blocked"}, {layout_ast_blocked, "AST blocked"},
{layout_halpst_blocked, "HALPST blocked"}, {layout_halpst_blocked, "HALPST blocked"},
@ -556,7 +566,7 @@ static const layout_info layout_info_list[] = {
{layout_blocked_ea_schl, "blocked (EA SCHl)"}, {layout_blocked_ea_schl, "blocked (EA SCHl)"},
{layout_blocked_ea_1snh, "blocked (EA 1SNh)"}, {layout_blocked_ea_1snh, "blocked (EA 1SNh)"},
{layout_blocked_caf, "blocked (CAF)"}, {layout_blocked_caf, "blocked (CAF)"},
{layout_wsi_blocked, ".wsi blocked"}, {layout_blocked_wsi, "blocked (WSI)"},
{layout_xvas_blocked, ".xvas blocked"}, {layout_xvas_blocked, ".xvas blocked"},
{layout_str_snds_blocked, ".str SNDS blocked"}, {layout_str_snds_blocked, ".str SNDS blocked"},
{layout_ws_aud_blocked, "Westwood Studios .aud blocked"}, {layout_ws_aud_blocked, "Westwood Studios .aud blocked"},
@ -577,17 +587,11 @@ static const layout_info layout_info_list[] = {
{layout_blocked_rws, "blocked (RWS)"}, {layout_blocked_rws, "blocked (RWS)"},
{layout_blocked_hwas, "blocked (HWAS)"}, {layout_blocked_hwas, "blocked (HWAS)"},
{layout_tra_blocked, "TRA blocked"}, {layout_tra_blocked, "TRA blocked"},
{layout_aix, "AIX interleave, internally 18-byte interleaved"},
{layout_segmented, "segmented"},
{layout_scd_int, "SCD multistream interleave"},
{layout_blocked_ea_sns, "blocked (EA SNS)"}, {layout_blocked_ea_sns, "blocked (EA SNS)"},
{layout_blocked_awc, "blocked (AWC)"}, {layout_blocked_awc, "blocked (AWC)"},
{layout_blocked_vgs, "blocked (VGS)"}, {layout_blocked_vgs, "blocked (VGS)"},
{layout_blocked_vawx, "blocked (VAWX)"}, {layout_blocked_vawx, "blocked (VAWX)"},
{layout_blocked_xvag_subsong, "blocked (XVAG subsong)"}, {layout_blocked_xvag_subsong, "blocked (XVAG subsong)"},
#ifdef VGM_USE_VORBIS
{layout_ogg_vorbis, "Ogg"},
#endif
}; };
static const meta_info meta_info_list[] = { static const meta_info meta_info_list[] = {
@ -653,7 +657,7 @@ static const meta_info meta_info_list[] = {
{meta_DSP_SADB, "Procyon Studio SADB header"}, {meta_DSP_SADB, "Procyon Studio SADB header"},
{meta_SADL, "Procyon Studio SADL header"}, {meta_SADL, "Procyon Studio SADL header"},
{meta_PS2_BMDX, "Beatmania .bmdx header"}, {meta_PS2_BMDX, "Beatmania .bmdx header"},
{meta_DSP_WSI, ".wsi header"}, {meta_DSP_WSI, "Alone in the Dark .WSI header"},
{meta_AIFC, "Audio Interchange File Format AIFF-C"}, {meta_AIFC, "Audio Interchange File Format AIFF-C"},
{meta_AIFF, "Audio Interchange File Format"}, {meta_AIFF, "Audio Interchange File Format"},
{meta_STR_SNDS, ".str SNDS SHDR chunk"}, {meta_STR_SNDS, ".str SNDS SHDR chunk"},
@ -707,7 +711,7 @@ static const meta_info meta_info_list[] = {
{meta_XNB, "Microsoft XNA Game Studio 4.0 header"}, {meta_XNB, "Microsoft XNA Game Studio 4.0 header"},
{meta_SCD_PCM, "Lunar: Eternal Blue .PCM header"}, {meta_SCD_PCM, "Lunar: Eternal Blue .PCM header"},
{meta_PS2_PCM, "Konami KCEJ East .PCM header"}, {meta_PS2_PCM, "Konami KCEJ East .PCM header"},
{meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV Header"}, {meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV PS2 header"},
{meta_PS2_PSW, "Rayman Raving Rabbids Riff Container File"}, {meta_PS2_PSW, "Rayman Raving Rabbids Riff Container File"},
{meta_PS2_VAS, "Pro Baseball Spirits 5 VAS Header"}, {meta_PS2_VAS, "Pro Baseball Spirits 5 VAS Header"},
{meta_PS2_TEC, "assumed TECMO badflagged stream by .tec extension"}, {meta_PS2_TEC, "assumed TECMO badflagged stream by .tec extension"},
@ -729,23 +733,24 @@ static const meta_info meta_info_list[] = {
{meta_PS2_MIHB, "MIH+MIB header"}, {meta_PS2_MIHB, "MIH+MIB header"},
{meta_DSP_WII_MUS, "mus header"}, {meta_DSP_WII_MUS, "mus header"},
{meta_WII_SNG, "SNG DSP Header"}, {meta_WII_SNG, "SNG DSP Header"},
{meta_RSD2VAG, "RSD2/VAG Header"}, {meta_RSD2VAG, "Radical RSD2/VAG header"},
{meta_RSD2PCMB, "RSD2/PCMB Header"}, {meta_RSD2PCMB, "Radical RSD2/PCMB header"},
{meta_RSD2XADP, "RSD2/XADP Header"}, {meta_RSD2XADP, "Radical RSD2/XADP header"},
{meta_RSD3VAG, "RSD3/VAG Header"}, {meta_RSD3VAG, "Radical RSD3/VAG header"},
{meta_RSD3GADP, "RSD3/GADP Header"}, {meta_RSD3GADP, "Radical RSD3/GADP header"},
{meta_RSD3PCM, "RSD3/PCM Header"}, {meta_RSD3PCM, "Radical RSD3/PCM header"},
{meta_RSD3PCMB, "RSD3/PCMB Header"}, {meta_RSD3PCMB, "Radical RSD3/PCMB header"},
{meta_RSD4PCMB, "RSD4/PCMB Header"}, {meta_RSD4PCMB, "Radical RSD4/PCMB header"},
{meta_RSD4PCM, "RSD4/PCM Header"}, {meta_RSD4PCM, "Radical RSD4/PCM header"},
{meta_RSD4RADP, "RSD4/RADP Header"}, {meta_RSD4RADP, "Radical RSD4/RADP header"},
{meta_RSD4VAG, "RSD4/VAG Header"}, {meta_RSD4VAG, "Radical RSD4/VAG header"},
{meta_RSD6XADP, "RSD6/XADP Header"}, {meta_RSD6XADP, "Radical RSD6/XADP header"},
{meta_RSD6VAG, "RSD6/VAG Header"}, {meta_RSD6VAG, "Radical RSD6/VAG header"},
{meta_RSD6WADP, "RSD6/WADP Header"}, {meta_RSD6WADP, "Radical RSD6/WADP header"},
{meta_RSD6RADP, "RSD6/RADP Header"}, {meta_RSD6RADP, "Radical RSD6/RADP header"},
{meta_RSD6XMA, "RSD6/XMA Header"}, {meta_RSD6XMA, "Radical RSD6/XMA header"},
{meta_RSD6AT3P, "RSD6/AT3+ Header"}, {meta_RSD6AT3P, "Radical RSD6/AT3+ header"},
{meta_RSD6WMA, "Radical RSD6/WMA header"},
{meta_DC_ASD, "ASD Header"}, {meta_DC_ASD, "ASD Header"},
{meta_NAOMI_SPSD, "SPSD Header"}, {meta_NAOMI_SPSD, "SPSD Header"},
{meta_FFXI_BGW, "BGW BGMStream header"}, {meta_FFXI_BGW, "BGW BGMStream header"},
@ -835,7 +840,7 @@ static const meta_info meta_info_list[] = {
{meta_PS2_MSA, "Psyvariar -Complete Edition- MSA header"}, {meta_PS2_MSA, "Psyvariar -Complete Edition- MSA header"},
{meta_PC_SMP, "Ghostbusters .smp Header"}, {meta_PC_SMP, "Ghostbusters .smp Header"},
{meta_NGC_PDT, "PDT DSP header"}, {meta_NGC_PDT, "PDT DSP header"},
{meta_NGC_BO2, "Blood Omen 2 DSP header"}, {meta_NGC_RKV, "Legacy of Kain - Blood Omen 2 RKV GC header"},
{meta_DSP_DDSP, ".DDSP header"}, {meta_DSP_DDSP, ".DDSP header"},
{meta_P3D, "Radical P3D header"}, {meta_P3D, "Radical P3D header"},
{meta_PS2_TK1, "Tekken TK5STRM1 Header"}, {meta_PS2_TK1, "Tekken TK5STRM1 Header"},
@ -922,7 +927,7 @@ static const meta_info meta_info_list[] = {
{meta_GTD, "GTD/GHS header"}, {meta_GTD, "GTD/GHS header"},
{meta_TA_AAC_X360, "tri-Ace AAC (X360) header"}, {meta_TA_AAC_X360, "tri-Ace AAC (X360) header"},
{meta_TA_AAC_PS3, "tri-Ace AAC (PS3) header"}, {meta_TA_AAC_PS3, "tri-Ace AAC (PS3) header"},
{meta_TA_AAC_VORBIS, "tri-Ace AAC (Mobile Vorbis) header"}, {meta_TA_AAC_MOBILE, "tri-Ace AAC (Mobile) header"},
{meta_PS3_MTA2, "Konami MTA2 header"}, {meta_PS3_MTA2, "Konami MTA2 header"},
{meta_NGC_ULW, "Criterion ULW raw header"}, {meta_NGC_ULW, "Criterion ULW raw header"},
{meta_PC_XA30, "Reflections XA30 PC header"}, {meta_PC_XA30, "Reflections XA30 PC header"},
@ -964,6 +969,8 @@ static const meta_info meta_info_list[] = {
{meta_WAF, "KID WAF header"}, {meta_WAF, "KID WAF header"},
{meta_WAVE, "EngineBlack .WAVE header"}, {meta_WAVE, "EngineBlack .WAVE header"},
{meta_WAVE_segmented, "EngineBlack .WAVE header (segmented)"}, {meta_WAVE_segmented, "EngineBlack .WAVE header (segmented)"},
{meta_SMV, "Cho Aniki Zero .SMV header"},
{meta_NXAP, "Nex NXAP header"},
#ifdef VGM_USE_MP4V2 #ifdef VGM_USE_MP4V2
{meta_MP4, "AAC header"}, {meta_MP4, "AAC header"},

View File

@ -89,8 +89,8 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
case layout_blocked_caf: case layout_blocked_caf:
block_update_caf(vgmstream->next_block_offset,vgmstream); block_update_caf(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_wsi_blocked: case layout_blocked_wsi:
wsi_block_update(vgmstream->next_block_offset,vgmstream); block_update_wsi(vgmstream->next_block_offset,vgmstream);
break; break;
case layout_str_snds_blocked: case layout_str_snds_blocked:
str_snds_block_update(vgmstream->next_block_offset,vgmstream); str_snds_block_update(vgmstream->next_block_offset,vgmstream);

21
src/layout/blocked_wsi.c Normal file
View File

@ -0,0 +1,21 @@
#include "layout.h"
#include "../vgmstream.h"
/* .wsi - headered blocks with a single channel */
void block_update_wsi(off_t block_offset, VGMSTREAM * vgmstream) {
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
int i;
off_t channel_block_size;
/* assume that all channels have the same size for this block */
channel_block_size = read_32bitBE(block_offset, streamFile);
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = channel_block_size - 0x10; /* remove header */
vgmstream->next_block_offset = block_offset + channel_block_size*vgmstream->channels;
for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset = block_offset + channel_block_size*i + 0x10;
}
}

View File

@ -10,12 +10,12 @@ void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREA
samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame; samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame;
if (vgmstream->layout_type == layout_interleave_shortblock && if (vgmstream->interleave_last_block_size && vgmstream->channels > 1 &&
vgmstream->current_sample - vgmstream->samples_into_block + samples_this_block> vgmstream->num_samples) { vgmstream->current_sample - vgmstream->samples_into_block + samples_this_block> vgmstream->num_samples) {
frame_size = get_vgmstream_shortframe_size(vgmstream); frame_size = get_vgmstream_shortframe_size(vgmstream);
samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream); samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream);
samples_this_block = vgmstream->interleave_smallblock_size / frame_size * samples_per_frame; samples_this_block = vgmstream->interleave_last_block_size / frame_size * samples_per_frame;
} }
while (samples_written<sample_count) { while (samples_written<sample_count) {
@ -23,7 +23,7 @@ void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREA
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) { if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
/* we assume that the loop is not back into a short block */ /* we assume that the loop is not back into a short block */
if (vgmstream->layout_type == layout_interleave_shortblock) { if (vgmstream->interleave_last_block_size && vgmstream->channels > 1) {
frame_size = get_vgmstream_frame_size(vgmstream); frame_size = get_vgmstream_frame_size(vgmstream);
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame; samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame;
@ -45,14 +45,14 @@ void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREA
if (vgmstream->samples_into_block==samples_this_block) { if (vgmstream->samples_into_block==samples_this_block) {
int chan; int chan;
if (vgmstream->layout_type == layout_interleave_shortblock && if (vgmstream->interleave_last_block_size && vgmstream->channels > 1 &&
vgmstream->current_sample + samples_this_block > vgmstream->num_samples) { vgmstream->current_sample + samples_this_block > vgmstream->num_samples) {
frame_size = get_vgmstream_shortframe_size(vgmstream); frame_size = get_vgmstream_shortframe_size(vgmstream);
samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream); samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream);
samples_this_block = vgmstream->interleave_smallblock_size / frame_size * samples_per_frame; samples_this_block = vgmstream->interleave_last_block_size / frame_size * samples_per_frame;
for (chan=0;chan<vgmstream->channels;chan++) for (chan=0;chan<vgmstream->channels;chan++)
vgmstream->ch[chan].offset+=vgmstream->interleave_block_size*(vgmstream->channels-chan)+vgmstream->interleave_smallblock_size*chan; vgmstream->ch[chan].offset+=vgmstream->interleave_block_size*(vgmstream->channels-chan)+vgmstream->interleave_last_block_size*chan;
} else { } else {
for (chan=0;chan<vgmstream->channels;chan++) for (chan=0;chan<vgmstream->channels;chan++)

View File

@ -18,8 +18,7 @@ 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_schl(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ea_1snh(off_t block_offset, VGMSTREAM * vgmstream); void block_update_ea_1snh(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_caf(off_t block_offset, VGMSTREAM * vgmstream); void block_update_caf(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_wsi(off_t block_offset, VGMSTREAM * vgmstream);
void wsi_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void str_snds_block_update(off_t block_offset, VGMSTREAM * vgmstream); void str_snds_block_update(off_t block_offset, VGMSTREAM * vgmstream);

View File

@ -1,23 +0,0 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void wsi_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
/* assume that all channels have the same size for this block */
vgmstream->current_block_offset = block_offset;
/* current_block_size is the data size in this block, so subtract header */
vgmstream->current_block_size = read_32bitBE(
vgmstream->current_block_offset,
vgmstream->ch[0].streamfile) - 0x10;
vgmstream->next_block_offset =
vgmstream->current_block_offset +
(vgmstream->current_block_size + 0x10) * vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset +
0x10 + (vgmstream->current_block_size+0x10)*i;
}
}

View File

@ -610,10 +610,6 @@
RelativePath=".\meta\ngc_bh2pcm.c" RelativePath=".\meta\ngc_bh2pcm.c"
> >
</File> </File>
<File
RelativePath=".\meta\ngc_bo2.c"
>
</File>
<File <File
RelativePath=".\meta\caf.c" RelativePath=".\meta\caf.c"
> >
@ -662,6 +658,10 @@
RelativePath=".\meta\ngc_ssm.c" RelativePath=".\meta\ngc_ssm.c"
> >
</File> </File>
<File
RelativePath=".\meta\ngc_str_cauldron.c"
>
</File>
<File <File
RelativePath=".\meta\ngc_tydsp.c" RelativePath=".\meta\ngc_tydsp.c"
> >
@ -698,6 +698,10 @@
RelativePath=".\meta\nwa.c" RelativePath=".\meta\nwa.c"
> >
</File> </File>
<File
RelativePath=".\meta\nxap.c"
>
</File>
<File <File
RelativePath=".\meta\ogg_vorbis.c" RelativePath=".\meta\ogg_vorbis.c"
> >
@ -1186,6 +1190,10 @@
RelativePath=".\meta\sli.c" RelativePath=".\meta\sli.c"
> >
</File> </File>
<File
RelativePath=".\meta\smv.c"
>
</File>
<File <File
RelativePath=".\meta\sps_n1.c" RelativePath=".\meta\sps_n1.c"
> >
@ -1471,7 +1479,7 @@
> >
</File> </File>
<File <File
RelativePath=".\coding\aica_decoder.c" RelativePath=".\coding\yamaha_decoder.c"
> >
</File> </File>
<File <File
@ -1815,7 +1823,7 @@
> >
</File> </File>
<File <File
RelativePath=".\layout\wsi_blocked.c" RelativePath=".\layout\blocked_wsi.c"
> >
</File> </File>
<File <File

View File

@ -258,7 +258,6 @@
<ClCompile Include="meta\nds_swav.c" /> <ClCompile Include="meta\nds_swav.c" />
<ClCompile Include="meta\ngc_adpdtk.c" /> <ClCompile Include="meta\ngc_adpdtk.c" />
<ClCompile Include="meta\ngc_bh2pcm.c" /> <ClCompile Include="meta\ngc_bh2pcm.c" />
<ClCompile Include="meta\ngc_bo2.c" />
<ClCompile Include="meta\caf.c" /> <ClCompile Include="meta\caf.c" />
<ClCompile Include="meta\ngc_dsp_konami.c" /> <ClCompile Include="meta\ngc_dsp_konami.c" />
<ClCompile Include="meta\ngc_dsp_mpds.c" /> <ClCompile Include="meta\ngc_dsp_mpds.c" />
@ -271,12 +270,14 @@
<ClCompile Include="meta\ngc_pdt.c" /> <ClCompile Include="meta\ngc_pdt.c" />
<ClCompile Include="meta\ngc_sck_dsp.c" /> <ClCompile Include="meta\ngc_sck_dsp.c" />
<ClCompile Include="meta\ngc_ssm.c" /> <ClCompile Include="meta\ngc_ssm.c" />
<ClCompile Include="meta\ngc_str_cauldron.c" />
<ClCompile Include="meta\ngc_tydsp.c" /> <ClCompile Include="meta\ngc_tydsp.c" />
<ClCompile Include="meta\ngc_ymf.c" /> <ClCompile Include="meta\ngc_ymf.c" />
<ClCompile Include="meta\ngc_ulw.c" /> <ClCompile Include="meta\ngc_ulw.c" />
<ClCompile Include="meta\ngc_vid1.c" /> <ClCompile Include="meta\ngc_vid1.c" />
<ClCompile Include="meta\nub_xma.c" /> <ClCompile Include="meta\nub_xma.c" />
<ClCompile Include="meta\nwa.c" /> <ClCompile Include="meta\nwa.c" />
<ClCompile Include="meta\nxap.c" />
<ClCompile Include="meta\ogg_vorbis.c" /> <ClCompile Include="meta\ogg_vorbis.c" />
<ClCompile Include="meta\ogl.c" /> <ClCompile Include="meta\ogl.c" />
<ClCompile Include="meta\omu.c" /> <ClCompile Include="meta\omu.c" />
@ -380,6 +381,7 @@
<ClCompile Include="meta\sdt.c" /> <ClCompile Include="meta\sdt.c" />
<ClCompile Include="meta\sfl.c" /> <ClCompile Include="meta\sfl.c" />
<ClCompile Include="meta\sli.c" /> <ClCompile Include="meta\sli.c" />
<ClCompile Include="meta\smv.c" />
<ClCompile Include="meta\sps_n1.c" /> <ClCompile Include="meta\sps_n1.c" />
<ClCompile Include="meta\spt_spd.c" /> <ClCompile Include="meta\spt_spd.c" />
<ClCompile Include="meta\stm.c" /> <ClCompile Include="meta\stm.c" />
@ -430,7 +432,7 @@
<ClCompile Include="meta\zwdsp.c" /> <ClCompile Include="meta\zwdsp.c" />
<ClCompile Include="coding\acm_decoder.c" /> <ClCompile Include="coding\acm_decoder.c" />
<ClCompile Include="coding\adx_decoder.c" /> <ClCompile Include="coding\adx_decoder.c" />
<ClCompile Include="coding\aica_decoder.c" /> <ClCompile Include="coding\yamaha_decoder.c" />
<ClCompile Include="coding\ea_mt_decoder.c" /> <ClCompile Include="coding\ea_mt_decoder.c" />
<ClCompile Include="coding\ea_xa_decoder.c" /> <ClCompile Include="coding\ea_xa_decoder.c" />
<ClCompile Include="coding\ea_xas_decoder.c" /> <ClCompile Include="coding\ea_xas_decoder.c" />
@ -498,7 +500,7 @@
<ClCompile Include="layout\thp_blocked.c" /> <ClCompile Include="layout\thp_blocked.c" />
<ClCompile Include="layout\vs_blocked.c" /> <ClCompile Include="layout\vs_blocked.c" />
<ClCompile Include="layout\ws_aud_blocked.c" /> <ClCompile Include="layout\ws_aud_blocked.c" />
<ClCompile Include="layout\wsi_blocked.c" /> <ClCompile Include="layout\blocked_wsi.c" />
<ClCompile Include="layout\xa_blocked.c" /> <ClCompile Include="layout\xa_blocked.c" />
<ClCompile Include="layout\xvas_block.c" /> <ClCompile Include="layout\xvas_block.c" />
<ClCompile Include="..\ext_libs\clHCA.c" /> <ClCompile Include="..\ext_libs\clHCA.c" />

View File

@ -358,9 +358,6 @@
<ClCompile Include="meta\ngc_bh2pcm.c"> <ClCompile Include="meta\ngc_bh2pcm.c">
<Filter>meta\Source Files</Filter> <Filter>meta\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="meta\ngc_bo2.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\caf.c"> <ClCompile Include="meta\caf.c">
<Filter>meta\Source Files</Filter> <Filter>meta\Source Files</Filter>
</ClCompile> </ClCompile>
@ -397,6 +394,9 @@
<ClCompile Include="meta\ngc_ssm.c"> <ClCompile Include="meta\ngc_ssm.c">
<Filter>meta\Source Files</Filter> <Filter>meta\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="meta\ngc_str_cauldron.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ngc_tydsp.c"> <ClCompile Include="meta\ngc_tydsp.c">
<Filter>meta\Source Files</Filter> <Filter>meta\Source Files</Filter>
</ClCompile> </ClCompile>
@ -415,6 +415,9 @@
<ClCompile Include="meta\nwa.c"> <ClCompile Include="meta\nwa.c">
<Filter>meta\Source Files</Filter> <Filter>meta\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="meta\nxap.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ogg_vorbis.c"> <ClCompile Include="meta\ogg_vorbis.c">
<Filter>meta\Source Files</Filter> <Filter>meta\Source Files</Filter>
</ClCompile> </ClCompile>
@ -724,6 +727,9 @@
<ClCompile Include="meta\sli.c"> <ClCompile Include="meta\sli.c">
<Filter>meta\Source Files</Filter> <Filter>meta\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="meta\smv.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\sps_n1.c"> <ClCompile Include="meta\sps_n1.c">
<Filter>meta\Source Files</Filter> <Filter>meta\Source Files</Filter>
</ClCompile> </ClCompile>
@ -868,7 +874,7 @@
<ClCompile Include="coding\adx_decoder.c"> <ClCompile Include="coding\adx_decoder.c">
<Filter>coding\Source Files</Filter> <Filter>coding\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="coding\aica_decoder.c"> <ClCompile Include="coding\yamaha_decoder.c">
<Filter>coding\Source Files</Filter> <Filter>coding\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="coding\ea_mt_decoder.c"> <ClCompile Include="coding\ea_mt_decoder.c">
@ -1069,7 +1075,7 @@
<ClCompile Include="layout\ws_aud_blocked.c"> <ClCompile Include="layout\ws_aud_blocked.c">
<Filter>layout\Source Files</Filter> <Filter>layout\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="layout\wsi_blocked.c"> <ClCompile Include="layout\blocked_wsi.c">
<Filter>layout\Source Files</Filter> <Filter>layout\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="layout\xa_blocked.c"> <ClCompile Include="layout\xa_blocked.c">

View File

@ -3,7 +3,7 @@
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
/* AKB (AAC only) - found in SQEX iOS games */ /* AKB (AAC only) - found in SQEX iOS games */
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_akb_mp4(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
size_t filesize; size_t filesize;
@ -34,74 +34,99 @@ fail:
/* AKB - found in SQEX iOS games */ /* AKB - found in SQEX iOS games */
VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset, extra_data_offset = 0; off_t start_offset, extradata_offset = 0;
size_t file_size, header_size, extra_header_size = 0, extra_data_size = 0; size_t stream_size, header_size, subheader_size = 0, extradata_size = 0;
int loop_flag = 0, channel_count, codec; int loop_flag = 0, channel_count, codec, sample_rate;
int num_samples, loop_start, loop_end;
/* check extensions */
/* checks */
/* .akb.bytes is the usual extension in later games */ /* .akb.bytes is the usual extension in later games */
if ( !check_extensions(streamFile, "akb") ) if ( !check_extensions(streamFile, "akb,bytes") )
goto fail; goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x414B4220) /* "AKB " */ if (read_32bitBE(0x00,streamFile) != 0x414B4220) /* "AKB " */
goto fail; goto fail;
if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile))
goto fail;
channel_count = read_8bit(0x0d,streamFile); /* 0x04(2): version? (iPad/IPhone?) */
loop_flag = read_32bitLE(0x18,streamFile) > 0; /* loop end */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* 0x04 (2): version (iPad/IPhone?) */
header_size = read_16bitLE(0x06,streamFile); header_size = read_16bitLE(0x06,streamFile);
file_size = read_32bitLE(0x08,streamFile);
codec = read_8bit(0x0c,streamFile);
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x0e,streamFile);
vgmstream->num_samples = read_32bitLE(0x10,streamFile);
vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile);
vgmstream->loop_end_sample = read_32bitLE(0x18,streamFile);
vgmstream->meta_type = meta_AKB;
/* should be ok but not exact (probably more complex, see AKB2) */ codec = read_8bit(0x0c,streamFile);
channel_count = read_8bit(0x0d,streamFile);
sample_rate = (uint16_t)read_16bitLE(0x0e,streamFile);
num_samples = read_32bitLE(0x10,streamFile);
loop_start = read_32bitLE(0x14,streamFile);
loop_end = read_32bitLE(0x18,streamFile);
/* possibly more complex, see AKB2 */
if (header_size >= 0x44) { /* v2 */ if (header_size >= 0x44) { /* v2 */
/* 0x10+: config? (pan, volume), 0x24: file_id? */ extradata_size = read_16bitLE(0x1c,streamFile);
extra_data_size = read_16bitLE(0x1c,streamFile); subheader_size = read_16bitLE(0x28,streamFile);
extra_header_size = read_16bitLE(0x28,streamFile); /* 0x20+: config? (pan, volume), 0x24: file_id? */
extra_data_offset = header_size + extra_header_size; extradata_offset = header_size + subheader_size;
start_offset = extra_data_offset + extra_data_size; start_offset = extradata_offset + extradata_size;
/* ~num_samples at extra_data_offset + 0x04/0x0c? */
} }
else { /* v0 */ else { /* v0 */
start_offset = header_size; start_offset = header_size;
} }
stream_size = get_streamfile_size(streamFile) - start_offset;
loop_flag = read_32bitLE(0x18,streamFile) > 0; /* loop end */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->meta_type = meta_AKB;
switch (codec) { switch (codec) {
case 0x02: { /* MSAPDCM [various SFX] */ case 0x02: { /* MSAPDCM [Dragon Quest II (iOS) sfx] */
vgmstream->coding_type = coding_MSADPCM; vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = read_16bitLE(extra_data_offset + 0x02,streamFile); vgmstream->interleave_block_size = read_16bitLE(extradata_offset + 0x02,streamFile);
/* adjusted samples; bigger or smaller than base samples, but seems more accurate /* adjusted samples; bigger or smaller than base samples, but seems more accurate
* (base samples may have more than possible and read over file size otherwise, very strange) * (base samples may have more than possible and read over file size otherwise, very strange)
* loop_end seems to exist even with loop disabled */ * loop_end seems to exist even with loop disabled */
vgmstream->num_samples = read_32bitLE(extra_data_offset + 0x04, streamFile); vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile);
vgmstream->loop_start_sample = read_32bitLE(extra_data_offset + 0x08, streamFile); vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, streamFile);
vgmstream->loop_end_sample = read_32bitLE(extra_data_offset + 0x0c, streamFile); vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, streamFile);
break; break;
} }
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_VORBIS
case 0x05: { /* Ogg Vorbis [Final Fantasy VI, Dragon Quest II-VI] */ case 0x05: { /* Ogg Vorbis [Final Fantasy VI (iOS), Dragon Quest II-VI (iOS)] */
/* Starting from an offset in the current libvorbis code is a bit hard so just use FFmpeg. VGMSTREAM *ogg_vgmstream = NULL;
* Decoding seems to produce the same output with (inaudible) +-1 lower byte differences due to rounding. */ ogg_vorbis_meta_info_t ovmi = {0};
ovmi.meta_type = vgmstream->meta_type;
ovmi.stream_size = stream_size;
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
if (ogg_vgmstream) {
close_vgmstream(vgmstream);
return ogg_vgmstream;
}
else {
goto fail;
}
break;
}
#elif defined(VGM_USE_FFMPEG)
/* Alt decoding without libvorbis (minor number of beginning samples difference).
* Otherwise same output with (inaudible) +-1 lower byte differences due to rounding. */
case 0x05: { /* Ogg Vorbis [Final Fantasy VI (iOS), Dragon Quest II-VI (iOS)] */
ffmpeg_codec_data *ffmpeg_data; ffmpeg_codec_data *ffmpeg_data;
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,file_size-start_offset); ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
if ( !ffmpeg_data ) goto fail; if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
@ -109,20 +134,30 @@ VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* These oggs have loop info in the comments, too */ /* These oggs have loop info in the comments, too */
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
break; break;
} }
#endif
#ifdef VGM_USE_FFMPEG
case 0x06: { /* aac [The World Ends with You (iPad)] */ case 0x06: { /* aac [The World Ends with You (iPad)] */
/* init_vgmstream_akb above has priority, but this works fine too */ /* init_vgmstream_akb_mp4 above has priority, but this works fine too */
ffmpeg_codec_data *ffmpeg_data; ffmpeg_codec_data *ffmpeg_data;
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,file_size-start_offset); ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size-start_offset);
if ( !ffmpeg_data ) goto fail; if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
/* remove encoder delay from the "global" sample values */ /* remove encoder delay from the "global" sample values */
vgmstream->num_samples -= ffmpeg_data->skipSamples; vgmstream->num_samples -= ffmpeg_data->skipSamples;
vgmstream->loop_start_sample -= ffmpeg_data->skipSamples; vgmstream->loop_start_sample -= ffmpeg_data->skipSamples;
@ -149,80 +184,134 @@ fail:
/* AKB2 - found in later SQEX iOS games */ /* AKB2 - found in later SQEX iOS games */
VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset, header_offset; off_t start_offset, material_offset, extradata_offset;
size_t datasize; size_t material_size, extradata_size, stream_size;
int loop_flag = 0, channel_count, codec; int loop_flag = 0, channel_count, encryption_flag, codec, sample_rate, num_samples, loop_start, loop_end;
int akb_header_size, sound_index = 0, sound_offset_data, sound, sound_header_size, material_offset_data, material_index = 0, material, extradata, encryption_flag; int total_subsongs, target_subsong = streamFile->stream_index;
/* check extensions */ /* check extensions */
/* .akb.bytes is the usual extension in later games */ /* .akb.bytes is the usual extension in later games */
if ( !check_extensions(streamFile, "akb") ) if ( !check_extensions(streamFile, "akb,bytes") )
goto fail; goto fail;
/* check header */ /* checks */
if (read_32bitBE(0x00,streamFile) != 0x414B4232) /* "AKB2" */ if (read_32bitBE(0x00,streamFile) != 0x414B4232) /* "AKB2" */
goto fail; goto fail;
if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile))
goto fail;
akb_header_size = read_16bitLE(0x06, streamFile); /* parse tables */
sound_offset_data = akb_header_size + sound_index * 0x10; {
sound = read_32bitLE(sound_offset_data + 0x04, streamFile); off_t table_offset;
sound_header_size = read_16bitLE(sound + 0x02, streamFile); size_t table_size, entry_size;
material_offset_data = sound + sound_header_size + material_index * 0x10; off_t akb_header_size = read_16bitLE(0x06, streamFile);
material = sound + read_32bitLE(material_offset_data + 0x04, streamFile); int table_count = read_8bit(0x0c, streamFile);
encryption_flag = read_8bit(material + 0x03, streamFile) & 0x08;
extradata = material + read_16bitLE(material + 0x04, streamFile);
start_offset = material + read_16bitLE(material + 0x04, streamFile) + read_32bitLE(material + 0x18, streamFile); /* probably each table has its type somewhere, but only seen last table = sound table */
header_offset = material; if (table_count > 2) /* 2 only seen in some Mobius FF sound banks */
goto fail;
entry_size = 0x10; /* technically every entry/table has its own size but to simplify... */
table_offset = read_32bitLE(akb_header_size + (table_count-1)*entry_size + 0x04, streamFile);
table_size = read_16bitLE(table_offset + 0x02, streamFile);
total_subsongs = read_8bit(table_offset + 0x0f, streamFile); /* can contain 0 entries too */
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
material_offset = table_offset + read_32bitLE(table_offset + table_size + (target_subsong-1)*entry_size + 0x04, streamFile);
}
/** stream header **/
/* 0x00: 0? */
codec = read_8bit(material_offset+0x01,streamFile);
channel_count = read_8bit(material_offset+0x02,streamFile);
encryption_flag = read_8bit(material_offset+0x03,streamFile);
material_size = read_16bitLE(material_offset+0x04,streamFile);
sample_rate = (uint16_t)read_16bitLE(material_offset+0x06,streamFile);
stream_size = read_32bitLE(material_offset+0x08,streamFile);
num_samples = read_32bitLE(material_offset+0x0c,streamFile);
loop_start = read_32bitLE(material_offset+0x10,streamFile);
loop_end = read_32bitLE(material_offset+0x14,streamFile);
extradata_size = read_32bitLE(material_offset+0x18,streamFile);
/* rest: ? (empty or 0x3f80) */
loop_flag = (loop_end > 0);
extradata_offset = material_offset + material_size;
start_offset = material_offset + material_size + extradata_size;
channel_count = read_8bit(header_offset+0x02,streamFile);
loop_flag = read_32bitLE(header_offset+0x14,streamFile) > 0; /* loop end */
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* 0x04: version? 0x08: filesize, 0x28: file_id?, others: no idea */ vgmstream->sample_rate = sample_rate;
codec = read_8bit(header_offset+0x01,streamFile); vgmstream->num_streams = total_subsongs;
datasize = read_32bitLE(header_offset+0x08,streamFile); vgmstream->stream_size = stream_size;
vgmstream->sample_rate = (uint16_t)read_16bitLE(header_offset+0x06,streamFile);
/* When loop_flag num_samples may be much larger than real num_samples (it's fine when looping is off)
* Actual num_samples would be loop_end_sample+1, but more testing is needed */
vgmstream->num_samples = read_32bitLE(header_offset+0x0c,streamFile);
vgmstream->loop_start_sample = read_32bitLE(header_offset+0x10,streamFile);
vgmstream->loop_end_sample = read_32bitLE(header_offset+0x14,streamFile);
vgmstream->meta_type = meta_AKB; vgmstream->meta_type = meta_AKB;
switch (codec) { switch (codec) {
case 0x02: { /* MSAPDCM [The Irregular at Magic High School Lost Zero (Android)] */ case 0x02: { /* MSADPCM [The Irregular at Magic High School Lost Zero (Android)] */
if (encryption_flag) goto fail; if (encryption_flag & 0x08) goto fail;
vgmstream->coding_type = coding_MSADPCM; vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = read_16bitLE(extradata + 0x02, streamFile); vgmstream->interleave_block_size = read_16bitLE(extradata_offset + 0x02, streamFile);
/* adjusted samples; bigger or smaller than base samples, but seems more accurate /* adjusted samples; bigger or smaller than base samples, but seems more accurate
* (base samples may have more than possible and read over file size otherwise, very strange) * (base samples may have more than possible and read over file size otherwise, very strange)
* loop_end seems to exist even with loop disabled */ * loop_end seems to exist even with loop disabled */
vgmstream->num_samples = read_32bitLE(extradata + 0x04, streamFile); vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile);
vgmstream->loop_start_sample = read_32bitLE(extradata + 0x08, streamFile); vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, streamFile);
vgmstream->loop_end_sample = read_32bitLE(extradata + 0x0c, streamFile); vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, streamFile);
break; break;
} }
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_VORBIS
case 0x05: { /* ogg vorbis [The World Ends with You (iPhone / latest update)] */ case 0x05: { /* Ogg Vorbis [The World Ends with You (iOS / latest update)] */
VGMSTREAM *ogg_vgmstream = NULL;
ogg_vorbis_meta_info_t ovmi = {0};
ovmi.meta_type = vgmstream->meta_type;
ovmi.total_subsongs = total_subsongs;
ovmi.stream_size = stream_size;
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
if (ogg_vgmstream) {
ogg_vgmstream->num_streams = vgmstream->num_streams;
ogg_vgmstream->stream_size = vgmstream->stream_size;
close_vgmstream(vgmstream);
return ogg_vgmstream;
}
else {
goto fail;
}
break;
}
#elif defined(VGM_USE_FFMPEG)
/* Alt decoding without libvorbis (minor number of beginning samples difference).
* Otherwise same output with (inaudible) +-1 lower byte differences due to rounding. */
case 0x05: { /* Ogg Vorbis [The World Ends with You (iOS / latest update)] */
ffmpeg_codec_data *ffmpeg_data; ffmpeg_codec_data *ffmpeg_data;
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,datasize); ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
if ( !ffmpeg_data ) goto fail; if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* When loop_flag num_samples may be much larger than real num_samples (it's fine when looping is off)
* Actual num_samples would be loop_end_sample+1, but more testing is needed */
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
break; break;
} }
#endif #endif

View File

@ -145,10 +145,8 @@ VGMSTREAM * init_vgmstream_apple_caff(STREAMFILE *streamFile) {
break; break;
default: /* "aac " "alac" etc: probably parsed by FFMpeg... */ default: /* "aac " "alac" etc: probably parsed by FFMpeg... */
VGM_LOG("CAFF: unknown codec %x\n", codec);
goto fail; goto fail;
} }
goto fail;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail; goto fail;

View File

@ -9,16 +9,16 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) {
VGMSTREAM *vgmstream = NULL; VGMSTREAM *vgmstream = NULL;
STREAMFILE *temp_streamFile = NULL; STREAMFILE *temp_streamFile = NULL;
int total_subsongs, target_subsong = streamFile->stream_index; int total_subsongs, target_subsong = streamFile->stream_index;
int type, big_endian = 0; int type, big_endian = 0, entries;
atsl_codec codec; atsl_codec codec;
const char* fake_ext; const char* fake_ext;
off_t subfile_offset; off_t subfile_offset = 0;
size_t subfile_size, header_size; size_t subfile_size = 0, header_size;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
/* check extensions /* checks */
* .atsl: header id (for G1L extractions), .atsl3: PS3 games, .atsl4: PS4 games */ /* .atsl: header id (for G1L extractions), .atsl3: PS3 games, .atsl4: PS4 games */
if ( !check_extensions(streamFile,"atsl,atsl3,atsl4")) if ( !check_extensions(streamFile,"atsl,atsl3,atsl4"))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x4154534C) /* "ATSL" */ if (read_32bitBE(0x00,streamFile) != 0x4154534C) /* "ATSL" */
@ -27,17 +27,11 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) {
/* main header (LE) */ /* main header (LE) */
header_size = read_32bitLE(0x04,streamFile); header_size = read_32bitLE(0x04,streamFile);
/* 0x08/0c: flags?, 0x10: fixed? (0x03E8) */ /* 0x08/0c: flags?, 0x10: fixed? (0x03E8) */
total_subsongs = read_32bitLE(0x14,streamFile); entries = read_32bitLE(0x14,streamFile);
/* 0x18: 0x28, or 0x30 (rarer) */ /* 0x18: 0x28, or 0x30 (rarer) */
/* 0x1c: null, 0x20: subheader size, 0x24/28: null */ /* 0x1c: null, 0x20: subheader size, 0x24/28: null */
//todo: sometimes entries are repeated/dummy and point to the first entry /* Type byte may be wrong (could need header id tests instead). Example flags at 0x08/0x0c:
if (target_subsong == 0) target_subsong = 1;
if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail;
/* Type byte may be wrong (could need header id tests instead).
* Example flags at 0x08/0x0c:
* - 00010101 00020001 .atsl3 from One Piece Pirate Warriors (PS3)[ATRAC3] * - 00010101 00020001 .atsl3 from One Piece Pirate Warriors (PS3)[ATRAC3]
* - 00000201 00020001 .atsl3 from Fist of North Star: Ken's Rage 2 (PS3)[ATRAC3] * - 00000201 00020001 .atsl3 from Fist of North Star: Ken's Rage 2 (PS3)[ATRAC3]
* 00000301 00020101 (same) * 00000301 00020101 (same)
@ -68,12 +62,47 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) {
read_32bit = big_endian ? read_32bitBE : read_32bitLE; read_32bit = big_endian ? read_32bitBE : read_32bitLE;
/* entry header (machine endianness) */ /* entries can point to the same file, count unique only */
/* 0x00: id */ {
subfile_offset = read_32bit(header_size + (target_subsong-1)*0x28 + 0x04,streamFile); int i,j;
subfile_size = read_32bit(header_size + (target_subsong-1)*0x28 + 0x08,streamFile);
/* 0x08+: sample rate/num_samples/loop_start/etc, matching subfile header */ total_subsongs = 0;
/* some kind of seek/switch table follows (optional, found in .atsl3) */ if (target_subsong == 0) target_subsong = 1;
/* parse entry header (in machine endianness) */
for (i = 0; i < entries; i++) {
int is_unique = 1;
off_t entry_offset = read_32bit(header_size + i*0x28 + 0x04,streamFile);
size_t entry_size = read_32bit(header_size + i*0x28 + 0x08,streamFile);
/* 0x00: id?, 0x08+: sample rate/num_samples/loop_start/etc, matching subfile header */
/* check if current entry was repeated in a prev entry */
for (j = 0; j < i; j++) {
off_t prev_offset = read_32bit(header_size + j*0x28 + 0x04,streamFile);
if (prev_offset == entry_offset) {
is_unique = 0;
break;
}
}
if (!is_unique)
continue;
total_subsongs++;
/* target GET, but keep going to count subsongs */
if (!subfile_offset && target_subsong == total_subsongs) {
subfile_offset = entry_offset;
subfile_size = entry_size;
}
}
}
if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail;
if (!subfile_offset || !subfile_size) goto fail;
/* some kind of seek/switch table may follow (optional, found in .atsl3) */
temp_streamFile = setup_atsl_streamfile(streamFile, subfile_offset,subfile_size, fake_ext); temp_streamFile = setup_atsl_streamfile(streamFile, subfile_offset,subfile_size, fake_ext);
if (!temp_streamFile) goto fail; if (!temp_streamFile) goto fail;

View File

@ -49,7 +49,7 @@ static STREAMFILE* setup_atx_streamfile(STREAMFILE *streamFile) {
num_segments = read_16bitLE(0x1e,streamFile); num_segments = read_16bitLE(0x1e,streamFile);
/* expected segment name: X_XXX_XXX_0n.ATX, starting from n=1 */ /* expected segment name: X_XXX_XXX_0n.ATX, starting from n=1 */
get_streamfile_name(streamFile, filename,PATH_LIMIT); get_streamfile_filename(streamFile, filename,PATH_LIMIT);
filename_len = strlen(filename); filename_len = strlen(filename);
if (filename_len < 7 || filename[filename_len - 5] != '1') goto fail; if (filename_len < 7 || filename[filename_len - 5] != '1') goto fail;
@ -96,12 +96,16 @@ static STREAMFILE* setup_atx_streamfile(STREAMFILE *streamFile) {
if (!new_streamFile) goto fail; if (!new_streamFile) goto fail;
temp_streamFile = new_streamFile; temp_streamFile = new_streamFile;
/* if all this worked we'll have this frankenstein streamfile:
* fakename( clamp( multifile( segment0=clamp(standard(FILE)), segment1=clamp(standard(FILE)) ) ) ) */
return temp_streamFile; return temp_streamFile;
fail: fail:
if (!temp_streamFile) { if (!temp_streamFile) {
for (i = 0; i < num_segments; i++) for (i = 0; i < num_segments; i++) {
close_streamfile(segment_streamFiles[i]); close_streamfile(segment_streamFiles[i]);
}
} else { } else {
close_streamfile(temp_streamFile); /* closes all segments */ close_streamfile(temp_streamFile); /* closes all segments */
} }

View File

@ -112,22 +112,14 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) {
} }
vgmstream->coding_type = coding_type; vgmstream->coding_type = coding_type;
if (channel_count == 1) vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
vgmstream->layout_type = layout_none;
else
{
if (ima)
vgmstream->layout_type = layout_interleave;
else
vgmstream->layout_type = layout_interleave_shortblock;
}
vgmstream->meta_type = meta_CSTM; vgmstream->meta_type = meta_CSTM;
if (ima) if (ima) {
vgmstream->interleave_block_size = 0x200; vgmstream->interleave_block_size = 0x200;
else { } else {
vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile); vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile);
vgmstream->interleave_smallblock_size = read_32bitLE(info_offset + 0x44, streamFile); vgmstream->interleave_last_block_size = read_32bitLE(info_offset + 0x44, streamFile);
} }
if (vgmstream->coding_type == coding_NGC_DSP) { if (vgmstream->coding_type == coding_NGC_DSP) {

View File

@ -121,22 +121,14 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) {
} }
vgmstream->coding_type = coding_type; vgmstream->coding_type = coding_type;
if (channel_count == 1) vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
vgmstream->layout_type = layout_none;
else
{
if (ima)
vgmstream->layout_type = layout_interleave;
else
vgmstream->layout_type = layout_interleave_shortblock;
}
vgmstream->meta_type = meta_FSTM; vgmstream->meta_type = meta_FSTM;
if (ima) if (ima)
vgmstream->interleave_block_size = 0x200; vgmstream->interleave_block_size = 0x200;
else { else {
vgmstream->interleave_block_size = read_32bit(info_offset + 0x34, streamFile); vgmstream->interleave_block_size = read_32bit(info_offset + 0x34, streamFile);
vgmstream->interleave_smallblock_size = read_32bit(info_offset + 0x44, streamFile); vgmstream->interleave_last_block_size = read_32bit(info_offset + 0x44, streamFile);
} }
if (vgmstream->coding_type == coding_NGC_DSP) { if (vgmstream->coding_type == coding_NGC_DSP) {

View File

@ -123,15 +123,10 @@ VGMSTREAM * init_vgmstream_bfwav(STREAMFILE *streamFile) {
{ {
int i; int i;
for (i = 0; i<channel_count; i++) { for (i = 0; i<channel_count; i++) {
if (vgmstream->layout_type == layout_interleave_shortblock) if (vgmstream->layout_type == layout_interleave)
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename, vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
vgmstream->interleave_block_size);
else if (vgmstream->layout_type == layout_interleave)
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
STREAMFILE_DEFAULT_BUFFER_SIZE);
else else
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename, vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,0x1000);
0x1000);
if (!vgmstream->ch[i].streamfile) goto fail; if (!vgmstream->ch[i].streamfile) goto fail;

View File

@ -91,10 +91,7 @@ VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_type; vgmstream->coding_type = coding_type;
if (channel_count==1) vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
vgmstream->layout_type = layout_none;
else
vgmstream->layout_type = layout_interleave_shortblock;
vgmstream->meta_type = meta_RSTM; vgmstream->meta_type = meta_RSTM;
if (atlus_shrunken_head) if (atlus_shrunken_head)
vgmstream->meta_type = meta_RSTM_shrunken; vgmstream->meta_type = meta_RSTM_shrunken;
@ -105,7 +102,7 @@ VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile) {
} }
vgmstream->interleave_block_size = read_32bitBE(head_offset+0x38,streamFile); vgmstream->interleave_block_size = read_32bitBE(head_offset+0x38,streamFile);
vgmstream->interleave_smallblock_size = read_32bitBE(head_offset+0x48,streamFile); vgmstream->interleave_last_block_size = read_32bitBE(head_offset+0x48,streamFile);
if (vgmstream->coding_type == coding_NGC_DSP) { if (vgmstream->coding_type == coding_NGC_DSP) {
off_t coef_offset; off_t coef_offset;
@ -139,12 +136,7 @@ VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile) {
{ {
int i; int i;
for (i=0;i<channel_count;i++) { for (i=0;i<channel_count;i++) {
if (vgmstream->layout_type==layout_interleave_shortblock) vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
vgmstream->interleave_block_size);
else
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
0x1000);
if (!vgmstream->ch[i].streamfile) goto fail; if (!vgmstream->ch[i].streamfile) goto fail;

View File

@ -5,9 +5,12 @@
VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset; off_t start_offset;
size_t data_size;
int loop_flag, channel_count; int loop_flag, channel_count;
/* check extension (.dvi: original, .idvi: renamed to header id) */
/* checks*/
/* .dvi: original, .idvi: renamed to header id */
if ( !check_extensions(streamFile,"dvi,idvi") ) if ( !check_extensions(streamFile,"dvi,idvi") )
goto fail; goto fail;
@ -18,6 +21,7 @@ VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
loop_flag = (read_32bitLE(0x0C,streamFile) != 0); loop_flag = (read_32bitLE(0x0C,streamFile) != 0);
channel_count = read_32bitLE(0x04,streamFile); /* always 2? */ channel_count = read_32bitLE(0x04,streamFile); /* always 2? */
start_offset = 0x800; start_offset = 0x800;
data_size = get_streamfile_size(streamFile) - start_offset;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
@ -25,21 +29,16 @@ VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x08,streamFile); vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
vgmstream->num_samples = ima_bytes_to_samples(get_streamfile_size(streamFile) - start_offset, channel_count); vgmstream->num_samples = ima_bytes_to_samples(data_size, channel_count);
vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile); vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile);
vgmstream->loop_end_sample = ima_bytes_to_samples(get_streamfile_size(streamFile) - start_offset, channel_count); vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_DVI_IMA_int;
vgmstream->meta_type = meta_DC_IDVI; vgmstream->meta_type = meta_DC_IDVI;
vgmstream->coding_type = coding_DVI_IMA_int;
/* Calculating the short block... */ vgmstream->layout_type = layout_interleave;
if (channel_count > 1) {
vgmstream->interleave_block_size = 0x400; vgmstream->interleave_block_size = 0x400;
vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%(vgmstream->channels*vgmstream->interleave_block_size))/vgmstream->channels; if (vgmstream->interleave_block_size)
vgmstream->layout_type = layout_interleave_shortblock; vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
} else {
vgmstream->layout_type = layout_none;
}
/* open the file for reading */ /* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )

View File

@ -26,17 +26,14 @@ VGMSTREAM * init_vgmstream_idsp2(STREAMFILE *streamFile) {
channel_count = read_32bitBE(0xC4,streamFile); channel_count = read_32bitBE(0xC4,streamFile);
if (channel_count > 8) if (channel_count > 8)
{
goto fail; goto fail;
}
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = (channel_count * 0x60) + 0x100; start_offset = (channel_count * 0x60) + 0x100;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0xC8,streamFile); vgmstream->sample_rate = read_32bitBE(0xC8,streamFile);
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = (read_32bitBE(0x14,streamFile))*14/8/channel_count; vgmstream->num_samples = (read_32bitBE(0x14,streamFile))*14/8/channel_count;
@ -45,19 +42,15 @@ VGMSTREAM * init_vgmstream_idsp2(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = (read_32bitBE(0xD4,streamFile)); vgmstream->loop_end_sample = (read_32bitBE(0xD4,streamFile));
} }
if (channel_count == 1) if (channel_count == 1) {
{
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
} }
else if (channel_count > 1) else if (channel_count > 1) {
{ if (read_32bitBE(0xD8,streamFile) == 0) {
if (read_32bitBE(0xD8,streamFile) == 0)
{
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = (get_streamfile_size(streamFile)-start_offset)/2; vgmstream->interleave_block_size = (get_streamfile_size(streamFile)-start_offset)/2;
} }
else if (read_32bitBE(0xD8,streamFile) > 0) else if (read_32bitBE(0xD8,streamFile) > 0) {
{
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0xD8,streamFile); vgmstream->interleave_block_size = read_32bitBE(0xD8,streamFile);
} }
@ -121,17 +114,13 @@ VGMSTREAM * init_vgmstream_idsp3(STREAMFILE *streamFile) {
channel_count = read_32bitBE(0x24,streamFile); channel_count = read_32bitBE(0x24,streamFile);
if (channel_count > 8) if (channel_count > 8)
{
goto fail; goto fail;
}
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = (channel_count*0x60)+0xC; start_offset = (channel_count*0x60)+0xC;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x14,streamFile); vgmstream->sample_rate = read_32bitBE(0x14,streamFile);
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x0C,streamFile); vgmstream->num_samples = read_32bitBE(0x0C,streamFile);
@ -141,8 +130,8 @@ VGMSTREAM * init_vgmstream_idsp3(STREAMFILE *streamFile) {
} }
vgmstream->interleave_block_size = read_32bitBE(0x04,streamFile); vgmstream->interleave_block_size = read_32bitBE(0x04,streamFile);
vgmstream->interleave_smallblock_size = ((vgmstream->num_samples/7*8)%(vgmstream->interleave_block_size)/vgmstream->channels); vgmstream->interleave_last_block_size = ((vgmstream->num_samples/7*8)%(vgmstream->interleave_block_size)/vgmstream->channels);
vgmstream->layout_type = layout_interleave_shortblock; vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_IDSP; vgmstream->meta_type = meta_IDSP;
@ -170,7 +159,6 @@ VGMSTREAM * init_vgmstream_idsp3(STREAMFILE *streamFile) {
vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+ vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i; vgmstream->interleave_block_size*i;
} }
} }
@ -201,17 +189,13 @@ VGMSTREAM * init_vgmstream_idsp4(STREAMFILE *streamFile) {
channel_count = read_32bitBE(0x0C,streamFile); channel_count = read_32bitBE(0x0C,streamFile);
if (channel_count > 2) // Refuse everything else for now if (channel_count > 2) // Refuse everything else for now
{
goto fail; goto fail;
}
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x70; start_offset = 0x70;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x08,streamFile); vgmstream->sample_rate = read_32bitBE(0x08,streamFile);
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x04,streamFile)/channel_count/8*14; vgmstream->num_samples = read_32bitBE(0x04,streamFile)/channel_count/8*14;
@ -220,12 +204,10 @@ VGMSTREAM * init_vgmstream_idsp4(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = read_32bitBE(0x04,streamFile)/channel_count/8*14; vgmstream->loop_end_sample = read_32bitBE(0x04,streamFile)/channel_count/8*14;
} }
if (channel_count == 1) if (channel_count == 1) {
{
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
} }
else else {
{
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x10,streamFile); vgmstream->interleave_block_size = read_32bitBE(0x10,streamFile);
} }

View File

@ -95,7 +95,6 @@ typedef struct {
int loop_end_found; int loop_end_found;
int32_t loop_end; int32_t loop_end;
meta_t meta_type; meta_t meta_type;
layout_t layout_type;
off_t stream_size; off_t stream_size;
int total_subsongs; int total_subsongs;
@ -106,9 +105,9 @@ typedef struct {
off_t scd_xor_length; off_t scd_xor_length;
uint32_t sngw_xor; uint32_t sngw_xor;
} vgm_vorbis_info_t; } ogg_vorbis_meta_info_t;
VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks, off_t other_header_bytes, const vgm_vorbis_info_t *vgm_inf); VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callbacks *callbacks, off_t other_header_bytes, const ogg_vorbis_meta_info_t *ovmi);
VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE * streamFile);
#endif #endif
@ -126,7 +125,7 @@ VGMSTREAM * init_vgmstream_mp4_aac_ffmpeg(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_mp4_aac(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_mp4_aac(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_mp4_aac_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size); VGMSTREAM * init_vgmstream_mp4_aac_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size);
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_akb_mp4(STREAMFILE *streamFile);
#endif #endif
VGMSTREAM * init_vgmstream_sfl(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_sfl(STREAMFILE * streamFile);
@ -308,6 +307,7 @@ VGMSTREAM * init_vgmstream_rsd6radp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_rsd6xma(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_rsd6xma(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_rsd6wma(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_dc_asd(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_dc_asd(STREAMFILE * streamFile);
@ -477,7 +477,7 @@ VGMSTREAM * init_vgmstream_ps2_khv(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pc_smp(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_pc_smp(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_bo2(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ngc_rkv(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_dsp_ddsp(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_dsp_ddsp(STREAMFILE* streamFile);
@ -622,8 +622,8 @@ VGMSTREAM * init_vgmstream_x360_cxs(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_dsp_adx(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_dsp_adx(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile);
@ -646,6 +646,7 @@ VGMSTREAM * init_vgmstream_gtd(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ta_aac_x360(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ta_aac_x360(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ta_aac_ps3(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ta_aac_ps3(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ta_aac_mobile_vorbis(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps3_mta2(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps3_mta2(STREAMFILE *streamFile);
@ -711,4 +712,9 @@ VGMSTREAM * init_vgmstream_waf(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_wave(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_wave(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_smv(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_nxap(STREAMFILE * streamFile);
#endif /*_META_H*/ #endif /*_META_H*/

View File

@ -12,23 +12,20 @@
/* MOGG - Harmonix Music Systems (Guitar Hero)[Unencrypted Type] */ /* MOGG - Harmonix Music Systems (Guitar Hero)[Unencrypted Type] */
VGMSTREAM * init_vgmstream_mogg(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_mogg(STREAMFILE *streamFile) {
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
/* check extension, case insensitive */ /* checks */
streamFile->get_name(streamFile, filename, sizeof(filename)); if (!check_extensions(streamFile, "mogg"))
if (strcasecmp("mogg", filename_extension(filename))) goto fail; goto fail;
{ {
vgm_vorbis_info_t inf; ogg_vorbis_meta_info_t ovmi = {0};
VGMSTREAM * result = NULL; VGMSTREAM * result = NULL;
memset(&inf, 0, sizeof(inf)); ovmi.meta_type = meta_MOGG;
inf.layout_type = layout_ogg_vorbis;
inf.meta_type = meta_MOGG;
start_offset = read_32bitLE(0x04, streamFile); start_offset = read_32bitLE(0x04, streamFile);
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); result = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
if (result != NULL) { if (result != NULL) {
return result; return result;

View File

@ -1,88 +1,55 @@
#include "meta.h" #include "meta.h"
#include "../util.h" #include "../util.h"
/* SPSD (Guilty Gear X [NAOMI GD-ROM]) */ /* SPSD - Naomi GD-ROM streams [Guilty Gear X (Naomi), Crazy Taxi (Naomi), Virtua Tennis 2 (Naomi)] */
VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
int coding; size_t data_size;
int loop_flag; int loop_flag, channel_count;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("spsd",filename_extension(filename))) goto fail;
/* check header */ /* checks */
if (!check_extensions(streamFile, "spsd"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53505344) /* "SPSD" */ if (read_32bitBE(0x00,streamFile) != 0x53505344) /* "SPSD" */
goto fail; goto fail;
loop_flag = 0; loop_flag = 0;
channel_count = 2; channel_count = 2;
start_offset = 0x40;
data_size = get_streamfile_size(streamFile) - start_offset;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x40;
vgmstream->channels = channel_count;
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x2A,streamFile); vgmstream->sample_rate = (uint16_t)read_16bitLE(0x2A,streamFile);
vgmstream->num_samples = read_32bitLE(0x0C,streamFile);
switch (read_8bit(0x8,streamFile)) vgmstream->meta_type = meta_NAOMI_SPSD;
{ switch (read_8bit(0x08,streamFile)) {
case 0x01: case 0x01: /* [Virtua Tennis 2 (Naomi)] */
coding = coding_PCM8; vgmstream->coding_type = coding_PCM8;
break; break;
case 0x03: case 0x03:
coding = coding_AICA; vgmstream->coding_type = coding_AICA;
break; break;
default: default:
goto fail; goto fail;
} }
vgmstream->layout_type = layout_interleave;
vgmstream->coding_type = coding;
vgmstream->num_samples = read_32bitLE(0x0C,streamFile);
#if 0
if (loop_flag)
{
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile);
}
#endif
vgmstream->interleave_block_size = 0x2000; vgmstream->interleave_block_size = 0x2000;
if (channel_count > 1) { if (vgmstream->interleave_block_size)
vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%(vgmstream->channels*vgmstream->interleave_block_size))/vgmstream->channels; vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
vgmstream->layout_type = layout_interleave_shortblock;
} else {
vgmstream->layout_type = layout_none;
}
vgmstream->meta_type = meta_NAOMI_SPSD;
/* 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;
vgmstream->ch[i].adpcm_step_index = 0x7f; /* AICA */
}
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -4,103 +4,66 @@
/* STRM - common Nintendo NDS streaming format */ /* STRM - common Nintendo NDS streaming format */
VGMSTREAM * init_vgmstream_nds_strm(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_nds_strm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
coding_t coding_type;
int codec_number;
int channel_count;
int loop_flag;
off_t start_offset; off_t start_offset;
int channel_count, loop_flag, codec;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("strm",filename_extension(filename))) goto fail;
/* check header */ /* checks */
if ((uint32_t)read_32bitBE(0x00,streamFile)!=0x5354524D) /* STRM */ if (!check_extensions(streamFile, "strm"))
goto fail;
if ((uint32_t)read_32bitBE(0x04,streamFile)!=0xFFFE0001 && /* Old Header Check */
((uint32_t)read_32bitBE(0x04,streamFile)!=0xFEFF0001)) /* Some newer games have a new flag */
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x5354524D) /* "STRM" */
goto fail;
/* check for HEAD section */ if (read_32bitBE(0x04,streamFile) != 0xFFFE0001 && /* Old Header Check */
if ((uint32_t)read_32bitBE(0x10,streamFile)!=0x48454144 && /* "HEAD" */ (read_32bitBE(0x04,streamFile) != 0xFEFF0001)) /* Some newer games have a new flag */
(uint32_t)read_32bitLE(0x14,streamFile)!=0x50) /* 0x50-sized head is all I've seen */
goto fail; goto fail;
/* check type details */ if (read_32bitBE(0x10,streamFile) != 0x48454144 && /* "HEAD" */
codec_number = read_8bit(0x18,streamFile); read_32bitLE(0x14,streamFile) != 0x50) /* 0x50-sized head is all I've seen */
goto fail;
codec = read_8bit(0x18,streamFile);
loop_flag = read_8bit(0x19,streamFile); loop_flag = read_8bit(0x19,streamFile);
channel_count = read_8bit(0x1a,streamFile); channel_count = read_8bit(0x1a,streamFile);
if (channel_count > 2) goto fail;
switch (codec_number) { start_offset = read_32bitLE(0x28,streamFile);
case 0:
coding_type = coding_PCM8;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x1c,streamFile);
vgmstream->num_samples = read_32bitLE(0x24,streamFile);
vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->meta_type = meta_STRM;
switch (codec) {
case 0x00: /* [Bleach - Dark Souls (DS)] */
vgmstream->coding_type = coding_PCM8;
break; break;
case 1: case 0x01:
coding_type = coding_PCM16LE; vgmstream->coding_type = coding_PCM16LE;
break; break;
case 2: case 0x02: /* [SaGa 2 (DS)] */
coding_type = coding_NDS_IMA; vgmstream->coding_type = coding_NDS_IMA;
break; break;
default: default:
goto fail; goto fail;
} }
vgmstream->layout_type = layout_interleave;
/* TODO: only mono and stereo supported */
if (channel_count < 1 || channel_count > 2) goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitLE(0x24,streamFile);
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x1c,streamFile);
/* channels and loop flag are set by allocate_vgmstream */
vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_type;
vgmstream->meta_type = meta_STRM;
vgmstream->interleave_block_size = read_32bitLE(0x30,streamFile); vgmstream->interleave_block_size = read_32bitLE(0x30,streamFile);
vgmstream->interleave_smallblock_size = read_32bitLE(0x38,streamFile); vgmstream->interleave_last_block_size = read_32bitLE(0x38,streamFile);
if (coding_type==coding_PCM8 || coding_type==coding_PCM16LE)
vgmstream->layout_type = layout_none;
else
vgmstream->layout_type = layout_interleave_shortblock;
start_offset = read_32bitLE(0x28,streamFile);
/* open the file for reading by each channel */
{
int i;
for (i=0;i<channel_count;i++) {
if (vgmstream->layout_type==layout_interleave_shortblock)
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
vgmstream->interleave_block_size);
else
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
0x1000);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=
start_offset + i*vgmstream->interleave_block_size;
}
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -1,100 +0,0 @@
#include "meta.h"
#include "../util.h"
/* BO2 (Blood Omen 2 NGC) */
VGMSTREAM * init_vgmstream_ngc_bo2(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag;
int channels;
int channel_count;
off_t start_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("bo2",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x0) /* "IDSP" */
goto fail;
switch (read_32bitBE(0x10,streamFile))
{
case 0x0:
channels = 1;
break;
case 0x1:
channels = 2;
break;
default:
goto fail;
}
if ((get_streamfile_size(streamFile)) < ((read_32bitBE(0x0C,streamFile)/14*8*channels)+0x800))
{
goto fail;
}
channel_count = channels;
loop_flag = (read_32bitBE(0x08,streamFile) != 0xFFFFFFFF);
/* 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_32bitBE(0x04,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x0C,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitBE(0x08,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile);
}
if (channel_count == 1)
{
vgmstream->layout_type = layout_none;
}
else
{
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x400;
}
vgmstream->meta_type = meta_NGC_BO2;
{
int i;
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x24+i*2,streamFile);
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x52+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;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -24,6 +24,7 @@ struct dsp_header {
uint16_t loop_ps; uint16_t loop_ps;
int16_t loop_hist1; int16_t loop_hist1;
int16_t loop_hist2; int16_t loop_hist2;
/* later/mdsp extension */
int16_t channel_count; int16_t channel_count;
int16_t block_size; int16_t block_size;
}; };
@ -158,8 +159,10 @@ VGMSTREAM * init_vgmstream_ngc_dsp_std(STREAMFILE *streamFile) {
int i; int i;
/* check extension, case insensitive */ /* check extension, case insensitive */
/* .dsp: standard, .adp: Dr. Muto (GC) mono files */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("dsp",filename_extension(filename))) goto fail; if (strcasecmp("dsp",filename_extension(filename)) &&
strcasecmp("adp", filename_extension(filename))) goto fail;
if (read_dsp_header(&header, 0, streamFile)) goto fail; if (read_dsp_header(&header, 0, streamFile)) goto fail;
@ -301,11 +304,11 @@ VGMSTREAM * init_vgmstream_ngc_mdsp_std(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave_shortblock; vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave;
vgmstream->meta_type = meta_DSP_STD; vgmstream->meta_type = meta_DSP_STD;
vgmstream->interleave_block_size = header.block_size * 8; vgmstream->interleave_block_size = header.block_size * 8;
if (vgmstream->interleave_block_size) if (vgmstream->interleave_block_size)
vgmstream->interleave_smallblock_size = (header.nibble_count / 2 % vgmstream->interleave_block_size + 7) / 8 * 8; vgmstream->interleave_last_block_size = (header.nibble_count / 2 % vgmstream->interleave_block_size + 7) / 8 * 8;
for (i = 0; i < channel_count; i++) { for (i = 0; i < channel_count; i++) {
if (read_dsp_header(&header, header_size * i, streamFile)) goto fail; if (read_dsp_header(&header, header_size * i, streamFile)) goto fail;
@ -581,67 +584,6 @@ fail:
return NULL; return NULL;
} }
/* str: a very simple header format with implicit loop values
* it's allways in interleaved stereo format
*/
VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
const off_t start_offset = 0x60;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("str",filename_extension(filename))) goto fail;
/* always 0xFAAF0001 @ offset 0 */
if (read_32bitBE(0x00,streamFile)!=0xFAAF0001) goto fail;
/* build the VGMSTREAM */
/* always loop & stereo */
vgmstream = allocate_vgmstream(2,1);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitBE(0x08,streamFile);
vgmstream->sample_rate = read_32bitBE(0x04,streamFile);
/* always loop to the beginning */
vgmstream->loop_start_sample=0;
vgmstream->loop_end_sample=vgmstream->num_samples;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x0C,streamFile);
vgmstream->meta_type = meta_DSP_STR;
/* coeffs */
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x10+(i*2),streamFile);
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x30+(i*2),streamFile);
}
/* open the file for reading */
for (i=0;i<2;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
vgmstream->interleave_block_size);
if (!vgmstream->ch[i].streamfile) goto fail;
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;
}
/* a bunch of formats that are identical except for file extension, /* a bunch of formats that are identical except for file extension,
* but have different interleaves */ * but have different interleaves */
VGMSTREAM * init_vgmstream_ngc_dsp_std_int(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_ngc_dsp_std_int(STREAMFILE *streamFile) {
@ -882,7 +824,6 @@ fail:
#define SADB_MAX_CHANNELS 2 #define SADB_MAX_CHANNELS 2
/* sadb - Procyon Studio header + interleaved dsp [Shiren the Wanderer 3 (Wii), Disaster: Day of Crisis (Wii)] */ /* sadb - Procyon Studio header + interleaved dsp [Shiren the Wanderer 3 (Wii), Disaster: Day of Crisis (Wii)] */
VGMSTREAM * init_vgmstream_sadb(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_sadb(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset, header_offset; off_t start_offset, header_offset;
size_t header_spacing, interleave; size_t header_spacing, interleave;
@ -936,180 +877,103 @@ fail:
return NULL; return NULL;
} }
/* .wsi as found in Alone in the Dark for Wii */ #define WSI_MAX_CHANNELS 2
/* These appear to be standard .dsp, but interleaved in a blocked format */ /* .wsi - blocked dsp [Alone in the Dark (Wii)] */
VGMSTREAM * init_vgmstream_wsi(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_wsi(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; off_t start_offset, header_offset;
struct dsp_header header[2]; size_t header_spacing;
off_t start_offset[2]; struct dsp_header ch_header[WSI_MAX_CHANNELS];
int channel_count; int channel_count;
size_t est_block_size = 0;
/* check extension, case insensitive */ /* checks */
streamFile->get_name(streamFile,filename,sizeof(filename)); if (!check_extensions(streamFile, "wsi"))
if (strcasecmp("wsi",filename_extension(filename))) goto fail; goto fail;
/* I don't know if this is actually the channel count, or a block type /* I don't know if this is actually the channel count, or a block type
for the first block. Won't know until I see a mono .wsi */ * for the first block. Won't know until I see a mono .wsi */
channel_count = read_32bitBE(0x04,streamFile); channel_count = read_32bitBE(0x04,streamFile);
/* I've only allocated two headers, and I want to be alerted if a mono
.wsi shows up */
if (channel_count != 2) goto fail; if (channel_count != 2) goto fail;
/* check for consistent block headers */ /* check for consistent block headers */
{ {
off_t check_offset; off_t block_offset;
off_t block_size_has_been; off_t block_size_has_been;
int i; int i;
check_offset = read_32bitBE(0x0,streamFile); block_offset = read_32bitBE(0x00,streamFile);
if (check_offset < 8) goto fail; if (block_offset < 0x08) goto fail;
block_size_has_been = check_offset; block_size_has_been = block_offset;
/* check 4 blocks, to get an idea */ /* check 4 blocks, to get an idea */
for (i = 0; i < 4*channel_count; i++) { for (i = 0; i < 4*channel_count; i++) {
off_t block_size; off_t block_size = read_32bitBE(block_offset,streamFile);
block_size = read_32bitBE(check_offset,streamFile);
/* expect at least the block header */ if (block_size < 0x10)
if (block_size < 0x10) goto fail; goto fail; /* expect at least the block header */
if (i%channel_count+1 != read_32bitBE(block_offset+0x08,streamFile))
goto fail; /* expect the channel numbers to alternate */
/* expect the channel numbers to alternate */ if (i%channel_count==0)
if (i%channel_count+1 != read_32bitBE(check_offset+8,streamFile)) goto fail; block_size_has_been = block_size;
else if (block_size != block_size_has_been)
goto fail; /* expect every block in a set of channels to have the same size */
/* expect every block in a set of channels to have the same size */ block_offset += block_size;
if (i%channel_count==0) block_size_has_been = block_size;
else if (block_size != block_size_has_been) goto fail;
/* get an estimate of block size for buffer sizing */
if (block_size > est_block_size) est_block_size = block_size;
check_offset += block_size;
} }
} }
/* look at DSP headers */ start_offset = read_32bitBE(0x00, streamFile);
header_offset = start_offset + 0x10;
header_spacing = read_32bitBE(start_offset,streamFile);
{ /* read dsp */
off_t check_offset; if (!dsp_load_header(ch_header, channel_count, streamFile,header_offset,header_spacing)) goto fail;
int i; if (!check_dsp_format(ch_header, channel_count)) goto fail;
if (!check_dsp_samples(ch_header, channel_count)) goto fail;
check_offset = read_32bitBE(0x0,streamFile); //if (!check_dsp_initial_ps(ch_header, channel_count, streamFile,start_offset,interleave)) goto fail;
//if (!check_dsp_loop_ps(ch_header, channel_count, streamFile,start_offset,interleave)) goto fail;
for (i=0;i<channel_count;i++) {
off_t block_size;
block_size = read_32bitBE(check_offset,streamFile);
/* make sure block is actually big enough to hold the dsp header
and beginning of first frame */
if (block_size < 0x61+0x10) goto fail;
if (read_dsp_header(&header[i], check_offset+0x10, streamFile)) goto fail;
start_offset[i] = check_offset + 0x60+0x10;
/* check initial predictor/scale */
if (header[i].initial_ps != (uint8_t)read_8bit(check_offset+0x60+0x10,streamFile))
goto fail;
/* check type==0 and gain==0 */
if (header[i].format || header[i].gain)
goto fail;
#if 0
/* difficult to use this with blocks, but might be worth doing */
if (header[i].loop_flag) {
off_t loop_off;
/* check loop predictor/scale */
loop_off = header[i].loop_start_offset/16*8;
if (header[i].loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile))
goto fail;
}
#endif
check_offset += block_size;
}
} /* done looking at headers */
/* check for agreement (two channels only) */
if (
header[0].sample_count != header[1].sample_count ||
header[0].nibble_count != header[1].nibble_count ||
header[0].sample_rate != header[1].sample_rate ||
header[0].loop_flag != header[1].loop_flag ||
header[0].loop_start_offset != header[1].loop_start_offset ||
header[0].loop_end_offset != header[1].loop_end_offset
) goto fail;
vgmstream = allocate_vgmstream(channel_count,header[0].loop_flag); /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,ch_header[0].loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ vgmstream->sample_rate = ch_header[0].sample_rate;
/* incomplete last frame is missing */
vgmstream->num_samples = header[0].sample_count/14*14;
vgmstream->sample_rate = header[0].sample_rate;
vgmstream->loop_start_sample = dsp_nibbles_to_samples( vgmstream->num_samples = ch_header[0].sample_count / 14 * 14; /* remove incomplete last frame */
header[0].loop_start_offset); vgmstream->loop_start_sample = dsp_nibbles_to_samples(ch_header[0].loop_start_offset);
vgmstream->loop_end_sample = dsp_nibbles_to_samples( vgmstream->loop_end_sample = dsp_nibbles_to_samples(ch_header[0].loop_end_offset)+1;
header[0].loop_end_offset)+1; if (vgmstream->loop_end_sample > vgmstream->num_samples) /* don't know why, but it does happen*/
/* don't know why, but it does happen*/
if (vgmstream->loop_end_sample > vgmstream->num_samples)
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_wsi_blocked;
vgmstream->meta_type = meta_DSP_WSI; vgmstream->meta_type = meta_DSP_WSI;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_blocked_wsi;
/* coeffs */ setup_vgmstream_dsp(vgmstream, ch_header);
{
int i,j;
for (j=0;j<channel_count;j++) {
for (i=0;i<16;i++) {
vgmstream->ch[j].adpcm_coef[i] = header[j].coef[i];
}
/* initial history */
/* always 0 that I've ever seen, but for completeness... */
vgmstream->ch[j].adpcm_history1_16 = header[j].initial_hist1;
vgmstream->ch[j].adpcm_history2_16 = header[j].initial_hist2;
}
}
/* open the file for reading */ if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,est_block_size*4); goto fail;
if (!vgmstream->ch[0].streamfile) goto fail; block_update_wsi(start_offset,vgmstream);
wsi_block_update(read_32bitBE(0,streamFile),vgmstream);
/* first block has DSP header */
{ {
int i; int i;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = vgmstream->ch[0].streamfile;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset[i];
}
}
/* first block isn't full of musics */
vgmstream->current_block_size -= 0x60; vgmstream->current_block_size -= 0x60;
for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset += 0x60;
}
}
return vgmstream; return vgmstream;
fail: fail:
/* clean up anything we may have opened */ close_vgmstream(vgmstream);
if (vgmstream) close_vgmstream(vgmstream);
return NULL; return NULL;
} }
@ -1970,119 +1834,60 @@ fail:
return NULL; return NULL;
} }
#define IADP_MAX_CHANNELS 2
/* dual dsp header with additional "iadp" header, found in Dr. Muto (NGC) */ /* iadp - custom header + interleaved dsp [Dr. Muto (GC)] */
VGMSTREAM * init_vgmstream_ngc_dsp_iadp(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_ngc_dsp_iadp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; off_t start_offset, header_offset;
struct dsp_header ch0_header,ch1_header; size_t header_spacing, interleave;
off_t ch1_header_start, ch2_header_start, ch1_start, ch2_start;
int channel_count; int channel_count;
int i; struct dsp_header ch_header[IADP_MAX_CHANNELS];
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); /* checks */
if (strcasecmp("iadp",filename_extension(filename))) /* .adp: actual extension, .iadp: header id */
if (!check_extensions(streamFile, "adp,iadp"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x69616470) /* "iadp" */
goto fail; goto fail;
/* check header */ channel_count = read_32bitBE(0x04,streamFile);
if (read_32bitBE(0x0,streamFile) != 0x69616470) /* iadp */ if (channel_count != IADP_MAX_CHANNELS) goto fail;
goto fail;
channel_count = read_32bitBE(0x4,streamFile); header_offset = 0x20;
header_spacing = 0x60;
start_offset = read_32bitBE(0x1C,streamFile);
interleave = read_32bitBE(0x08,streamFile);
if (channel_count != 0x2) /* read dsp */
goto fail; if (!dsp_load_header(ch_header, channel_count, streamFile,header_offset,header_spacing)) goto fail;
if (!check_dsp_format(ch_header, channel_count)) goto fail;
if (!check_dsp_samples(ch_header, channel_count)) goto fail;
ch1_header_start = 0x20; if (!check_dsp_initial_ps(ch_header, channel_count, streamFile,start_offset,interleave)) goto fail;
ch2_header_start = 0x80; if (!check_dsp_loop_ps(ch_header, channel_count, streamFile,start_offset,interleave)) goto fail;
ch1_start = read_32bitBE(0x1C,streamFile);
ch2_start = ch1_start + read_32bitBE(0x8,streamFile);
/* get DSP headers */
if (read_dsp_header(&ch0_header, ch1_header_start, streamFile)) goto fail;
if (read_dsp_header(&ch1_header, ch2_header_start, streamFile)) goto fail;
/* check initial predictor/scale */
if (ch0_header.initial_ps != (uint8_t)read_8bit(ch1_start, streamFile))
goto fail;
if (ch1_header.initial_ps != (uint8_t)read_8bit(ch2_start, streamFile))
goto fail;
/* check type==0 and gain==0 */
if (ch0_header.format || ch0_header.gain)
goto fail;
if (ch1_header.format || ch1_header.gain)
goto fail;
/* check for agreement */
if (
ch0_header.sample_count != ch1_header.sample_count ||
ch0_header.nibble_count != ch1_header.nibble_count ||
ch0_header.sample_rate != ch1_header.sample_rate ||
ch0_header.loop_flag != ch1_header.loop_flag ||
ch0_header.loop_start_offset != ch1_header.loop_start_offset ||
ch0_header.loop_end_offset != ch1_header.loop_end_offset
) goto fail;
if (ch0_header.loop_flag)
{
off_t loop_off;
/* check loop predictor/scale */
loop_off = ch0_header.loop_start_offset/16*8;
if (ch0_header.loop_ps != (uint8_t)read_8bit(ch1_start+loop_off,streamFile))
goto fail;
if (ch1_header.loop_ps != (uint8_t)read_8bit(ch2_start+loop_off,streamFile))
goto fail;
}
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,ch0_header.loop_flag); vgmstream = allocate_vgmstream(channel_count,ch_header[0].loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ vgmstream->sample_rate = ch_header[0].sample_rate;
vgmstream->num_samples = ch0_header.sample_count; vgmstream->num_samples = ch_header[0].sample_count;
vgmstream->sample_rate = ch0_header.sample_rate; vgmstream->loop_start_sample = dsp_nibbles_to_samples(ch_header[0].loop_start_offset);
vgmstream->loop_end_sample = dsp_nibbles_to_samples(ch_header[0].loop_end_offset)+1;
vgmstream->loop_start_sample = dsp_nibbles_to_samples(ch0_header.loop_start_offset);
vgmstream->loop_end_sample = dsp_nibbles_to_samples(ch0_header.loop_end_offset)+1;
vgmstream->meta_type = meta_NGC_DSP_IADP;
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->interleave_block_size = read_32bitBE(0x8,streamFile); vgmstream->interleave_block_size = read_32bitBE(0x8,streamFile);
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_NGC_DSP_IADP; setup_vgmstream_dsp(vgmstream, ch_header);
/* coeffs */
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i];
vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i];
}
/* initial history */ if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
/* always 0 that I've ever seen, but for completeness... */
vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1;
vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2;
vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1;
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; 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;
return vgmstream; return vgmstream;
fail: fail:
/* clean up anything we may have opened */ close_vgmstream(vgmstream);
if (vgmstream) close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -0,0 +1,46 @@
#include "meta.h"
#include "../coding/coding.h"
/* .str - Cauldron/Conan mini-header + interleaved dsp data [Conan (GC)] */
VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int channel_count, loop_flag;
/* checks */
if (!check_extensions(streamFile, "str"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0xFAAF0001) /* header id */
goto fail;
channel_count = 2; /* always loop & stereo */
loop_flag = 1;
start_offset = 0x60;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitBE(0x04,streamFile);
vgmstream->num_samples = read_32bitBE(0x08,streamFile);
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->meta_type = meta_DSP_STR;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x0C,streamFile);
dsp_read_coefs_be(vgmstream, streamFile, 0x10, 0x20);
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -14,29 +14,20 @@ VGMSTREAM * init_vgmstream_ngc_ulw(STREAMFILE *streamFile) {
/* raw data, the info is in the filename (really!) */ /* raw data, the info is in the filename (really!) */
{ {
char* path; char filename[PATH_LIMIT] = {0};
char basename[PATH_LIMIT];
char filename[PATH_LIMIT];
/* get base name */ get_streamfile_filename(streamFile, filename,PATH_LIMIT);
streamFile->get_name(streamFile,filename,sizeof(filename));
path = strrchr(filename,DIR_SEPARATOR);
if (path!=NULL)
path = path+1;
else
path = filename;
strcpy(basename,path);
/* first letter gives the channels */ /* first letter gives the channels */
if (basename[0]=='M') /* Mono */ if (filename[0]=='M') /* Mono */
channel_count = 1; channel_count = 1;
else if (basename[0]=='S' || basename[0]=='D') /* Stereo/Dolby */ else if (filename[0]=='S' || filename[0]=='D') /* Stereo/Dolby */
channel_count = 2; channel_count = 2;
else else
goto fail; goto fail;
/* not very robust but meh (other tracks don't loop) */ /* not very robust but meh (other tracks don't loop) */
if (strcmp(basename,"MMenu.ulw")==0 || strcmp(basename,"DMenu.ulw")==0) { if (strcmp(filename,"MMenu.ulw")==0 || strcmp(filename,"DMenu.ulw")==0) {
loop_flag = 1; loop_flag = 1;
} }
} }

49
src/meta/nxap.c Normal file
View File

@ -0,0 +1,49 @@
#include "meta.h"
#include "../coding/coding.h"
/* NXAP - Nex Entertainment header [Time Crisis 4 (PS3), Time Crisis Razing Storm (PS3)] */
VGMSTREAM * init_vgmstream_nxap(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
/* checks */
if (!check_extensions(streamFile, "adp"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x4E584150) /* "NXAP" */
goto fail;
if (read_32bitLE(0x14,streamFile) != 0x40 || /* expected frame size? */
read_32bitLE(0x18,streamFile) != 0x40) /* expected interleave? */
goto fail;
start_offset = read_32bitLE(0x04,streamFile);
channel_count = read_32bitLE(0x0c,streamFile);
loop_flag = 0; //(read_32bitLE(0x24,streamFile) > 0); //todo
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x10, streamFile);
vgmstream->num_samples = read_32bitLE(0x1c,streamFile) * (0x40-0x04)*2 / channel_count; /* number of frames */
/* unknown loop format, also 0x28/2c values seem related */
//vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile) * (0x40-0x04)*2 / channel_count;
//vgmstream->loop_end_sample = read_32bitLE(0x24,streamFile) * (0x40-0x04)*2 / channel_count;
//vgmstream->loop_end_sample = vgmstream->loop_start_sample + vgmstream->loop_end_sample;
vgmstream->meta_type = meta_NXAP;
vgmstream->coding_type = coding_YAMAHA_NXAP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x40;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -179,8 +179,7 @@ static void l2sd_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, v
/* Ogg Vorbis, by way of libvorbisfile; may contain loop comments */ /* Ogg Vorbis, by way of libvorbisfile; may contain loop comments */
VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
char filename[PATH_LIMIT]; ogg_vorbis_meta_info_t ovmi = {0};
vgm_vorbis_info_t inf = {0};
off_t start_offset = 0; off_t start_offset = 0;
int is_ogg = 0; int is_ogg = 0;
@ -210,7 +209,6 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
} else { } else {
goto fail; goto fail;
} }
streamFile->get_name(streamFile,filename,sizeof(filename));
/* check standard Ogg Vorbis */ /* check standard Ogg Vorbis */
if (is_ogg) { if (is_ogg) {
@ -218,11 +216,11 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
/* check Psychic Software obfuscation (Darkwind: War on Wheels PC) */ /* check Psychic Software obfuscation (Darkwind: War on Wheels PC) */
if (read_32bitBE(0x00,streamFile) == 0x2c444430) { if (read_32bitBE(0x00,streamFile) == 0x2c444430) {
is_psychic = 1; is_psychic = 1;
inf.decryption_callback = psychic_ogg_decryption_callback; ovmi.decryption_callback = psychic_ogg_decryption_callback;
} }
else if (read_32bitBE(0x00,streamFile) == 0x4C325344) { /* "L2SD" [Lineage II Chronicle 4 (PC)] */ else if (read_32bitBE(0x00,streamFile) == 0x4C325344) { /* "L2SD" [Lineage II Chronicle 4 (PC)] */
is_l2sd = 1; is_l2sd = 1;
inf.decryption_callback = l2sd_ogg_decryption_callback; ovmi.decryption_callback = l2sd_ogg_decryption_callback;
} }
else if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */ else if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */
goto fail; /* not known (ex. Wwise) */ goto fail; /* not known (ex. Wwise) */
@ -232,7 +230,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
/* check "Ultramarine3" (???), may be encrypted */ /* check "Ultramarine3" (???), may be encrypted */
if (is_um3) { if (is_um3) {
if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */ if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */
inf.decryption_callback = um3_ogg_decryption_callback; ovmi.decryption_callback = um3_ogg_decryption_callback;
} }
} }
@ -241,9 +239,9 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x4b4f5653) { /* "KOVS" */ if (read_32bitBE(0x00,streamFile) != 0x4b4f5653) { /* "KOVS" */
goto fail; goto fail;
} }
inf.loop_start = read_32bitLE(0x08,streamFile); ovmi.loop_start = read_32bitLE(0x08,streamFile);
inf.loop_flag = (inf.loop_start != 0); ovmi.loop_flag = (ovmi.loop_start != 0);
inf.decryption_callback = kovs_ogg_decryption_callback; ovmi.decryption_callback = kovs_ogg_decryption_callback;
start_offset = 0x20; start_offset = 0x20;
} }
@ -251,14 +249,14 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
/* check SNGW (Capcom's MT Framework PC games), may be encrypted */ /* check SNGW (Capcom's MT Framework PC games), may be encrypted */
if (is_sngw) { if (is_sngw) {
if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */ if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */
inf.sngw_xor = read_32bitBE(0x00,streamFile); ovmi.sngw_xor = read_32bitBE(0x00,streamFile);
inf.decryption_callback = sngw_ogg_decryption_callback; ovmi.decryption_callback = sngw_ogg_decryption_callback;
} }
} }
/* check ISD (Gunvolt PC) */ /* check ISD (Gunvolt PC) */
if (is_isd) { if (is_isd) {
inf.decryption_callback = isd_ogg_decryption_callback; ovmi.decryption_callback = isd_ogg_decryption_callback;
//todo looping unknown, not in Ogg comments //todo looping unknown, not in Ogg comments
// game has sound/GV_steam.* files with info about sound/stream/*.isd // game has sound/GV_steam.* files with info about sound/stream/*.isd
@ -271,42 +269,41 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
if (is_um3) { if (is_um3) {
inf.meta_type = meta_OGG_UM3; ovmi.meta_type = meta_OGG_UM3;
} else if (is_kovs) { } else if (is_kovs) {
inf.meta_type = meta_OGG_KOVS; ovmi.meta_type = meta_OGG_KOVS;
} else if (is_psychic) { } else if (is_psychic) {
inf.meta_type = meta_OGG_PSYCHIC; ovmi.meta_type = meta_OGG_PSYCHIC;
} else if (is_sngw) { } else if (is_sngw) {
inf.meta_type = meta_OGG_SNGW; ovmi.meta_type = meta_OGG_SNGW;
} else if (is_isd) { } else if (is_isd) {
inf.meta_type = meta_OGG_ISD; ovmi.meta_type = meta_OGG_ISD;
} else if (is_l2sd) { } else if (is_l2sd) {
inf.meta_type = meta_OGG_L2SD; ovmi.meta_type = meta_OGG_L2SD;
} else { } else {
inf.meta_type = meta_OGG_VORBIS; ovmi.meta_type = meta_OGG_VORBIS;
} }
inf.layout_type = layout_ogg_vorbis;
return init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); return init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
fail: fail:
return NULL; return NULL;
} }
VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks_p, off_t start, const vgm_vorbis_info_t *vgm_inf) { VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callbacks *callbacks_p, off_t start, const ogg_vorbis_meta_info_t *ovmi) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
ogg_vorbis_codec_data * data = NULL; ogg_vorbis_codec_data * data = NULL;
OggVorbis_File *ovf = NULL; OggVorbis_File *ovf = NULL;
vorbis_info *vi; vorbis_info *vi;
int loop_flag = vgm_inf->loop_flag; int loop_flag = ovmi->loop_flag;
int32_t loop_start = vgm_inf->loop_start; int32_t loop_start = ovmi->loop_start;
int loop_length_found = vgm_inf->loop_length_found; int loop_length_found = ovmi->loop_length_found;
int32_t loop_length = vgm_inf->loop_length; int32_t loop_length = ovmi->loop_length;
int loop_end_found = vgm_inf->loop_end_found; int loop_end_found = ovmi->loop_end_found;
int32_t loop_end = vgm_inf->loop_end; int32_t loop_end = ovmi->loop_end;
size_t stream_size = vgm_inf->stream_size ? size_t stream_size = ovmi->stream_size ?
vgm_inf->stream_size : ovmi->stream_size :
get_streamfile_size(streamFile) - start; get_streamfile_size(streamFile) - start;
ov_callbacks default_callbacks; ov_callbacks default_callbacks;
@ -331,10 +328,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
temp_streamfile.offset = 0; temp_streamfile.offset = 0;
temp_streamfile.size = stream_size; temp_streamfile.size = stream_size;
temp_streamfile.decryption_callback = vgm_inf->decryption_callback; temp_streamfile.decryption_callback = ovmi->decryption_callback;
temp_streamfile.scd_xor = vgm_inf->scd_xor; temp_streamfile.scd_xor = ovmi->scd_xor;
temp_streamfile.scd_xor_length = vgm_inf->scd_xor_length; temp_streamfile.scd_xor_length = ovmi->scd_xor_length;
temp_streamfile.sngw_xor = vgm_inf->sngw_xor; temp_streamfile.sngw_xor = ovmi->sngw_xor;
/* open the ogg vorbis file for testing */ /* open the ogg vorbis file for testing */
memset(&temp_ovf, 0, sizeof(temp_ovf)); memset(&temp_ovf, 0, sizeof(temp_ovf));
@ -348,9 +345,12 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
/* proceed to init codec_data and reopen a STREAMFILE for this stream */ /* proceed to init codec_data and reopen a STREAMFILE for this stream */
{ {
char filename[PATH_LIMIT];
data = calloc(1,sizeof(ogg_vorbis_codec_data)); data = calloc(1,sizeof(ogg_vorbis_codec_data));
if (!data) goto fail; if (!data) goto fail;
streamFile->get_name(streamFile,filename,sizeof(filename));
data->ov_streamfile.streamfile = streamFile->open(streamFile,filename, STREAMFILE_DEFAULT_BUFFER_SIZE); data->ov_streamfile.streamfile = streamFile->open(streamFile,filename, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!data->ov_streamfile.streamfile) goto fail; if (!data->ov_streamfile.streamfile) goto fail;
@ -358,10 +358,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
data->ov_streamfile.offset = 0; data->ov_streamfile.offset = 0;
data->ov_streamfile.size = stream_size; data->ov_streamfile.size = stream_size;
data->ov_streamfile.decryption_callback = vgm_inf->decryption_callback; data->ov_streamfile.decryption_callback = ovmi->decryption_callback;
data->ov_streamfile.scd_xor = vgm_inf->scd_xor; data->ov_streamfile.scd_xor = ovmi->scd_xor;
data->ov_streamfile.scd_xor_length = vgm_inf->scd_xor_length; data->ov_streamfile.scd_xor_length = ovmi->scd_xor_length;
data->ov_streamfile.sngw_xor = vgm_inf->sngw_xor; data->ov_streamfile.sngw_xor = ovmi->sngw_xor;
/* open the ogg vorbis file for real */ /* open the ogg vorbis file for real */
if (ov_open_callbacks(&data->ov_streamfile, &data->ogg_vorbis_file, NULL, 0, *callbacks_p)) if (ov_open_callbacks(&data->ov_streamfile, &data->ogg_vorbis_file, NULL, 0, *callbacks_p))
@ -441,7 +441,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
vgmstream->codec_data = data; /* store our fun extra datas */ vgmstream->codec_data = data; /* store our fun extra datas */
vgmstream->channels = vi->channels; vgmstream->channels = vi->channels;
vgmstream->sample_rate = vi->rate; vgmstream->sample_rate = vi->rate;
vgmstream->num_streams = vgm_inf->total_subsongs; vgmstream->num_streams = ovmi->total_subsongs;
vgmstream->stream_size = stream_size; vgmstream->stream_size = stream_size;
vgmstream->num_samples = ov_pcm_total(ovf,-1); /* let libvorbisfile find total samples */ vgmstream->num_samples = ov_pcm_total(ovf,-1); /* let libvorbisfile find total samples */
@ -460,8 +460,8 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
} }
vgmstream->coding_type = coding_OGG_VORBIS; vgmstream->coding_type = coding_OGG_VORBIS;
vgmstream->layout_type = vgm_inf->layout_type; vgmstream->layout_type = layout_none;
vgmstream->meta_type = vgm_inf->meta_type; vgmstream->meta_type = ovmi->meta_type;
return vgmstream; return vgmstream;

View File

@ -1,79 +1,53 @@
#include "meta.h" #include "meta.h"
#include "../util.h" #include "../util.h"
/* SND (Warriors of Might and Magic Heroes of M&M:Dragonbone Staff) */ /* SND - Might and Magic games [Warriors of M&M (PS2), Heroes of M&M: Quest for the DragonBone Staff (PS2)] */
VGMSTREAM * init_vgmstream_ps2_snd(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_ps2_snd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
size_t data_size;
int loop_flag, channel_count;
int loop_flag; /* checks */
int channel_count; if (!check_extensions(streamFile, "snd"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53534E44) /* "SSND" */
goto fail;
/* check extension, case insensitive */ start_offset = read_32bitLE(0x04,streamFile)+0x08;
streamFile->get_name(streamFile,filename,sizeof(filename)); data_size = get_streamfile_size(streamFile) - start_offset;
if (strcasecmp("snd",filename_extension(filename))) goto fail;
/* check header */ loop_flag = 1; /* force full Loop */
if (read_32bitBE(0x0,streamFile) !=0x53534e44) goto fail;
/* Force Loop 0->end */
loop_flag = 1;
channel_count = read_16bitLE(0x0a,streamFile); channel_count = read_16bitLE(0x0a,streamFile);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ vgmstream->sample_rate = (uint16_t)read_16bitLE(0x0e,streamFile);
start_offset = read_32bitLE(0x04,streamFile)+8;
vgmstream->sample_rate = (uint16_t)read_16bitLE(0xe,streamFile);
if(read_8bit(0x08,streamFile)==1) {
vgmstream->coding_type = coding_DVI_IMA_int;
}
else
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = read_32bitLE(0x16,streamFile); vgmstream->num_samples = read_32bitLE(0x16,streamFile);
vgmstream->interleave_block_size = (uint16_t)read_16bitLE(0x12,streamFile);
if((get_streamfile_size(streamFile)-start_offset)%vgmstream->interleave_block_size)
{
/* not sure if this is right ... */
vgmstream->layout_type = layout_interleave_shortblock;
vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%vgmstream->interleave_block_size)/vgmstream->channels;
} else {
vgmstream->layout_type = layout_interleave;
}
vgmstream->meta_type = meta_PS2_SND;
if(loop_flag) {
vgmstream->loop_start_sample = 0; vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
}
/* open the file for reading */ vgmstream->meta_type = meta_PS2_SND;
{
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 (read_8bit(0x08,streamFile)==1) {
vgmstream->coding_type = coding_DVI_IMA_int; /* Warriors of M&M DragonBone */
} }
else {
vgmstream->coding_type = coding_PCM16LE; /* Heroes of M&M */
} }
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = (uint16_t)read_16bitLE(0x12,streamFile);
if (vgmstream->interleave_block_size)
vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -1,85 +1,53 @@
#include "meta.h" #include "meta.h"
#include "../util.h" #include "../coding/coding.h"
/* SVAG
PS2 SVAG format is an interleaved format found in many konami Games
The header start with a Svag id and have the sentence :
"ALL RIGHTS RESERVED.KONAMITYO Sound Design Dept. "
or "ALL RIGHTS RESERVED.KCE-Tokyo Sound Design Dept. "
2008-05-13 - Fastelbja : First version ...
Thx to HCS for his awesome work on shortblock interleave
*/
/* SVAG - from Konami Tokyo games [OZ (PS2), Neo Contra (PS2)]] */
VGMSTREAM * init_vgmstream_ps2_svag(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_ps2_svag(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; off_t start_offset;
size_t data_size;
int loop_flag, channel_count;
int loop_flag=0;
int channel_count;
int i;
/* check extension, case insensitive */ /* checks */
streamFile->get_name(streamFile,filename,sizeof(filename)); if (!check_extensions(streamFile, "svag"))
if (strcasecmp("svag",filename_extension(filename))) goto fail;
/* check SVAG Header */
if (read_32bitBE(0x00,streamFile) != 0x53766167)
goto fail; goto fail;
/* check loop */ if (read_32bitBE(0x00,streamFile) != 0x53766167) /* "Svag" */
goto fail;
channel_count = read_16bitLE(0x0C,streamFile); /* always 2? ("S"tereo vag?) */
loop_flag = (read_32bitLE(0x14,streamFile)==1); loop_flag = (read_32bitLE(0x14,streamFile)==1);
channel_count=read_16bitLE(0x0C,streamFile); start_offset = 0x800; /* header repeated at 0x400 too */
data_size = read_32bitLE(0x04,streamFile);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = read_16bitLE(0x0C,streamFile);
vgmstream->sample_rate = read_32bitLE(0x08,streamFile); vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
/* Compression Scheme */ vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x04,streamFile), vgmstream->channels);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitLE(0x04,streamFile)/16*28/vgmstream->channels;
/* Get loop point values */
if(vgmstream->loop_flag) { if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile)/16*28; vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitLE(0x18,streamFile)*vgmstream->channels, vgmstream->channels);
vgmstream->loop_end_sample = read_32bitLE(0x04,streamFile)/16*28/vgmstream->channels; vgmstream->loop_end_sample = vgmstream->num_samples;
} }
vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile);
if (channel_count > 1) {
vgmstream->interleave_smallblock_size = (read_32bitLE(0x04,streamFile)%(vgmstream->channels*vgmstream->interleave_block_size))/vgmstream->channels;
vgmstream->layout_type = layout_interleave_shortblock;
} else {
vgmstream->layout_type = layout_none;
}
vgmstream->meta_type = meta_PS2_SVAG; vgmstream->meta_type = meta_PS2_SVAG;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile);
if (vgmstream->interleave_block_size)
vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
if (channel_count > 1)
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size);
else
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=
(off_t)(0x800+vgmstream->interleave_block_size*i);
}
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -17,8 +17,9 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) {
int channel_count = 0; int channel_count = 0;
int is_swag = 0; int is_swag = 0;
/* check extension (.swag: Frantix PSP, .str: Ben10 Galactic Racing, .vig: MX vs. ATV Untamed PS2) */ /* checks */
if ( !check_extensions(streamFile,"vag,swag,str,vig") ) /* .swag: Frantix (PSP), .str: Ben10 Galactic Racing, .vig: MX vs. ATV Untamed (PS2) .l/r: Crash Nitro Kart (PS2) */
if ( !check_extensions(streamFile,"vag,swag,str,vig,l,r") )
goto fail; goto fail;
/* check VAG Header */ /* check VAG Header */

View File

@ -838,15 +838,13 @@ static VGMSTREAM *parse_riff_ogg(STREAMFILE * streamFile, off_t start_offset, si
{ {
VGMSTREAM *vgmstream = NULL; VGMSTREAM *vgmstream = NULL;
STREAMFILE *custom_streamFile = NULL; STREAMFILE *custom_streamFile = NULL;
char filename[PATH_LIMIT]; ogg_vorbis_meta_info_t ovmi = {0};
vgm_vorbis_info_t inf = {0};
riff_ogg_io_data io_data = {0}; riff_ogg_io_data io_data = {0};
size_t io_data_size = sizeof(riff_ogg_io_data); size_t io_data_size = sizeof(riff_ogg_io_data);
inf.layout_type = layout_ogg_vorbis; ovmi.meta_type = meta_RIFF_WAVE;
inf.meta_type = meta_RIFF_WAVE; ovmi.stream_size = real_size;
inf.stream_size = real_size;
//inf.loop_flag = 0; /* not observed */ //inf.loop_flag = 0; /* not observed */
io_data.patch_offset = patch_offset; io_data.patch_offset = patch_offset;
@ -854,8 +852,7 @@ static VGMSTREAM *parse_riff_ogg(STREAMFILE * streamFile, off_t start_offset, si
custom_streamFile = open_io_streamfile(open_wrap_streamfile(streamFile), &io_data,io_data_size, riff_ogg_io_read); custom_streamFile = open_io_streamfile(open_wrap_streamfile(streamFile), &io_data,io_data_size, riff_ogg_io_read);
if (!custom_streamFile) return NULL; if (!custom_streamFile) return NULL;
streamFile->get_name(streamFile,filename,sizeof(filename)); vgmstream = init_vgmstream_ogg_vorbis_callbacks(custom_streamFile, NULL, start_offset, &ovmi);
vgmstream = init_vgmstream_ogg_vorbis_callbacks(custom_streamFile, filename, NULL, start_offset, &inf);
close_streamfile(custom_streamFile); close_streamfile(custom_streamFile);

View File

@ -1,77 +1,115 @@
#include "meta.h" #include "meta.h"
#include "../util.h" #include "../coding/coding.h"
/* RKV (from Legacy of Kain - Blood Omen 2) */ /* RKV - from Legacy of Kain - Blood Omen 2 (PS2) */
VGMSTREAM * init_vgmstream_ps2_rkv(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_ps2_rkv(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; off_t start_offset, header_offset;
off_t start_offset=0; size_t data_size;
int loop_flag; int loop_flag, channel_count;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("rkv",filename_extension(filename))) goto fail;
// Some RKV got info @ offset 0 /* checks */
// Some other @ offset 4 if (!check_extensions(streamFile, "rkv"))
if(read_32bitLE(0,streamFile)==0) goto fail;
start_offset=4; if (read_32bitBE(0x24,streamFile) != 0x00) /* quick test vs GC rkv (coef position) */
goto fail;
/* some RKV got info at offset 0x00, some other at 0x0 4 */
if (read_32bitLE(0x00,streamFile)==0)
header_offset = 0x04;
else
header_offset = 0x00;
switch (read_32bitLE(header_offset+0x0c,streamFile)) {
case 0x00: channel_count = 1; break;
case 0x01: channel_count = 2; break;
default: goto fail;
}
loop_flag = (read_32bitLE(header_offset+0x04,streamFile) != 0xFFFFFFFF);
start_offset = 0x800;
data_size = get_streamfile_size(streamFile) - start_offset;
loop_flag = (read_32bitLE(start_offset+4,streamFile)!=0xFFFFFFFF);
channel_count = read_32bitLE(start_offset+0x0c,streamFile)+1;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ vgmstream->sample_rate = read_32bitLE(header_offset,streamFile);
vgmstream->channels = channel_count; vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count);
vgmstream->sample_rate = read_32bitLE(start_offset,streamFile); //vgmstream->num_samples = read_32bitLE(header_offset+0x08,streamFile); /* sometimes not set */
vgmstream->coding_type = coding_PSX;
// sometimes sample count is not set on the header
vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)/16*28/channel_count;
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(start_offset+4,streamFile); vgmstream->loop_start_sample = read_32bitLE(header_offset+0x04,streamFile);
vgmstream->loop_end_sample = read_32bitLE(start_offset+8,streamFile); vgmstream->loop_end_sample = read_32bitLE(header_offset+0x08,streamFile);
} }
start_offset = 0x800;
if((get_streamfile_size(streamFile)-0x800)%0x400)
{
vgmstream->layout_type = layout_interleave_shortblock;
vgmstream->interleave_smallblock_size=((get_streamfile_size(streamFile)-0x800)%0x400)/channel_count;
} else {
vgmstream->layout_type = layout_interleave;
}
vgmstream->interleave_block_size = 0x400;
vgmstream->meta_type = meta_PS2_RKV; vgmstream->meta_type = meta_PS2_RKV;
/* open the file for reading */ vgmstream->coding_type = coding_PSX;
{ vgmstream->layout_type = layout_interleave;
int i; vgmstream->interleave_block_size = 0x400;
STREAMFILE * file; if (vgmstream->interleave_block_size)
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
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; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }
/* RKV - from Legacy of Kain - Blood Omen 2 (GC) */
VGMSTREAM * init_vgmstream_ngc_rkv(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
/* checks */
/* "": empty (files have names but no extensions), .rkv: container bigfile extension, .bo2: fake extension */
if (!check_extensions(streamFile, ",rkv,bo2"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x00)
goto fail;
if (read_32bitBE(0x24,streamFile) == 0x00) /* quick test vs GC rkv (coef position) */
goto fail;
switch (read_32bitBE(0x10,streamFile)) {
case 0x00: channel_count = 1; break;
case 0x01: channel_count = 2; break;
default: goto fail;
}
loop_flag = (read_32bitBE(0x08,streamFile) != 0xFFFFFFFF);
start_offset = 0x800;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitBE(0x04,streamFile);
vgmstream->num_samples = read_32bitBE(0x0C,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitBE(0x08,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile);
}
vgmstream->meta_type = meta_NGC_RKV;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x400;
dsp_read_coefs_be(vgmstream,streamFile,0x24,0x2e);
/* hist at 0x44/0x72? */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,81 +1,54 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
#include "../util.h"
/* .dsp w/ RS03 header - from Metroid Prime 2 */
/* RS03 - from Metroid Prime 2 (GC) */
VGMSTREAM * init_vgmstream_rs03(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_rs03(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int channel_count;
int loop_flag;
off_t start_offset; off_t start_offset;
int i; size_t data_size;
int channel_count, loop_flag;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("dsp",filename_extension(filename))) goto fail;
/* check header */ /* checks */
if ((uint32_t)read_32bitBE(0,streamFile)!=0x52530003) /* "RS03" */ if (!check_extensions(streamFile, "dsp"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x52530003) /* "RS03" */
goto fail; goto fail;
channel_count = read_32bitBE(4,streamFile); channel_count = read_32bitBE(0x04,streamFile);
if (channel_count != 1 && channel_count != 2) goto fail; if (channel_count != 1 && channel_count != 2) goto fail;
/* build the VGMSTREAM */
loop_flag = read_16bitBE(0x14,streamFile); loop_flag = read_16bitBE(0x14,streamFile);
start_offset = 0x60;
data_size = (get_streamfile_size(streamFile) - start_offset);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitBE(8,streamFile);
vgmstream->sample_rate = read_32bitBE(0xc,streamFile); vgmstream->sample_rate = read_32bitBE(0xc,streamFile);
vgmstream->num_samples = read_32bitBE(8,streamFile);
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample = read_32bitBE(0x18,streamFile)/8*14; vgmstream->loop_start_sample = read_32bitBE(0x18,streamFile)/8*14;
vgmstream->loop_end_sample = read_32bitBE(0x1c,streamFile)/8*14; vgmstream->loop_end_sample = read_32bitBE(0x1c,streamFile)/8*14;
} }
start_offset = 0x60;
vgmstream->coding_type = coding_NGC_DSP;
if (channel_count == 2) {
vgmstream->layout_type = layout_interleave_shortblock;
vgmstream->interleave_block_size = 0x8f00;
vgmstream->interleave_smallblock_size = (((get_streamfile_size(streamFile)-start_offset)%(0x8f00*2))/2+7)/8*8;
} else
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_DSP_RS03; vgmstream->meta_type = meta_DSP_RS03;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x8f00;
if (vgmstream->interleave_block_size)
vgmstream->interleave_last_block_size = ((data_size % (vgmstream->interleave_block_size*vgmstream->channels))/2+7)/8*8;
for (i=0;i<16;i++) dsp_read_coefs_be(vgmstream,streamFile,0x20,0x20);
vgmstream->ch[0].adpcm_coef[i]=read_16bitBE(0x20+i*2,streamFile);
if (channel_count==2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i]=read_16bitBE(0x40+i*2,streamFile);
}
/* open the file for reading by each channel */
{
int i;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8f00);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=
start_offset+0x8f00*i;
}
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -903,12 +903,11 @@ fail:
/* RSD6OGG */ /* RSD6OGG */
VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE *streamFile) {
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
/* check extension, case insensitive */ /* check extension */
streamFile->get_name(streamFile,filename,sizeof(filename)); if (!check_extensions(streamFile, "rsd"))
if (strcasecmp("rsd",filename_extension(filename))) goto fail; goto fail;
/* check header */ /* check header */
if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */ if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */
@ -917,15 +916,13 @@ VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE *streamFile) {
goto fail; goto fail;
{ {
vgm_vorbis_info_t inf; ogg_vorbis_meta_info_t ovmi = {0};
VGMSTREAM * result = NULL; VGMSTREAM * result = NULL;
memset(&inf, 0, sizeof(inf)); ovmi.meta_type = meta_RSD6OOGV;
inf.layout_type = layout_ogg_vorbis;
inf.meta_type = meta_RSD6OOGV;
start_offset = 0x800; start_offset = 0x800;
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); result = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
if (result != NULL) { if (result != NULL) {
return result; return result;
@ -938,7 +935,7 @@ fail:
return NULL; return NULL;
} }
/* RSD6XADP - from Crash Tag Team Racing (Xbox) */ /* RSD6XADP - from Crash Tag Team Racing (Xbox), Scarface (Xbox) */
VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t start_offset; off_t start_offset;
@ -966,9 +963,10 @@ VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE *streamFile) {
vgmstream->sample_rate = read_32bitLE(0x10,streamFile); vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels); vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_RSD6XADP; vgmstream->meta_type = meta_RSD6XADP;
vgmstream->coding_type = (channel_count > 2) ? coding_XBOX_IMA_mch : coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail; goto fail;
@ -1082,7 +1080,6 @@ fail:
return NULL; return NULL;
} }
/* RSD6AT3+ [Crash of the Titans (PSP)] */ /* RSD6AT3+ [Crash of the Titans (PSP)] */
VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
@ -1096,13 +1093,13 @@ VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE *streamFile) {
goto fail; goto fail;
/* check header */ /* check header */
if (read_32bitBE(0x0, streamFile) != 0x52534436) /* "RSD6" */ if (read_32bitBE(0x00,streamFile) != 0x52534436) /* "RSD6" */
goto fail; goto fail;
if (read_32bitBE(0x04,streamFile) != 0x4154332B) /* "AT3+" */ if (read_32bitBE(0x04,streamFile) != 0x4154332B) /* "AT3+" */
goto fail; goto fail;
loop_flag = 0; loop_flag = 0;
channel_count = read_32bitLE(0x8, streamFile); channel_count = read_32bitLE(0x08, streamFile);
start_offset = 0x800; start_offset = 0x800;
data_size = get_streamfile_size(streamFile) - start_offset; data_size = get_streamfile_size(streamFile) - start_offset;
@ -1117,7 +1114,7 @@ VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE *streamFile) {
{ {
ffmpeg_codec_data *ffmpeg_data = NULL; ffmpeg_codec_data *ffmpeg_data = NULL;
/* full RIFF header at start_offset/post_meta_offset (same) */ /* full RIFF header at start_offset */
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,data_size); ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,data_size);
if (!ffmpeg_data) goto fail; if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
@ -1154,3 +1151,60 @@ fail:
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }
/* RSD6WMA [Scarface (Xbox)] */
VGMSTREAM * init_vgmstream_rsd6wma(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
size_t data_size;
int loop_flag, channel_count;
/* checks */
if (!check_extensions(streamFile,"rsd"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x52534436) /* "RSD6" */
goto fail;
if (read_32bitBE(0x04,streamFile) != 0x574D4120) /* "WMA " */
goto fail;
loop_flag = 0;
channel_count = read_32bitLE(0x08, streamFile);
start_offset = 0x800;
data_size = get_streamfile_size(streamFile) - start_offset;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_RSD6WMA;
//vgmstream->num_samples = read_32bitLE(start_offset + 0x00, streamFile); /* ? */
vgmstream->sample_rate = read_32bitLE(start_offset + 0x04, streamFile);
#ifdef VGM_USE_FFMPEG
{
ffmpeg_codec_data *ffmpeg_data = NULL;
/* mini header + WMA header at start_offset */
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset+0x08,data_size);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = (int32_t)ffmpeg_data->totalSamples; /* probably an estimation */
#else
goto fail;
#endif
}
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

50
src/meta/smv.c Normal file
View File

@ -0,0 +1,50 @@
#include "meta.h"
#include "../coding/coding.h"
/* .SMV - from Cho Aniki Zero (PSP) */
VGMSTREAM * init_vgmstream_smv(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
size_t channel_size, loop_start;
/* check extension */
if (!check_extensions(streamFile, "smv"))
goto fail;
channel_size = read_32bitLE(0x00,streamFile);
/* 0x08: number of full interleave blocks */
channel_count = read_16bitLE(0x0a,streamFile);
loop_start = read_32bitLE(0x18,streamFile);
loop_flag = (loop_start != -1);
start_offset = 0x800;
if (channel_size * channel_count + start_offset != get_streamfile_size(streamFile))
goto fail;
channel_size -= 0x10; /* last value has SPU end frame without flag 0x7 as it should */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x10, streamFile);
vgmstream->num_samples = ps_bytes_to_samples(channel_size*channel_count, channel_count);
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start*channel_count, channel_count);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->meta_type = meta_SMV;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x04, streamFile);
vgmstream->interleave_last_block_size = read_32bitLE(0x0c, streamFile);
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -12,8 +12,8 @@ static void scd_ogg_v3_decryption_callback(void *ptr, size_t size, size_t nmemb,
VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
off_t start_offset, tables_offset, meta_offset, post_meta_offset, name_offset = 0; off_t start_offset, tables_offset, meta_offset, extradata_offset, name_offset = 0;
int32_t stream_size, subheader_size, loop_start, loop_end; int32_t stream_size, extradata_size, loop_start, loop_end;
int loop_flag = 0, channel_count, codec, sample_rate; int loop_flag = 0, channel_count, codec, sample_rate;
int version, target_entry, aux_chunk_count; int version, target_entry, aux_chunk_count;
@ -113,13 +113,13 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
loop_start = read_32bit(meta_offset+0x10,streamFile); loop_start = read_32bit(meta_offset+0x10,streamFile);
loop_end = read_32bit(meta_offset+0x14,streamFile); loop_end = read_32bit(meta_offset+0x14,streamFile);
subheader_size = read_32bit(meta_offset+0x18,streamFile); extradata_size = read_32bit(meta_offset+0x18,streamFile);
aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile); aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile);
/* 0x01e(2): unknown, seen in some FF XIV sfx (MSADPCM) */ /* 0x01e(2): unknown, seen in some FF XIV sfx (MSADPCM) */
loop_flag = (loop_end > 0); loop_flag = (loop_end > 0);
post_meta_offset = meta_offset + 0x20; extradata_offset = meta_offset + 0x20;
start_offset = post_meta_offset + subheader_size; start_offset = extradata_offset + extradata_size;
/* only "MARK" chunk is known (some FF XIV PS3 have "STBL" but it's not counted) */ /* only "MARK" chunk is known (some FF XIV PS3 have "STBL" but it's not counted) */
if (aux_chunk_count > 1 && aux_chunk_count < 0xFFFF) { /* some FF XIV Heavensward IMA sfx have 0x01000000 */ if (aux_chunk_count > 1 && aux_chunk_count < 0xFFFF) { /* some FF XIV Heavensward IMA sfx have 0x01000000 */
@ -128,8 +128,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
} }
/* skips aux chunks, sometimes needed (Lightning Returns X360, FF XIV PC) */ /* skips aux chunks, sometimes needed (Lightning Returns X360, FF XIV PC) */
if (aux_chunk_count && read_32bitBE(post_meta_offset, streamFile) == 0x4D41524B) { /* "MARK" */ if (aux_chunk_count && read_32bitBE(extradata_offset, streamFile) == 0x4D41524B) { /* "MARK" */
post_meta_offset += read_32bit(post_meta_offset+0x04, streamFile); extradata_offset += read_32bit(extradata_offset+0x04, streamFile);
} }
/* find name if possible */ /* find name if possible */
@ -151,41 +151,40 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
if (codec == 0x06) { if (codec == 0x06) {
VGMSTREAM *ogg_vgmstream; VGMSTREAM *ogg_vgmstream;
uint8_t ogg_version, ogg_byte; uint8_t ogg_version, ogg_byte;
vgm_vorbis_info_t inf = {0}; ogg_vorbis_meta_info_t ovmi = {0};
inf.layout_type = layout_ogg_vorbis; ovmi.meta_type = meta_SQEX_SCD;
inf.meta_type = meta_SQEX_SCD; ovmi.total_subsongs = total_subsongs;
inf.total_subsongs = total_subsongs;
/* loop values are in bytes, let init_vgmstream_ogg_vorbis find loop comments instead */ /* loop values are in bytes, let init_vgmstream_ogg_vorbis find loop comments instead */
ogg_version = read_8bit(post_meta_offset + 0x00, streamFile); ogg_version = read_8bit(extradata_offset + 0x00, streamFile);
/* 0x01(1): 0x20 in v2/3, this ogg miniheader size? */ /* 0x01(1): 0x20 in v2/3, this ogg miniheader size? */
ogg_byte = read_8bit(post_meta_offset + 0x02, streamFile); ogg_byte = read_8bit(extradata_offset + 0x02, streamFile);
/* 0x03(1): ? in v3 */ /* 0x03(1): ? in v3 */
if (ogg_version == 0) { /* 0x10? header, then custom Vorbis header before regular Ogg (FF XIV PC v1) */ if (ogg_version == 0) { /* 0x10? header, then custom Vorbis header before regular Ogg (FF XIV PC v1) */
inf.stream_size = stream_size; ovmi.stream_size = stream_size;
} }
else { /* 0x20 header, then seek table */ else { /* 0x20 header, then seek table */
size_t seek_table_size = read_32bit(post_meta_offset+0x10, streamFile); size_t seek_table_size = read_32bit(extradata_offset+0x10, streamFile);
size_t vorb_header_size = read_32bit(post_meta_offset+0x14, streamFile); size_t vorb_header_size = read_32bit(extradata_offset+0x14, streamFile);
/* 0x18(4): ? (can be 0) */ /* 0x18(4): ? (can be 0) */
if ((post_meta_offset-meta_offset) + seek_table_size + vorb_header_size != subheader_size) if ((extradata_offset-meta_offset) + seek_table_size + vorb_header_size != extradata_size)
goto fail; goto fail;
inf.stream_size = vorb_header_size + stream_size; ovmi.stream_size = vorb_header_size + stream_size;
start_offset = post_meta_offset + 0x20 + seek_table_size; /* subheader_size skips vorb_header */ start_offset = extradata_offset + 0x20 + seek_table_size; /* extradata_size skips vorb_header */
if (ogg_version == 2) { /* header is XOR'ed using byte (FF XIV PC) */ if (ogg_version == 2) { /* header is XOR'ed using byte (FF XIV PC) */
inf.decryption_callback = scd_ogg_v2_decryption_callback; ovmi.decryption_callback = scd_ogg_v2_decryption_callback;
inf.scd_xor = ogg_byte; ovmi.scd_xor = ogg_byte;
inf.scd_xor_length = vorb_header_size; ovmi.scd_xor_length = vorb_header_size;
} }
else if (ogg_version == 3) { /* file is XOR'ed using table (FF XIV Heavensward PC) */ else if (ogg_version == 3) { /* file is XOR'ed using table (FF XIV Heavensward PC) */
inf.decryption_callback = scd_ogg_v3_decryption_callback; ovmi.decryption_callback = scd_ogg_v3_decryption_callback;
inf.scd_xor = stream_size & 0xFF; /* ogg_byte not used? */ ovmi.scd_xor = stream_size & 0xFF; /* ogg_byte not used? */
inf.scd_xor_length = vorb_header_size + stream_size; ovmi.scd_xor_length = vorb_header_size + stream_size;
} }
else { else {
VGM_LOG("SCD: unknown ogg_version 0x%x\n", ogg_version); VGM_LOG("SCD: unknown ogg_version 0x%x\n", ogg_version);
@ -193,7 +192,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
} }
/* actual Ogg init */ /* actual Ogg init */
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
if (ogg_vgmstream && name_offset) if (ogg_vgmstream && name_offset)
read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile); read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile);
return ogg_vgmstream; return ogg_vgmstream;
@ -270,8 +269,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
case 0x0C: /* MS ADPCM [Final Fantasy XIV (PC) sfx] */ case 0x0C: /* MS ADPCM [Final Fantasy XIV (PC) sfx] */
vgmstream->coding_type = coding_MSADPCM; vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = read_16bit(post_meta_offset+0x0c,streamFile); vgmstream->interleave_block_size = read_16bit(extradata_offset+0x0c,streamFile);
/* in post_meta_offset is a WAVEFORMATEX (including coefs and all) */ /* in extradata_offset is a WAVEFORMATEX (including coefs and all) */
vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->interleave_block_size, vgmstream->channels); vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->interleave_block_size, vgmstream->channels);
if (loop_flag) { if (loop_flag) {
@ -346,8 +345,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
uint8_t buf[200]; uint8_t buf[200];
int32_t bytes; int32_t bytes;
/* post_meta_offset+0x00: fmt0x166 header (BE), post_meta_offset+0x34: seek table */ /* extradata_offset+0x00: fmt0x166 header (BE), extradata_offset+0x34: seek table */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, post_meta_offset,0x34, stream_size, streamFile, 1); bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, extradata_offset,0x34, stream_size, streamFile, 1);
if (bytes <= 0) goto fail; if (bytes <= 0) goto fail;
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size); ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size);
@ -365,7 +364,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
case 0x0E: { /* ATRAC3/ATRAC3plus [Lord of Arcana (PSP), Final Fantasy Type-0] */ case 0x0E: { /* ATRAC3/ATRAC3plus [Lord of Arcana (PSP), Final Fantasy Type-0] */
ffmpeg_codec_data *ffmpeg_data = NULL; ffmpeg_codec_data *ffmpeg_data = NULL;
/* full RIFF header at start_offset/post_meta_offset (same) */ /* full RIFF header at start_offset/extradata_offset (same) */
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size); ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
if (!ffmpeg_data) goto fail; if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data; vgmstream->codec_data = ffmpeg_data;
@ -401,17 +400,17 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
/* post header has various typical ATRAC9 values */ /* post header has various typical ATRAC9 values */
cfg.channels = vgmstream->channels; cfg.channels = vgmstream->channels;
cfg.config_data = read_32bit(post_meta_offset+0x0c,streamFile); cfg.config_data = read_32bit(extradata_offset+0x0c,streamFile);
cfg.encoder_delay = read_32bit(post_meta_offset+0x18,streamFile); cfg.encoder_delay = read_32bit(extradata_offset+0x18,streamFile);
vgmstream->codec_data = init_atrac9(&cfg); vgmstream->codec_data = init_atrac9(&cfg);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_ATRAC9; vgmstream->coding_type = coding_ATRAC9;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = read_32bit(post_meta_offset+0x10,streamFile); /* loop values above are also weird and ignored */ vgmstream->num_samples = read_32bit(extradata_offset+0x10,streamFile); /* loop values above are also weird and ignored */
vgmstream->loop_start_sample = read_32bit(post_meta_offset+0x20, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_start vgmstream->loop_start_sample = read_32bit(extradata_offset+0x20, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_start
vgmstream->loop_end_sample = read_32bit(post_meta_offset+0x24, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_end vgmstream->loop_end_sample = read_32bit(extradata_offset+0x24, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_end
break; break;
} }
#endif #endif

View File

@ -187,19 +187,15 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) {
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
case 0x03: { /* OGG [Final Fantasy XV Benchmark sfx (PC)] */ case 0x03: { /* OGG [Final Fantasy XV Benchmark sfx (PC)] */
VGMSTREAM *ogg_vgmstream = NULL; VGMSTREAM *ogg_vgmstream = NULL;
vgm_vorbis_info_t inf = {0}; ogg_vorbis_meta_info_t ovmi = {0};
off_t subfile_offset = extradata_offset + extradata_size; off_t subfile_offset = extradata_offset + extradata_size;
char filename[PATH_LIMIT];
streamFile->get_name(streamFile,filename,sizeof(filename)); ovmi.meta_type = vgmstream->meta_type;
ovmi.total_subsongs = total_subsongs;
inf.layout_type = layout_ogg_vorbis; ovmi.stream_size = stream_size;
inf.meta_type = vgmstream->meta_type;
inf.total_subsongs = total_subsongs;
inf.stream_size = stream_size;
/* post header has some kind of repeated values, config/table? */ /* post header has some kind of repeated values, config/table? */
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, subfile_offset, &inf); ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, subfile_offset, &ovmi);
if (ogg_vgmstream) { if (ogg_vgmstream) {
ogg_vgmstream->num_streams = vgmstream->num_streams; ogg_vgmstream->num_streams = vgmstream->num_streams;
ogg_vgmstream->stream_size = vgmstream->stream_size; ogg_vgmstream->stream_size = vgmstream->stream_size;

View File

@ -210,13 +210,11 @@ fail:
} }
/* Android/iOS Variants (Star Ocean Anamnesis (APK v1.9.2), Heaven x Inferno (iOS)) */ /* Android/iOS Variants (Star Ocean Anamnesis (APK v1.9.2), Heaven x Inferno (iOS)) */
VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_ta_aac_mobile_vorbis(STREAMFILE *streamFile) {
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
off_t start_offset; off_t start_offset;
char filename[PATH_LIMIT];
int8_t codec_id; int8_t codec_id;
streamFile->get_name(streamFile, filename, sizeof(filename));
/* check extension, case insensitive */ /* check extension, case insensitive */
/* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */ /* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */
if (!check_extensions(streamFile, "aac,laac,ace")) if (!check_extensions(streamFile, "aac,laac,ace"))
@ -231,19 +229,17 @@ VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile) {
codec_id = read_8bit(0x104, streamFile); codec_id = read_8bit(0x104, streamFile);
if (codec_id == 0xe) /* Vorbis */ if (codec_id == 0xe) /* Vorbis */
{ {
vgm_vorbis_info_t inf; ogg_vorbis_meta_info_t ovmi = {0};
VGMSTREAM * result = NULL; VGMSTREAM * result = NULL;
memset(&inf, 0, sizeof(inf)); ovmi.meta_type = meta_TA_AAC_MOBILE;
inf.layout_type = layout_ogg_vorbis; ovmi.loop_start = read_32bitLE(0x140, streamFile);
inf.meta_type = meta_TA_AAC_VORBIS; ovmi.loop_end = read_32bitLE(0x144, streamFile);
inf.loop_start = read_32bitLE(0x140, streamFile); ovmi.loop_flag = ovmi.loop_end > ovmi.loop_start;
inf.loop_end = read_32bitLE(0x144, streamFile); ovmi.loop_end_found = ovmi.loop_flag;
inf.loop_flag = inf.loop_end > inf.loop_start;
inf.loop_end_found = inf.loop_flag;
start_offset = read_32bitLE(0x120, streamFile); start_offset = read_32bitLE(0x120, streamFile);
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); result = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
if (result != NULL) { if (result != NULL) {
return result; return result;
@ -255,3 +251,65 @@ fail:
#endif #endif
return NULL; return NULL;
} }
/* Android/iOS Variants, before they switched to Vorbis (Star Ocean Anamnesis (Android), Heaven x Inferno (iOS)) */
VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int channel_count, loop_flag, codec;
size_t data_size;
/* check extension, case insensitive */
/* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */
if (!check_extensions(streamFile, "aac,laac,ace"))
goto fail;
if (read_32bitLE(0x00, streamFile) != 0x41414320) /* "AAC " */
goto fail;
if (read_32bitLE(0xf0, streamFile) != 0x57415645) /* "WAVE" */
goto fail;
codec = read_8bit(0x104, streamFile);
channel_count = read_8bit(0x105, streamFile);
/* 0x106: 0x01?, 0x107: 0x10? */
data_size = read_32bitLE(0x10c, streamFile); /* usable data only, cuts last frame */
start_offset = read_32bitLE(0x120, streamFile);
/* 0x124: full data size */
loop_flag = (read_32bitLE(0x134, streamFile) > 0);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x108, streamFile);
vgmstream->meta_type = meta_TA_AAC_MOBILE;
switch(codec) {
case 0x0d:
if (read_32bitLE(0x144, streamFile) != 0x40) goto fail; /* frame size */
if (read_32bitLE(0x148, streamFile) != (0x40-0x04*channel_count)*2 / channel_count) goto fail; /* frame samples */
if (channel_count > 2) goto fail; /* unknown data layout */
vgmstream->coding_type = coding_YAMAHA;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = yamaha_bytes_to_samples(data_size, channel_count);
vgmstream->loop_start_sample = yamaha_bytes_to_samples(read_32bitLE(0x130, streamFile), channel_count);;
vgmstream->loop_end_sample = yamaha_bytes_to_samples(read_32bitLE(0x134, streamFile), channel_count);;
break;
default:
goto fail;
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_waf(STREAMFILE *streamFile) {
int loop_flag, channel_count; int loop_flag, channel_count;
/* check extension */ /* checks */
if (!check_extensions(streamFile, "waf")) if (!check_extensions(streamFile, "waf"))
goto fail; goto fail;

View File

@ -4,7 +4,7 @@
#define MAX_SEGMENTS 4 #define MAX_SEGMENTS 4
/* .WAVE - WayForward "EngineBlack" games, segmented [Shantae and the Pirate's Curse (PC/3DS), TMNT: Danger of the Ooze (PS3/3DS)] */ /* .WAVE - "EngineBlack" games, segmented [Shantae and the Pirate's Curse (PC/3DS), TMNT: Danger of the Ooze (PS3/3DS)] */
VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
off_t segments_offset; off_t segments_offset;
@ -135,18 +135,15 @@ VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) {
} }
case 0x04: { /* "vorbis" */ case 0x04: { /* "vorbis" */
char filename[PATH_LIMIT]; ogg_vorbis_meta_info_t ovmi = {0};
vgm_vorbis_info_t ovi = {0};
segment_offset = read_32bit(table_offset, streamFile); segment_offset = read_32bit(table_offset, streamFile);
segment_size = read_32bitBE(segment_offset, streamFile); /* always BE */ segment_size = read_32bitBE(segment_offset, streamFile); /* always BE */
ovi.layout_type = layout_ogg_vorbis; ovmi.meta_type = meta_WAVE;
ovi.meta_type = meta_WAVE; ovmi.stream_size = segment_size;
ovi.stream_size = segment_size;
streamFile->get_name(streamFile,filename,sizeof(filename)); data->segments[i] = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, segment_offset+0x04, &ovmi);
data->segments[i] = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, segment_offset+0x04, &ovi);
if (!data->segments[i]) goto fail; if (!data->segments[i]) goto fail;
if (data->segments[i]->num_samples != segment_samples) { if (data->segments[i]->num_samples != segment_samples) {

View File

@ -9,12 +9,10 @@ VGMSTREAM * init_vgmstream_wii_04sw(STREAMFILE *streamFile) {
size_t file_size, data_size; size_t file_size, data_size;
/* check extension, case insensitive */ /* checks */
/* ".04sw" is just the ID, the real filename inside the file uses .XA */ /* ".04sw" is just the ID, the real filename inside the file uses .XA */
if (!check_extensions(streamFile,"xa,04sw")) if (!check_extensions(streamFile,"xa,04sw"))
goto fail; goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x30345357) /* "04SW" */ if (read_32bitBE(0x00,streamFile) != 0x30345357) /* "04SW" */
goto fail; goto fail;
@ -39,9 +37,9 @@ VGMSTREAM * init_vgmstream_wii_04sw(STREAMFILE *streamFile) {
vgmstream->num_samples = read_32bitBE(0x04,streamFile); vgmstream->num_samples = read_32bitBE(0x04,streamFile);
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave_shortblock; vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave;
vgmstream->interleave_block_size = 0x8000; vgmstream->interleave_block_size = 0x8000;
vgmstream->interleave_smallblock_size = (read_32bitBE(0x08,streamFile) / 2 % vgmstream->interleave_block_size + 7) / 8 * 8; vgmstream->interleave_last_block_size = (read_32bitBE(0x08,streamFile) / 2 % vgmstream->interleave_block_size + 7) / 8 * 8;
dsp_read_coefs_be(vgmstream,streamFile,0x20, 0x60); dsp_read_coefs_be(vgmstream,streamFile,0x20, 0x60);
/* the initial history offset seems different thatn standard DSP and possibly always zero */ /* the initial history offset seems different thatn standard DSP and possibly always zero */
@ -50,10 +48,8 @@ VGMSTREAM * init_vgmstream_wii_04sw(STREAMFILE *streamFile) {
/* the rest of the header has unknown values (several repeats) and the filename */ /* the rest of the header has unknown values (several repeats) and the filename */
/* open the file for reading */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;
fail: fail:

View File

@ -1,20 +1,17 @@
#include "meta.h" #include "meta.h"
#include "../util.h" #include "../coding/coding.h"
/* RAS (from Donkey Kong Country Returns) */ /* RAS_ - from Donkey Kong Country Returns (Wii) */
VGMSTREAM * init_vgmstream_wii_ras(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_wii_ras(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
int loop_flag; int loop_flag, channel_count;
int channel_count;
/* check extension, case insensitive */ /* checks */
streamFile->get_name(streamFile,filename,sizeof(filename)); if (!check_extensions(streamFile, "ras"))
if (strcasecmp("ras",filename_extension(filename))) goto fail; goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x5241535F) /* "RAS_" */ if (read_32bitBE(0x00,streamFile) != 0x5241535F) /* "RAS_" */
goto fail; goto fail;
@ -26,63 +23,32 @@ VGMSTREAM * init_vgmstream_wii_ras(STREAMFILE *streamFile) {
loop_flag = 1; loop_flag = 1;
} }
channel_count = 2; channel_count = 2;
start_offset = read_32bitBE(0x18,streamFile);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = read_32bitBE(0x18,streamFile);
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x14,streamFile); vgmstream->sample_rate = read_32bitBE(0x14,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x1c,streamFile)/channel_count/8*14;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x20,streamFile);
vgmstream->meta_type = meta_WII_RAS; vgmstream->meta_type = meta_WII_RAS;
if (loop_flag) { vgmstream->coding_type = coding_NGC_DSP;
// loop is block + samples into block vgmstream->layout_type = layout_interleave;
vgmstream->loop_start_sample = vgmstream->interleave_block_size = read_32bitBE(0x20,streamFile);
read_32bitBE(0x30,streamFile)*vgmstream->interleave_block_size/8*14 +
vgmstream->num_samples = read_32bitBE(0x1c,streamFile)/channel_count/8*14;
if (loop_flag) { /* loop is block + samples into block */
vgmstream->loop_start_sample = read_32bitBE(0x30,streamFile)*vgmstream->interleave_block_size/8*14 +
read_32bitBE(0x34,streamFile); read_32bitBE(0x34,streamFile);
vgmstream->loop_end_sample = vgmstream->loop_end_sample = read_32bitBE(0x38,streamFile)*vgmstream->interleave_block_size/8*14 +
read_32bitBE(0x38,streamFile)*vgmstream->interleave_block_size/8*14 +
read_32bitBE(0x3C,streamFile); read_32bitBE(0x3C,streamFile);
} }
if (vgmstream->coding_type == coding_NGC_DSP) { dsp_read_coefs_be(vgmstream,streamFile,0x40,0x30);
int i;
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x40+i*2,streamFile); if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
}
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x70+i*2,streamFile);
}
} else {
goto fail; goto fail;
}
/* open the file for reading */
{
int i;
for (i=0;i<channel_count;i++) {
if (vgmstream->layout_type==layout_interleave_shortblock)
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
vgmstream->interleave_block_size);
else
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
0x1000);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=
start_offset + i*vgmstream->interleave_block_size;
}
}
return vgmstream; return vgmstream;
/* clean up anything we may have opened */ /* clean up anything we may have opened */

View File

@ -229,8 +229,8 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
/* older Wwise (~<2012) */ /* older Wwise (~<2012) */
switch(vorb_size) { switch(vorb_size) {
//case 0x2C: /* early (~2009), some EVE Online Apocrypha files? */ case 0x2C: /* earliest (~2009), ex. UFC Undisputed 2009 (PS3), some EVE Online Apocrypha files? */
case 0x28: /* early (~2009), ex. The Lord of the Rings: Conquest PC */ case 0x28: /* early (~2009), ex. The Lord of the Rings: Conquest (PC) */
data_offsets = 0x18; data_offsets = 0x18;
block_offsets = 0; /* no need, full headers are present */ block_offsets = 0; /* no need, full headers are present */
cfg.header_type = WWV_TYPE_8; cfg.header_type = WWV_TYPE_8;
@ -589,15 +589,15 @@ fail:
0x31 (1): blocksize_0_exp (large) 0x31 (1): blocksize_0_exp (large)
0x32 (2): empty 0x32 (2): empty
"vorb" size 0x28 / 0x2a "vorb" size 0x28 / 0x2c / 0x2a
0x00 (4): num_samples 0x00 (4): num_samples
0x04 (4): data start offset after seek table+setup, or loop start when "smpl" is present 0x04 (4): data start offset after seek table+setup, or loop start when "smpl" is present
0x08 (4): data end offset after seek table (setup+packets), or loop end when "smpl" is present 0x08 (4): data end offset after seek table (setup+packets), or loop end when "smpl" is present
0x0c (2): ? (small, 0..~0x400) 0x0c (2): ? (small, 0..~0x400) [(4) when size is 0x2C]
0x10 (4): setup_offset within data (0 = no seek table) 0x10 (4): setup_offset within data (0 = no seek table)
0x14 (4): audio_offset within data 0x14 (4): audio_offset within data
0x18 (2): biggest packet size (not including header)? 0x18 (2): biggest packet size (not including header)?
0x1a (2): ? (small, N..~0x100) uLastGranuleExtra? 0x1a (2): ? (small, N..~0x100) uLastGranuleExtra? [(4) when size is 0x2C]
0x1c (4): ? (mid, 0~0x5000) dwDecodeAllocSize? 0x1c (4): ? (mid, 0~0x5000) dwDecodeAllocSize?
0x20 (4): ? (mid, 0~0x5000) dwDecodeX64AllocSize? 0x20 (4): ? (mid, 0~0x5000) dwDecodeX64AllocSize?
0x24 (4): parent bank/event id? uHashCodebook? (shared by several .wem a game, but not all need to share it) 0x24 (4): parent bank/event id? uHashCodebook? (shared by several .wem a game, but not all need to share it)

View File

@ -35,6 +35,11 @@ typedef struct {
size_t base_size; size_t base_size;
off_t entry_offset; off_t entry_offset;
size_t entry_size; size_t entry_size;
off_t names_offset;
size_t names_size;
size_t names_entry_size;
off_t extra_offset;
size_t extra_size;
off_t data_offset; off_t data_offset;
size_t data_size; size_t data_size;
@ -63,7 +68,7 @@ typedef struct {
uint32_t loop_end_sample; uint32_t loop_end_sample;
} xwb_header; } xwb_header;
static void get_xsb_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile); static void get_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile);
/* XWB - XACT Wave Bank (Microsoft SDK format for XBOX/XBOX360/Windows) */ /* XWB - XACT Wave Bank (Microsoft SDK format for XBOX/XBOX360/Windows) */
@ -100,12 +105,20 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
/* read segment offsets (SEGIDX) */ /* read segment offsets (SEGIDX) */
if (xwb.version <= XACT1_0_MAX) { if (xwb.version <= XACT1_0_MAX) {
xwb.total_subsongs = read_32bit(0x0c, streamFile); xwb.total_subsongs = read_32bit(0x0c, streamFile);
/* 0x10: bank name */ /* 0x10: bank name (size 0x10) */
xwb.entry_elem_size = 0x14; xwb.base_offset = 0;
xwb.base_size = 0;
xwb.entry_offset = 0x50; xwb.entry_offset = 0x50;
xwb.entry_size = xwb.entry_elem_size * xwb.total_subsongs; xwb.entry_size = xwb.entry_elem_size * xwb.total_subsongs;
xwb.entry_elem_size = 0x14;
xwb.data_offset = xwb.entry_offset + xwb.entry_size; xwb.data_offset = xwb.entry_offset + xwb.entry_size;
xwb.data_size = get_streamfile_size(streamFile) - xwb.data_offset; xwb.data_size = get_streamfile_size(streamFile) - xwb.data_offset;
xwb.names_offset = 0;
xwb.names_size = 0;
xwb.names_entry_size= 0;
xwb.extra_offset = 0;
xwb.extra_size = 0;
} }
else { else {
off = xwb.version <= XACT2_2_MAX ? 0x08 : 0x0c; off = xwb.version <= XACT2_2_MAX ? 0x08 : 0x0c;
@ -113,10 +126,32 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
xwb.base_size = read_32bit(off+0x04, streamFile); xwb.base_size = read_32bit(off+0x04, streamFile);
xwb.entry_offset= read_32bit(off+0x08, streamFile);//ENTRYMETADATA xwb.entry_offset= read_32bit(off+0x08, streamFile);//ENTRYMETADATA
xwb.entry_size = read_32bit(off+0x0c, streamFile); xwb.entry_size = read_32bit(off+0x0c, streamFile);
/* go to last segment (XACT2/3 have 5 segments, XACT1 4) */
//0x10: XACT1/2: ENTRYNAMES, XACT3: SEEKTABLES /* read extra segments (values can be 0 == no segment) */
//0x14: XACT1: none (ENTRYWAVEDATA), XACT2: EXTRA, XACT3: ENTRYNAMES if (xwb.version <= XACT1_1_MAX) {
suboff = xwb.version <= XACT1_1_MAX ? 0x08 : 0x08+0x08; xwb.names_offset = read_32bit(off+0x10, streamFile);//ENTRYNAMES
xwb.names_size = read_32bit(off+0x14, streamFile);
xwb.names_entry_size= 0x40;
xwb.extra_offset = 0;
xwb.extra_size = 0;
suboff = 0x04*2;
}
else if (xwb.version <= XACT2_1_MAX) {
xwb.names_offset = read_32bit(off+0x10, streamFile);//ENTRYNAMES
xwb.names_size = read_32bit(off+0x14, streamFile);
xwb.names_entry_size= 0x40;
xwb.extra_offset = read_32bit(off+0x18, streamFile);//EXTRA
xwb.extra_size = read_32bit(off+0x1c, streamFile);
suboff = 0x04*2 + 0x04*2;
} else {
xwb.extra_offset = read_32bit(off+0x10, streamFile);//SEEKTABLES
xwb.extra_size = read_32bit(off+0x14, streamFile);
xwb.names_offset = read_32bit(off+0x18, streamFile);//ENTRYNAMES
xwb.names_size = read_32bit(off+0x1c, streamFile);
xwb.names_entry_size= 0x40;
suboff = 0x04*2 + 0x04*2;
}
xwb.data_offset = read_32bit(off+0x10+suboff, streamFile);//ENTRYWAVEDATA xwb.data_offset = read_32bit(off+0x10+suboff, streamFile);//ENTRYWAVEDATA
xwb.data_size = read_32bit(off+0x14+suboff, streamFile); xwb.data_size = read_32bit(off+0x14+suboff, streamFile);
@ -127,7 +162,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
off = xwb.base_offset; off = xwb.base_offset;
xwb.base_flags = (uint32_t)read_32bit(off+0x00, streamFile); xwb.base_flags = (uint32_t)read_32bit(off+0x00, streamFile);
xwb.total_subsongs = read_32bit(off+0x04, streamFile); xwb.total_subsongs = read_32bit(off+0x04, streamFile);
/* 0x08 bank_name */ /* 0x08: bank name (size 0x40) */
suboff = 0x08 + (xwb.version <= XACT1_1_MAX ? 0x10 : 0x40); suboff = 0x08 + (xwb.version <= XACT1_1_MAX ? 0x10 : 0x40);
xwb.entry_elem_size = read_32bit(off+suboff+0x00, streamFile); xwb.entry_elem_size = read_32bit(off+suboff+0x00, streamFile);
/* suboff+0x04: meta name entry size */ /* suboff+0x04: meta name entry size */
@ -315,8 +350,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
else if (xwb.version <= XACT2_1_MAX && (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) { else if (xwb.version <= XACT2_1_MAX && (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) {
/* v38: byte offset, v40+: sample offset, v39: ? */ /* v38: byte offset, v40+: sample offset, v39: ? */
/* need to manually find sample offsets, thanks to Microsoft dumb headers */ /* need to manually find sample offsets, thanks to Microsoft dumb headers */
ms_sample_data msd; ms_sample_data msd = {0};
memset(&msd,0,sizeof(ms_sample_data));
msd.xma_version = xwb.codec == XMA1 ? 1 : 2; msd.xma_version = xwb.codec == XMA1 ? 1 : 2;
msd.channels = xwb.channels; msd.channels = xwb.channels;
@ -360,7 +394,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
vgmstream->num_streams = xwb.total_subsongs; vgmstream->num_streams = xwb.total_subsongs;
vgmstream->stream_size = xwb.stream_size; vgmstream->stream_size = xwb.stream_size;
vgmstream->meta_type = meta_XWB; vgmstream->meta_type = meta_XWB;
get_xsb_name(vgmstream->stream_name,STREAM_NAME_SIZE, target_subsong, &xwb, streamFile); get_name(vgmstream->stream_name,STREAM_NAME_SIZE, target_subsong, &xwb, streamFile);
switch(xwb.codec) { switch(xwb.codec) {
case PCM: /* Unreal Championship (Xbox)[PCM8], KOF2003 (Xbox)[PCM16LE], Otomedius (X360)[PCM16BE] */ case PCM: /* Unreal Championship (Xbox)[PCM8], KOF2003 (Xbox)[PCM16LE], Otomedius (X360)[PCM16BE] */
@ -496,6 +530,24 @@ fail:
} }
/* ****************************************************************************** */
/* try to get the stream name in the .xwb, though they are very rarely included */
static int get_xwb_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile) {
int read;
if (!xwb->names_offset || !xwb->names_size || xwb->names_entry_size > maxsize)
goto fail;
read = read_string(buf,xwb->names_entry_size, xwb->names_offset + xwb->names_entry_size*(target_subsong-1),streamFile);
if (read <= 0) goto fail;
return 1;
fail:
return 0;
}
/* ****************************************************************************** */ /* ****************************************************************************** */
/* XSB parsing from xwb_split (mostly untouched), could be improved */ /* XSB parsing from xwb_split (mostly untouched), could be improved */
@ -539,24 +591,19 @@ typedef struct {
/* try to find the stream name in a companion XSB file, a comically complex cue format. */ /* try to find the stream name in a companion XSB file, a comically complex cue format. */
static void get_xsb_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamXwb) { static int get_xsb_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamXwb) {
STREAMFILE *streamFile = NULL; STREAMFILE *streamFile = NULL;
int i,j, start_sound, cfg__start_sound = 0, cfg__selected_wavebank = 0; int i,j, start_sound, cfg__start_sound = 0, cfg__selected_wavebank = 0;
int xsb_version; int xsb_version;
off_t off, suboff, name_offset = 0; off_t off, suboff, name_offset = 0;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
xsb_header xsb; xsb_header xsb = {0};
memset(&xsb,0,sizeof(xsb_header)); /* before any "fail"! */
streamFile = open_stream_ext(streamXwb, "xsb"); streamFile = open_stream_ext(streamXwb, "xsb");
if (!streamFile) goto fail; if (!streamFile) goto fail;
//todo try common names (xwb and xsb often are named slightly differently using a common convention)
/* check header */ /* check header */
if ((read_32bitBE(0x00,streamFile) != 0x5344424B) && /* "SDBK" (LE) */ if ((read_32bitBE(0x00,streamFile) != 0x5344424B) && /* "SDBK" (LE) */
(read_32bitBE(0x00,streamFile) != 0x4B424453)) /* "KBDS" (BE) */ (read_32bitBE(0x00,streamFile) != 0x4B424453)) /* "KBDS" (BE) */
@ -817,6 +864,25 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_subsong, xwb_hea
fail: fail:
free(xsb.xsb_sounds); free(xsb.xsb_sounds);
free(xsb.xsb_wavebanks); free(xsb.xsb_wavebanks);
if (streamFile) close_streamfile(streamFile); close_streamfile(streamFile);
return;
return (name_offset);
}
static void get_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile) {
int name_found;
/* try inside this xwb */
name_found = get_xwb_name(buf, maxsize, target_subsong, xwb, streamFile);
if (name_found) return;
/* try again in external .xsb */
get_xsb_name(buf, maxsize, target_subsong, xwb, streamFile);
//todo try again with common names (xwb and xsb often are named slightly differently using a common convention):
// InGameMusic.xwb + ingamemusic.xsb
// UIMusicBank.xwb + UISoundBank.xsb
// NB_BGM_m0100_WB.xwb + NB_BGM_m0100_SB.xsb
// Wave Bank.xwb + Sound Bank.xsb
} }

View File

@ -628,9 +628,10 @@ fail:
static void multifile_close(MULTIFILE_STREAMFILE *streamfile) { static void multifile_close(MULTIFILE_STREAMFILE *streamfile) {
int i; int i;
for (i = 0; i < streamfile->inner_sfs_size; i++) { for (i = 0; i < streamfile->inner_sfs_size; i++) {
for (i = 0; i < streamfile->inner_sfs_size; i++) for (i = 0; i < streamfile->inner_sfs_size; i++) {
close_streamfile(streamfile->inner_sfs[i]); close_streamfile(streamfile->inner_sfs[i]);
} }
}
free(streamfile->inner_sfs); free(streamfile->inner_sfs);
free(streamfile->sizes); free(streamfile->sizes);
free(streamfile); free(streamfile);

View File

@ -69,7 +69,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_mp4_aac, init_vgmstream_mp4_aac,
#endif #endif
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) #if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
init_vgmstream_akb, init_vgmstream_akb_mp4,
#endif #endif
init_vgmstream_sadb, init_vgmstream_sadb,
init_vgmstream_ps2_bmdx, init_vgmstream_ps2_bmdx,
@ -257,7 +257,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_ps2_voi, init_vgmstream_ps2_voi,
init_vgmstream_ps2_khv, init_vgmstream_ps2_khv,
init_vgmstream_pc_smp, init_vgmstream_pc_smp,
init_vgmstream_ngc_bo2, init_vgmstream_ngc_rkv,
init_vgmstream_dsp_ddsp, init_vgmstream_dsp_ddsp,
init_vgmstream_p3d, init_vgmstream_p3d,
init_vgmstream_ps2_tk1, init_vgmstream_ps2_tk1,
@ -330,8 +330,8 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_ps2_vds_vdm, init_vgmstream_ps2_vds_vdm,
init_vgmstream_x360_cxs, init_vgmstream_x360_cxs,
init_vgmstream_dsp_adx, init_vgmstream_dsp_adx,
init_vgmstream_akb_multi, init_vgmstream_akb,
init_vgmstream_akb2_multi, init_vgmstream_akb2,
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
init_vgmstream_mp4_aac_ffmpeg, init_vgmstream_mp4_aac_ffmpeg,
#endif #endif
@ -350,6 +350,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_ta_aac_x360, init_vgmstream_ta_aac_x360,
init_vgmstream_ta_aac_ps3, init_vgmstream_ta_aac_ps3,
init_vgmstream_ta_aac_mobile, init_vgmstream_ta_aac_mobile,
init_vgmstream_ta_aac_mobile_vorbis,
init_vgmstream_ps3_mta2, init_vgmstream_ps3_mta2,
init_vgmstream_ngc_ulw, init_vgmstream_ngc_ulw,
init_vgmstream_pc_xa30, init_vgmstream_pc_xa30,
@ -383,6 +384,9 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_wave, init_vgmstream_wave,
init_vgmstream_wave_segmented, init_vgmstream_wave_segmented,
init_vgmstream_rsd6at3p, init_vgmstream_rsd6at3p,
init_vgmstream_rsd6wma,
init_vgmstream_smv,
init_vgmstream_nxap,
init_vgmstream_txth, /* should go at the end (lower priority) */ init_vgmstream_txth, /* should go at the end (lower priority) */
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
@ -884,12 +888,8 @@ void vgmstream_force_loop(VGMSTREAM* vgmstream, int loop_flag, int loop_start_sa
void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
switch (vgmstream->layout_type) { switch (vgmstream->layout_type) {
case layout_interleave: case layout_interleave:
case layout_interleave_shortblock:
render_vgmstream_interleave(buffer,sample_count,vgmstream); render_vgmstream_interleave(buffer,sample_count,vgmstream);
break; break;
#ifdef VGM_USE_VORBIS
case layout_ogg_vorbis:
#endif
case layout_none: case layout_none:
render_vgmstream_nolayout(buffer,sample_count,vgmstream); render_vgmstream_nolayout(buffer,sample_count,vgmstream);
break; break;
@ -900,7 +900,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
case layout_blocked_ea_schl: case layout_blocked_ea_schl:
case layout_blocked_ea_1snh: case layout_blocked_ea_1snh:
case layout_blocked_caf: case layout_blocked_caf:
case layout_wsi_blocked: case layout_blocked_wsi:
case layout_str_snds_blocked: case layout_str_snds_blocked:
case layout_ws_aud_blocked: case layout_ws_aud_blocked:
case layout_matx_blocked: case layout_matx_blocked:
@ -1006,6 +1006,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_3DS_IMA: case coding_3DS_IMA:
return 2; return 2;
case coding_XBOX_IMA: case coding_XBOX_IMA:
case coding_XBOX_IMA_mch:
case coding_XBOX_IMA_int: case coding_XBOX_IMA_int:
case coding_FSB_IMA: case coding_FSB_IMA:
case coding_WWISE_IMA: case coding_WWISE_IMA:
@ -1048,6 +1049,10 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
return vgmstream->ws_output_size; return vgmstream->ws_output_size;
case coding_AICA: case coding_AICA:
return 2; return 2;
case coding_YAMAHA:
return (0x40-0x04*vgmstream->channels) * 2 / vgmstream->channels;
case coding_YAMAHA_NXAP:
return (0x40-0x04) * 2;
case coding_NDS_PROCYON: case coding_NDS_PROCYON:
return 30; return 30;
case coding_L5_555: case coding_L5_555:
@ -1175,9 +1180,11 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
//todo should be 0x48 when stereo, but blocked/interleave layout don't understand stereo codecs //todo should be 0x48 when stereo, but blocked/interleave layout don't understand stereo codecs
return 0x24; //vgmstream->channels==1 ? 0x24 : 0x48; return 0x24; //vgmstream->channels==1 ? 0x24 : 0x48;
case coding_XBOX_IMA_int: case coding_XBOX_IMA_int:
case coding_FSB_IMA:
case coding_WWISE_IMA: case coding_WWISE_IMA:
return 0x24; return 0x24;
case coding_XBOX_IMA_mch:
case coding_FSB_IMA:
return 0x24 * vgmstream->channels;
case coding_APPLE_IMA4: case coding_APPLE_IMA4:
return 0x22; return 0x22;
@ -1208,6 +1215,9 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
return vgmstream->current_block_size; return vgmstream->current_block_size;
case coding_AICA: case coding_AICA:
return 0x01; return 0x01;
case coding_YAMAHA:
case coding_YAMAHA_NXAP:
return 0x40;
case coding_NDS_PROCYON: case coding_NDS_PROCYON:
return 0x10; return 0x10;
case coding_L5_555: case coding_L5_555:
@ -1251,7 +1261,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) { int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) {
switch (vgmstream->coding_type) { switch (vgmstream->coding_type) {
case coding_NDS_IMA: case coding_NDS_IMA:
return (vgmstream->interleave_smallblock_size-4)*2; return (vgmstream->interleave_last_block_size-4)*2;
default: default:
return get_vgmstream_samples_per_frame(vgmstream); return get_vgmstream_samples_per_frame(vgmstream);
} }
@ -1259,7 +1269,7 @@ int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) {
int get_vgmstream_shortframe_size(VGMSTREAM * vgmstream) { int get_vgmstream_shortframe_size(VGMSTREAM * vgmstream) {
switch (vgmstream->coding_type) { switch (vgmstream->coding_type) {
case coding_NDS_IMA: case coding_NDS_IMA:
return vgmstream->interleave_smallblock_size; return vgmstream->interleave_last_block_size;
default: default:
return get_vgmstream_frame_size(vgmstream); return get_vgmstream_frame_size(vgmstream);
} }
@ -1433,7 +1443,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
break; break;
case coding_XBOX_IMA: case coding_XBOX_IMA:
for (chan=0;chan<vgmstream->channels;chan++) { for (chan=0;chan<vgmstream->channels;chan++) {
decode_xbox_ima(vgmstream,&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, decode_xbox_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do,chan);
}
break;
case coding_XBOX_IMA_mch:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_xbox_ima_mch(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block, vgmstream->channels,vgmstream->samples_into_block,
samples_to_do,chan); samples_to_do,chan);
} }
@ -1799,6 +1816,20 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do); samples_to_do);
} }
break; break;
case coding_YAMAHA:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_yamaha(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do, chan);
}
break;
case coding_YAMAHA_NXAP:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_yamaha_nxap(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do);
}
break;
case coding_NDS_PROCYON: case coding_NDS_PROCYON:
for (chan=0;chan<vgmstream->channels;chan++) { for (chan=0;chan<vgmstream->channels;chan++) {
decode_nds_procyon(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, decode_nds_procyon(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
@ -2109,17 +2140,16 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
"\n"); "\n");
concatn(length,desc,temp); concatn(length,desc,temp);
if (vgmstream->layout_type == layout_interleave if (vgmstream->layout_type == layout_interleave) {
|| vgmstream->layout_type == layout_interleave_shortblock) {
snprintf(temp,TEMPSIZE, snprintf(temp,TEMPSIZE,
"interleave: %#x bytes\n", "interleave: %#x bytes\n",
(int32_t)vgmstream->interleave_block_size); (int32_t)vgmstream->interleave_block_size);
concatn(length,desc,temp); concatn(length,desc,temp);
if (vgmstream->layout_type == layout_interleave_shortblock) { if (vgmstream->interleave_last_block_size) {
snprintf(temp,TEMPSIZE, snprintf(temp,TEMPSIZE,
"last block interleave: %#x bytes\n", "interleave last block: %#x bytes\n",
(int32_t)vgmstream->interleave_smallblock_size); (int32_t)vgmstream->interleave_last_block_size);
concatn(length,desc,temp); concatn(length,desc,temp);
} }
} }
@ -2192,7 +2222,8 @@ static void try_dual_file_stereo(VGMSTREAM * opened_vgmstream, STREAMFILE *strea
{"l","r"}, {"l","r"},
{"left","right"}, {"left","right"},
{"Left","Right"}, {"Left","Right"},
{".V0",".V1"}, {".V0",".V1"}, /* Homura (PS2) */
{".L",".R"}, /* Crash Nitro Racing (PS2) */
{"_0","_1"}, //unneeded? {"_0","_1"}, //unneeded?
}; };
char new_filename[PATH_LIMIT]; char new_filename[PATH_LIMIT];
@ -2269,7 +2300,7 @@ static void try_dual_file_stereo(VGMSTREAM * opened_vgmstream, STREAMFILE *strea
/* check even if the layout doesn't use them, because it is /* check even if the layout doesn't use them, because it is
* difficult to determine when it does, and they should be zero otherwise, anyway */ * difficult to determine when it does, and they should be zero otherwise, anyway */
new_vgmstream->interleave_block_size == opened_vgmstream->interleave_block_size && new_vgmstream->interleave_block_size == opened_vgmstream->interleave_block_size &&
new_vgmstream->interleave_smallblock_size == opened_vgmstream->interleave_smallblock_size)) { new_vgmstream->interleave_last_block_size == opened_vgmstream->interleave_last_block_size)) {
goto fail; goto fail;
} }

View File

@ -128,6 +128,7 @@ typedef enum {
coding_3DS_IMA, /* 3DS IMA ADPCM */ coding_3DS_IMA, /* 3DS IMA ADPCM */
coding_MS_IMA, /* Microsoft IMA ADPCM */ coding_MS_IMA, /* Microsoft IMA ADPCM */
coding_XBOX_IMA, /* XBOX IMA ADPCM */ coding_XBOX_IMA, /* XBOX IMA ADPCM */
coding_XBOX_IMA_mch, /* XBOX IMA ADPCM (multichannel) */
coding_XBOX_IMA_int, /* XBOX IMA ADPCM (interleaved/mono) */ coding_XBOX_IMA_int, /* XBOX IMA ADPCM (interleaved/mono) */
coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */ coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */
coding_DAT4_IMA, /* Eurocom 'DAT4' IMA ADPCM */ coding_DAT4_IMA, /* Eurocom 'DAT4' IMA ADPCM */
@ -145,6 +146,8 @@ typedef enum {
coding_MSADPCM, /* Microsoft ADPCM */ coding_MSADPCM, /* Microsoft ADPCM */
coding_WS, /* Westwood Studios VBR ADPCM */ coding_WS, /* Westwood Studios VBR ADPCM */
coding_AICA, /* Yamaha AICA ADPCM */ coding_AICA, /* Yamaha AICA ADPCM */
coding_YAMAHA, /* Yamaha ADPCM */
coding_YAMAHA_NXAP, /* Yamaha ADPCM (NXAP variation) */
coding_NDS_PROCYON, /* Procyon Studio ADPCM */ coding_NDS_PROCYON, /* Procyon Studio ADPCM */
coding_L5_555, /* Level-5 0x555 ADPCM */ coding_L5_555, /* Level-5 0x555 ADPCM */
coding_SASSC, /* Activision EXAKT SASSC DPCM */ coding_SASSC, /* Activision EXAKT SASSC DPCM */
@ -212,7 +215,6 @@ typedef enum {
/* interleave */ /* interleave */
layout_interleave, /* equal interleave throughout the stream */ layout_interleave, /* equal interleave throughout the stream */
layout_interleave_shortblock, /* interleave with a short last block */
/* headered blocks */ /* headered blocks */
layout_ast_blocked, layout_ast_blocked,
@ -221,7 +223,7 @@ typedef enum {
layout_blocked_ea_schl, layout_blocked_ea_schl,
layout_blocked_ea_1snh, layout_blocked_ea_1snh,
layout_blocked_caf, layout_blocked_caf,
layout_wsi_blocked, layout_blocked_wsi,
layout_str_snds_blocked, layout_str_snds_blocked,
layout_ws_aud_blocked, layout_ws_aud_blocked,
layout_matx_blocked, layout_matx_blocked,
@ -254,9 +256,6 @@ typedef enum {
layout_segmented, /* song divided in segments, each a complete VGMSTREAM */ layout_segmented, /* song divided in segments, each a complete VGMSTREAM */
layout_scd_int, /* deinterleave done by the SCDINTSTREAMFILE */ layout_scd_int, /* deinterleave done by the SCDINTSTREAMFILE */
#ifdef VGM_USE_VORBIS
layout_ogg_vorbis, /* ogg vorbis file */
#endif
} layout_t; } layout_t;
/* The meta type specifies how we know what we know about the file. /* The meta type specifies how we know what we know about the file.
@ -371,7 +370,7 @@ typedef enum {
meta_PS2_PSH, /* Dawn of Mana - Seiken Densetsu 4 */ meta_PS2_PSH, /* Dawn of Mana - Seiken Densetsu 4 */
meta_SCD_PCM, /* Lunar - Eternal Blue */ meta_SCD_PCM, /* Lunar - Eternal Blue */
meta_PS2_PCM, /* Konami KCEJ East: Ephemeral Fantasia, Yu-Gi-Oh! The Duelists of the Roses, 7 Blades */ meta_PS2_PCM, /* Konami KCEJ East: Ephemeral Fantasia, Yu-Gi-Oh! The Duelists of the Roses, 7 Blades */
meta_PS2_RKV, /* Legacy of Kain - Blood Omen 2 */ meta_PS2_RKV, /* Legacy of Kain - Blood Omen 2 (PS2) */
meta_PS2_PSW, /* Rayman Raving Rabbids */ meta_PS2_PSW, /* Rayman Raving Rabbids */
meta_PS2_VAS, /* Pro Baseball Spirits 5 */ meta_PS2_VAS, /* Pro Baseball Spirits 5 */
meta_PS2_TEC, /* TECMO badflagged stream */ meta_PS2_TEC, /* TECMO badflagged stream */
@ -428,6 +427,7 @@ typedef enum {
meta_RSD6OOGV, /* RSD6OOGV */ meta_RSD6OOGV, /* RSD6OOGV */
meta_RSD6XMA, /* RSD6XMA */ meta_RSD6XMA, /* RSD6XMA */
meta_RSD6AT3P, /* RSD6AT3+ */ meta_RSD6AT3P, /* RSD6AT3+ */
meta_RSD6WMA, /* RSD6WMA */
meta_PS2_ASS, /* ASS */ meta_PS2_ASS, /* ASS */
meta_PS2_SEG, /* Eragon */ meta_PS2_SEG, /* Eragon */
@ -535,7 +535,7 @@ typedef enum {
meta_P3D, /* Prototype P3D */ meta_P3D, /* Prototype P3D */
meta_PS2_TK1, /* Tekken (NamCollection) */ meta_PS2_TK1, /* Tekken (NamCollection) */
meta_PS2_ADSC, /* Kenka Bancho 2: Full Throttle */ meta_PS2_ADSC, /* Kenka Bancho 2: Full Throttle */
meta_NGC_BO2, /* Blood Omen 2 (NGC) */ meta_NGC_RKV, /* Legacy of Kain - Blood Omen 2 (GC) */
meta_DSP_DDSP, /* Various (2 dsp files stuck together */ meta_DSP_DDSP, /* Various (2 dsp files stuck together */
meta_NGC_DSP_MPDS, /* Big Air Freestyle, Terminator 3 */ meta_NGC_DSP_MPDS, /* Big Air Freestyle, Terminator 3 */
meta_DSP_STR_IG, /* Micro Machines, Superman Superman: Shadow of Apokolis */ meta_DSP_STR_IG, /* Micro Machines, Superman Superman: Shadow of Apokolis */
@ -617,7 +617,7 @@ typedef enum {
meta_GTD, /* Knights Contract (X360/PS3), Valhalla Knights 3 (PSV) */ meta_GTD, /* Knights Contract (X360/PS3), Valhalla Knights 3 (PSV) */
meta_TA_AAC_X360, /* tri-Ace AAC (Star Ocean 4, End of Eternity, Infinite Undiscovery) */ meta_TA_AAC_X360, /* tri-Ace AAC (Star Ocean 4, End of Eternity, Infinite Undiscovery) */
meta_TA_AAC_PS3, /* tri-Ace AAC (Star Ocean International, Resonance of Fate) */ meta_TA_AAC_PS3, /* tri-Ace AAC (Star Ocean International, Resonance of Fate) */
meta_TA_AAC_VORBIS, /* tri-Ace AAC (Star Ocean Anamnesis, Heaven x Inferno) */ meta_TA_AAC_MOBILE, /* tri-Ace AAC (Star Ocean Anamnesis, Heaven x Inferno) */
meta_PS3_MTA2, /* Metal Gear Solid 4 MTA2 */ meta_PS3_MTA2, /* Metal Gear Solid 4 MTA2 */
meta_NGC_ULW, /* Burnout 1 (GC only) */ meta_NGC_ULW, /* Burnout 1 (GC only) */
meta_PC_XA30, /* Driver - Parallel Lines (PC) */ meta_PC_XA30, /* Driver - Parallel Lines (PC) */
@ -656,8 +656,10 @@ typedef enum {
meta_SQEX_MAB, /* Square-Enix newest middleware (music) */ meta_SQEX_MAB, /* Square-Enix newest middleware (music) */
meta_OGG_L2SD, /* Ogg Vorbis with obfuscation [Lineage II Chronicle 4 (PC)] */ meta_OGG_L2SD, /* Ogg Vorbis with obfuscation [Lineage II Chronicle 4 (PC)] */
meta_WAF, /* KID WAF [Ever 17 (PC)] */ meta_WAF, /* KID WAF [Ever 17 (PC)] */
meta_WAVE, /* WayForward "EngineBlack" games [Mighty Switch Force! (3DS)] */ meta_WAVE, /* EngineBlack games [Mighty Switch Force! (3DS)] */
meta_WAVE_segmented, /* WayForward "EngineBlack" games, segmented [Shantae and the Pirate's Curse (PC)] */ meta_WAVE_segmented, /* EngineBlack games, segmented [Shantae and the Pirate's Curse (PC)] */
meta_SMV, /* Cho Aniki Zero (PSP) */
meta_NXAP, /* Nex Entertainment games [Time Crisis 4 (PS3), Time Crisis Razing Storm (PS3)] */
#ifdef VGM_USE_MP4V2 #ifdef VGM_USE_MP4V2
meta_MP4, /* AAC (iOS) */ meta_MP4, /* AAC (iOS) */
@ -745,7 +747,7 @@ typedef struct {
/* layouts/block */ /* layouts/block */
size_t interleave_block_size; /* interleave, or block/frame size (depending on the codec) */ 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 interleave_last_block_size; /* smaller interleave for last block */
/* channel state */ /* channel state */
VGMSTREAMCHANNEL * ch; /* pointer to array of channels */ VGMSTREAMCHANNEL * ch; /* pointer to array of channels */