Merge pull request #196 from bnnm/ima-raki-ogg-etc

IMA, RAKI, OGG, etc
This commit is contained in:
Christopher Snowhill 2018-02-17 14:44:02 -08:00 committed by GitHub
commit 16b4cf2294
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 858 additions and 822 deletions

View File

@ -32,8 +32,9 @@ void decode_wwise_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample *
void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ubi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels);
size_t ima_bytes_to_samples(size_t bytes, int channels);
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels);
size_t xbox_ima_bytes_to_samples(size_t bytes, int channels);
size_t ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFile, off_t offset);
/* ngc_dsp_decoder */

View File

@ -403,7 +403,7 @@ ffmpeg_codec_data * init_ffmpeg_config(STREAMFILE *streamFile, uint8_t * header,
for (i = 0; i < data->formatCtx->nb_streams; ++i) {
stream = data->formatCtx->streams[i];
if (stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
if (stream->codecpar && stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
streamCount++;
/* select Nth audio stream if specified, or first one */

View File

@ -272,46 +272,126 @@ void decode_otns_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample *
}
/* ************************************ */
/* MS IMA */
/* MS-IMA */
/* ************************************ */
/* IMA with frames with header and custom sizes */
void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
int i, sample_count;
/* IMA with variable-sized frames, header and custom nibble layout (outputs non-aligned number of samples).
* Officially defined in "Microsoft Multimedia Standards Update" doc (RIFFNEW.pdf). */
void decode_ms_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, samples_read = 0, samples_done = 0, max_samples;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
int32_t hist1;// = stream->adpcm_history1_32;
int step_index;// = stream->adpcm_step_index;
//internal interleave (configurable size), mixed channels (4 byte per ch)
int block_samples = (vgmstream->interleave_block_size - 4*vgmstream->channels) * 2 / vgmstream->channels;
/* internal interleave (configurable size), mixed channels (4 byte per ch) */
int block_samples = ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;
first_sample = first_sample % block_samples;
//normal header (per channel)
if (first_sample == 0) {
off_t header_offset = stream->offset + 4*channel;
/* normal header (hist+step+reserved per channel) */
{
off_t header_offset = stream->offset + 0x04*channel;
hist1 = read_16bitLE(header_offset,stream->streamfile);
step_index = read_8bit(header_offset+2,stream->streamfile);
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
step_index = read_8bit(header_offset+0x02,stream->streamfile); /* 0x03: reserved */
if (step_index < 0) step_index = 0;
if (step_index > 88) step_index = 88;
/* write header sample */
if (samples_read >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = (short)hist1;
samples_done++;
}
samples_read++;
}
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 4*channel + 4*vgmstream->channels + i/8*4*vgmstream->channels + (i%8)/2;
int nibble_shift = (i&1?4:0); //low nibble first
max_samples = (block_samples - samples_read);
if (max_samples > samples_to_do + first_sample - samples_done)
max_samples = samples_to_do + first_sample - samples_done; /* for smaller last block */
/* decode nibbles (layout: alternates 4*2 nibbles per channel) */
for (i = 0; i < max_samples; i++) {
off_t byte_offset = stream->offset + 0x04*vgmstream->channels + 0x04*channel + 0x04*vgmstream->channels*(i/8) + (i%8)/2;
int nibble_shift = (i&1?4:0); /* low nibble first */
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
outbuf[sample_count] = (short)(hist1);
if (samples_read >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = (short)(hist1);
samples_done++;
}
samples_read++;
}
//internal interleave: increment offset on complete frame
if (i == block_samples) stream->offset += vgmstream->interleave_block_size;
/* internal interleave: increment offset on complete frame */
if (first_sample + samples_done == block_samples) {
stream->offset += vgmstream->interleave_block_size;
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
//stream->adpcm_history1_32 = hist1;
//stream->adpcm_step_index = step_index;
}
/* MS IMA with fixed frame size and custom multichannel nibble layout.
/* Reflection's MS-IMA (some layout info from XA2WAV by Deniz Oezmen) */
void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, samples_read = 0, samples_done = 0, max_samples;
int32_t hist1;// = stream->adpcm_history1_32;
int step_index;// = stream->adpcm_step_index;
/* internal interleave (configurable size), mixed channels (4 byte per ch) */
int block_channel_size = (vgmstream->interleave_block_size - 0x04*vgmstream->channels) / vgmstream->channels;
int block_samples = ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;
first_sample = first_sample % block_samples;
/* normal header (hist+step+reserved per channel) */
{
off_t header_offset = stream->offset + 0x04*channel;
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
step_index = read_8bit(header_offset+0x02,stream->streamfile); /* 0x03: reserved */
if (step_index < 0) step_index = 0;
if (step_index > 88) step_index = 88;
/* write header sample */
if (samples_read >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = (short)hist1;
samples_done++;
}
samples_read++;
}
max_samples = (block_samples - samples_read);
if (max_samples > samples_to_do + first_sample - samples_done)
max_samples = samples_to_do + first_sample - samples_done; /* for smaller last block */
/* decode nibbles (layout: all nibbles from one channel, then other channels) */
for (i = 0; i < max_samples; i++) {
off_t byte_offset = stream->offset + 0x04*vgmstream->channels + block_channel_size*channel + i/2;
int nibble_shift = (i&1?4:0); /* low nibble first */
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
if (samples_read >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = (short)(hist1);
samples_done++;
}
samples_read++;
}
/* internal interleave: increment offset on complete frame */
if (first_sample + samples_done == block_samples) {
stream->offset += vgmstream->interleave_block_size;
}
//stream->adpcm_history1_32 = hist1;
//stream->adpcm_step_index = step_index;
}
/* ************************************ */
/* XBOX-IMA */
/* ************************************ */
/* MS-IMA with fixed frame size, skips last sample per channel (for aligment) and custom multichannel nibble layout.
* For multichannel the layout is (I think) mixed stereo channels (ex. 6ch: 2ch + 2ch + 2ch) */
void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
int i, sample_count;
@ -351,19 +431,19 @@ void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * o
}
//internal interleave: increment offset on complete frame
if (channelspacing==1) {
if(offset-stream->offset==32+3) // ??
stream->offset+=36;
if (channelspacing==1) { /* mono */
if (offset-stream->offset == 32+3) // ??
stream->offset += 0x24;
} else {
if(offset-stream->offset==64+(4*(channel%2))+3) // ??
stream->offset+=36*channelspacing;
if (offset-stream->offset == 64+(4*(channel%2))+3) // ??
stream->offset += 0x24*channelspacing;
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}
/* mono XBOX ADPCM for interleave */
/* mono XBOX-IMA ADPCM for interleave */
void decode_xbox_ima_int(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;
@ -565,6 +645,7 @@ void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelsp
stream->adpcm_step_index = step_index;
}
/* XBOX-IMA with modified data layout */
void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
int i, sample_count;
@ -572,7 +653,7 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o
int step_index = stream->adpcm_step_index;
//internal interleave
int block_samples = (36 - 4) * 2; /* block size - header, 2 samples per byte */
int block_samples = (0x24 - 4) * 2; /* block size - header, 2 samples per byte */
first_sample = first_sample % block_samples;
//interleaved header (all hist per channel + all step_index per channel)
@ -601,7 +682,7 @@ void decode_fsb_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o
stream->adpcm_step_index = step_index;
}
/* XBOX-IMA with modified data layout */
void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count = 0;
@ -638,7 +719,6 @@ void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample *
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
outbuf[sample_count] = (short)(hist1);
sample_count+=channelspacing;
//todo atenuation: apparently from hcs's analysis Wwise IMA decodes nibbles slightly different, reducing dbs
}
}
@ -648,45 +728,23 @@ void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample *
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}
//todo atenuation: apparently from hcs's analysis Wwise IMA expands nibbles slightly different, reducing clipping/dbs
/*
From Wwise_v2015.1.6_Build5553_SDK.Linux
<_ZN13CAkADPCMCodec12DecodeSampleEiii>:
10: 83 e0 07 and $0x7,%eax ; sample
13: 01 c0 add %eax,%eax ; sample*2
15: 83 c0 01 add $0x1,%eax ; sample*2+1
18: 0f af 45 e4 imul -0x1c(%rbp),%eax ; (sample*2+1)*scale
1c: 8d 50 07 lea 0x7(%rax),%edx ; result+7
1f: 85 c0 test %eax,%eax ; result negative?
21: 0f 48 c2 cmovs %edx,%eax ; adjust if negative to fix rounding for below division
24: c1 f8 03 sar $0x3,%eax ; (sample*2+1)*scale/8
/* Reflection's MS-IMA (some layout info from XA2WAV) */
void decode_ref_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
int i, sample_count;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
//internal interleave (configurable size), mixed channels (4 byte per ch)
int block_channel_size = (vgmstream->interleave_block_size - 4*vgmstream->channels) / vgmstream->channels;
int block_samples = (vgmstream->interleave_block_size - 4*vgmstream->channels) * 2 / vgmstream->channels;
first_sample = first_sample % block_samples;
//normal header (per channel)
if (first_sample == 0) {
off_t header_offset = stream->offset + 4*channel;
hist1 = read_16bitLE(header_offset,stream->streamfile);
step_index = read_8bit(header_offset+2,stream->streamfile);
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
}
//layout: all nibbles from one channel, then all nibbles from other
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 4*vgmstream->channels + block_channel_size*channel + i/2;
int nibble_shift = (i&1?4:0); //low nibble first
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
outbuf[sample_count] = (short)(hist1);
}
//internal interleave: increment offset on complete frame
if (i == block_samples) stream->offset += vgmstream->interleave_block_size;
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}
Different rounding model vs IMA's shift-and-add (also "adjust" step may be unnecessary).
*/
/* MS-IMA with possibly the XBOX-IMA model of even number of samples per block (more tests are needed) */
void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i, sample_count;
@ -785,17 +843,24 @@ void decode_ubi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
}
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels) {
/* MS IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */
return (bytes / block_align) * (block_align - 4 * channels) * 2 / channels
+ ((bytes % block_align) ? ((bytes % block_align) - 4 * channels) * 2 / channels : 0);
}
size_t ima_bytes_to_samples(size_t bytes, int channels) {
/* 2 samples per byte (2 nibbles) in stereo or mono config */
return bytes * 2 / channels;
}
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels) {
/* MS IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */
return (bytes / block_align) * ((block_align - 0x04*channels) * 2 / channels + 1)
+ ((bytes % block_align) ? (((bytes % block_align) - 0x04*channels) * 2 / channels + 1) : 0);
}
size_t xbox_ima_bytes_to_samples(size_t bytes, int channels) {
int block_align = 0x24 * channels;
/* XBOX IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */
return (bytes / block_align) * (block_align - 4 * channels) * 2 / channels
+ ((bytes % block_align) ? ((bytes % block_align) - 4 * channels) * 2 / channels : 0); //todo probably not possible (aligned)
}
size_t ubi_ima_bytes_to_samples(size_t bytes, int channels, STREAMFILE *streamFile, off_t offset) {
int version, big_endian, header_samples;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;

View File

@ -21,10 +21,6 @@ static const int ADPCMCoeffs[7][2] =
{ 392, -232 }
};
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels) {
return bytes/block_size*((block_size-(7-1)*channels)*2/channels);
}
void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do) {
VGMSTREAMCHANNEL *ch1,*ch2;
int i;
@ -161,3 +157,8 @@ void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_s
}
}
}
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels) {
return (bytes / block_size) * (block_size - (7-1)*channels) * 2 / channels
+ ((bytes % block_size) ? ((bytes % block_size) - (7-1)*channels) * 2 / channels : 0);
}

View File

@ -470,8 +470,8 @@ static const coding_info coding_info_list[] = {
{coding_DVI_IMA_int, "Intel DVI 4-bit IMA ADPCM (mono/interleave)"},
{coding_3DS_IMA, "3DS IMA 4-bit ADPCM"},
{coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"},
{coding_XBOX, "XBOX 4-bit IMA ADPCM"},
{coding_XBOX_int, "XBOX 4-bit IMA ADPCM (mono/interleave)"},
{coding_XBOX_IMA, "XBOX 4-bit IMA ADPCM"},
{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"},
{coding_RAD_IMA, "Radical 4-bit IMA ADPCM"},
@ -564,7 +564,7 @@ static const layout_info layout_info_list[] = {
{layout_gsb_blocked, "GSB blocked"},
{layout_thp_blocked, "THP Movie Audio blocked"},
{layout_filp_blocked, "FILp blocked"},
{layout_psx_mgav_blocked, "MGAV blocked"},
{layout_blocked_ea_swvr, "blocked (EA SWVR)"},
{layout_ps2_adm_blocked, "ADM blocked"},
{layout_dsp_bdsp_blocked, "DSP blocked"},
{layout_blocked_ivaud, "blocked (IVAUD)"},
@ -641,7 +641,7 @@ static const meta_info meta_info_list[] = {
{meta_PS2_STR, "assumed STR + STH File by .str & .sth extension"},
{meta_PS2_ILD, "ILD header"},
{meta_PS2_PNB, "assumed PNB (PsychoNauts Bgm File) by .pnb extension"},
{meta_XBOX_WAVM, "assumed Xbox WAVM file by .wavm extension"},
{meta_XBOX_WAVM, "Xbox WAVM raw header"},
{meta_XBOX_RIFF, "Microsoft XWAV RIFF header"},
{meta_DSP_STR, "assumed Conan Gamecube STR File by .str extension"},
{meta_EA_SCHL, "Electronic Arts SCHl header (variable)"},
@ -717,7 +717,7 @@ static const meta_info meta_info_list[] = {
{meta_DC_STR, "Sega Stream Asset Builder header"},
{meta_DC_STR_V2, "variant of Sega Stream Asset Builder header"},
{meta_XBOX_XMU, "XMU header"},
{meta_XBOX_XVAS, "assumed TMNT file by .xvas extension"},
{meta_XBOX_XVAS, "Konami .XVAS header"},
{meta_PS2_XA2, "Acclaim XA2 Header"},
{meta_DC_IDVI, "Capcom IDVI header"},
{meta_KRAW, "Geometry Wars: Galaxies KRAW header"},
@ -838,7 +838,7 @@ static const meta_info meta_info_list[] = {
{meta_PS2_ADSC, "ADSC Header"},
{meta_NGC_DSP_MPDS, "MPDS DSP header"},
{meta_DSP_STR_IG, "Infogrames dual dsp header"},
{meta_PSX_MGAV, "Electronic Arts RVWS header"},
{meta_EA_SWVR, "Electronic Arts SWVR header"},
{meta_PS2_B1S, "B1S header"},
{meta_PS2_WAD, "WAD header"},
{meta_DSP_XIII, "XIII dsp header"},
@ -955,6 +955,7 @@ static const meta_info meta_info_list[] = {
{meta_XWC, "Starbreeze XWC header"},
{meta_SQEX_SAB, "Square-Enix SAB header"},
{meta_SQEX_MAB, "Square-Enix MAB header"},
{meta_OGG_L2SD, "Ogg Vorbis (L2SD)"},
#ifdef VGM_USE_MP4V2
{meta_MP4, "AAC header"},

View File

@ -128,8 +128,8 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
case layout_blocked_ivaud:
block_update_ivaud(vgmstream->next_block_offset,vgmstream);
break;
case layout_psx_mgav_blocked:
psx_mgav_block_update(vgmstream->next_block_offset,vgmstream);
case layout_blocked_ea_swvr:
block_update_ea_swvr(vgmstream->next_block_offset,vgmstream);
break;
case layout_ps2_adm_blocked:
ps2_adm_block_update(vgmstream->next_block_offset,vgmstream);

View File

@ -0,0 +1,18 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void block_update_ea_swvr(off_t block_offset, VGMSTREAM * vgmstream) {
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
int i;
int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bit(vgmstream->current_block_offset+0x04,streamFile)-0x1C;
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x1C;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+0x1C+(vgmstream->current_block_size*i);
}
}

View File

@ -46,7 +46,7 @@ void filp_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ivaud(off_t block_offset, VGMSTREAM * vgmstream);
void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void block_update_ea_swvr(off_t block_offset, VGMSTREAM * vgmstream);
void ps2_adm_block_update(off_t block_offset, VGMSTREAM * vgmstream);

View File

@ -1,17 +0,0 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitLE(vgmstream->current_block_offset+0x04,vgmstream->ch[0].streamfile)-0x1C;
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x1C;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+0x1C+(vgmstream->current_block_size*i);
}
}

View File

@ -795,7 +795,7 @@
>
</File>
<File
RelativePath=".\meta\ps2_aus.c"
RelativePath=".\meta\aus.c"
>
</File>
<File
@ -1103,7 +1103,7 @@
>
</File>
<File
RelativePath=".\meta\psx_str_mgav.c"
RelativePath=".\meta\ea_swvr.c"
>
</File>
<File
@ -1771,7 +1771,7 @@
>
</File>
<File
RelativePath=".\layout\psx_mgav_blocked.c"
RelativePath=".\layout\blocked_ea_swvr.c"
>
</File>
<File

View File

@ -294,7 +294,7 @@
<ClCompile Include="meta\ps2_adsc.c" />
<ClCompile Include="meta\ps2_ass.c" />
<ClCompile Include="meta\ps2_ast.c" />
<ClCompile Include="meta\ps2_aus.c" />
<ClCompile Include="meta\aus.c" />
<ClCompile Include="meta\ps2_b1s.c" />
<ClCompile Include="meta\ps2_bg00.c" />
<ClCompile Include="meta\ps2_bmdx.c" />
@ -359,7 +359,7 @@
<ClCompile Include="meta\psx_cdxa.c" />
<ClCompile Include="meta\psx_fag.c" />
<ClCompile Include="meta\psx_gms.c" />
<ClCompile Include="meta\psx_str_mgav.c" />
<ClCompile Include="meta\ea_swvr.c" />
<ClCompile Include="meta\raw.c" />
<ClCompile Include="meta\redspark.c" />
<ClCompile Include="meta\riff.c" />
@ -487,7 +487,7 @@
<ClCompile Include="layout\mxch_blocked.c" />
<ClCompile Include="layout\nolayout.c" />
<ClCompile Include="layout\ps2_adm_blocked.c" />
<ClCompile Include="layout\psx_mgav_blocked.c" />
<ClCompile Include="layout\blocked_ea_swvr.c" />
<ClCompile Include="layout\rws_blocked.c" />
<ClCompile Include="layout\hwas_blocked.c" />
<ClCompile Include="layout\str_snds_blocked.c" />

View File

@ -472,7 +472,7 @@
<ClCompile Include="meta\ps2_ast.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ps2_aus.c">
<ClCompile Include="meta\aus.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ps2_b1s.c">
@ -667,7 +667,7 @@
<ClCompile Include="meta\psx_gms.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\psx_str_mgav.c">
<ClCompile Include="meta\ea_swvr.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\raw.c">
@ -1045,7 +1045,7 @@
<ClCompile Include="layout\ps2_adm_blocked.c">
<Filter>layout\Source Files</Filter>
</ClCompile>
<ClCompile Include="layout\psx_mgav_blocked.c">
<ClCompile Include="layout\blocked_ea_swvr.c">
<Filter>layout\Source Files</Filter>
</ClCompile>
<ClCompile Include="layout\rws_blocked.c">

View File

@ -6,38 +6,33 @@
VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag;
int channel_count;
int identifer_byte;
int loop_flag, channel_count, codec;
/* check extension, case insensitive */
if (!check_extensions(streamFile,"ads")) goto fail;
/* check dhSS Header */
if (read_32bitBE(0x00,streamFile) != 0x64685353)
if (read_32bitBE(0x00,streamFile) != 0x64685353) /* "dhSS" */
goto fail;
/* check dbSS Header */
if (read_32bitBE(0x20,streamFile) != 0x64625353)
if (read_32bitBE(0x20,streamFile) != 0x64625353) /* "dbSS" */
goto fail;
loop_flag = 1;
channel_count = read_32bitBE(0x10,streamFile);
if (channel_count > 0x2)
if (channel_count > 2)
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
identifer_byte = read_32bitBE(0x08,streamFile);
switch (identifer_byte) {
vgmstream->sample_rate = read_32bitBE(0x0c,streamFile);
codec = read_32bitBE(0x08,streamFile);
switch (codec) {
case 0x00000020: /* GC */
start_offset = 0x28 + 0x60 * channel_count;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x0c,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x28,streamFile);
if (loop_flag) {
@ -45,9 +40,9 @@ VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = vgmstream->num_samples;
}
if (channel_count == 1){
if (channel_count == 1) {
vgmstream->layout_type = layout_none;
} else if (channel_count == 2){
} else if (channel_count == 2) {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x14,streamFile);
}
@ -57,10 +52,8 @@ VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) {
case 0x00000021: /* Xbox */
start_offset = 0x28;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x0c,streamFile);
vgmstream->coding_type = coding_XBOX_int;
vgmstream->num_samples = (read_32bitBE(0x24,streamFile) / 36 *64 / vgmstream->channels)-64; // to avoid the "pop" at the loop point
vgmstream->coding_type = coding_XBOX_IMA_int;
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitBE(0x24,streamFile), vgmstream->channels);
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave;
vgmstream->interleave_block_size = 0x24;
if (loop_flag) {

View File

@ -31,7 +31,7 @@ VGMSTREAM * init_vgmstream_aus(STREAMFILE *streamFile) {
vgmstream->num_samples = read_32bitLE(0x08,streamFile);
if(read_16bitLE(0x06,streamFile)==0x02) {
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type=layout_none;
} else {
vgmstream->coding_type = coding_PSX;

View File

@ -37,9 +37,6 @@ VGMSTREAM * init_vgmstream_awc(STREAMFILE *streamFile) {
if (!parse_awc_header(streamFile, &awc))
goto fail;
if (awc.is_encrypted)
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(awc.channel_count, 0);
@ -156,6 +153,10 @@ static int parse_awc_header(STREAMFILE* streamFile, awc_header* awc) {
if (flags & 0x00080000) /* encrypted data chunk (most of GTA5 PC) */
awc->is_encrypted = 1;
if (awc->is_encrypted) {
VGM_LOG("AWC: encrypted data found\n");
goto fail;
}
/* Music when the first id is 0 (base/fake entry with info for all channels), sfx pack otherwise.
* sfx = N single streams, music = N-1 interleaved mono channels (even for MP3/XMA).
@ -267,7 +268,7 @@ static int parse_awc_header(STREAMFILE* streamFile, awc_header* awc) {
/* If music, data is divided into blocks of block_chunk size with padding.
* Each block has a header/seek table and interleaved data for all channels */
if (awc->is_music && read_32bit(awc->stream_offset, streamFile) != 0) {
VGM_LOG("AWC: music found, but block doesn't start with seek table\n");
VGM_LOG("AWC: music found, but block doesn't start with seek table at %lx\n", awc->stream_offset);
goto fail;
}

View File

@ -292,7 +292,7 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
break;
case EA_CODEC2_XBOXADPCM: /* XBOX IMA (interleaved mono) */
vgmstream->coding_type = coding_XBOX_int;
vgmstream->coding_type = coding_XBOX_IMA_int;
break;
case EA_CODEC2_GCADPCM: /* DSP */

80
src/meta/ea_swvr.c Normal file
View File

@ -0,0 +1,80 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
/* SWVR - from EA games [Future Cop L.A.P.D. (PS/PC), Freekstyle (PS2/GC), EA Sports Supercross (PS)] */
VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag = 0, channel_count;
int big_endian;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
/* check extension */
if (!check_extensions(streamFile,"str"))
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) == 0x53575652) { /* "SWVR" (GC) */
big_endian = 1;
read_32bit = read_32bitBE;
}
else if (read_32bitBE(0x00,streamFile) == 0x52565753) { /* "RVWS" (PS/PS2) */
big_endian = 0;
read_32bit = read_32bitLE;
}
else {
goto fail;
}
start_offset = read_32bit(0x04,streamFile);
loop_flag = 1;
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = 16000;
vgmstream->codec_endian = big_endian;
vgmstream->meta_type = meta_EA_SWVR;
vgmstream->layout_type = layout_blocked_ea_swvr;
vgmstream->coding_type = coding_PSX;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
/* calculate samples */
{
off_t current_chunk = start_offset;
vgmstream->num_samples = 0;
while ((current_chunk + start_offset) < (get_streamfile_size(streamFile))) {
uint32_t block_id = (read_32bit(current_chunk,streamFile));
if (block_id == 0x5641474D) { /* "VAGM" */
block_update_ea_swvr(start_offset,vgmstream);
vgmstream->num_samples += vgmstream->current_block_size/16*28;
current_chunk += vgmstream->current_block_size + 0x1C;
}
current_chunk += 0x10;
}
}
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -288,7 +288,7 @@ VGMSTREAM * init_vgmstream_fsb(STREAMFILE *streamFile) {
/* FSOUND_IMAADPCMSTEREO is "noninterleaved, true stereo IMA", but doesn't seem to be any different
* (found in FSB4: Shatter, Blade Kitten (PC), Hard Corps: Uprising (PS3)) */
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
/* "interleaved header" IMA, only used with >2ch (ex. Blade Kitten 6ch)
* or (seemingly) when flag is used (ex. Dead to Rights 2 (Xbox) 2ch in FSB3.1 */

View File

@ -237,7 +237,7 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
break;
case 0x07: /* FMOD_SOUND_FORMAT_IMAADPCM */
vgmstream->coding_type = (vgmstream->channels > 2) ? coding_FSB_IMA : coding_XBOX;
vgmstream->coding_type = (vgmstream->channels > 2) ? coding_FSB_IMA : coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
break;

View File

@ -84,7 +84,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
/* type to coding conversion */
switch (genh.codec) {
case PSX: coding = coding_PSX; break;
case XBOX: coding = coding_XBOX; break;
case XBOX: coding = coding_XBOX_IMA; break;
case NGC_DTK: coding = coding_NGC_DTK; break;
case PCM16BE: coding = coding_PCM16BE; break;
case PCM16LE: coding = coding_PCM16LE; break;
@ -194,7 +194,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = genh.interleave;
vgmstream->layout_type = layout_none;
break;
case coding_XBOX:
case coding_XBOX_IMA:
vgmstream->layout_type = layout_none;
break;
case coding_NGC_DTK:

View File

@ -490,7 +490,7 @@ VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_dsp_str_ig(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_psx_mgav(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str1(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str2(STREAMFILE* streamFile);

View File

@ -18,6 +18,8 @@ VGMSTREAM * init_vgmstream_mss(STREAMFILE *streamFile) {
loop_flag = 0;
channel_count = read_16bitLE(0x16,streamFile);
if (read_32bitLE(0x18,streamFile) == 0x4800 && vgmstream->channels > 2)
channel_count = 2; //todo add support for interleave stereo streams
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
@ -36,14 +38,12 @@ VGMSTREAM * init_vgmstream_mss(STREAMFILE *streamFile) {
/* no other way to know */
if (vgmstream->interleave_block_size == 0x4800) {
/* interleaved stereo streams (2ch 0x4800 + 2ch 0x4800 = 4ch) */
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_interleave;
/* header values are somehow off? */
data_size = get_streamfile_size(streamFile);
vgmstream->num_samples = ms_ima_bytes_to_samples(data_size, 0x24*vgmstream->channels, vgmstream->channels);
vgmstream->channels = 2; //todo add support for interleave stereo streams
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
}
else {
/* 0x800 interleave */

View File

@ -232,7 +232,8 @@ VGMSTREAM * init_vgmstream_ngc_mdsp_std(STREAMFILE *streamFile) {
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave_shortblock;
vgmstream->meta_type = meta_DSP_STD;
vgmstream->interleave_block_size = header.block_size * 8;
vgmstream->interleave_smallblock_size = (header.nibble_count / 2 % vgmstream->interleave_block_size + 7) / 8 * 8;
if (vgmstream->interleave_block_size)
vgmstream->interleave_smallblock_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;

View File

@ -156,6 +156,26 @@ static void isd_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo
}
}
static void l2sd_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) {
size_t bytes_read = size*nmemb;
ogg_vorbis_streamfile * const ov_streamfile = datasource;
int i;
char *header_id = "OggS";
/* First "OggS" is changed */
{
for (i = 0; i < bytes_read; i++) {
if (ov_streamfile->offset+i < 0x04) {
/* replace key in the first 4 bytes with "OggS" */
((uint8_t*)ptr)[i] = (uint8_t)header_id[(ov_streamfile->offset + i) % 4];
}
else {
break;
}
}
}
}
/* Ogg Vorbis, by way of libvorbisfile; may contain loop comments */
VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
@ -169,6 +189,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
int is_psychic = 0;
int is_sngw = 0;
int is_isd = 0;
int is_l2sd = 0;
/* check extension */
@ -195,6 +216,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
is_psychic = 1;
inf.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;
}
else if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */
goto fail; /* not known (ex. Wwise) */
}
@ -251,6 +276,8 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
inf.meta_type = meta_OGG_SNGW;
} else if (is_isd) {
inf.meta_type = meta_OGG_ISD;
} else if (is_l2sd) {
inf.meta_type = meta_OGG_L2SD;
} else {
inf.meta_type = meta_OGG_VORBIS;
}

View File

@ -1,77 +0,0 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
/* STR (Future Cop L.A.P.D.) */
VGMSTREAM * init_vgmstream_psx_mgav(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
off_t current_chunk;
char filename[PATH_LIMIT];
int loop_flag = 0;
int channel_count;
int dataBuffer = 0;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("str",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x52565753) /* "RVWS" */
goto fail;
loop_flag = 1;
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = read_32bitLE(0x4,streamFile);
vgmstream->channels = channel_count;
vgmstream->sample_rate = 16000;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_psx_mgav_blocked;
vgmstream->meta_type = meta_PSX_MGAV;
/* open the file for reading */
{
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;
}
}
// calculate samples
current_chunk = start_offset;
vgmstream->num_samples = 0;
while ((current_chunk + start_offset) < (get_streamfile_size(streamFile)))
{
dataBuffer = (read_32bitBE(current_chunk,streamFile));
if (dataBuffer == 0x4D474156) /* "MGAV" */
{
psx_mgav_block_update(start_offset,vgmstream);
vgmstream->num_samples += vgmstream->current_block_size/16*28;
current_chunk += vgmstream->current_block_size + 0x1C;
}
current_chunk += 0x10;
}
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -126,18 +126,18 @@ static int read_fmt(int big_endian, STREAMFILE * streamFile, off_t current_chunk
fmt->coding_type = coding_MSADPCM;
break;
case 0x11: /* MS IMA ADPCM */
case 0x11: /* MS IMA ADPCM [Layton Brothers: Mystery Room (iOS/Android)] */
if (fmt->bps != 4) goto fail;
fmt->coding_type = coding_MS_IMA;
break;
case 0x69: /* MS IMA ADPCM (XBOX) - Rayman Raving Rabbids 2 (PC) */
case 0x69: /* XBOX IMA ADPCM [Rayman Raving Rabbids 2 (PC) --maybe waa/wac/wam/wad?] */
if (fmt->bps != 4) goto fail;
fmt->coding_type = coding_MS_IMA;
fmt->coding_type = coding_XBOX_IMA;
break;
case 0x007A: /* MS IMA ADPCM (LA Rush, Psi Ops PC) */
/* 0x007A is apparently "Voxware SC3" but in .MED it's just MS-IMA */
case 0x007A: /* MS IMA ADPCM [LA Rush (PC), Psi Ops (PC)] */
/* 0x007A is apparently "Voxware SC3" but in .MED it's just MS-IMA (0x11) */
if (!check_extensions(streamFile,"med"))
goto fail;
@ -228,8 +228,8 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
size_t file_size, riff_size, data_size = 0;
off_t start_offset = 0;
int fact_sample_count = -1;
int fact_sample_skip = -1;
int fact_sample_count = 0;
int fact_sample_skip = 0;
int loop_flag = 0;
long loop_start_ms = -1;
@ -246,9 +246,10 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
int at3 = 0; /* Sony ATRAC3 / ATRAC3plus */
int at9 = 0; /* Sony ATRAC9 */
/* check extension, case insensitive
* .da: The Great Battle VI (PS), .cd: Exector (PS), .med: Psi Ops (PC) */
if ( check_extensions(streamFile, "wav,lwav,da,cd,med") ) {
/* check extension */
/* .da: The Great Battle VI (PS), .cd: Exector (PS), .med: Psi Ops (PC), .snd: Layton Brothers (iOS/Android) */
if ( check_extensions(streamFile, "wav,lwav,da,cd,med,snd") ) {
;
}
else if ( check_extensions(streamFile, "mwv") ) {
@ -355,7 +356,9 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
mwv_ctrl_offset = current_chunk;
break;
case 0x66616374: /* fact */
if (sns && chunk_size == 0x10) {
if (chunk_size == 0x04) { /* standard, usually found with ADPCM */
fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile);
} else if (sns && chunk_size == 0x10) {
fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile);
} else if ((at3 || at9) && chunk_size == 0x08) {
fact_sample_count = read_32bitLE(current_chunk+0x08, streamFile);
@ -380,13 +383,14 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
if (!FormatChunkFound || !DataChunkFound) goto fail;
//todo improve detection using fmt sizes/values as Wwise's don't match the RIFF standard
/* JUNK is an optional Wwise chunk, and Wwise hijacks the MSADPCM/MS_IMA/XBOX IMA ids (how nice).
* To ensure their stuff is parsed in wwise.c we reject their JUNK, which they put almost always.
* As JUNK is legal (if unusual) we only reject those codecs.
* (ex. Cave PC games have PCM16LE + JUNK + smpl created by "Samplitude software") */
if (JunkFound
&& check_extensions(streamFile,"wav,lwav") /* for some .MED IMA */
&& (fmt.coding_type==coding_MSADPCM || fmt.coding_type==coding_MS_IMA))
&& (fmt.coding_type==coding_MSADPCM /*|| fmt.coding_type==coding_MS_IMA*/ || fmt.coding_type==coding_XBOX_IMA))
goto fail;
@ -409,9 +413,11 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
case coding_PCM16LE:
vgmstream->num_samples = pcm_bytes_to_samples(data_size, fmt.channel_count, 16);
break;
case coding_PCM8_U_int:
vgmstream->num_samples = pcm_bytes_to_samples(data_size, vgmstream->channels, 8);
break;
case coding_L5_555:
if (!mwv) goto fail;
vgmstream->num_samples = data_size / 0x12 / fmt.channel_count * 32;
@ -437,12 +443,22 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
}
break;
case coding_MSADPCM:
vgmstream->num_samples = msadpcm_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count);
vgmstream->num_samples = fact_sample_count ? fact_sample_count :
msadpcm_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count);
break;
case coding_MS_IMA:
vgmstream->num_samples = ms_ima_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count);
vgmstream->num_samples = fact_sample_count ? fact_sample_count :
ms_ima_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count);
break;
case coding_XBOX_IMA:
vgmstream->num_samples = fact_sample_count ? fact_sample_count :
xbox_ima_bytes_to_samples(data_size, fmt.channel_count);
break;
case coding_NGC_DSP:
if (!sns) goto fail;
if (fact_sample_count <= 0) goto fail;
@ -531,6 +547,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
switch (fmt.coding_type) {
case coding_MSADPCM:
case coding_MS_IMA:
case coding_XBOX_IMA:
#ifdef VGM_USE_FFMPEG
case coding_FFmpeg:
#endif

View File

@ -142,74 +142,44 @@ fail:
}
/* RSD2XADP */
VGMSTREAM * init_vgmstream_rsd2xadp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag, channel_count;
size_t data_size;
int loop_flag;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("rsd",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x52534432) /* RSD2 */
goto fail;
if (read_32bitBE(0x4,streamFile) != 0x58414450) /* XADP */
/* check extension */
if (!check_extensions(streamFile,"rsd"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x52534432) /* RSD2 */
goto fail;
if (read_32bitBE(0x04,streamFile) != 0x58414450) /* XADP */
goto fail;
start_offset = read_32bitLE(0x18,streamFile); /* not sure about this */
data_size = get_streamfile_size(streamFile);
loop_flag = 0;
channel_count = read_32bitLE(0x8,streamFile);
channel_count = read_32bitLE(0x08,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_32bitLE(0x18,streamFile); /* not sure about this */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)*64/36/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = loop_flag;
vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count;
}
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_RSD2XADP;
/* 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;
if (vgmstream->coding_type == coding_XBOX) {
vgmstream->layout_type=layout_none;
vgmstream->ch[i].channel_start_offset=start_offset;
} else {
vgmstream->ch[i].channel_start_offset=
start_offset+vgmstream->interleave_block_size*i;
}
vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset;
}
}
return vgmstream;
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}
@ -968,72 +938,44 @@ fail:
return NULL;
}
/* RSD6XADP */
/* RSD6XADP - from Crash Tag Team Racing (Xbox) */
VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag, channel_count;
size_t data_size;
int loop_flag;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("rsd",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */
goto fail;
if (read_32bitBE(0x4,streamFile) != 0x58414450) /* XADP */
/* check extension */
if (!check_extensions(streamFile,"rsd"))
goto fail;
if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */
goto fail;
if (read_32bitBE(0x4,streamFile) != 0x58414450) /* XADP */
goto fail;
start_offset = 0x800;
data_size = get_streamfile_size(streamFile) - start_offset;
loop_flag = 0;
channel_count = read_32bitLE(0x8,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 = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)*64/36/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = loop_flag;
vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count;
}
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;
/* 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;
if (vgmstream->coding_type == coding_XBOX) {
vgmstream->layout_type=layout_none;
vgmstream->ch[i].channel_start_offset=start_offset;
} else {
vgmstream->ch[i].channel_start_offset=
start_offset+vgmstream->interleave_block_size*i;
}
vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset;
}
}
return vgmstream;
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -189,13 +189,13 @@ VGMSTREAM * init_vgmstream_rws(STREAMFILE *streamFile) {
vgmstream->num_samples = dsp_bytes_to_samples(stream_size, channel_count);
break;
case 0x936538EF: /* MS-IMA PC (936538EF 11B62D43 957FA71A DE44227A) */
case 0x2BA22F63: /* MS-IMA Xbox (2BA22F63 DD118F45 AA27A5C3 46E9790E) */
case 0x936538EF: /* XBOX-IMA PC (936538EF 11B62D43 957FA71A DE44227A) */
case 0x2BA22F63: /* XBOX-IMA Xbox (2BA22F63 DD118F45 AA27A5C3 46E9790E) */
/* ex. Broken Sword 3 (PC), Jacked (PC/Xbox), Burnout 2 (Xbox) */
vgmstream->coding_type = coding_XBOX;
vgmstream->interleave_block_size = 0; /* uses regular XBOX/MS-IMA interleave */
vgmstream->coding_type = coding_XBOX_IMA; /* PC and Xbox share the same data */
vgmstream->interleave_block_size = 0;
vgmstream->num_samples = ms_ima_bytes_to_samples(stream_size, 0x24 * channel_count, channel_count);
vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, channel_count);
break;
default:

View File

@ -55,7 +55,7 @@ VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_SAB;
switch(codec) {
case 0x01:
case 0x01: /* PC */
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = is_stream ? align : 0x02;
@ -66,7 +66,7 @@ VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) {
break;
case 0x04:
case 0x04: /* PS2 */
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = is_stream ? align : 0x10;
@ -76,14 +76,14 @@ VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end, vgmstream->channels);
break;
case 0x08:
vgmstream->coding_type = is_stream ? coding_XBOX_int : coding_XBOX;
case 0x08: /* Xbox */
vgmstream->coding_type = is_stream ? coding_XBOX_IMA_int : coding_XBOX_IMA;
vgmstream->layout_type = is_stream ? layout_interleave : layout_none;
vgmstream->interleave_block_size = is_stream ? align : 0x00;
vgmstream->num_samples = ms_ima_bytes_to_samples(stream_size, 0x24*vgmstream->channels, vgmstream->channels);
vgmstream->loop_start_sample = ms_ima_bytes_to_samples(loop_start, 0x24*vgmstream->channels, vgmstream->channels);
vgmstream->loop_end_sample = ms_ima_bytes_to_samples(loop_end, 0x24*vgmstream->channels, vgmstream->channels);
vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, vgmstream->channels);
vgmstream->loop_start_sample = xbox_ima_bytes_to_samples(loop_start, vgmstream->channels);
vgmstream->loop_end_sample = xbox_ima_bytes_to_samples(loop_end, vgmstream->channels);
break;
default:

View File

@ -1,7 +1,8 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/* SEG (found in Eragon) */
/* SEG - found in Eragon */
VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
@ -24,7 +25,7 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
}
else if (read_32bitBE(0x04,streamFile) == 0x78627800) /* "xbx\0" */
{
coding = coding_XBOX;
coding = coding_XBOX_IMA;
}
else goto fail;
@ -60,9 +61,9 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = 0x2000;
}
}
else if (coding_XBOX == coding)
else if (coding_XBOX_IMA == coding)
{
vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)-start_offset)/36/channel_count*64;
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(0x0C,streamFile)-start_offset, channel_count);
vgmstream->meta_type = meta_XBOX_SEG;
vgmstream->layout_type = layout_none;
}

View File

@ -95,7 +95,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
/* type to coding conversion */
switch (txth.codec) {
case PSX: coding = coding_PSX; break;
case XBOX: coding = coding_XBOX; break;
case XBOX: coding = coding_XBOX_IMA; break;
case NGC_DTK: coding = coding_NGC_DTK; break;
case PCM16BE: coding = coding_PCM16BE; break;
case PCM16LE: coding = coding_PCM16LE; break;
@ -205,7 +205,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = txth.interleave;
vgmstream->layout_type = layout_none;
break;
case coding_XBOX:
case coding_XBOX_IMA:
vgmstream->layout_type = layout_none;
break;
case coding_NGC_DTK:
@ -634,7 +634,7 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) {
if (!txth->interleave) return 0;
return ms_ima_bytes_to_samples(bytes, txth->interleave, txth->channels);
case XBOX:
return ms_ima_bytes_to_samples(bytes, 0x24 * txth->channels, txth->channels);
return xbox_ima_bytes_to_samples(bytes, txth->channels);
case NGC_DSP:
return dsp_bytes_to_samples(bytes, txth->channels);
case PSX:

View File

@ -78,7 +78,8 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
switch(((uint64_t)platform << 32) | type) {
case 0x57696E2070636D20: /* "Win pcm " */
case 0x4F72626970636D20: /* "Orbipcm " (Orbis = PS4)*/
case 0x4F72626970636D20: /* "Orbipcm " (Orbis = PS4) */
case 0x4E78202070636D20: /* "Nx pcm " (Nx = Switch) */
/* chunks: "data" */
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
@ -162,7 +163,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
#endif
#ifdef VGM_USE_ATRAC9
case 0x5649544161743920: { /*"VITAat9 "*/
case 0x5649544161743920: { /* "VITAat9 " */
/* chunks: "fact" (equivalent to a RIFF "fact", num_samples + skip_samples), "data" */
atrac9_config cfg = {0};
@ -181,6 +182,48 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE *streamFile) {
}
#endif
#ifdef VGM_USE_FFMPEG
case 0x4E7820204E782020: { /* "Nx Nx " */
/* chunks: "MARK" (optional seek table), "STRG" (optional description) */
uint8_t buf[0x100];
size_t bytes, skip, opus_size;
ffmpeg_custom_config cfg = {0};
/* a standard Switch Opus header */
skip = read_32bitLE(start_offset + 0x1c, streamFile);
opus_size = read_32bitLE(start_offset + 0x10, streamFile) + 0x08;
start_offset += opus_size;
data_size -= opus_size;
cfg.type = FFMPEG_SWITCH_OPUS;
bytes = ffmpeg_make_opus_header(buf,0x100, vgmstream->channels, skip, vgmstream->sample_rate);
if (bytes <= 0) goto fail;
vgmstream->codec_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,data_size, &cfg);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
if (((ffmpeg_codec_data*)vgmstream->codec_data)->skipSamples <= 0)
ffmpeg_set_skip_samples(vgmstream->codec_data, skip);
{
off_t chunk_offset = off + 0x20 + 0xc; /* after "fmt" */
while (chunk_offset < header_size) {
if (read_32bitBE(chunk_offset,streamFile) == 0x4164496E) { /*"AdIn" additional info */
off_t adin_offset = read_32bitLE(chunk_offset+0x04,streamFile);
vgmstream->num_samples = read_32bitLE(adin_offset,streamFile);
break;
}
chunk_offset += 0xc;
}
}
break;
}
#endif
default:
VGM_LOG("RAKI: unknown platform %x and type %x\n", platform, type);
goto fail;

View File

@ -119,6 +119,7 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
start_offset = sb.main_size + sb.section1_size + sb.section2_size + sb.extra_size + sb.section3_size;
start_offset += sb.stream_offset;
}
//;VGM_LOG("start offset=%lx, external=%i\n", start_offset, sb.is_external);
/* build the VGMSTREAM */
@ -154,9 +155,9 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
break;
case RAW_XBOX:
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = ms_ima_bytes_to_samples(sb.stream_size, 0x24*sb.channels,sb.channels);
vgmstream->num_samples = xbox_ima_bytes_to_samples(sb.stream_size, sb.channels);
break;
case RAW_DSP:
@ -886,5 +887,21 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
return 1;
}
/* Surf's Up (2007)(PC) */
if (sb->version == 0x00190005 && is_sb0) {
sb->section1_entry_size = 0x68;
sb->section2_entry_size = 0x74;
sb->external_flag_offset = 0x28; /* maybe 0x2c */
sb->channels_offset = 0x3c;
sb->sample_rate_offset = 0x40;
sb->num_samples_offset = 0x48;
sb->stream_type_offset = 0x5c;
sb->extra_name_offset = 0x58;
sb->has_extra_name_flag = 1;
return 1;
}
return 0;
}

View File

@ -1,146 +1,146 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/*
const short wad_coef[16][2] =
{
{0x4002,0x2003},
{0x2016,0xc600},
{0xC600,0x98ab},
{0x96bf,0x29c5},
{0x2003,0x0081},
{0x0e00,0x2004},
{0x8e01,0xc500},
{0x70bf,0x8128},
{0x288e,0xc600},
{0x016e,0x0e5b},
{0xbe20,0x2003},
{0x03c6,0xc600},
{0x0048,0xe85a},
{0xbe28,0x28c6},
{0xc600,0x00F6},
{0xbeab,0x5520}
{0x4002,0x2003},
{0x2016,0xc600},
{0xC600,0x98ab},
{0x96bf,0x29c5},
{0x2003,0x0081},
{0x0e00,0x2004},
{0x8e01,0xc500},
{0x70bf,0x8128},
{0x288e,0xc600},
{0x016e,0x0e5b},
{0xbe20,0x2003},
{0x03c6,0xc600},
{0x0048,0xe85a},
{0xbe28,0x28c6},
{0xc600,0x00F6},
{0xbeab,0x5520}
};*/
const short wad_coef[16] =
{
0x04ab, 0xfced,
0x0789, 0xfedf,
0x09a2, 0xfae5,
0x0c90, 0xfac1,
0x084d, 0xfaa4,
0x0982, 0xfdf7,
0x0af6, 0xfafa,
0x0be6, 0xfbf5
0x04ab, 0xfced,
0x0789, 0xfedf,
0x09a2, 0xfae5,
0x0c90, 0xfac1,
0x084d, 0xfaa4,
0x0982, 0xfdf7,
0x0af6, 0xfafa,
0x0be6, 0xfbf5
};
/* WAC - WAD - WAM (Beyond Good & Evil GC/PS2/Xbox/Wii) */
/* Note: A "Flat Layout" has no interleave */
/* WAC/WAD/WAM/WAA - from Beyond Good & Evil (PS2/Xbox/GC/Wii) */
VGMSTREAM * init_vgmstream_waa_wac_wad_wam(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int i;
int i;
off_t start_offset;
int loop_flag;
int channel_count;
int coef1_start;
int coef2_start;
int second_channel_start = -1;
int channel_count;
int coef1_start;
int coef2_start;
int second_channel_start = -1;
// Check file extensions
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("waa",filename_extension(filename)) &&
strcasecmp("wac",filename_extension(filename)) &&
strcasecmp("wad",filename_extension(filename)) &&
strcasecmp("wam",filename_extension(filename))) goto fail;
strcasecmp("wac",filename_extension(filename)) &&
strcasecmp("wad",filename_extension(filename)) &&
strcasecmp("wam",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x52494646 || /* "RIFF" */
read_32bitBE(0x08,streamFile) != 0x57415645 || /* "WAVE" */
read_32bitBE(0x0C,streamFile) != 0x666D7420 || /* "fmt\0x20" */
read_32bitBE(0x10,streamFile) != 0x12000000) /* "0x12000000" */
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x52494646 || /* "RIFF" */
read_32bitBE(0x08,streamFile) != 0x57415645 || /* "WAVE" */
read_32bitBE(0x0C,streamFile) != 0x666D7420 || /* "fmt " */
read_32bitBE(0x10,streamFile) != 0x12000000) /* "0x12000000" */
goto fail;
/* files don't contain looping information,
so the looping is not done depending on extension.
wam and waa contain ambient sounds and music, so often they contain
looped music. Change extension to wac or wad to make the sound non-looping.
*/
/* files don't contain looping information,
so the looping is not done depending on extension.
wam and waa contain ambient sounds and music, so often they contain
looped music. Change extension to wac or wad to make the sound non-looping.
*/
loop_flag = strcasecmp("wac",filename_extension(filename)) &&
strcasecmp("wad",filename_extension(filename));
strcasecmp("wad",filename_extension(filename));
channel_count = (uint16_t)read_16bitLE(0x16,streamFile);
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* Check what encoder is needed */
//FIXME: //PC version uses pcm, but which encoder?
/* Check what encoder is needed */
//FIXME: //PC version uses pcm, but which encoder?
vgmstream->channels = channel_count;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x18,streamFile);
vgmstream->meta_type = meta_WAA_WAC_WAD_WAM;
vgmstream->meta_type = meta_WAA_WAC_WAD_WAM;
vgmstream->layout_type = layout_none;
switch((uint16_t)read_16bitLE(0x14,streamFile)) {
switch((uint16_t)read_16bitLE(0x14,streamFile)) {
case 0x0069: // XBOX IMA ADPCM
start_offset = 0x2E;
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))/36/channel_count*64;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))/36/channel_count*64;
}
start_offset = 0x2E;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(0x2A,streamFile), channel_count);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = xbox_ima_bytes_to_samples(read_32bitLE(0x2A,streamFile),channel_count);
}
break;
case 0xFFFF: // PS2 ADPCM
start_offset = 0x2E;
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))/16*28/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))/16*28/channel_count;
}
start_offset = 0x2E;
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))/16*28/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))/16*28/channel_count;
}
second_channel_start = (read_32bitLE(0x2A,streamFile)/2)+start_offset;
break;
case 0xFFFE: // GameCube/WII DSP
start_offset = 0x5C;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))*14/8/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))*14/8/channel_count;
}
if(read_16bitLE(0x24,streamFile)==0x00)//is a wii file with no coeff table
{
//FIXME: WII version of WAM/WAD/WAC need some coeff table from somewhere
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i] = wad_coef[i];
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = wad_coef[i];
}
goto fail;
}
else
{
second_channel_start = (read_32bitLE(0x2A,streamFile)/2)+0x8A;
/* Retrieveing the coef tables */
coef1_start = 0x2E;
coef2_start = (read_32bitLE(0x2A,streamFile)/2)+0x5C;
start_offset = 0x5C;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))*14/8/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))*14/8/channel_count;
}
if(read_16bitLE(0x24,streamFile)==0x00)//is a wii file with no coeff table
{
//FIXME: WII version of WAM/WAD/WAC need some coeff table from somewhere
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i] = wad_coef[i];
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = wad_coef[i];
}
goto fail;
}
else
{
second_channel_start = (read_32bitLE(0x2A,streamFile)/2)+0x8A;
/* Retrieveing the coef tables */
coef1_start = 0x2E;
coef2_start = (read_32bitLE(0x2A,streamFile)/2)+0x5C;
{
int i;
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(coef1_start+i*2,streamFile);
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(coef2_start+i*2,streamFile);
}
}
}
{
int i;
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(coef1_start+i*2,streamFile);
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(coef2_start+i*2,streamFile);
}
}
}
break;
default:
goto fail;
}
default:
goto fail;
}
@ -154,7 +154,7 @@ VGMSTREAM * init_vgmstream_waa_wac_wad_wam(STREAMFILE *streamFile) {
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
if (vgmstream->coding_type == coding_XBOX) {
if (vgmstream->coding_type == coding_XBOX_IMA) {
/* xbox interleaving is a little odd */
vgmstream->ch[i].channel_start_offset=start_offset;
} else {

View File

@ -1,68 +1,50 @@
#include "meta.h"
#include "../util.h"
/*
WVS (found in Metal Arms - Glitch in the System)
XBOX and GameCube
*/
#include "../coding/coding.h"
/* WVS - found in Metal Arms - Glitch in the System (Xbox) */
VGMSTREAM * init_vgmstream_xbox_wvs(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag, channel_count;
size_t data_size;
int loop_flag=0;
int channel_count;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("wvs",filename_extension(filename))) goto fail;
/* check extension */
if (!check_extensions(streamFile,"wvs"))
goto fail;
if((read_16bitLE(0x0C,streamFile)!=0x69) &&
(read_16bitLE(0x08,streamFile)!=0x4400) &&
(read_32bitLE(0x0,streamFile)!=get_streamfile_size(streamFile)+0x20))
goto fail;
if (read_16bitLE(0x0C,streamFile) != 0x69 && /* codec */
read_16bitLE(0x08,streamFile) != 0x4400)
goto fail;
/* Loop seems to be set if offset(0x0A) == 0x472C */
loop_flag = (read_16bitLE(0x0A,streamFile)==0x472C);
start_offset = 0x20;
data_size = read_32bitLE(0x00,streamFile);
loop_flag = (read_16bitLE(0x0a,streamFile) == 0x472C); /* loop seems to be like this */
channel_count = read_16bitLE(0x0e,streamFile); /* always stereo files */
/* Always stereo files */
channel_count=read_16bitLE(0x0E,streamFile);
/* build the VGMSTREAM */
if (data_size + start_offset != get_streamfile_size(streamFile))
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
/* allways 2 channels @ 44100 Hz */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = read_32bitLE(0,streamFile) / 36 * 64 / vgmstream->channels;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_XBOX_WVS;
if(loop_flag) {
vgmstream->loop_start_sample=0;
vgmstream->loop_end_sample=vgmstream->num_samples;
}
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = 0x20;
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
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;
}
@ -75,7 +57,7 @@ VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -94,7 +76,7 @@ VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile) {
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
/* fill in the vital statistics */
start_offset = 0x60;
if (channel_count == 1) {
@ -103,8 +85,8 @@ VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile) {
vgmstream->sample_rate = 44100;
}
vgmstream->channels = channel_count;
vgmstream->channels = channel_count;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/8/channel_count*14; //(read_32bitBE(0x0C,streamFile)-start_offset)/8/channel_count*14;
if (loop_flag) {

View File

@ -194,11 +194,12 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
break;
case IMA: /* common */
/* slightly modified MS IMA with interleaved sub-blocks and LE/BE header */
/* slightly modified XBOX-IMA with interleaved sub-blocks and LE/BE header */
/* Wwise uses common codecs (ex. 0x0002 MSADPCM) so this parser should go AFTER riff.c avoid misdetection */
if (ww.bits_per_sample != 4) goto fail;
if (ww.block_align != 0x24 * ww.channels) goto fail;
vgmstream->coding_type = coding_WWISE_IMA;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = ww.block_align;
@ -207,7 +208,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
if (ww.truncated) /* enough to get real samples */
ww.data_size = ww.file_size - ww.data_offset;
vgmstream->num_samples = ms_ima_bytes_to_samples(ww.data_size, ww.block_align, ww.channels);
vgmstream->num_samples = xbox_ima_bytes_to_samples(ww.data_size, ww.channels);
break;
#ifdef VGM_USE_VORBIS

View File

@ -58,11 +58,11 @@ VGMSTREAM * init_vgmstream_xau(STREAMFILE *streamFile) {
goto fail;
vgmstream->sample_rate = read_32bitLE(0x58, streamFile);
vgmstream->num_samples = ms_ima_bytes_to_samples(read_32bitLE(start_offset-4, streamFile), read_16bitLE(0x60, streamFile), channel_count);
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(start_offset-4, streamFile), channel_count);
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
break;

View File

@ -29,8 +29,8 @@ VGMSTREAM * init_vgmstream_xbox_matx(STREAMFILE *streamFile) {
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_16bitLE(0x06,streamFile) & 0xffff;
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_matx_blocked;
vgmstream->meta_type = meta_XBOX_MATX;

View File

@ -1,62 +1,37 @@
#include "meta.h"
#include "../util.h"
/* WAVM
WAVM is an headerless format which can be found on XBOX
known extensions : WAVM
2008-05-23 - Fastelbja : First version ...
*/
#include "../coding/coding.h"
/* WAVM - headerless format which can be found on XBOX */
VGMSTREAM * init_vgmstream_xbox_wavm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset = 0;
int loop_flag, channel_count;
int loop_flag=0;
int channel_count;
int i;
/* check extension */
if (!check_extensions(streamFile,"wavm"))
goto fail;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("wavm",filename_extension(filename))) goto fail;
/* No loop on wavm */
loop_flag = 0;
start_offset = 0;
loop_flag = 0;
channel_count = 2;
/* Always stereo files */
channel_count=2;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
/* allways 2 channels @ 44100 Hz */
vgmstream->channels = 2;
vgmstream->sample_rate = 44100;
vgmstream->num_samples = xbox_ima_bytes_to_samples(get_streamfile_size(streamFile), vgmstream->channels);
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile) / 36 * 64 / vgmstream->channels);
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_XBOX_WAVM;
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = 0;
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
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,65 +1,44 @@
#include "meta.h"
#include "../util.h"
/* XMU
XMU (found in Alter Echo)
*/
#include "../coding/coding.h"
/* XMU- found in Alter Echo (Xbox) */
VGMSTREAM * init_vgmstream_xbox_xmu(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
size_t start_offset;
int loop_flag, channel_count;
size_t data_size;
int loop_flag=0;
int channel_count;
int i;
/* check extension */
if (!check_extensions(streamFile,"xmu"))
goto fail;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("xmu",filename_extension(filename))) goto fail;
if (read_32bitBE(0x00,streamFile) != 0x584D5520 && /* "XMU " */
read_32bitBE(0x08,streamFile) != 0x46524D54) /* "FRMT" */
goto fail;
if((read_32bitBE(0x00,streamFile)!=0x584D5520) &&
(read_32bitBE(0x08,streamFile)!=0x46524D54))
goto fail;
start_offset = 0x800;
channel_count=read_8bit(0x14,streamFile); /* always stereo files */
loop_flag = read_8bit(0x16,streamFile); /* no Loop found atm */
data_size = read_32bitLE(0x7FC,streamFile); /* next to "DATA" */
/* No Loop found atm */
loop_flag = read_8bit(0x16,streamFile);;
/* Always stereo files */
channel_count=read_8bit(0x14,streamFile);
/* build the VGMSTREAM */
/* 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(0x10,streamFile);
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = read_32bitLE(0x7FC,streamFile) / 36 * 64 / vgmstream->channels;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_XBOX_XMU;
if(loop_flag) {
vgmstream->loop_start_sample=0;
vgmstream->loop_end_sample=vgmstream->num_samples;
}
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = 0x800;
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
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,72 +1,52 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
/* XVAS
XVAS (found in TMNT 2 & TMNT 3))
*/
#include "../coding/coding.h"
/* XVAS - found in TMNT 2 & TMNT 3 (Xbox) */
VGMSTREAM * init_vgmstream_xbox_xvas(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag, channel_count;
size_t data_size;
int loop_flag=0;
int channel_count;
int i;
/* check extension */
if (!check_extensions(streamFile,"xvas"))
goto fail;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("xvas",filename_extension(filename))) goto fail;
if (read_32bitLE(0x00,streamFile) != 0x69 && /* codec */
read_32bitLE(0x08,streamFile) != 0x48) /* block size (probably 0x24 for mono) */
goto fail;
if((read_32bitLE(0x00,streamFile)!=0x69) &&
(read_32bitLE(0x08,streamFile)!=0x48))
goto fail;
start_offset = 0x800;
channel_count = read_32bitLE(0x04,streamFile); /* always stereo files */
loop_flag = (read_32bitLE(0x14,streamFile) == read_32bitLE(0x24,streamFile));
data_size = read_32bitLE(0x24,streamFile);
data_size -= (data_size / 0x20000) * 0x20; /* blocks of 0x20000 with padding */
/* No Loop found atm */
loop_flag = (read_32bitLE(0x14,streamFile)==read_32bitLE(0x24,streamFile));
/* Always stereo files */
channel_count=read_32bitLE(0x04,streamFile);
/* build the VGMSTREAM */
/* 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(0x0c,streamFile);
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
if(loop_flag) {
size_t loop_size = read_32bitLE(0x10,streamFile);
loop_size -= (loop_size / 0x20000) * 0x20;
vgmstream->loop_start_sample = xbox_ima_bytes_to_samples(loop_size, vgmstream->channels);
vgmstream->loop_end_sample = vgmstream->num_samples;
}
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = read_32bitLE(0x24,streamFile);
vgmstream->num_samples -= ((vgmstream->num_samples/0x20000)*0x20);
vgmstream->num_samples = vgmstream->num_samples / 36 * 64 / vgmstream->channels;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_xvas_blocked;
vgmstream->meta_type = meta_XBOX_XVAS;
if(loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x10,streamFile);
vgmstream->loop_start_sample -= ((vgmstream->loop_start_sample/0x20000)*0x20);
vgmstream->loop_start_sample = vgmstream->loop_start_sample / 36 * 64 / vgmstream->channels;
vgmstream->loop_end_sample=vgmstream->num_samples;
}
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = 0x800;
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
xvas_block_update(0x800,vgmstream);
xvas_block_update(start_offset,vgmstream);
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,107 +1,91 @@
#include "meta.h"
#include "../util.h"
/* XWAV
XWAV use the common RIFF/WAVE format with Codec ID = 0x0069
It has been renamed to xwav to avoid vgmstream to handle all RIFF/WAV format
known extensions : XWAV
2008-05-24 - Fastelbja : First version ...
*/
#include "../coding/coding.h"
/* XWAV - renamed WAV with XBOX-IMA
* (could be parsed as RIFF/.lwav but has a custom loop chunk and multichannel) */
VGMSTREAM * init_vgmstream_xbox_xwav(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag=0;
int channel_count;
int loop_flag, channel_count;
off_t start_offset;
int i,j=0;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("xwav",filename_extension(filename))) goto fail;
/* check extension */
if (!check_extensions(streamFile,"xwav"))
goto fail;
/* Check for headers */
if(!((read_32bitBE(0x00,streamFile)==0x52494646) &&
(read_32bitBE(0x08,streamFile)==0x57415645) &&
(read_32bitBE(0x0C,streamFile)==0x666D7420) &&
(read_16bitLE(0x14,streamFile)==0x0069)))
goto fail;
/* check for headers */
if(!((read_32bitBE(0x00,streamFile) == 0x52494646) && /* "RIFF" */
(read_32bitBE(0x08,streamFile) == 0x57415645) && /* "WAVE" */
(read_32bitBE(0x0C,streamFile) == 0x666D7420) && /* "fmt " */
(read_16bitLE(0x14,streamFile) == 0x0069))) /* codec */
goto fail;
/* No loop on wavm */
if(read_32bitBE(0x28,streamFile)==0x77736D70)
loop_flag = 1;
else
loop_flag = 0;
/* Always stereo files */
channel_count=read_16bitLE(0x16,streamFile);
/* build the VGMSTREAM */
/* loop chunk found on Koei/Omega Force games [Crimson Sea, Dynasty Warriors 5] */
loop_flag = (read_32bitBE(0x28,streamFile) == 0x77736D70); /* "wsmp" */
channel_count = read_16bitLE(0x16,streamFile);
/* search for "data" */
start_offset = 0x1C;
do {
if (read_32bitBE(start_offset,streamFile)==0x64617461)
break;
start_offset += 0x04;
} while (start_offset < (off_t)get_streamfile_size(streamFile));
if (start_offset >= (off_t)get_streamfile_size(streamFile))
goto fail;
start_offset += 0x04;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* hack for loop wave found on Dynasty warriors */
if(loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x4C,streamFile);
vgmstream->loop_end_sample = vgmstream->loop_start_sample + read_32bitLE(0x50,streamFile);
}
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(start_offset,streamFile), vgmstream->channels);
vgmstream->sample_rate = read_32bitLE(0x18,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x4C,streamFile);
vgmstream->loop_end_sample = vgmstream->loop_start_sample + read_32bitLE(0x50,streamFile);
}
/* search for "data" */
start_offset=0x1C;
do {
if(read_32bitBE(start_offset,streamFile)==0x64617461)
break;
start_offset+=4;
} while (start_offset<(off_t)get_streamfile_size(streamFile));
if(start_offset>=(off_t)get_streamfile_size(streamFile))
goto fail;
start_offset+=4;
vgmstream->coding_type = coding_XBOX;
vgmstream->num_samples = read_32bitLE(start_offset,streamFile) / 36 * 64 / vgmstream->channels;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_XBOX_RIFF;
/* open the file for reading by each channel */
//if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
// goto fail;
//custom init
{
if(channel_count>2) {
for (i=0;i<channel_count;i++,j++) {
if((j&2) && (i!=0)) {
j=0;
start_offset+=36*2;
}
int i, ch;
char filename[PATH_LIMIT];
streamFile->get_name(streamFile,filename,sizeof(filename));
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = start_offset+4;
if (channel_count > 2) { /* multichannel interleaved init */
for (i=0, ch=0;i<channel_count;i++,ch++) {
if ((ch&2) && (i!=0)) {
ch = 0;
start_offset += 0x24*2;
}
if (!vgmstream->ch[i].streamfile) goto fail;
}
} else {
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
vgmstream->ch[i].offset = start_offset+4;
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x24);
vgmstream->ch[i].offset = start_offset + 0x04;
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
else {
for (i=0; i < channel_count; i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x24);
vgmstream->ch[i].offset = start_offset + 0x04;
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -19,7 +19,8 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) {
if ((read_32bitBE(0,streamFile) & 0xFFFFFF00) != 0x584E4200) /* "XNB" */
goto fail;
/* 0x04: platform: w = Windows, m = Windows Phone 7, x = X360, 'a' = Android, 'P': PS4 */
/* XNA Studio platforms: 'w' = Windows, 'm' = Windows Phone 7, 'x' = X360
* MonoGame extensions: 'i' = iOS, 'a' = Android, 'X' = MacOSX, 'P': PS4, etc */
platform = read_8bit(0x03,streamFile);
big_endian = (platform == 'x');
@ -28,8 +29,8 @@ VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) {
flags = read_8bit(0x05,streamFile);
//if (flags & 0x01) goto fail; /* "HiDef profile" content (no actual difference) */
if (flags & 0x80) goto fail; /* compressed with XMemCompress (at 0x0a is decompressed size) */
if (flags & 0x40) goto fail; /* custom compression? seen in Square Heroes (PS4) */
if (flags & 0x80) goto fail; /* compressed with LZX/XMemCompress (at 0x0a is decompressed size) */
if (flags & 0x40) goto fail; /* compressed with LZ4, MonoGame extension [ex. Square Heroes (PS4)] */
/* full size */
if (read_32bitLE(0x06,streamFile) != get_streamfile_size(streamFile))

View File

@ -295,11 +295,11 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
}
}
else if (xwb.version <= XACT1_1_MAX && xwb.codec == XBOX_ADPCM) {
xwb.block_align = 0x24 * xwb.channels;
xwb.num_samples = ms_ima_bytes_to_samples(xwb.stream_size, xwb.block_align, xwb.channels);
xwb.block_align = 0x24 * xwb.channels; /* not really needed... */
xwb.num_samples = xbox_ima_bytes_to_samples(xwb.stream_size, xwb.channels);
if (xwb.loop_flag) {
xwb.loop_start_sample = ms_ima_bytes_to_samples(xwb.loop_start, xwb.block_align, xwb.channels);
xwb.loop_end_sample = ms_ima_bytes_to_samples(xwb.loop_start + xwb.loop_end, xwb.block_align, xwb.channels);
xwb.loop_start_sample = xbox_ima_bytes_to_samples(xwb.loop_start, xwb.channels);
xwb.loop_end_sample = xbox_ima_bytes_to_samples(xwb.loop_start + xwb.loop_end, xwb.channels);
}
}
else if (xwb.version <= XACT2_2_MAX && xwb.codec == MS_ADPCM && xwb.loop_flag) {
@ -367,7 +367,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
break;
case XBOX_ADPCM: /* Silent Hill 4 (Xbox) */
vgmstream->coding_type = coding_XBOX;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
break;

View File

@ -265,7 +265,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_ps2_adsc,
init_vgmstream_ngc_dsp_mpds,
init_vgmstream_dsp_str_ig,
init_vgmstream_psx_mgav,
init_vgmstream_ea_swvr,
init_vgmstream_ngc_dsp_sth_str1,
init_vgmstream_ngc_dsp_sth_str2,
init_vgmstream_ngc_dsp_sth_str3,
@ -968,7 +968,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
case layout_thp_blocked:
case layout_filp_blocked:
case layout_blocked_ivaud:
case layout_psx_mgav_blocked:
case layout_blocked_ea_swvr:
case layout_ps2_adm_blocked:
case layout_dsp_bdsp_blocked:
case layout_tra_blocked:
@ -1010,11 +1010,17 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_CRI_ADX_enc_8:
case coding_CRI_ADX_enc_9:
return (vgmstream->interleave_block_size - 2) * 2;
case coding_L5_555:
return 32;
case coding_NGC_DSP:
case coding_NGC_DSP_subint:
return 14;
case coding_NGC_AFC:
return 16;
case coding_NGC_DTK:
return 28;
case coding_G721:
return 1;
case coding_PCM16LE:
case coding_PCM16LE_XOR_int:
case coding_PCM16BE:
@ -1052,12 +1058,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_NWA5:
case coding_SASSC:
return 1;
case coding_NDS_IMA:
case coding_DAT4_IMA:
return (vgmstream->interleave_block_size-4)*2;
case coding_NGC_DTK:
return 28;
case coding_G721:
case coding_IMA:
case coding_DVI_IMA:
case coding_SNDS_IMA:
@ -1067,22 +1068,36 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_IMA_int:
case coding_DVI_IMA_int:
case coding_3DS_IMA:
case coding_AICA:
return 2;
case coding_NGC_AFC:
return 16;
case coding_XBOX_IMA:
case coding_XBOX_IMA_int:
case coding_FSB_IMA:
return 64;
case coding_APPLE_IMA4:
return 64;
case coding_MS_IMA:
case coding_REF_IMA:
return ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;
case coding_RAD_IMA:
case coding_WWISE_IMA:
return (vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels;
case coding_NDS_IMA:
case coding_DAT4_IMA:
return (vgmstream->interleave_block_size - 0x04) * 2;
case coding_AWC_IMA:
return (0x800 - 0x04) * 2;
case coding_RAD_IMA_mono:
return 32;
case coding_XA:
case coding_PSX:
case coding_PSX_badflags:
case coding_PSX_bmdx:
case coding_HEVAG:
case coding_XA:
return 28;
case coding_PSX_cfg:
return (vgmstream->interleave_block_size - 1) * 2; /* decodes 1 byte into 2 bytes */
case coding_XBOX:
case coding_XBOX_int:
case coding_FSB_IMA:
return 64;
case coding_EA_XA:
case coding_EA_XA_int:
case coding_EA_XA_V2:
@ -1090,24 +1105,20 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
return 28;
case coding_EA_XAS:
return 128;
case coding_WS:
/* only works if output sample size is 8 bit, which always is for WS ADPCM */
return vgmstream->ws_output_size;
case coding_MSADPCM:
return (vgmstream->interleave_block_size-(7-1)*vgmstream->channels)*2/vgmstream->channels;
case coding_APPLE_IMA4:
return 64;
case coding_MS_IMA:
case coding_RAD_IMA:
case coding_WWISE_IMA:
case coding_REF_IMA:
return (vgmstream->interleave_block_size-4*vgmstream->channels)*2/vgmstream->channels;
case coding_AWC_IMA:
return (0x800-4)*2;
case coding_RAD_IMA_mono:
return 32;
case coding_WS: /* only works if output sample size is 8 bit, which always is for WS ADPCM */
return vgmstream->ws_output_size;
case coding_AICA:
return 2;
case coding_NDS_PROCYON:
return 30;
case coding_L5_555:
return 32;
case coding_LSF:
return 54;
#ifdef VGM_USE_G7221
case coding_G7221C:
return 32000/50;
@ -1120,18 +1131,15 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
#endif
#ifdef VGM_USE_FFMPEG
case coding_FFmpeg:
{
ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data;
if (data) {
/* must know the full block size for edge loops */
return data->sampleBufferBlock;
if (vgmstream->codec_data) {
ffmpeg_codec_data *data = (ffmpeg_codec_data*)vgmstream->codec_data;
return data->sampleBufferBlock; /* must know the full block size for edge loops */
}
else {
return 0;
}
return 0;
}
break;
#endif
case coding_LSF:
return 54;
case coding_MTAF:
return 128*2;
case coding_MTA2:
@ -1168,17 +1176,23 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_CRI_ADX_enc_8:
case coding_CRI_ADX_enc_9:
return vgmstream->interleave_block_size;
case coding_L5_555:
return 18;
case coding_NGC_DSP:
return 0x08;
case coding_NGC_DSP_subint:
return 0x08 * vgmstream->channels;
case coding_NGC_AFC:
return 0x09;
case coding_NGC_DTK:
return 0x20;
case coding_G721:
return 0;
case coding_PCM16LE:
case coding_PCM16LE_XOR_int:
case coding_PCM16BE:
case coding_PCM16_int:
return 2;
return 0x02;
case coding_PCM8:
case coding_PCM8_U:
case coding_PCM8_int:
@ -1187,9 +1201,10 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_ULAW:
case coding_ULAW_int:
case coding_ALAW:
return 1;
return 0x01;
case coding_PCMFLOAT:
return 4;
return 0x04;
case coding_SDX2:
case coding_SDX2_int:
case coding_CBD2:
@ -1200,7 +1215,14 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_NWA4:
case coding_NWA5:
case coding_SASSC:
return 1;
return 0x01;
case coding_IMA:
case coding_IMA_int:
case coding_DVI_IMA:
case coding_DVI_IMA_int:
case coding_3DS_IMA:
return 0x01;
case coding_MS_IMA:
case coding_RAD_IMA:
case coding_NDS_IMA:
@ -1212,30 +1234,28 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
return 0x800;
case coding_RAD_IMA_mono:
return 0x14;
case coding_NGC_DTK:
return 32;
case coding_G721:
case coding_SNDS_IMA:
case coding_OTNS_IMA:
return 0;
case coding_UBI_IMA: /* variable (PCM then IMA) */
return 0;
case coding_NGC_AFC:
return 9;
case coding_XBOX_IMA:
case coding_XBOX_IMA_int:
case coding_FSB_IMA:
return 0x24;
case coding_APPLE_IMA4:
return 0x22;
case coding_XA:
return 0x0e*vgmstream->channels;
case coding_PSX:
case coding_PSX_badflags:
case coding_PSX_bmdx:
case coding_HEVAG:
case coding_NDS_PROCYON:
return 16;
return 0x10;
case coding_PSX_cfg:
return vgmstream->interleave_block_size;
case coding_XA:
return 14*vgmstream->channels;
case coding_XBOX:
case coding_XBOX_int:
case coding_FSB_IMA:
return 36;
case coding_EA_XA:
return 0x1E;
case coding_EA_XA_int:
@ -1246,20 +1266,20 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
return 0; /* variable (ADPCM frames of 0x0f or PCM frames of 0x3d) */
case coding_EA_XAS:
return 0x4c*vgmstream->channels;
case coding_MSADPCM:
return vgmstream->interleave_block_size;
case coding_WS:
return vgmstream->current_block_size;
case coding_IMA:
case coding_IMA_int:
case coding_DVI_IMA:
case coding_DVI_IMA_int:
case coding_3DS_IMA:
return 0x01;
case coding_AICA:
return 1;
case coding_APPLE_IMA4:
return 34;
return 0x01;
case coding_NDS_PROCYON:
return 0x10;
case coding_L5_555:
return 0x12;
case coding_LSF:
return 28;
return 0x1C;
#ifdef VGM_USE_G7221
case coding_G7221C:
case coding_G7221:
@ -1273,7 +1293,6 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
#ifdef VGM_USE_FFMPEG
case coding_FFmpeg:
#endif
case coding_MSADPCM:
case coding_MTAF:
return vgmstream->interleave_block_size;
case coding_MTA2:
@ -1286,7 +1305,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_ATRAC9:
return 0; /* varies with config data, usually 0x100-200 */
#endif
default:
default: /* Vorbis, MPEG, ACM, etc */
return 0;
}
}
@ -1475,14 +1494,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do);
}
break;
case coding_XBOX:
case coding_XBOX_IMA:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_xbox_ima(vgmstream,&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do,chan);
}
break;
case coding_XBOX_int:
case coding_XBOX_IMA_int:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_xbox_ima_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,

View File

@ -127,8 +127,8 @@ typedef enum {
coding_DVI_IMA_int, /* DVI IMA ADPCM (mono/interleave, high nibble first) */
coding_3DS_IMA, /* 3DS IMA ADPCM */
coding_MS_IMA, /* Microsoft IMA ADPCM */
coding_XBOX, /* XBOX IMA ADPCM */
coding_XBOX_int, /* XBOX IMA ADPCM (interleaved) */
coding_XBOX_IMA, /* XBOX IMA ADPCM */
coding_XBOX_IMA_int, /* XBOX IMA ADPCM (interleaved/mono) */
coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */
coding_DAT4_IMA, /* Eurocom 'DAT4' IMA ADPCM */
coding_RAD_IMA, /* Radical IMA ADPCM */
@ -237,7 +237,7 @@ typedef enum {
layout_gsb_blocked,
layout_thp_blocked,
layout_filp_blocked,
layout_psx_mgav_blocked,
layout_blocked_ea_swvr,
layout_ps2_adm_blocked,
layout_dsp_bdsp_blocked,
layout_mxch_blocked,
@ -544,7 +544,7 @@ typedef enum {
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 */
meta_PSX_MGAV, /* Future Cop L.A.P.D. */
meta_EA_SWVR, /* Future Cop L.A.P.D., Freekstyle */
meta_NGC_DSP_STH_STR, /* SpongeBob Squarepants (NGC), Taz Wanted (NGC), Cubix (NGC), Tak (WII)*/
meta_PS2_B1S, /* 7 Wonders of the ancient world */
meta_PS2_WAD, /* The golden Compass */
@ -659,6 +659,7 @@ typedef enum {
meta_XWC, /* Starbreeze games */
meta_SQEX_SAB, /* Square-Enix newest middleware (sound) */
meta_SQEX_MAB, /* Square-Enix newest middleware (music) */
meta_OGG_L2SD, /* Ogg Vorbis with obfuscation [Lineage II Chronicle 4 (PC)] */
#ifdef VGM_USE_MP4V2
meta_MP4, /* AAC (iOS) */