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,"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,"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,"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,8 +17,9 @@ void g72x_init_state(struct g72x_state *state_ptr);
/* ima_decoder */
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_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_int(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_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_3ds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
@ -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);
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_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 */
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).
* 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) {
* Defined in Xbox's SDK. Multichannel interleaves 2ch*N/2, or 1ch*N with odd num_channels
* (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;
int32_t hist1 = stream->adpcm_history1_32;
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 */
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;
@ -613,6 +658,7 @@ void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channel
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) {
int i, sample_count, num_frame;
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",
"kvs",
"l",
"laac", //fake extension, for AAC (tri-Ace/FFmpeg)
"lac3", //fake extension, for AC3
"leg",
@ -240,6 +241,7 @@ static const char* extension_list[] = {
"psnd",
"psw",
"r",
"rac", //txth/reserved [Manhunt (Xbox)]
"rak",
"ras",
@ -291,6 +293,7 @@ static const char* extension_list[] = {
"sli",
"smp",
"smpl", //fake extension (to be removed)
"smv",
"snd",
"snds",
"sng",
@ -479,6 +482,7 @@ static const coding_info coding_info_list[] = {
{coding_3DS_IMA, "3DS IMA 4-bit ADPCM"},
{coding_MS_IMA, "Microsoft 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_NDS_IMA, "NDS-style 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_WS, "Westwood Studios VBR 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_L5_555, "Level-5 0x555 4-bit ADPCM"},
{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[] = {
{layout_none, "flat (no layout)"},
{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_ast_blocked, "AST 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_1snh, "blocked (EA 1SNh)"},
{layout_blocked_caf, "blocked (CAF)"},
{layout_wsi_blocked, ".wsi blocked"},
{layout_blocked_wsi, "blocked (WSI)"},
{layout_xvas_blocked, ".xvas blocked"},
{layout_str_snds_blocked, ".str SNDS 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_hwas, "blocked (HWAS)"},
{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_awc, "blocked (AWC)"},
{layout_blocked_vgs, "blocked (VGS)"},
{layout_blocked_vawx, "blocked (VAWX)"},
{layout_blocked_xvag_subsong, "blocked (XVAG subsong)"},
#ifdef VGM_USE_VORBIS
{layout_ogg_vorbis, "Ogg"},
#endif
};
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_SADL, "Procyon Studio SADL 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_AIFF, "Audio Interchange File Format"},
{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_SCD_PCM, "Lunar: Eternal Blue .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_VAS, "Pro Baseball Spirits 5 VAS Header"},
{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_DSP_WII_MUS, "mus header"},
{meta_WII_SNG, "SNG DSP Header"},
{meta_RSD2VAG, "RSD2/VAG Header"},
{meta_RSD2PCMB, "RSD2/PCMB Header"},
{meta_RSD2XADP, "RSD2/XADP Header"},
{meta_RSD3VAG, "RSD3/VAG Header"},
{meta_RSD3GADP, "RSD3/GADP Header"},
{meta_RSD3PCM, "RSD3/PCM Header"},
{meta_RSD3PCMB, "RSD3/PCMB Header"},
{meta_RSD4PCMB, "RSD4/PCMB Header"},
{meta_RSD4PCM, "RSD4/PCM Header"},
{meta_RSD4RADP, "RSD4/RADP Header"},
{meta_RSD4VAG, "RSD4/VAG Header"},
{meta_RSD6XADP, "RSD6/XADP Header"},
{meta_RSD6VAG, "RSD6/VAG Header"},
{meta_RSD6WADP, "RSD6/WADP Header"},
{meta_RSD6RADP, "RSD6/RADP Header"},
{meta_RSD6XMA, "RSD6/XMA Header"},
{meta_RSD6AT3P, "RSD6/AT3+ Header"},
{meta_RSD2VAG, "Radical RSD2/VAG header"},
{meta_RSD2PCMB, "Radical RSD2/PCMB header"},
{meta_RSD2XADP, "Radical RSD2/XADP header"},
{meta_RSD3VAG, "Radical RSD3/VAG header"},
{meta_RSD3GADP, "Radical RSD3/GADP header"},
{meta_RSD3PCM, "Radical RSD3/PCM header"},
{meta_RSD3PCMB, "Radical RSD3/PCMB header"},
{meta_RSD4PCMB, "Radical RSD4/PCMB header"},
{meta_RSD4PCM, "Radical RSD4/PCM header"},
{meta_RSD4RADP, "Radical RSD4/RADP header"},
{meta_RSD4VAG, "Radical RSD4/VAG header"},
{meta_RSD6XADP, "Radical RSD6/XADP header"},
{meta_RSD6VAG, "Radical RSD6/VAG header"},
{meta_RSD6WADP, "Radical RSD6/WADP header"},
{meta_RSD6RADP, "Radical RSD6/RADP header"},
{meta_RSD6XMA, "Radical RSD6/XMA header"},
{meta_RSD6AT3P, "Radical RSD6/AT3+ header"},
{meta_RSD6WMA, "Radical RSD6/WMA header"},
{meta_DC_ASD, "ASD Header"},
{meta_NAOMI_SPSD, "SPSD 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_PC_SMP, "Ghostbusters .smp 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_P3D, "Radical P3D header"},
{meta_PS2_TK1, "Tekken TK5STRM1 Header"},
@ -922,7 +927,7 @@ static const meta_info meta_info_list[] = {
{meta_GTD, "GTD/GHS header"},
{meta_TA_AAC_X360, "tri-Ace AAC (X360) 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_NGC_ULW, "Criterion ULW raw 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_WAVE, "EngineBlack .WAVE header"},
{meta_WAVE_segmented, "EngineBlack .WAVE header (segmented)"},
{meta_SMV, "Cho Aniki Zero .SMV header"},
{meta_NXAP, "Nex NXAP header"},
#ifdef VGM_USE_MP4V2
{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:
block_update_caf(vgmstream->next_block_offset,vgmstream);
break;
case layout_wsi_blocked:
wsi_block_update(vgmstream->next_block_offset,vgmstream);
case layout_blocked_wsi:
block_update_wsi(vgmstream->next_block_offset,vgmstream);
break;
case layout_str_snds_blocked:
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;
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) {
frame_size = get_vgmstream_shortframe_size(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) {
@ -23,7 +23,7 @@ void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREA
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
/* 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);
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
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) {
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) {
frame_size = get_vgmstream_shortframe_size(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++)
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 {
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_1snh(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_caf(off_t block_offset, VGMSTREAM * vgmstream);
void wsi_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_wsi(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"
>
</File>
<File
RelativePath=".\meta\ngc_bo2.c"
>
</File>
<File
RelativePath=".\meta\caf.c"
>
@ -662,6 +658,10 @@
RelativePath=".\meta\ngc_ssm.c"
>
</File>
<File
RelativePath=".\meta\ngc_str_cauldron.c"
>
</File>
<File
RelativePath=".\meta\ngc_tydsp.c"
>
@ -698,6 +698,10 @@
RelativePath=".\meta\nwa.c"
>
</File>
<File
RelativePath=".\meta\nxap.c"
>
</File>
<File
RelativePath=".\meta\ogg_vorbis.c"
>
@ -1186,6 +1190,10 @@
RelativePath=".\meta\sli.c"
>
</File>
<File
RelativePath=".\meta\smv.c"
>
</File>
<File
RelativePath=".\meta\sps_n1.c"
>
@ -1471,7 +1479,7 @@
>
</File>
<File
RelativePath=".\coding\aica_decoder.c"
RelativePath=".\coding\yamaha_decoder.c"
>
</File>
<File
@ -1815,7 +1823,7 @@
>
</File>
<File
RelativePath=".\layout\wsi_blocked.c"
RelativePath=".\layout\blocked_wsi.c"
>
</File>
<File

View File

@ -258,7 +258,6 @@
<ClCompile Include="meta\nds_swav.c" />
<ClCompile Include="meta\ngc_adpdtk.c" />
<ClCompile Include="meta\ngc_bh2pcm.c" />
<ClCompile Include="meta\ngc_bo2.c" />
<ClCompile Include="meta\caf.c" />
<ClCompile Include="meta\ngc_dsp_konami.c" />
<ClCompile Include="meta\ngc_dsp_mpds.c" />
@ -271,12 +270,14 @@
<ClCompile Include="meta\ngc_pdt.c" />
<ClCompile Include="meta\ngc_sck_dsp.c" />
<ClCompile Include="meta\ngc_ssm.c" />
<ClCompile Include="meta\ngc_str_cauldron.c" />
<ClCompile Include="meta\ngc_tydsp.c" />
<ClCompile Include="meta\ngc_ymf.c" />
<ClCompile Include="meta\ngc_ulw.c" />
<ClCompile Include="meta\ngc_vid1.c" />
<ClCompile Include="meta\nub_xma.c" />
<ClCompile Include="meta\nwa.c" />
<ClCompile Include="meta\nxap.c" />
<ClCompile Include="meta\ogg_vorbis.c" />
<ClCompile Include="meta\ogl.c" />
<ClCompile Include="meta\omu.c" />
@ -380,6 +381,7 @@
<ClCompile Include="meta\sdt.c" />
<ClCompile Include="meta\sfl.c" />
<ClCompile Include="meta\sli.c" />
<ClCompile Include="meta\smv.c" />
<ClCompile Include="meta\sps_n1.c" />
<ClCompile Include="meta\spt_spd.c" />
<ClCompile Include="meta\stm.c" />
@ -430,7 +432,7 @@
<ClCompile Include="meta\zwdsp.c" />
<ClCompile Include="coding\acm_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_xa_decoder.c" />
<ClCompile Include="coding\ea_xas_decoder.c" />
@ -498,7 +500,7 @@
<ClCompile Include="layout\thp_blocked.c" />
<ClCompile Include="layout\vs_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\xvas_block.c" />
<ClCompile Include="..\ext_libs\clHCA.c" />

View File

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

View File

@ -3,7 +3,7 @@
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
/* AKB (AAC only) - found in SQEX iOS games */
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
VGMSTREAM * init_vgmstream_akb_mp4(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
size_t filesize;
@ -34,74 +34,99 @@ fail:
/* AKB - found in SQEX iOS games */
VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile) {
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset, extra_data_offset = 0;
size_t file_size, header_size, extra_header_size = 0, extra_data_size = 0;
int loop_flag = 0, channel_count, codec;
off_t start_offset, extradata_offset = 0;
size_t stream_size, header_size, subheader_size = 0, extradata_size = 0;
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 */
if ( !check_extensions(streamFile, "akb") )
if ( !check_extensions(streamFile, "akb,bytes") )
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x414B4220) /* "AKB " */
goto fail;
if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile))
goto fail;
channel_count = read_8bit(0x0d,streamFile);
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?) */
/* 0x04(2): version? (iPad/IPhone?) */
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) */
if ( header_size >= 0x44) { /* v2 */
/* 0x10+: config? (pan, volume), 0x24: file_id? */
extra_data_size = read_16bitLE(0x1c,streamFile);
extra_header_size = read_16bitLE(0x28,streamFile);
extra_data_offset = header_size + extra_header_size;
start_offset = extra_data_offset + extra_data_size;
/* ~num_samples at extra_data_offset + 0x04/0x0c? */
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 */
extradata_size = read_16bitLE(0x1c,streamFile);
subheader_size = read_16bitLE(0x28,streamFile);
/* 0x20+: config? (pan, volume), 0x24: file_id? */
extradata_offset = header_size + subheader_size;
start_offset = extradata_offset + extradata_size;
}
else { /* v0 */
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) {
case 0x02: { /* MSAPDCM [various SFX] */
case 0x02: { /* MSAPDCM [Dragon Quest II (iOS) sfx] */
vgmstream->coding_type = coding_MSADPCM;
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
* (base samples may have more than possible and read over file size otherwise, very strange)
* loop_end seems to exist even with loop disabled */
vgmstream->num_samples = read_32bitLE(extra_data_offset + 0x04, streamFile);
vgmstream->loop_start_sample = read_32bitLE(extra_data_offset + 0x08, streamFile);
vgmstream->loop_end_sample = read_32bitLE(extra_data_offset + 0x0c, streamFile);
vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile);
vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, streamFile);
vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, streamFile);
break;
}
#ifdef VGM_USE_FFMPEG
case 0x05: { /* Ogg Vorbis [Final Fantasy VI, Dragon Quest II-VI] */
/* Starting from an offset in the current libvorbis code is a bit hard so just use FFmpeg.
* Decoding seems to produce the same output with (inaudible) +-1 lower byte differences due to rounding. */
#ifdef VGM_USE_VORBIS
case 0x05: { /* Ogg Vorbis [Final Fantasy VI (iOS), Dragon Quest II-VI (iOS)] */
VGMSTREAM *ogg_vgmstream = NULL;
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_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;
vgmstream->codec_data = ffmpeg_data;
@ -109,20 +134,30 @@ VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none;
/* 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;
}
#endif
#ifdef VGM_USE_FFMPEG
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_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;
vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg;
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 */
vgmstream->num_samples -= ffmpeg_data->skipSamples;
vgmstream->loop_start_sample -= ffmpeg_data->skipSamples;
@ -149,80 +184,134 @@ fail:
/* AKB2 - found in later SQEX iOS games */
VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile) {
VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset, header_offset;
size_t datasize;
int loop_flag = 0, channel_count, codec;
int akb_header_size, sound_index = 0, sound_offset_data, sound, sound_header_size, material_offset_data, material_index = 0, material, extradata, encryption_flag;
off_t start_offset, material_offset, extradata_offset;
size_t material_size, extradata_size, stream_size;
int loop_flag = 0, channel_count, encryption_flag, codec, sample_rate, num_samples, loop_start, loop_end;
int total_subsongs, target_subsong = streamFile->stream_index;
/* check extensions */
/* .akb.bytes is the usual extension in later games */
if ( !check_extensions(streamFile, "akb") )
if ( !check_extensions(streamFile, "akb,bytes") )
goto fail;
/* check header */
/* checks */
if (read_32bitBE(0x00,streamFile) != 0x414B4232) /* "AKB2" */
goto fail;
if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile))
goto fail;
akb_header_size = read_16bitLE(0x06, streamFile);
sound_offset_data = akb_header_size + sound_index * 0x10;
sound = read_32bitLE(sound_offset_data + 0x04, streamFile);
sound_header_size = read_16bitLE(sound + 0x02, streamFile);
material_offset_data = sound + sound_header_size + material_index * 0x10;
material = sound + read_32bitLE(material_offset_data + 0x04, streamFile);
encryption_flag = read_8bit(material + 0x03, streamFile) & 0x08;
extradata = material + read_16bitLE(material + 0x04, streamFile);
/* parse tables */
{
off_t table_offset;
size_t table_size, entry_size;
off_t akb_header_size = read_16bitLE(0x06, streamFile);
int table_count = read_8bit(0x0c, streamFile);
start_offset = material + read_16bitLE(material + 0x04, streamFile) + read_32bitLE(material + 0x18, streamFile);
header_offset = material;
/* probably each table has its type somewhere, but only seen last table = sound table */
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 */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* 0x04: version? 0x08: filesize, 0x28: file_id?, others: no idea */
codec = read_8bit(header_offset+0x01,streamFile);
datasize = read_32bitLE(header_offset+0x08,streamFile);
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->sample_rate = sample_rate;
vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = stream_size;
vgmstream->meta_type = meta_AKB;
switch (codec) {
case 0x02: { /* MSAPDCM [The Irregular at Magic High School Lost Zero (Android)] */
if (encryption_flag) goto fail;
case 0x02: { /* MSADPCM [The Irregular at Magic High School Lost Zero (Android)] */
if (encryption_flag & 0x08) goto fail;
vgmstream->coding_type = coding_MSADPCM;
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
* (base samples may have more than possible and read over file size otherwise, very strange)
* loop_end seems to exist even with loop disabled */
vgmstream->num_samples = read_32bitLE(extradata + 0x04, streamFile);
vgmstream->loop_start_sample = read_32bitLE(extradata + 0x08, streamFile);
vgmstream->loop_end_sample = read_32bitLE(extradata + 0x0c, streamFile);
vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile);
vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, streamFile);
vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, streamFile);
break;
}
#ifdef VGM_USE_FFMPEG
case 0x05: { /* ogg vorbis [The World Ends with You (iPhone / latest update)] */
#ifdef VGM_USE_VORBIS
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_data = init_ffmpeg_offset(streamFile, start_offset,datasize);
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
if ( !ffmpeg_data ) goto fail;
vgmstream->codec_data = ffmpeg_data;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* 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;
}
#endif

View File

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

View File

@ -9,16 +9,16 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) {
VGMSTREAM *vgmstream = NULL;
STREAMFILE *temp_streamFile = NULL;
int total_subsongs, target_subsong = streamFile->stream_index;
int type, big_endian = 0;
int type, big_endian = 0, entries;
atsl_codec codec;
const char* fake_ext;
off_t subfile_offset;
size_t subfile_size, header_size;
off_t subfile_offset = 0;
size_t subfile_size = 0, header_size;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
/* check extensions
* .atsl: header id (for G1L extractions), .atsl3: PS3 games, .atsl4: PS4 games */
/* checks */
/* .atsl: header id (for G1L extractions), .atsl3: PS3 games, .atsl4: PS4 games */
if ( !check_extensions(streamFile,"atsl,atsl3,atsl4"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x4154534C) /* "ATSL" */
@ -27,17 +27,11 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) {
/* main header (LE) */
header_size = read_32bitLE(0x04,streamFile);
/* 0x08/0c: flags?, 0x10: fixed? (0x03E8) */
total_subsongs = read_32bitLE(0x14,streamFile);
entries = read_32bitLE(0x14,streamFile);
/* 0x18: 0x28, or 0x30 (rarer) */
/* 0x1c: null, 0x20: subheader size, 0x24/28: null */
//todo: sometimes entries are repeated/dummy and point to the first entry
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:
/* 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]
* - 00000201 00020001 .atsl3 from Fist of North Star: Ken's Rage 2 (PS3)[ATRAC3]
* 00000301 00020101 (same)
@ -68,12 +62,47 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) {
read_32bit = big_endian ? read_32bitBE : read_32bitLE;
/* entry header (machine endianness) */
/* 0x00: id */
subfile_offset = read_32bit(header_size + (target_subsong-1)*0x28 + 0x04,streamFile);
subfile_size = read_32bit(header_size + (target_subsong-1)*0x28 + 0x08,streamFile);
/* 0x08+: sample rate/num_samples/loop_start/etc, matching subfile header */
/* some kind of seek/switch table follows (optional, found in .atsl3) */
/* entries can point to the same file, count unique only */
{
int i,j;
total_subsongs = 0;
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);
if (!temp_streamFile) goto fail;

View File

@ -49,7 +49,7 @@ static STREAMFILE* setup_atx_streamfile(STREAMFILE *streamFile) {
num_segments = read_16bitLE(0x1e,streamFile);
/* 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);
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;
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;
fail:
if (!temp_streamFile) {
for (i = 0; i < num_segments; i++)
for (i = 0; i < num_segments; i++) {
close_streamfile(segment_streamFiles[i]);
}
} else {
close_streamfile(temp_streamFile); /* closes all segments */
}

View File

@ -112,22 +112,14 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) {
}
vgmstream->coding_type = coding_type;
if (channel_count == 1)
vgmstream->layout_type = layout_none;
else
{
if (ima)
vgmstream->layout_type = layout_interleave;
else
vgmstream->layout_type = layout_interleave_shortblock;
}
vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
vgmstream->meta_type = meta_CSTM;
if (ima)
if (ima) {
vgmstream->interleave_block_size = 0x200;
else {
} else {
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) {

View File

@ -121,22 +121,14 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) {
}
vgmstream->coding_type = coding_type;
if (channel_count == 1)
vgmstream->layout_type = layout_none;
else
{
if (ima)
vgmstream->layout_type = layout_interleave;
else
vgmstream->layout_type = layout_interleave_shortblock;
}
vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
vgmstream->meta_type = meta_FSTM;
if (ima)
vgmstream->interleave_block_size = 0x200;
else {
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) {

View File

@ -123,15 +123,10 @@ VGMSTREAM * init_vgmstream_bfwav(STREAMFILE *streamFile) {
{
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 if (vgmstream->layout_type == layout_interleave)
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
STREAMFILE_DEFAULT_BUFFER_SIZE);
if (vgmstream->layout_type == layout_interleave)
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
else
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
0x1000);
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,0x1000);
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->coding_type = coding_type;
if (channel_count==1)
vgmstream->layout_type = layout_none;
else
vgmstream->layout_type = layout_interleave_shortblock;
vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
vgmstream->meta_type = meta_RSTM;
if (atlus_shrunken_head)
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_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) {
off_t coef_offset;
@ -139,12 +136,7 @@ VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile) {
{
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);
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[i].streamfile) goto fail;

View File

@ -5,9 +5,12 @@
VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
size_t data_size;
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") )
goto fail;
@ -18,28 +21,24 @@ VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
loop_flag = (read_32bitLE(0x0C,streamFile) != 0);
channel_count = read_32bitLE(0x04,streamFile); /* always 2? */
start_offset = 0x800;
data_size = get_streamfile_size(streamFile) - start_offset;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->channels = channel_count;
vgmstream->channels = channel_count;
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_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;
/* Calculating the short block... */
if (channel_count > 1) {
vgmstream->interleave_block_size = 0x400;
vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%(vgmstream->channels*vgmstream->interleave_block_size))/vgmstream->channels;
vgmstream->layout_type = layout_interleave_shortblock;
} else {
vgmstream->layout_type = layout_none;
}
vgmstream->coding_type = coding_DVI_IMA_int;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x400;
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 */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )

View File

@ -1,16 +1,16 @@
#include "meta.h"
#include "../util.h"
/* "idsp/IDSP"
Soul Calibur Legends (Wii)
Sky Crawlers: Innocent Aces (Wii)
/* "idsp/IDSP"
Soul Calibur Legends (Wii)
Sky Crawlers: Innocent Aces (Wii)
*/
VGMSTREAM * init_vgmstream_idsp2(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag;
int channel_count;
int i, j;
int channel_count;
int i, j;
off_t start_offset;
/* check extension, case insensitive */
@ -20,60 +20,53 @@ VGMSTREAM * init_vgmstream_idsp2(STREAMFILE *streamFile) {
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x69647370 || /* "idsp" */
read_32bitBE(0xBC,streamFile) != 0x49445350) /* IDSP */
goto fail;
goto fail;
loop_flag = read_32bitBE(0x20,streamFile);
channel_count = read_32bitBE(0xC4,streamFile);
if (channel_count > 8)
{
goto fail;
}
goto fail;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = (channel_count * 0x60) + 0x100;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0xC8,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = (read_32bitBE(0x14,streamFile))*14/8/channel_count;
start_offset = (channel_count * 0x60) + 0x100;
vgmstream->sample_rate = read_32bitBE(0xC8,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = (read_32bitBE(0x14,streamFile))*14/8/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = (read_32bitBE(0xD0,streamFile));
vgmstream->loop_end_sample = (read_32bitBE(0xD4,streamFile));
}
if (channel_count == 1)
{
vgmstream->layout_type = layout_none;
if (channel_count == 1) {
vgmstream->layout_type = layout_none;
}
else if (channel_count > 1)
{
if (read_32bitBE(0xD8,streamFile) == 0)
{
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = (get_streamfile_size(streamFile)-start_offset)/2;
else if (channel_count > 1) {
if (read_32bitBE(0xD8,streamFile) == 0) {
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = (get_streamfile_size(streamFile)-start_offset)/2;
}
else if (read_32bitBE(0xD8,streamFile) > 0)
{
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0xD8,streamFile);
else if (read_32bitBE(0xD8,streamFile) > 0) {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0xD8,streamFile);
}
}
vgmstream->meta_type = meta_IDSP;
vgmstream->meta_type = meta_IDSP;
{
if (vgmstream->coding_type == coding_NGC_DSP) {
off_t coef_table[8] = {0x118,0x178,0x1D8,0x238,0x298,0x2F8,0x358,0x3B8};
for (j=0;j<vgmstream->channels;j++) {
for (i=0;i<16;i++) {
vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile);
}
{
if (vgmstream->coding_type == coding_NGC_DSP) {
off_t coef_table[8] = {0x118,0x178,0x1D8,0x238,0x298,0x2F8,0x358,0x3B8};
for (j=0;j<vgmstream->channels;j++) {
for (i=0;i<16;i++) {
vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile);
}
}
}
}
}
/* open the file for reading */
@ -121,17 +114,13 @@ VGMSTREAM * init_vgmstream_idsp3(STREAMFILE *streamFile) {
channel_count = read_32bitBE(0x24,streamFile);
if (channel_count > 8)
{
goto fail;
}
goto fail;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = (channel_count*0x60)+0xC;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x14,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x0C,streamFile);
@ -141,9 +130,9 @@ VGMSTREAM * init_vgmstream_idsp3(STREAMFILE *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->layout_type = layout_interleave_shortblock;
vgmstream->interleave_last_block_size = ((vgmstream->num_samples/7*8)%(vgmstream->interleave_block_size)/vgmstream->channels);
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_IDSP;
if (vgmstream->coding_type == coding_NGC_DSP) {
@ -170,7 +159,6 @@ VGMSTREAM * init_vgmstream_idsp3(STREAMFILE *streamFile) {
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
@ -187,7 +175,7 @@ VGMSTREAM * init_vgmstream_idsp4(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag = 0;
int channel_count;
int channel_count;
off_t start_offset;
/* check extension, case insensitive */
@ -201,17 +189,13 @@ VGMSTREAM * init_vgmstream_idsp4(STREAMFILE *streamFile) {
channel_count = read_32bitBE(0x0C,streamFile);
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);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x70;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x08,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x04,streamFile)/channel_count/8*14;
@ -220,27 +204,25 @@ VGMSTREAM * init_vgmstream_idsp4(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = read_32bitBE(0x04,streamFile)/channel_count/8*14;
}
if (channel_count == 1)
{
vgmstream->layout_type = layout_none;
if (channel_count == 1) {
vgmstream->layout_type = layout_none;
}
else
{
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x10,streamFile);
else {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x10,streamFile);
}
vgmstream->meta_type = meta_IDSP;
{
int i;
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x14+i*2,streamFile);
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x42+i*2,streamFile);
}
}
{
int i;
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x14+i*2,streamFile);
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x42+i*2,streamFile);
}
}
/* open the file for reading */
{

View File

@ -95,7 +95,6 @@ typedef struct {
int loop_end_found;
int32_t loop_end;
meta_t meta_type;
layout_t layout_type;
off_t stream_size;
int total_subsongs;
@ -106,9 +105,9 @@ typedef struct {
off_t scd_xor_length;
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);
#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_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size);
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_akb_mp4(STREAMFILE *streamFile);
#endif
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_rsd6xma(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_rsd6wma(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_ngc_bo2(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_rkv(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_akb_multi(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_akb2(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_ps3(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);
@ -711,4 +712,9 @@ VGMSTREAM * init_vgmstream_waf(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_wave(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_smv(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_nxap(STREAMFILE * streamFile);
#endif /*_META_H*/

View File

@ -1,9 +1,9 @@
/*
2017-12-10: Preliminary MOGG Support. As long as the stream is unencrypted, this should be fine.
This will also work on unconventional 5 channel Vorbis streams but some sound cards might not like it.
TODO (Eventually): Add decryption for encrypted MOGG types (Rock Band, etc.)
This will also work on unconventional 5 channel Vorbis streams but some sound cards might not like it.
TODO (Eventually): Add decryption for encrypted MOGG types (Rock Band, etc.)
-bxaimc
-bxaimc
*/
#include "meta.h"
@ -12,31 +12,28 @@
/* MOGG - Harmonix Music Systems (Guitar Hero)[Unencrypted Type] */
VGMSTREAM * init_vgmstream_mogg(STREAMFILE *streamFile) {
#ifdef VGM_USE_VORBIS
char filename[PATH_LIMIT];
off_t start_offset;
off_t start_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile, filename, sizeof(filename));
if (strcasecmp("mogg", filename_extension(filename))) goto fail;
/* checks */
if (!check_extensions(streamFile, "mogg"))
goto fail;
{
vgm_vorbis_info_t inf;
VGMSTREAM * result = NULL;
{
ogg_vorbis_meta_info_t ovmi = {0};
VGMSTREAM * result = NULL;
memset(&inf, 0, sizeof(inf));
inf.layout_type = layout_ogg_vorbis;
inf.meta_type = meta_MOGG;
ovmi.meta_type = meta_MOGG;
start_offset = read_32bitLE(0x04, streamFile);
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf);
start_offset = read_32bitLE(0x04, streamFile);
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
if (result != NULL) {
return result;
}
}
if (result != NULL) {
return result;
}
}
fail:
/* clean up anything we may have opened */
/* clean up anything we may have opened */
#endif
return NULL;
}
return NULL;
}

View File

@ -1,88 +1,55 @@
#include "meta.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 * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int coding;
int loop_flag;
int channel_count;
size_t data_size;
int loop_flag, 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" */
goto fail;
loop_flag = 0;
channel_count = 2;
start_offset = 0x40;
data_size = get_streamfile_size(streamFile) - start_offset;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
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);
switch (read_8bit(0x8,streamFile))
{
case 0x01:
coding = coding_PCM8;
break;
case 0x03:
coding = coding_AICA;
break;
default:
goto fail;
}
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;
if (channel_count > 1) {
vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%(vgmstream->channels*vgmstream->interleave_block_size))/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 */
}
switch (read_8bit(0x08,streamFile)) {
case 0x01: /* [Virtua Tennis 2 (Naomi)] */
vgmstream->coding_type = coding_PCM8;
break;
case 0x03:
vgmstream->coding_type = coding_AICA;
break;
default:
goto fail;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x2000;
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;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -4,103 +4,66 @@
/* STRM - common Nintendo NDS streaming format */
VGMSTREAM * init_vgmstream_nds_strm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
coding_t coding_type;
int codec_number;
int channel_count;
int loop_flag;
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 */
if ((uint32_t)read_32bitBE(0x00,streamFile)!=0x5354524D) /* 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 */
/* checks */
if (!check_extensions(streamFile, "strm"))
goto fail;
/* check for HEAD section */
if ((uint32_t)read_32bitBE(0x10,streamFile)!=0x48454144 && /* "HEAD" */
(uint32_t)read_32bitLE(0x14,streamFile)!=0x50) /* 0x50-sized head is all I've seen */
if (read_32bitBE(0x00,streamFile) != 0x5354524D) /* "STRM" */
goto fail;
if (read_32bitBE(0x04,streamFile) != 0xFFFE0001 && /* Old Header Check */
(read_32bitBE(0x04,streamFile) != 0xFEFF0001)) /* Some newer games have a new flag */
goto fail;
/* check type details */
codec_number = read_8bit(0x18,streamFile);
if (read_32bitBE(0x10,streamFile) != 0x48454144 && /* "HEAD" */
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);
channel_count = read_8bit(0x1a,streamFile);
if (channel_count > 2) goto fail;
switch (codec_number) {
case 0:
coding_type = coding_PCM8;
start_offset = read_32bitLE(0x28,streamFile);
/* 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;
case 1:
coding_type = coding_PCM16LE;
case 0x01:
vgmstream->coding_type = coding_PCM16LE;
break;
case 2:
coding_type = coding_NDS_IMA;
case 0x02: /* [SaGa 2 (DS)] */
vgmstream->coding_type = coding_NDS_IMA;
break;
default:
goto fail;
}
/* 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->layout_type = layout_interleave;
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;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
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;
int16_t loop_hist1;
int16_t loop_hist2;
/* later/mdsp extension */
int16_t channel_count;
int16_t block_size;
};
@ -158,8 +159,10 @@ VGMSTREAM * init_vgmstream_ngc_dsp_std(STREAMFILE *streamFile) {
int i;
/* check extension, case insensitive */
/* .dsp: standard, .adp: Dr. Muto (GC) mono files */
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;
@ -301,11 +304,11 @@ VGMSTREAM * init_vgmstream_ngc_mdsp_std(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = vgmstream->num_samples;
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->interleave_block_size = header.block_size * 8;
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++) {
if (read_dsp_header(&header, header_size * i, streamFile)) goto fail;
@ -581,67 +584,6 @@ fail:
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,
* but have different interleaves */
VGMSTREAM * init_vgmstream_ngc_dsp_std_int(STREAMFILE *streamFile) {
@ -882,7 +824,6 @@ fail:
#define SADB_MAX_CHANNELS 2
/* sadb - Procyon Studio header + interleaved dsp [Shiren the Wanderer 3 (Wii), Disaster: Day of Crisis (Wii)] */
VGMSTREAM * init_vgmstream_sadb(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset, header_offset;
size_t header_spacing, interleave;
@ -936,180 +877,103 @@ fail:
return NULL;
}
/* .wsi as found in Alone in the Dark for Wii */
/* These appear to be standard .dsp, but interleaved in a blocked format */
#define WSI_MAX_CHANNELS 2
/* .wsi - blocked dsp [Alone in the Dark (Wii)] */
VGMSTREAM * init_vgmstream_wsi(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
struct dsp_header header[2];
off_t start_offset[2];
off_t start_offset, header_offset;
size_t header_spacing;
struct dsp_header ch_header[WSI_MAX_CHANNELS];
int channel_count;
size_t est_block_size = 0;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("wsi",filename_extension(filename))) goto fail;
/* checks */
if (!check_extensions(streamFile, "wsi"))
goto fail;
/* 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);
/* I've only allocated two headers, and I want to be alerted if a mono
.wsi shows up */
if (channel_count != 2) goto fail;
/* check for consistent block headers */
{
off_t check_offset;
off_t block_offset;
off_t block_size_has_been;
int i;
check_offset = read_32bitBE(0x0,streamFile);
if (check_offset < 8) goto fail;
block_offset = read_32bitBE(0x00,streamFile);
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 */
for (i=0;i<4*channel_count;i++) {
off_t block_size;
block_size = read_32bitBE(check_offset,streamFile);
for (i = 0; i < 4*channel_count; i++) {
off_t block_size = read_32bitBE(block_offset,streamFile);
/* expect at least the block header */
if (block_size < 0x10) goto fail;
if (block_size < 0x10)
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+1 != read_32bitBE(check_offset+8,streamFile)) goto fail;
if (i%channel_count==0)
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 */
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;
block_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);
{
off_t check_offset;
int i;
check_offset = read_32bitBE(0x0,streamFile);
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;
/* read dsp */
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;
//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;
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;
/* fill in the vital statistics */
/* incomplete last frame is missing */
vgmstream->num_samples = header[0].sample_count/14*14;
vgmstream->sample_rate = header[0].sample_rate;
vgmstream->sample_rate = ch_header[0].sample_rate;
vgmstream->loop_start_sample = dsp_nibbles_to_samples(
header[0].loop_start_offset);
vgmstream->loop_end_sample = dsp_nibbles_to_samples(
header[0].loop_end_offset)+1;
/* don't know why, but it does happen*/
if (vgmstream->loop_end_sample > vgmstream->num_samples)
vgmstream->num_samples = ch_header[0].sample_count / 14 * 14; /* remove incomplete last frame */
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;
if (vgmstream->loop_end_sample > vgmstream->num_samples) /* don't know why, but it does happen*/
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->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_blocked_wsi;
/* coeffs */
{
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;
}
}
setup_vgmstream_dsp(vgmstream, ch_header);
/* open the file for reading */
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,est_block_size*4);
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
if (!vgmstream->ch[0].streamfile) goto fail;
wsi_block_update(read_32bitBE(0,streamFile),vgmstream);
block_update_wsi(start_offset,vgmstream);
/* first block has DSP header */
{
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];
vgmstream->current_block_size -= 0x60;
for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset += 0x60;
}
}
/* first block isn't full of musics */
vgmstream->current_block_size -= 0x60;
return vgmstream;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}
@ -1970,119 +1834,60 @@ fail:
return NULL;
}
/* dual dsp header with additional "iadp" header, found in Dr. Muto (NGC) */
#define IADP_MAX_CHANNELS 2
/* iadp - custom header + interleaved dsp [Dr. Muto (GC)] */
VGMSTREAM * init_vgmstream_ngc_dsp_iadp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
struct dsp_header ch0_header,ch1_header;
off_t ch1_header_start, ch2_header_start, ch1_start, ch2_start;
off_t start_offset, header_offset;
size_t header_spacing, interleave;
int channel_count;
int i;
struct dsp_header ch_header[IADP_MAX_CHANNELS];
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("iadp",filename_extension(filename)))
/* checks */
/* .adp: actual extension, .iadp: header id */
if (!check_extensions(streamFile, "adp,iadp"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x69616470) /* "iadp" */
goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x69616470) /* iadp */
goto fail;
channel_count = read_32bitBE(0x4,streamFile);
if (channel_count != 0x2)
goto fail;
channel_count = read_32bitBE(0x04,streamFile);
if (channel_count != IADP_MAX_CHANNELS) goto fail;
ch1_header_start = 0x20;
ch2_header_start = 0x80;
ch1_start = read_32bitBE(0x1C,streamFile);
ch2_start = ch1_start + read_32bitBE(0x8,streamFile);
header_offset = 0x20;
header_spacing = 0x60;
start_offset = read_32bitBE(0x1C,streamFile);
interleave = read_32bitBE(0x08,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;
}
/* read dsp */
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;
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;
/* 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;
/* fill in the vital statistics */
vgmstream->num_samples = ch0_header.sample_count;
vgmstream->sample_rate = ch0_header.sample_rate;
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->sample_rate = ch_header[0].sample_rate;
vgmstream->num_samples = ch_header[0].sample_count;
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->meta_type = meta_NGC_DSP_IADP;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->interleave_block_size = read_32bitBE(0x8,streamFile);
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 */
/* 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)
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
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;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
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!) */
{
char* path;
char basename[PATH_LIMIT];
char filename[PATH_LIMIT];
char filename[PATH_LIMIT] = {0};
/* get base name */
streamFile->get_name(streamFile,filename,sizeof(filename));
path = strrchr(filename,DIR_SEPARATOR);
if (path!=NULL)
path = path+1;
else
path = filename;
strcpy(basename,path);
get_streamfile_filename(streamFile, filename,PATH_LIMIT);
/* first letter gives the channels */
if (basename[0]=='M') /* Mono */
if (filename[0]=='M') /* Mono */
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;
else
goto fail;
/* 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;
}
}

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 */
VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
vgm_vorbis_info_t inf = {0};
ogg_vorbis_meta_info_t ovmi = {0};
off_t start_offset = 0;
int is_ogg = 0;
@ -210,7 +209,6 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
} else {
goto fail;
}
streamFile->get_name(streamFile,filename,sizeof(filename));
/* check standard Ogg Vorbis */
if (is_ogg) {
@ -218,11 +216,11 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
/* check Psychic Software obfuscation (Darkwind: War on Wheels PC) */
if (read_32bitBE(0x00,streamFile) == 0x2c444430) {
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)] */
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" */
goto fail; /* not known (ex. Wwise) */
@ -232,7 +230,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
/* check "Ultramarine3" (???), may be encrypted */
if (is_um3) {
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" */
goto fail;
}
inf.loop_start = read_32bitLE(0x08,streamFile);
inf.loop_flag = (inf.loop_start != 0);
inf.decryption_callback = kovs_ogg_decryption_callback;
ovmi.loop_start = read_32bitLE(0x08,streamFile);
ovmi.loop_flag = (ovmi.loop_start != 0);
ovmi.decryption_callback = kovs_ogg_decryption_callback;
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 */
if (is_sngw) {
if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */
inf.sngw_xor = read_32bitBE(0x00,streamFile);
inf.decryption_callback = sngw_ogg_decryption_callback;
ovmi.sngw_xor = read_32bitBE(0x00,streamFile);
ovmi.decryption_callback = sngw_ogg_decryption_callback;
}
}
/* check ISD (Gunvolt PC) */
if (is_isd) {
inf.decryption_callback = isd_ogg_decryption_callback;
ovmi.decryption_callback = isd_ogg_decryption_callback;
//todo looping unknown, not in Ogg comments
// 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) {
inf.meta_type = meta_OGG_UM3;
ovmi.meta_type = meta_OGG_UM3;
} else if (is_kovs) {
inf.meta_type = meta_OGG_KOVS;
ovmi.meta_type = meta_OGG_KOVS;
} else if (is_psychic) {
inf.meta_type = meta_OGG_PSYCHIC;
ovmi.meta_type = meta_OGG_PSYCHIC;
} else if (is_sngw) {
inf.meta_type = meta_OGG_SNGW;
ovmi.meta_type = meta_OGG_SNGW;
} else if (is_isd) {
inf.meta_type = meta_OGG_ISD;
ovmi.meta_type = meta_OGG_ISD;
} else if (is_l2sd) {
inf.meta_type = meta_OGG_L2SD;
ovmi.meta_type = meta_OGG_L2SD;
} 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:
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;
ogg_vorbis_codec_data * data = NULL;
OggVorbis_File *ovf = NULL;
vorbis_info *vi;
int loop_flag = vgm_inf->loop_flag;
int32_t loop_start = vgm_inf->loop_start;
int loop_length_found = vgm_inf->loop_length_found;
int32_t loop_length = vgm_inf->loop_length;
int loop_end_found = vgm_inf->loop_end_found;
int32_t loop_end = vgm_inf->loop_end;
size_t stream_size = vgm_inf->stream_size ?
vgm_inf->stream_size :
int loop_flag = ovmi->loop_flag;
int32_t loop_start = ovmi->loop_start;
int loop_length_found = ovmi->loop_length_found;
int32_t loop_length = ovmi->loop_length;
int loop_end_found = ovmi->loop_end_found;
int32_t loop_end = ovmi->loop_end;
size_t stream_size = ovmi->stream_size ?
ovmi->stream_size :
get_streamfile_size(streamFile) - start;
ov_callbacks default_callbacks;
@ -331,10 +328,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
temp_streamfile.offset = 0;
temp_streamfile.size = stream_size;
temp_streamfile.decryption_callback = vgm_inf->decryption_callback;
temp_streamfile.scd_xor = vgm_inf->scd_xor;
temp_streamfile.scd_xor_length = vgm_inf->scd_xor_length;
temp_streamfile.sngw_xor = vgm_inf->sngw_xor;
temp_streamfile.decryption_callback = ovmi->decryption_callback;
temp_streamfile.scd_xor = ovmi->scd_xor;
temp_streamfile.scd_xor_length = ovmi->scd_xor_length;
temp_streamfile.sngw_xor = ovmi->sngw_xor;
/* open the ogg vorbis file for testing */
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 */
{
char filename[PATH_LIMIT];
data = calloc(1,sizeof(ogg_vorbis_codec_data));
if (!data) goto fail;
streamFile->get_name(streamFile,filename,sizeof(filename));
data->ov_streamfile.streamfile = streamFile->open(streamFile,filename, STREAMFILE_DEFAULT_BUFFER_SIZE);
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.size = stream_size;
data->ov_streamfile.decryption_callback = vgm_inf->decryption_callback;
data->ov_streamfile.scd_xor = vgm_inf->scd_xor;
data->ov_streamfile.scd_xor_length = vgm_inf->scd_xor_length;
data->ov_streamfile.sngw_xor = vgm_inf->sngw_xor;
data->ov_streamfile.decryption_callback = ovmi->decryption_callback;
data->ov_streamfile.scd_xor = ovmi->scd_xor;
data->ov_streamfile.scd_xor_length = ovmi->scd_xor_length;
data->ov_streamfile.sngw_xor = ovmi->sngw_xor;
/* open the ogg vorbis file for real */
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->channels = vi->channels;
vgmstream->sample_rate = vi->rate;
vgmstream->num_streams = vgm_inf->total_subsongs;
vgmstream->num_streams = ovmi->total_subsongs;
vgmstream->stream_size = stream_size;
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->layout_type = vgm_inf->layout_type;
vgmstream->meta_type = vgm_inf->meta_type;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = ovmi->meta_type;
return vgmstream;

View File

@ -1,79 +1,53 @@
#include "meta.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 * vgmstream = NULL;
off_t start_offset;
size_t data_size;
int loop_flag, channel_count;
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
/* checks */
if (!check_extensions(streamFile, "snd"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53534E44) /* "SSND" */
goto fail;
int loop_flag;
int channel_count;
start_offset = read_32bitLE(0x04,streamFile)+0x08;
data_size = get_streamfile_size(streamFile) - start_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("snd",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) !=0x53534e44) goto fail;
/* Force Loop 0->end */
loop_flag = 1;
loop_flag = 1; /* force full Loop */
channel_count = read_16bitLE(0x0a,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
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->sample_rate = (uint16_t)read_16bitLE(0x0e,streamFile);
vgmstream->num_samples = read_32bitLE(0x16,streamFile);
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
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_end_sample=vgmstream->num_samples;
}
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;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,85 +1,53 @@
#include "meta.h"
#include "../util.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
*/
#include "../coding/coding.h"
/* SVAG - from Konami Tokyo games [OZ (PS2), Neo Contra (PS2)]] */
VGMSTREAM * init_vgmstream_ps2_svag(STREAMFILE *streamFile) {
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 */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("svag",filename_extension(filename))) goto fail;
/* check SVAG Header */
if (read_32bitBE(0x00,streamFile) != 0x53766167)
/* checks */
if (!check_extensions(streamFile, "svag"))
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);
channel_count=read_16bitLE(0x0C,streamFile);
start_offset = 0x800; /* header repeated at 0x400 too */
data_size = read_32bitLE(0x04,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = read_16bitLE(0x0C,streamFile);
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
/* Compression Scheme */
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitLE(0x04,streamFile)/16*28/vgmstream->channels;
/* Get loop point values */
vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x04,streamFile), vgmstream->channels);
if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile)/16*28;
vgmstream->loop_end_sample = read_32bitLE(0x04,streamFile)/16*28/vgmstream->channels;
vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitLE(0x18,streamFile)*vgmstream->channels, 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->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;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -17,8 +17,9 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) {
int channel_count = 0;
int is_swag = 0;
/* check extension (.swag: Frantix PSP, .str: Ben10 Galactic Racing, .vig: MX vs. ATV Untamed PS2) */
if ( !check_extensions(streamFile,"vag,swag,str,vig") )
/* checks */
/* .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;
/* check VAG Header */

View File

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

View File

@ -1,77 +1,115 @@
#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 * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset=0;
int loop_flag;
int channel_count;
off_t start_offset, header_offset;
size_t data_size;
int loop_flag, 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
// Some other @ offset 4
if(read_32bitLE(0,streamFile)==0)
start_offset=4;
/* checks */
if (!check_extensions(streamFile, "rkv"))
goto fail;
if (read_32bitBE(0x24,streamFile) != 0x00) /* quick test vs GC rkv (coef position) */
goto fail;
loop_flag = (read_32bitLE(start_offset+4,streamFile)!=0xFFFFFFFF);
channel_count = read_32bitLE(start_offset+0x0c,streamFile)+1;
/* build the VGMSTREAM */
/* 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;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(start_offset,streamFile);
vgmstream->sample_rate = read_32bitLE(header_offset,streamFile);
vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count);
//vgmstream->num_samples = read_32bitLE(header_offset+0x08,streamFile); /* sometimes not set */
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(header_offset+0x04,streamFile);
vgmstream->loop_end_sample = read_32bitLE(header_offset+0x08,streamFile);
}
vgmstream->meta_type = meta_PS2_RKV;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x400;
if (vgmstream->interleave_block_size)
vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
// sometimes sample count is not set on the header
vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)/16*28/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(start_offset+4,streamFile);
vgmstream->loop_end_sample = read_32bitLE(start_offset+8,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;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}
/* 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 "../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 * vgmstream = NULL;
char filename[PATH_LIMIT];
int channel_count;
int loop_flag;
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 */
if ((uint32_t)read_32bitBE(0,streamFile)!=0x52530003) /* "RS03" */
/* checks */
if (!check_extensions(streamFile, "dsp"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x52530003) /* "RS03" */
goto fail;
channel_count = read_32bitBE(4,streamFile);
channel_count = read_32bitBE(0x04,streamFile);
if (channel_count != 1 && channel_count != 2) goto fail;
/* build the VGMSTREAM */
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);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitBE(8,streamFile);
vgmstream->sample_rate = read_32bitBE(0xc,streamFile);
vgmstream->num_samples = read_32bitBE(8,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitBE(0x18,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->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++)
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);
}
dsp_read_coefs_be(vgmstream,streamFile,0x20,0x20);
/* 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;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -903,12 +903,11 @@ fail:
/* RSD6OGG */
VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE *streamFile) {
#ifdef VGM_USE_VORBIS
char filename[PATH_LIMIT];
off_t start_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("rsd",filename_extension(filename))) goto fail;
/* check extension */
if (!check_extensions(streamFile, "rsd"))
goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */
@ -917,15 +916,13 @@ VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE *streamFile) {
goto fail;
{
vgm_vorbis_info_t inf;
ogg_vorbis_meta_info_t ovmi = {0};
VGMSTREAM * result = NULL;
memset(&inf, 0, sizeof(inf));
inf.layout_type = layout_ogg_vorbis;
inf.meta_type = meta_RSD6OOGV;
ovmi.meta_type = meta_RSD6OOGV;
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) {
return result;
@ -938,7 +935,7 @@ fail:
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 * vgmstream = NULL;
off_t start_offset;
@ -966,9 +963,10 @@ VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE *streamFile) {
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
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->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))
goto fail;
@ -1082,7 +1080,6 @@ fail:
return NULL;
}
/* RSD6AT3+ [Crash of the Titans (PSP)] */
VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
@ -1096,13 +1093,13 @@ VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE *streamFile) {
goto fail;
/* check header */
if (read_32bitBE(0x0, streamFile) != 0x52534436) /* "RSD6" */
if (read_32bitBE(0x00,streamFile) != 0x52534436) /* "RSD6" */
goto fail;
if (read_32bitBE(0x04,streamFile) != 0x4154332B) /* "AT3+" */
goto fail;
loop_flag = 0;
channel_count = read_32bitLE(0x8, streamFile);
channel_count = read_32bitLE(0x08, streamFile);
start_offset = 0x800;
data_size = get_streamfile_size(streamFile) - start_offset;
@ -1117,7 +1114,7 @@ VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE *streamFile) {
{
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);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
@ -1154,3 +1151,60 @@ fail:
close_vgmstream(vgmstream);
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 * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset, tables_offset, meta_offset, post_meta_offset, name_offset = 0;
int32_t stream_size, subheader_size, loop_start, loop_end;
off_t start_offset, tables_offset, meta_offset, extradata_offset, name_offset = 0;
int32_t stream_size, extradata_size, loop_start, loop_end;
int loop_flag = 0, channel_count, codec, sample_rate;
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_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);
/* 0x01e(2): unknown, seen in some FF XIV sfx (MSADPCM) */
loop_flag = (loop_end > 0);
post_meta_offset = meta_offset + 0x20;
start_offset = post_meta_offset + subheader_size;
extradata_offset = meta_offset + 0x20;
start_offset = extradata_offset + extradata_size;
/* 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 */
@ -128,8 +128,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
}
/* skips aux chunks, sometimes needed (Lightning Returns X360, FF XIV PC) */
if (aux_chunk_count && read_32bitBE(post_meta_offset, streamFile) == 0x4D41524B) { /* "MARK" */
post_meta_offset += read_32bit(post_meta_offset+0x04, streamFile);
if (aux_chunk_count && read_32bitBE(extradata_offset, streamFile) == 0x4D41524B) { /* "MARK" */
extradata_offset += read_32bit(extradata_offset+0x04, streamFile);
}
/* find name if possible */
@ -151,41 +151,40 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
if (codec == 0x06) {
VGMSTREAM *ogg_vgmstream;
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;
inf.meta_type = meta_SQEX_SCD;
inf.total_subsongs = total_subsongs;
ovmi.meta_type = meta_SQEX_SCD;
ovmi.total_subsongs = total_subsongs;
/* 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? */
ogg_byte = read_8bit(post_meta_offset + 0x02, streamFile);
ogg_byte = read_8bit(extradata_offset + 0x02, streamFile);
/* 0x03(1): ? in v3 */
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 */
size_t seek_table_size = read_32bit(post_meta_offset+0x10, streamFile);
size_t vorb_header_size = read_32bit(post_meta_offset+0x14, streamFile);
size_t seek_table_size = read_32bit(extradata_offset+0x10, streamFile);
size_t vorb_header_size = read_32bit(extradata_offset+0x14, streamFile);
/* 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;
inf.stream_size = vorb_header_size + stream_size;
start_offset = post_meta_offset + 0x20 + seek_table_size; /* subheader_size skips vorb_header */
ovmi.stream_size = vorb_header_size + stream_size;
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) */
inf.decryption_callback = scd_ogg_v2_decryption_callback;
inf.scd_xor = ogg_byte;
inf.scd_xor_length = vorb_header_size;
ovmi.decryption_callback = scd_ogg_v2_decryption_callback;
ovmi.scd_xor = ogg_byte;
ovmi.scd_xor_length = vorb_header_size;
}
else if (ogg_version == 3) { /* file is XOR'ed using table (FF XIV Heavensward PC) */
inf.decryption_callback = scd_ogg_v3_decryption_callback;
inf.scd_xor = stream_size & 0xFF; /* ogg_byte not used? */
inf.scd_xor_length = vorb_header_size + stream_size;
ovmi.decryption_callback = scd_ogg_v3_decryption_callback;
ovmi.scd_xor = stream_size & 0xFF; /* ogg_byte not used? */
ovmi.scd_xor_length = vorb_header_size + stream_size;
}
else {
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 */
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)
read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile);
return ogg_vgmstream;
@ -270,8 +269,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
case 0x0C: /* MS ADPCM [Final Fantasy XIV (PC) sfx] */
vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = read_16bit(post_meta_offset+0x0c,streamFile);
/* in post_meta_offset is a WAVEFORMATEX (including coefs and all) */
vgmstream->interleave_block_size = read_16bit(extradata_offset+0x0c,streamFile);
/* 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);
if (loop_flag) {
@ -346,8 +345,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
uint8_t buf[200];
int32_t bytes;
/* post_meta_offset+0x00: fmt0x166 header (BE), post_meta_offset+0x34: seek table */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, post_meta_offset,0x34, stream_size, streamFile, 1);
/* extradata_offset+0x00: fmt0x166 header (BE), extradata_offset+0x34: seek table */
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, extradata_offset,0x34, stream_size, streamFile, 1);
if (bytes <= 0) goto fail;
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] */
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);
if (!ffmpeg_data) goto fail;
vgmstream->codec_data = ffmpeg_data;
@ -401,17 +400,17 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
/* post header has various typical ATRAC9 values */
cfg.channels = vgmstream->channels;
cfg.config_data = read_32bit(post_meta_offset+0x0c,streamFile);
cfg.encoder_delay = read_32bit(post_meta_offset+0x18,streamFile);
cfg.config_data = read_32bit(extradata_offset+0x0c,streamFile);
cfg.encoder_delay = read_32bit(extradata_offset+0x18,streamFile);
vgmstream->codec_data = init_atrac9(&cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_ATRAC9;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = read_32bit(post_meta_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_end_sample = read_32bit(post_meta_offset+0x24, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_end
vgmstream->num_samples = read_32bit(extradata_offset+0x10,streamFile); /* loop values above are also weird and ignored */
vgmstream->loop_start_sample = read_32bit(extradata_offset+0x20, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_start
vgmstream->loop_end_sample = read_32bit(extradata_offset+0x24, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_end
break;
}
#endif

View File

@ -187,19 +187,15 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) {
#ifdef VGM_USE_VORBIS
case 0x03: { /* OGG [Final Fantasy XV Benchmark sfx (PC)] */
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;
char filename[PATH_LIMIT];
streamFile->get_name(streamFile,filename,sizeof(filename));
inf.layout_type = layout_ogg_vorbis;
inf.meta_type = vgmstream->meta_type;
inf.total_subsongs = total_subsongs;
inf.stream_size = stream_size;
ovmi.meta_type = vgmstream->meta_type;
ovmi.total_subsongs = total_subsongs;
ovmi.stream_size = stream_size;
/* 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) {
ogg_vgmstream->num_streams = vgmstream->num_streams;
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)) */
VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile) {
VGMSTREAM * init_vgmstream_ta_aac_mobile_vorbis(STREAMFILE *streamFile) {
#ifdef VGM_USE_VORBIS
off_t start_offset;
char filename[PATH_LIMIT];
int8_t codec_id;
streamFile->get_name(streamFile, filename, sizeof(filename));
/* check extension, case insensitive */
/* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */
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);
if (codec_id == 0xe) /* Vorbis */
{
vgm_vorbis_info_t inf;
ogg_vorbis_meta_info_t ovmi = {0};
VGMSTREAM * result = NULL;
memset(&inf, 0, sizeof(inf));
inf.layout_type = layout_ogg_vorbis;
inf.meta_type = meta_TA_AAC_VORBIS;
inf.loop_start = read_32bitLE(0x140, streamFile);
inf.loop_end = read_32bitLE(0x144, streamFile);
inf.loop_flag = inf.loop_end > inf.loop_start;
inf.loop_end_found = inf.loop_flag;
ovmi.meta_type = meta_TA_AAC_MOBILE;
ovmi.loop_start = read_32bitLE(0x140, streamFile);
ovmi.loop_end = read_32bitLE(0x144, streamFile);
ovmi.loop_flag = ovmi.loop_end > ovmi.loop_start;
ovmi.loop_end_found = ovmi.loop_flag;
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) {
return result;
@ -255,3 +251,65 @@ fail:
#endif
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

@ -5,12 +5,12 @@
VGMSTREAM * init_vgmstream_waf(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
int loop_flag, channel_count;
/* check extension */
if (!check_extensions(streamFile, "waf"))
goto fail;
/* checks */
if (!check_extensions(streamFile, "waf"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x57414600) /* "WAF\0" "*/
goto fail;
@ -21,7 +21,7 @@ VGMSTREAM * init_vgmstream_waf(STREAMFILE *streamFile) {
loop_flag = 0;
start_offset = 0x38;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
@ -33,8 +33,8 @@ VGMSTREAM * init_vgmstream_waf(STREAMFILE *streamFile) {
vgmstream->num_samples = msadpcm_bytes_to_samples(read_32bitLE(0x34,streamFile), vgmstream->interleave_block_size, channel_count);
/* 0x04: null?, 0x0c: avg br, 0x12: bps, 0x14: s_p_f, 0x16~34: count + standard MSADPCM coefs (a modified RIFF fmt) */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:

View File

@ -4,7 +4,7 @@
#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 * vgmstream = NULL;
off_t segments_offset;
@ -135,18 +135,15 @@ VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) {
}
case 0x04: { /* "vorbis" */
char filename[PATH_LIMIT];
vgm_vorbis_info_t ovi = {0};
ogg_vorbis_meta_info_t ovmi = {0};
segment_offset = read_32bit(table_offset, streamFile);
segment_size = read_32bitBE(segment_offset, streamFile); /* always BE */
ovi.layout_type = layout_ogg_vorbis;
ovi.meta_type = meta_WAVE;
ovi.stream_size = segment_size;
ovmi.meta_type = meta_WAVE;
ovmi.stream_size = segment_size;
streamFile->get_name(streamFile,filename,sizeof(filename));
data->segments[i] = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, segment_offset+0x04, &ovi);
data->segments[i] = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, segment_offset+0x04, &ovmi);
if (!data->segments[i]) goto fail;
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;
/* check extension, case insensitive */
/* checks */
/* ".04sw" is just the ID, the real filename inside the file uses .XA */
if (!check_extensions(streamFile,"xa,04sw"))
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x30345357) /* "04SW" */
goto fail;
@ -39,9 +37,9 @@ VGMSTREAM * init_vgmstream_wii_04sw(STREAMFILE *streamFile) {
vgmstream->num_samples = read_32bitBE(0x04,streamFile);
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_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);
/* 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 */
/* open the file for reading */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:

View File

@ -1,20 +1,17 @@
#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 * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
int loop_flag, channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("ras",filename_extension(filename))) goto fail;
/* checks */
if (!check_extensions(streamFile, "ras"))
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x5241535F) /* "RAS_" */
goto fail;
@ -26,63 +23,32 @@ VGMSTREAM * init_vgmstream_wii_ras(STREAMFILE *streamFile) {
loop_flag = 1;
}
channel_count = 2;
start_offset = read_32bitBE(0x18,streamFile);
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
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->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;
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);
vgmstream->loop_end_sample =
read_32bitBE(0x38,streamFile)*vgmstream->interleave_block_size/8*14 +
read_32bitBE(0x3C,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x20,streamFile);
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);
vgmstream->loop_end_sample = read_32bitBE(0x38,streamFile)*vgmstream->interleave_block_size/8*14 +
read_32bitBE(0x3C,streamFile);
}
if (vgmstream->coding_type == coding_NGC_DSP) {
int i;
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x40+i*2,streamFile);
}
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x70+i*2,streamFile);
}
} else {
dsp_read_coefs_be(vgmstream,streamFile,0x40,0x30);
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
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;
/* clean up anything we may have opened */

View File

@ -229,8 +229,8 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
/* older Wwise (~<2012) */
switch(vorb_size) {
//case 0x2C: /* early (~2009), some EVE Online Apocrypha files? */
case 0x28: /* early (~2009), ex. The Lord of the Rings: Conquest PC */
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) */
data_offsets = 0x18;
block_offsets = 0; /* no need, full headers are present */
cfg.header_type = WWV_TYPE_8;
@ -589,15 +589,15 @@ fail:
0x31 (1): blocksize_0_exp (large)
0x32 (2): empty
"vorb" size 0x28 / 0x2a
"vorb" size 0x28 / 0x2c / 0x2a
0x00 (4): num_samples
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
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)
0x14 (4): audio_offset within data
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?
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)

View File

@ -35,6 +35,11 @@ typedef struct {
size_t base_size;
off_t entry_offset;
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;
size_t data_size;
@ -63,7 +68,7 @@ typedef struct {
uint32_t loop_end_sample;
} 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) */
@ -100,12 +105,20 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
/* read segment offsets (SEGIDX) */
if (xwb.version <= XACT1_0_MAX) {
xwb.total_subsongs = read_32bit(0x0c, streamFile);
/* 0x10: bank name */
/* 0x10: bank name (size 0x10) */
xwb.base_offset = 0;
xwb.base_size = 0;
xwb.entry_offset = 0x50;
xwb.entry_size = xwb.entry_elem_size * xwb.total_subsongs;
xwb.entry_elem_size = 0x14;
xwb.entry_offset= 0x50;
xwb.entry_size = xwb.entry_elem_size * xwb.total_subsongs;
xwb.data_offset = xwb.entry_offset + xwb.entry_size;
xwb.data_size = get_streamfile_size(streamFile) - xwb.data_offset;
xwb.data_offset = xwb.entry_offset + xwb.entry_size;
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 {
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.entry_offset= read_32bit(off+0x08, streamFile);//ENTRYMETADATA
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
//0x14: XACT1: none (ENTRYWAVEDATA), XACT2: EXTRA, XACT3: ENTRYNAMES
suboff = xwb.version <= XACT1_1_MAX ? 0x08 : 0x08+0x08;
/* read extra segments (values can be 0 == no segment) */
if (xwb.version <= XACT1_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 = 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_size = read_32bit(off+0x14+suboff, streamFile);
@ -127,7 +162,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
off = xwb.base_offset;
xwb.base_flags = (uint32_t)read_32bit(off+0x00, 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);
xwb.entry_elem_size = read_32bit(off+suboff+0x00, streamFile);
/* 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) {
/* v38: byte offset, v40+: sample offset, v39: ? */
/* need to manually find sample offsets, thanks to Microsoft dumb headers */
ms_sample_data msd;
memset(&msd,0,sizeof(ms_sample_data));
ms_sample_data msd = {0};
msd.xma_version = xwb.codec == XMA1 ? 1 : 2;
msd.channels = xwb.channels;
@ -360,7 +394,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
vgmstream->num_streams = xwb.total_subsongs;
vgmstream->stream_size = xwb.stream_size;
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) {
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 */
@ -539,24 +591,19 @@ typedef struct {
/* 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;
int i,j, start_sound, cfg__start_sound = 0, cfg__selected_wavebank = 0;
int xsb_version;
off_t off, suboff, name_offset = 0;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
xsb_header xsb;
memset(&xsb,0,sizeof(xsb_header)); /* before any "fail"! */
xsb_header xsb = {0};
streamFile = open_stream_ext(streamXwb, "xsb");
if (!streamFile) goto fail;
//todo try common names (xwb and xsb often are named slightly differently using a common convention)
/* check header */
if ((read_32bitBE(0x00,streamFile) != 0x5344424B) && /* "SDBK" (LE) */
(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:
free(xsb.xsb_sounds);
free(xsb.xsb_wavebanks);
if (streamFile) close_streamfile(streamFile);
return;
close_streamfile(streamFile);
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,8 +628,9 @@ fail:
static void multifile_close(MULTIFILE_STREAMFILE *streamfile) {
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++) {
close_streamfile(streamfile->inner_sfs[i]);
}
}
free(streamfile->inner_sfs);
free(streamfile->sizes);

View File

@ -69,7 +69,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_mp4_aac,
#endif
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
init_vgmstream_akb,
init_vgmstream_akb_mp4,
#endif
init_vgmstream_sadb,
init_vgmstream_ps2_bmdx,
@ -257,7 +257,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_ps2_voi,
init_vgmstream_ps2_khv,
init_vgmstream_pc_smp,
init_vgmstream_ngc_bo2,
init_vgmstream_ngc_rkv,
init_vgmstream_dsp_ddsp,
init_vgmstream_p3d,
init_vgmstream_ps2_tk1,
@ -330,8 +330,8 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_ps2_vds_vdm,
init_vgmstream_x360_cxs,
init_vgmstream_dsp_adx,
init_vgmstream_akb_multi,
init_vgmstream_akb2_multi,
init_vgmstream_akb,
init_vgmstream_akb2,
#ifdef VGM_USE_FFMPEG
init_vgmstream_mp4_aac_ffmpeg,
#endif
@ -350,6 +350,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_ta_aac_x360,
init_vgmstream_ta_aac_ps3,
init_vgmstream_ta_aac_mobile,
init_vgmstream_ta_aac_mobile_vorbis,
init_vgmstream_ps3_mta2,
init_vgmstream_ngc_ulw,
init_vgmstream_pc_xa30,
@ -383,6 +384,9 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_wave,
init_vgmstream_wave_segmented,
init_vgmstream_rsd6at3p,
init_vgmstream_rsd6wma,
init_vgmstream_smv,
init_vgmstream_nxap,
init_vgmstream_txth, /* should go at the end (lower priority) */
#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) {
switch (vgmstream->layout_type) {
case layout_interleave:
case layout_interleave_shortblock:
render_vgmstream_interleave(buffer,sample_count,vgmstream);
break;
#ifdef VGM_USE_VORBIS
case layout_ogg_vorbis:
#endif
case layout_none:
render_vgmstream_nolayout(buffer,sample_count,vgmstream);
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_1snh:
case layout_blocked_caf:
case layout_wsi_blocked:
case layout_blocked_wsi:
case layout_str_snds_blocked:
case layout_ws_aud_blocked:
case layout_matx_blocked:
@ -1006,6 +1006,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_3DS_IMA:
return 2;
case coding_XBOX_IMA:
case coding_XBOX_IMA_mch:
case coding_XBOX_IMA_int:
case coding_FSB_IMA:
case coding_WWISE_IMA:
@ -1048,6 +1049,10 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
return vgmstream->ws_output_size;
case coding_AICA:
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:
return 30;
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
return 0x24; //vgmstream->channels==1 ? 0x24 : 0x48;
case coding_XBOX_IMA_int:
case coding_FSB_IMA:
case coding_WWISE_IMA:
return 0x24;
case coding_XBOX_IMA_mch:
case coding_FSB_IMA:
return 0x24 * vgmstream->channels;
case coding_APPLE_IMA4:
return 0x22;
@ -1208,6 +1215,9 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
return vgmstream->current_block_size;
case coding_AICA:
return 0x01;
case coding_YAMAHA:
case coding_YAMAHA_NXAP:
return 0x40;
case coding_NDS_PROCYON:
return 0x10;
case coding_L5_555:
@ -1251,7 +1261,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) {
switch (vgmstream->coding_type) {
case coding_NDS_IMA:
return (vgmstream->interleave_smallblock_size-4)*2;
return (vgmstream->interleave_last_block_size-4)*2;
default:
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) {
switch (vgmstream->coding_type) {
case coding_NDS_IMA:
return vgmstream->interleave_smallblock_size;
return vgmstream->interleave_last_block_size;
default:
return get_vgmstream_frame_size(vgmstream);
}
@ -1433,7 +1443,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
break;
case coding_XBOX_IMA:
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,
samples_to_do,chan);
}
@ -1799,6 +1816,20 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do);
}
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:
for (chan=0;chan<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");
concatn(length,desc,temp);
if (vgmstream->layout_type == layout_interleave
|| vgmstream->layout_type == layout_interleave_shortblock) {
if (vgmstream->layout_type == layout_interleave) {
snprintf(temp,TEMPSIZE,
"interleave: %#x bytes\n",
(int32_t)vgmstream->interleave_block_size);
concatn(length,desc,temp);
if (vgmstream->layout_type == layout_interleave_shortblock) {
if (vgmstream->interleave_last_block_size) {
snprintf(temp,TEMPSIZE,
"last block interleave: %#x bytes\n",
(int32_t)vgmstream->interleave_smallblock_size);
"interleave last block: %#x bytes\n",
(int32_t)vgmstream->interleave_last_block_size);
concatn(length,desc,temp);
}
}
@ -2192,7 +2222,8 @@ static void try_dual_file_stereo(VGMSTREAM * opened_vgmstream, STREAMFILE *strea
{"l","r"},
{"left","right"},
{"Left","Right"},
{".V0",".V1"},
{".V0",".V1"}, /* Homura (PS2) */
{".L",".R"}, /* Crash Nitro Racing (PS2) */
{"_0","_1"}, //unneeded?
};
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
* 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_smallblock_size == opened_vgmstream->interleave_smallblock_size)) {
new_vgmstream->interleave_last_block_size == opened_vgmstream->interleave_last_block_size)) {
goto fail;
}

View File

@ -128,6 +128,7 @@ typedef enum {
coding_3DS_IMA, /* 3DS IMA ADPCM */
coding_MS_IMA, /* Microsoft 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_NDS_IMA, /* IMA ADPCM w/ NDS layout */
coding_DAT4_IMA, /* Eurocom 'DAT4' IMA ADPCM */
@ -145,6 +146,8 @@ typedef enum {
coding_MSADPCM, /* Microsoft ADPCM */
coding_WS, /* Westwood Studios VBR ADPCM */
coding_AICA, /* Yamaha AICA ADPCM */
coding_YAMAHA, /* Yamaha ADPCM */
coding_YAMAHA_NXAP, /* Yamaha ADPCM (NXAP variation) */
coding_NDS_PROCYON, /* Procyon Studio ADPCM */
coding_L5_555, /* Level-5 0x555 ADPCM */
coding_SASSC, /* Activision EXAKT SASSC DPCM */
@ -212,7 +215,6 @@ typedef enum {
/* interleave */
layout_interleave, /* equal interleave throughout the stream */
layout_interleave_shortblock, /* interleave with a short last block */
/* headered blocks */
layout_ast_blocked,
@ -221,7 +223,7 @@ typedef enum {
layout_blocked_ea_schl,
layout_blocked_ea_1snh,
layout_blocked_caf,
layout_wsi_blocked,
layout_blocked_wsi,
layout_str_snds_blocked,
layout_ws_aud_blocked,
layout_matx_blocked,
@ -254,9 +256,6 @@ typedef enum {
layout_segmented, /* song divided in segments, each a complete VGMSTREAM */
layout_scd_int, /* deinterleave done by the SCDINTSTREAMFILE */
#ifdef VGM_USE_VORBIS
layout_ogg_vorbis, /* ogg vorbis file */
#endif
} layout_t;
/* 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_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_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_VAS, /* Pro Baseball Spirits 5 */
meta_PS2_TEC, /* TECMO badflagged stream */
@ -428,6 +427,7 @@ typedef enum {
meta_RSD6OOGV, /* RSD6OOGV */
meta_RSD6XMA, /* RSD6XMA */
meta_RSD6AT3P, /* RSD6AT3+ */
meta_RSD6WMA, /* RSD6WMA */
meta_PS2_ASS, /* ASS */
meta_PS2_SEG, /* Eragon */
@ -535,7 +535,7 @@ typedef enum {
meta_P3D, /* Prototype P3D */
meta_PS2_TK1, /* Tekken (NamCollection) */
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_NGC_DSP_MPDS, /* Big Air Freestyle, Terminator 3 */
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_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_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_NGC_ULW, /* Burnout 1 (GC only) */
meta_PC_XA30, /* Driver - Parallel Lines (PC) */
@ -656,8 +656,10 @@ typedef enum {
meta_SQEX_MAB, /* Square-Enix newest middleware (music) */
meta_OGG_L2SD, /* Ogg Vorbis with obfuscation [Lineage II Chronicle 4 (PC)] */
meta_WAF, /* KID WAF [Ever 17 (PC)] */
meta_WAVE, /* WayForward "EngineBlack" games [Mighty Switch Force! (3DS)] */
meta_WAVE_segmented, /* WayForward "EngineBlack" games, segmented [Shantae and the Pirate's Curse (PC)] */
meta_WAVE, /* EngineBlack games [Mighty Switch Force! (3DS)] */
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
meta_MP4, /* AAC (iOS) */
@ -745,7 +747,7 @@ typedef struct {
/* layouts/block */
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 */
VGMSTREAMCHANNEL * ch; /* pointer to array of channels */