Updated VGMStream to r1050-1391-g4ed16da3.

CQTexperiment
Christopher Snowhill 2018-07-14 18:36:08 -07:00
parent ccf4b1506b
commit a6efe31256
30 changed files with 708 additions and 473 deletions

View File

@ -1,66 +1,93 @@
#include "coding.h"
#include "../util.h"
const int SH = 4;
const int SHC = 10;
// todo this is based on Kazzuya's old code; different emus (PCSX, Mame, Mednafen, etc) do
// XA coefs int math in different ways (see comments below), so may not be 100% accurate.
// May be implemented like the SNES/SPC700 BRR (per-filter code?).
double K0[4] = { 0.0, 0.9375, 1.796875, 1.53125};
double K1[4] = { 0.0, 0.0, -0.8125,-0.859375};
static int IK0(int fid)
{ return ((int)((-K0[fid]) * (1 << SHC))); }
static int IK1(int fid)
{ return ((int)((-K1[fid]) * (1 << SHC))); }
static int CLAMP(int value, int Minim, int Maxim)
{
if (value < Minim) value = Minim;
if (value > Maxim) value = Maxim;
return value;
}
/* XA ADPCM gain values */
static const double K0[4] = { 0.0, 0.9375, 1.796875, 1.53125 };
static const double K1[4] = { 0.0, 0.0, -0.8125,-0.859375};
static int IK0(int fid) { return ((int)((-K0[fid]) * (1 << 10))); } /* K0/1 floats to int, K*2^10 = K*1024 */
static int IK1(int fid) { return ((int)((-K1[fid]) * (1 << 10))); }
/* Sony XA ADPCM, defined for CD-DA/CD-i in the "Red Book" (private) or "Green Book" (public) specs.
* The algorithm basically is BRR (Bit Rate Reduction) from the SNES SPC700, while the data layout is new.
*
* Decoding is defined in diagrams, roughly as:
* pcm = clamp( signed_nibble * 2^(12-range) + K0[index]*hist1 + K1[index]*hist2 )
* - Range (12-range=shift) and filter index are renewed every ~28 samples.
* - nibble is expanded to a signed 16b sample, reimplemented as:
* short sample = ((nibble << 12) & 0xf000) >> shift
* or: int sample = ((nibble << 28) & 0xf0000000) >> (shift + N)
* - K0/K1 are float coefs are typically redefined with int math in various ways, with non-equivalent rounding:
* (sample + K0*2^N*hist1 + K1*2^N*hist1 + [(2^N)/2]) / 2^N
* (sample + K0*2^N*hist1 + K1*2^N*hist1 + [(2^N)/2]) >> N
* sample + (K0<<N*hist1 + K1<<N*hist1)>>N
* sample + (K0*2^N*hist1)>>N + (K1*2^N*hist1)>>N
* etc
* (rounding differences should be inaudible, so public implementations may be approximations)
*
* Various XA descendants (PS-ADPCM, EA-XA, NGC DTK, FADPCM, etc) do filters/rounding slightly
* differently, using one of the above methods.
* int coef tables commonly use N = 6 or 8, so K0 0.9375*64 = 60 or 0.9375*256 = 240
* PS1 XA is apparently upsampled and interpolated to 44100, vgmstream doesn't simulate this.
*
* Info (Green Book): https://www.lscdweb.com/data/downloadables/2/8/cdi_may94_r2.pdf
*/
void decode_xa(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
static int head_table[8] = {0,2,8,10};
VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]);
int predict_nr, shift_factor, sample;
off_t sp_offset;
int i;
int frames_in, sample_count = 0;
int32_t coef1, coef2, coef_index, shift_factor;
int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32;
int HeadTable[8]={0,2,8,10};
short scale;
int i;
int32_t sample_count;
int framesin = first_sample / (56 / channelspacing);
/* external interleave (fixed size), mono/stereo */
frames_in = first_sample / (28*2 / channelspacing);
first_sample = first_sample % 28;
/* hack for mono/stereo handling */
vgmstream->xa_get_high_nibble = !vgmstream->xa_get_high_nibble;
if (first_sample && channelspacing==1)
vgmstream->xa_get_high_nibble = !vgmstream->xa_get_high_nibble;
if((first_sample) && (channelspacing==1))
vgmstream->xa_get_high_nibble=!vgmstream->xa_get_high_nibble;
/* parse current sound unit (subframe) sound parameters */
sp_offset = stream->offset+head_table[frames_in]+vgmstream->xa_get_high_nibble;
coef_index = (read_8bit(sp_offset,stream->streamfile) >> 4) & 0xf;
shift_factor = (read_8bit(sp_offset,stream->streamfile) ) & 0xf;
predict_nr = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->xa_get_high_nibble,stream->streamfile) >> 4;
shift_factor = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->xa_get_high_nibble,stream->streamfile) & 0xf;
VGM_ASSERT(coef_index > 4 || shift_factor > 12, "XA: incorrect coefs/shift at %lx\n", sp_offset);
if (coef_index > 4)
coef_index = 0; /* only 4 filters are used, rest is apparently 0 */
if (shift_factor > 12)
shift_factor = 9; /* supposedly, from Nocash PSX docs */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
short sample_byte = (short)read_8bit(stream->offset+16+framesin+(i*4),stream->streamfile);
coef1 = IK0(coef_index);
coef2 = IK1(coef_index);
scale = ((vgmstream->xa_get_high_nibble ?
sample_byte >> 4 :
sample_byte & 0x0f)<<12);
sample = (short)(scale & 0xf000) >> shift_factor;
sample <<= SH;
sample -= (IK0(predict_nr) * hist1 + (IK1(predict_nr) * hist2)) >> SHC;
/* decode nibbles */
for (i = first_sample; i < first_sample + samples_to_do; i++) {
int32_t new_sample;
uint8_t nibbles = (uint8_t)read_8bit(stream->offset+0x10+frames_in+(i*0x04),stream->streamfile);
new_sample = vgmstream->xa_get_high_nibble ?
(nibbles >> 4) & 0x0f :
(nibbles ) & 0x0f;
new_sample = (int16_t)((new_sample << 12) & 0xf000) >> shift_factor; /* 16b sign extend + scale */
new_sample = new_sample << 4;
new_sample = new_sample - ((coef1*hist1 + coef2*hist2) >> 10);
hist2 = hist1;
hist1=sample;
hist1 = new_sample; /* must go before clamp, somehow */
new_sample = new_sample >> 4;
new_sample = clamp16(new_sample);
sample = CLAMP(sample, -32768 << SH, 32767 << SH);
outbuf[sample_count] = (short)(sample >> SH);
outbuf[sample_count] = new_sample;
sample_count += channelspacing;
}
stream->adpcm_history1_32 = hist1;

View File

@ -1,13 +1,16 @@
#include "vgmstream.h"
//#define VGM_REGISTER_TYPE(extension) ...
//#define VGM_REGISTER_TYPE_COMMON(extension) ... /* for common extensions like aiff */
/* defines the list of accepted extensions. vgmstream doesn't use it internally so it's here
* to inform plugins that need it. Common extensions are commented out to avoid stealing them. */
/* some extensions could be #ifdef but no really needed */
/* some extensions require external libraries and could be #ifdef, no really needed */
/* some formats marked as "not parsed" mean they'll go through FFmpeg, the header/extension is not parsed */
static const char* extension_list[] = {
//"", /* vgmstream can plays extensionless files too, but plugins must accept them manually */
"04sw",
"2dx9",
"2pfs",
@ -38,6 +41,7 @@ static const char* extension_list[] = {
"al2",
"amts", //fake extension/header id for .stm (to be removed)
"ao", //txth/reserved [Cloudphobia (PC)]
"apc", //txth/reserved [MegaRace 3 (PC)]
"as4",
"asd",
"asf",
@ -343,6 +347,7 @@ static const char* extension_list[] = {
"stx",
"svag",
"svs",
"svg", //txth/reserved [Hunter: The Reckoning - Wayward (PS2)]
"swag",
"swav",
"swd",
@ -367,6 +372,7 @@ static const char* extension_list[] = {
"v0",
//"v1", //dual channel with v0
"vag",
"vai", //txth/reserved [Ratatouille (GC)]
"vas",
"vawx",
"vb",
@ -435,7 +441,7 @@ static const char* extension_list[] = {
"zsd",
"zwdsp",
"vgmstream"
"vgmstream" /* fake extension, catch-all for FFmpeg/txth/etc */
//, NULL //end mark
};
@ -829,7 +835,7 @@ static const meta_info meta_info_list[] = {
{meta_PS2_MCG, "Gunvari MCG Header"},
{meta_ZSD, "ZSD Header"},
{meta_RedSpark, "RedSpark Header"},
{meta_PC_IVAUD, "assumed GTA IV Audio file by .ivaud extension"},
{meta_IVAUD, "Rockstar .ivaud header"},
{meta_DSP_WII_WSD, ".WSD header"},
{meta_WII_NDP, "Icon Games NDP header"},
{meta_PS2_SPS, "Ape Escape 2 SPS Header"},
@ -907,7 +913,7 @@ static const meta_info meta_info_list[] = {
{meta_X360_TRA, "Terminal Reality .TRA raw header"},
{meta_PS2_VGS, "Princess Soft VGS header"},
{meta_PS2_IAB, "Runtime .IAB header"},
{meta_PS2_STRLR, "STR L/R header"},
{meta_PS2_STRLR, "The Bouncer STR header"},
{meta_LSF_N1NJ4N, ".lsf !n1nj4n header"},
{meta_VAWX, "feelplus VAWX header"},
{meta_PC_SNDS, "assumed Heavy Iron IMA by .snds extension"},
@ -1023,6 +1029,7 @@ static const meta_info meta_info_list[] = {
{meta_OGG_GWM, "Ogg Vorbis (GWM header)"},
{meta_DSP_SADF, "Procyon Studio SADF header"},
{meta_H4M, "Hudson HVQM4 header"},
{meta_OGG_MUS, "Ogg Vorbis (MUS header)"},
#ifdef VGM_USE_FFMPEG
{meta_FFmpeg, "FFmpeg supported file format"},

View File

@ -69,6 +69,16 @@ void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) {
}
vgmstream->current_block_offset = block_offset;
vgmstream->next_block_offset = block_offset + block_size;
vgmstream->current_block_samples = block_samples;
vgmstream->current_block_size = 0; /* uses current_block_samples instead */
/* no need to setup offsets (plus could read over filesize near EOF) */
if (block_samples == 0)
return;
/* set new channel offsets and ADPCM history */
/* ADPCM hist could be considered part of the stream/decoder (some EAXA decoders call it "EAXA R1" when it has hist), and BNKs
* (with no blocks) may also have them in the first offset, but also may not. To simplify we just read them here. */
@ -179,9 +189,4 @@ void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) {
break;
}
vgmstream->current_block_offset = block_offset;
vgmstream->next_block_offset = block_offset + block_size;
vgmstream->current_block_samples = block_samples;
vgmstream->current_block_size = 0; /* uses current_block_samples instead */
}

View File

@ -1,25 +1,53 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
/* GTA IV blocks */
void block_update_ivaud(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
off_t start_offset;
off_t interleave_size;
int32_t nextFrame=0;
STREAMFILE *streamFile = vgmstream->ch[0].streamfile;
size_t header_size, block_samples;
int i;
off_t seek_info_offset;
/* base header */
seek_info_offset = read_32bitLE(block_offset+0x00,streamFile); /*64b */
/* 0x08(8): seek table offset */
/* 0x10(8): seek table offset again? */
/* seek info (per channel) */
/* 0x00: start entry */
/* 0x04: number of entries */
/* 0x08: unknown */
/* 0x0c: data size */
/* seek table (per all entries) */
/* 0x00: start? */
/* 0x04: end? */
/* find header size */
/* can't see a better way to calc, as there may be dummy entries after usable ones
* (table is max 0x7b8 + seek table offset + 0x800-padded) */
if (vgmstream->channels > 3)
header_size = 0x1000;
else
header_size = 0x800;
/* get max data_size as channels may vary slightly (data is padded, hopefully won't create pops) */
block_samples = 0;
for(i = 0;i < vgmstream->channels; i++) {
size_t channel_samples = read_32bitLE(block_offset + seek_info_offset+0x0c + 0x10*i,streamFile);
if (block_samples < channel_samples)
block_samples = channel_samples;
}
vgmstream->current_block_offset = block_offset;
nextFrame=(read_32bitLE(vgmstream->current_block_offset+0x28,streamFile)<<12)+0x800;
vgmstream->next_block_offset = vgmstream->current_block_offset + nextFrame;
vgmstream->current_block_size=read_32bitLE(block_offset+0x24,streamFile)/2;
start_offset=vgmstream->current_block_offset + 0x800;
interleave_size=(read_32bitLE(block_offset+0x28,streamFile)<<12)/2;
vgmstream->next_block_offset = block_offset + vgmstream->full_block_size;
vgmstream->current_block_samples = block_samples;
vgmstream->current_block_size = 0;
for(i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset = start_offset + (i*interleave_size);
/* use seek table's start entry to find channel offset */
size_t interleave_size = read_32bitLE(block_offset + seek_info_offset+0x00 + 0x10*i,streamFile) * 0x800;
vgmstream->ch[i].offset = block_offset + header_size + interleave_size;
}
}

View File

@ -1,19 +1,17 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
/* The Bouncer STRx blocks, one block per channel when stereo */
void block_update_ps2_strlr(off_t block_offset, VGMSTREAM * vgmstream) {
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitLE(
vgmstream->current_block_offset+0x4,
vgmstream->ch[0].streamfile)*2;
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x40;
//vgmstream->current_block_size/=vgmstream->channels;
vgmstream->current_block_size = read_32bitLE(block_offset+0x04,streamFile); /* can be smaller than 0x800 */
vgmstream->next_block_offset = block_offset + 0x800*vgmstream->channels;
/* 0x08: number of remaning blocks, 0x10: some id/size? (shared in all blocks) */
for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+0x20+(0x800*i);
vgmstream->ch[i].offset = block_offset + 0x20 + 0x800*i;
}
}

View File

@ -48,9 +48,8 @@ VGMSTREAM * init_vgmstream_ahx(STREAMFILE *streamFile) {
{
#ifdef VGM_USE_MPEG
mpeg_custom_config cfg;
mpeg_custom_config cfg = {0};
memset(&cfg, 0, sizeof(mpeg_custom_config));
cfg.encryption = read_8bit(0x13,streamFile); /* 0x08 = keyword encryption */
cfg.cri_type = type;

View File

@ -28,7 +28,7 @@ static int parse_awc_header(STREAMFILE* streamFile, awc_header* awc);
/* AWC - from RAGE (Rockstar Advanced Game Engine) audio (Red Dead Redemption, Max Payne 3, GTA5) */
VGMSTREAM * init_vgmstream_awc(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
awc_header awc;
awc_header awc = {0};
/* check extension */
if (!check_extensions(streamFile,"awc"))
@ -137,8 +137,7 @@ VGMSTREAM * init_vgmstream_awc(STREAMFILE *streamFile) {
#endif
#ifdef VGM_USE_MPEG
case 0x07: { /* MPEG (PS3) */
mpeg_custom_config cfg;
memset(&cfg, 0, sizeof(mpeg_custom_config));
mpeg_custom_config cfg = {0};
cfg.chunk_size = awc.block_chunk;
cfg.big_endian = awc.big_endian;
@ -183,8 +182,6 @@ static int parse_awc_header(STREAMFILE* streamFile, awc_header* awc) {
off_t off;
int target_subsong = streamFile->stream_index;
memset(awc,0,sizeof(awc_header));
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x41444154 && /* "ADAT" (LE) */

View File

@ -36,8 +36,8 @@ VGMSTREAM * init_vgmstream_bik(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
{
ffmpeg_custom_config cfg;
memset(&cfg, 0, sizeof(ffmpeg_custom_config));
ffmpeg_custom_config cfg = {0};
cfg.stream_index = stream_index;
vgmstream->codec_data = init_ffmpeg_config(streamFile, NULL,0, 0x0,get_streamfile_size(streamFile), &cfg);

View File

@ -108,22 +108,26 @@ fail:
return NULL;
}
/* .SPS? - from Frostbite engine games? [Need for Speed Rivals (PS4)], v1 header */
/* .SPS - from Frostbite engine games, v1 header */
VGMSTREAM * init_vgmstream_ea_sps_fb(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset = 0, header_offset = 0, sps_offset, max_offset;
/* checks */
/* assumed to be .sps (no extensions in the archives) */
/* should be .sps once extracted (filenames are hashed) */
if (!check_extensions(streamFile,"sps"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x011006C0)
if (read_32bitBE(0x00,streamFile) != 0x011006C0 && /* Need for Speed: The Run (PS3), Need for Speed: Rivals (PS4) */
read_32bitBE(0x00,streamFile) != 0x01100180 && /* Need for Speed: The Run (X360) */
read_32bitBE(0x00,streamFile) != 0x01100000) /* Need for Speed: The Run (PC) */
goto fail;
/* file has a Frostbite descriptor (SoundWaveAsset segments) data before actual .sps, exact size unknown.
* 0x00: segments/flags/sizes? 0x04: SegmentLength?, 0x08: SeekTableOffset?, 0x0c: mini SPS header
* rest: unknown fields? may be padded? (ex. 0x22 > 0x24, 0x1d > 0x20 */
/* file has some kind of data before .sps, exact offset unknown.
* Actual offsets are probably somewhere but for now just manually search. */
sps_offset = read_32bitBE(0x08, streamFile); /* points to some kind of table, number of entries unknown */
/* actual offsets are probably somewhere but for now just manually search. */
sps_offset = read_32bitBE(0x08, streamFile); /* seek table, number of entries unknown */
max_offset = sps_offset + 0x3000;
if (max_offset > get_streamfile_size(streamFile))
max_offset = get_streamfile_size(streamFile);
@ -171,7 +175,7 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
/* rest is optional, depends on flags header used (ex. SNU and SPS may have bigger headers):
* &0x20: 1 int (usually 0x00), &0x00/40: nothing, &0x60: 2 ints (usually 0x00 and 0x14) */
/* V0: SNR+SNS, V1: SPR+SPS (not apparent differences, other than the block flags used) */
/* V0: SNR+SNS, V1: SPR+SPS (no apparent differences, other than the block flags used) */
if (version != 0 && version != 1) {
VGM_LOG("EA SNS/SPS: unknown version\n");
goto fail;

View File

@ -39,7 +39,7 @@ static size_t eaac_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset,
off_t intrablock_offset, intradata_offset;
uint32_t block_flag, block_size, data_size, skip_size;
block_flag = read_8bit(data->physical_offset+0x00,streamfile);
block_flag = (uint8_t)read_8bit(data->physical_offset+0x00,streamfile);
block_size = read_32bitBE(data->physical_offset+0x00,streamfile) & 0x00FFFFFF;
if (data->version == 1 && block_flag == 0x48) {
@ -47,7 +47,7 @@ static size_t eaac_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset,
continue; /* skip header block */
}
if (data->version == 1 && block_flag == 0x45)
return total_read; /* stop on last block (always empty) */
break; /* stop on last block (always empty) */
switch(data->codec) {
#if 0
@ -92,13 +92,13 @@ static size_t eaac_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset,
if (to_read > length)
to_read = length;
if (to_read == 0)
return total_read; /* should never happen... */
break; /* should never happen... */
/* finally read and move buffer/offsets */
bytes_read = read_streamfile(dest, data->physical_offset + intrablock_offset, to_read, streamfile);
total_read += bytes_read;
if (bytes_read != to_read)
return total_read; /* couldn't read fully */
break; /* couldn't read fully */
dest += bytes_read;
offset += bytes_read;
@ -131,7 +131,7 @@ static size_t eaac_io_size(STREAMFILE *streamfile, eaac_io_data* data) {
while (physical_offset < max_physical_offset) {
uint32_t block_flag, block_size, data_size;
block_flag = read_8bit(physical_offset+0x00,streamfile);
block_flag = (uint8_t)read_8bit(physical_offset+0x00,streamfile);
block_size = read_32bitBE(physical_offset+0x00,streamfile) & 0x00FFFFFF;
if (data->version == 0 && block_flag != 0x00 && block_flag != 0x80)

View File

@ -10,7 +10,7 @@
#define EA_VERSION_V3 0x03 // ~PS2 era
/* platform constants (unasigned values seem internal only) */
#define EA_PLATFORM_GENERIC -1 // typically Wii/X360/PS3
#define EA_PLATFORM_GENERIC -1 // typically Wii/X360/PS3/videos
#define EA_PLATFORM_PC 0x00
#define EA_PLATFORM_PSX 0x01
#define EA_PLATFORM_N64 0x02
@ -21,6 +21,7 @@
#define EA_PLATFORM_XBOX 0x07
#define EA_PLATFORM_X360 0x09 // also "Xenon"
#define EA_PLATFORM_PSP 0x0A
#define EA_PLATFORM_PS3 0x0E // very rare [Need for Speed: Carbon (PS3)]
#define EA_PLATFORM_3DS 0x14
/* codec constants (undefined are probably reserved, ie.- sx.exe encodes PCM24/DVI but no platform decodes them) */
@ -350,11 +351,19 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
#endif
case EA_CODEC2_MT10: /* MicroTalk (10:1 compression) */
case EA_CODEC2_MT5: /* MicroTalk (5:1 compression) */
case EA_CODEC2_MT5: { /* MicroTalk (5:1 compression) */
int use_pcm_blocks = 0;
if (ea->version == EA_VERSION_V3 || (ea->version == EA_VERSION_V2 &&
(ea->platform == EA_PLATFORM_PC || ea->platform == EA_PLATFORM_MAC))) {
use_pcm_blocks = 1;
}
vgmstream->coding_type = coding_EA_MT;
vgmstream->codec_data = init_ea_mt(vgmstream->channels, ea->version == EA_VERSION_V3);
vgmstream->codec_data = init_ea_mt(vgmstream->channels, use_pcm_blocks);
if (!vgmstream->codec_data) goto fail;
break;
}
case EA_CODEC2_ATRAC3PLUS: /* regular ATRAC3plus chunked in SCxx blocks, including RIFF header */
default:
@ -509,6 +518,7 @@ static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t be
case 0x13: /* effect bus (0..127) */
case 0x14: /* emdedded user data (free size/value) */
case 0x19: /* related to playback envelope (BNK only) */
case 0x1A: /* unknown and very rare, size 0 (BNK only) [SSX3 (PS2)] */
case 0x1B: /* unknown (movie only?) */
case 0x1C: /* initial envelope volume (BNK only) */
case 0x24: /* master random detune range (BNK only) */
@ -608,7 +618,7 @@ static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t be
case 0x9F: /* azimuth ch4 */
case 0xA6: /* azimuth ch5 */
case 0xA7: /* azimuth ch6 */
case 0xA1: /* unknown and very rare, always 0x02 (FIFA 2001 PS2) */
case 0xA1: /* unknown and very rare, always 0x02 [FIFA 2001 (PS2)] */
read_patch(streamFile, &offset);
break;
@ -636,6 +646,7 @@ static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t be
|| ea->platform == EA_PLATFORM_SAT
|| ea->platform == EA_PLATFORM_GC_WII
|| ea->platform == EA_PLATFORM_X360
|| ea->platform == EA_PLATFORM_PS3
|| ea->platform == EA_PLATFORM_GENERIC) {
ea->big_endian = 1;
}
@ -658,6 +669,7 @@ static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t be
case EA_PLATFORM_XBOX: ea->version = EA_VERSION_V2; break;
case EA_PLATFORM_X360: ea->version = EA_VERSION_V3; break;
case EA_PLATFORM_PSP: ea->version = EA_VERSION_V3; break;
case EA_PLATFORM_PS3: ea->version = EA_VERSION_V3; break;
case EA_PLATFORM_3DS: ea->version = EA_VERSION_V3; break;
case EA_PLATFORM_GENERIC: ea->version = EA_VERSION_V2; break;
default:
@ -707,6 +719,7 @@ static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t be
case EA_PLATFORM_XBOX: ea->codec2 = EA_CODEC2_S16LE; break;
case EA_PLATFORM_X360: ea->codec2 = EA_CODEC2_EAXA; break;
case EA_PLATFORM_PSP: ea->codec2 = EA_CODEC2_EAXA; break;
case EA_PLATFORM_PS3: ea->codec2 = EA_CODEC2_EAXA; break;
case EA_PLATFORM_3DS: ea->codec2 = EA_CODEC2_GCADPCM; break;
default:
VGM_LOG("EA SCHl: unknown default codec2 for platform 0x%02x\n", ea->platform);
@ -728,6 +741,7 @@ static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t be
case EA_PLATFORM_XBOX: ea->sample_rate = 24000; break;
case EA_PLATFORM_X360: ea->sample_rate = 44100; break;
case EA_PLATFORM_PSP: ea->sample_rate = 22050; break;
case EA_PLATFORM_PS3: ea->sample_rate = 44100; break;
//case EA_PLATFORM_3DS: ea->sample_rate = 44100; break;//todo (not 22050/16000)
default:
VGM_LOG("EA SCHl: unknown default sample rate for platform 0x%02x\n", ea->platform);

View File

@ -26,7 +26,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
size_t header_size;
ea_header ea;
ea_header ea = {0};
/* check extension */
@ -94,8 +94,6 @@ fail:
static int parse_fixed_header(STREAMFILE* streamFile, ea_header* ea, off_t begin_offset) {
off_t offset = begin_offset;
memset(ea,0,sizeof(ea_header));
if (read_32bitBE(offset+0x00, streamFile) != 0x5041546C && /* "PATl" */
read_32bitBE(offset+0x38, streamFile) != 0x544D706C) /* "TMpl" */
goto fail;

View File

@ -34,8 +34,10 @@ VGMSTREAM * init_vgmstream_fsb5(STREAMFILE *streamFile) {
* type 0x00 has an extra field (always 0?) at 0x1c */
BaseHeaderLength = (Version==0x00) ? 0x40 : 0x3C;
if ((SampleHeaderLength + NameTableLength + SampleDataLength + BaseHeaderLength) != get_streamfile_size(streamFile))
if ((SampleHeaderLength + NameTableLength + SampleDataLength + BaseHeaderLength) != get_streamfile_size(streamFile)) {
VGM_LOG("FSB5: bad size (%x + %x + %x + %x != %x)\n", SampleHeaderLength, NameTableLength, SampleDataLength, BaseHeaderLength, get_streamfile_size(streamFile));
goto fail;
}
if (TargetSubsong == 0) TargetSubsong = 1; /* default to 1 */
if (TargetSubsong > TotalSubsongs || TotalSubsongs <= 0) goto fail;

View File

@ -240,6 +240,12 @@ static const hcakey_info hcakey_list[] = {
// PriPara: All Idol Perfect Stage (Takara Tomy) [Switch]
{217735759}, // 000000000CFA624F
// Space Invaders Extreme (Taito Corporation, Backbone Entertainment) [PC]
{91380310056}, // 0000001546B0E028
// CR Another God Hades Advent (Universal Entertainment Corporation) [iOS/Android]
{64813795}, // 0000000003DCFAE3
};
#endif/*_HCA_KEYS_H_*/

View File

@ -2,67 +2,195 @@
#include "../layout/layout.h"
#include "../util.h"
/* ivaud (from GTA IV (PC)) */
typedef struct {
int is_music;
int total_subsongs;
int channel_count;
int sample_rate;
int codec;
int num_samples;
size_t block_count;
size_t block_size;
off_t stream_offset;
size_t stream_size;
} ivaud_header;
static int parse_ivaud_header(STREAMFILE* streamFile, ivaud_header* ivaud);
/* .ivaud - from GTA IV (PC) */
VGMSTREAM * init_vgmstream_ivaud(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
ivaud_header ivaud = {0};
int loop_flag;
char filename[PATH_LIMIT];
off_t start_offset;
off_t block_table_offset;
int loop_flag = 0;
int channel_count;
int i;
/* at this time, i only check for extension */
/* i'll make further checks later */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("ivaud",filename_extension(filename))) goto fail;
/* multiple sounds .ivaud files are not implemented */
/* only used for voices & sfx */
if(read_32bitLE(0x10,streamFile)!=0)
/* checks */
/* (hashed filenames are likely extensionless and .ivaud is added by tools) */
if (!check_extensions(streamFile, "ivaud,"))
goto fail;
/* never looped and allways 2 channels */
/* check header */
if (!parse_ivaud_header(streamFile, &ivaud))
goto fail;
loop_flag = 0;
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(ivaud.channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
block_table_offset = read_32bitLE(0,streamFile);
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(block_table_offset + 0x04,streamFile);
vgmstream->sample_rate = ivaud.sample_rate;
vgmstream->num_samples = ivaud.num_samples;
vgmstream->num_streams = ivaud.total_subsongs;
vgmstream->stream_size = ivaud.stream_size;
vgmstream->meta_type = meta_IVAUD;
switch(ivaud.codec) {
case 0x0001: /* common in sfx, uncommon in music (ex. EP2_SFX/MENU_MUSIC) */
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = ivaud.is_music ? layout_blocked_ivaud : layout_none;
vgmstream->full_block_size = ivaud.block_size;
break;
case 0x0400:
vgmstream->coding_type = coding_IMA_int;
vgmstream->layout_type = ivaud.is_music ? layout_blocked_ivaud : layout_none;
vgmstream->full_block_size = ivaud.block_size;
break;
vgmstream->layout_type = layout_blocked_ivaud;
vgmstream->meta_type = meta_PC_IVAUD;
/* open the file for reading */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x2000);
if (!vgmstream->ch[i].streamfile) goto fail;
}
default:
VGM_LOG("IVAUD: unknown codec 0x%x\n", ivaud.codec);
goto fail;
}
/* Calc num_samples */
start_offset = read_32bitLE(0x2C,streamFile);
//block_count = read_32bitLE(0x08,streamFile);
vgmstream->next_block_offset = read_32bitLE(0x2C,streamFile);
// to avoid troubles with "extra" samples
vgmstream->num_samples=((read_32bitLE(0x60,streamFile)/2)*2);
if (!vgmstream_open_stream(vgmstream,streamFile,ivaud.stream_offset))
goto fail;
block_update_ivaud(start_offset,vgmstream);
if (vgmstream->layout_type == layout_blocked_ivaud)
block_update_ivaud(ivaud.stream_offset, vgmstream);
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}
/* Parse Rockstar's .ivaud header (much info from SparkIV). */
static int parse_ivaud_header(STREAMFILE* streamFile, ivaud_header* ivaud) {
int target_subsong = streamFile->stream_index;
/* use bank's stream count to detect */
ivaud->is_music = (read_32bitLE(0x10,streamFile) == 0);
if (ivaud->is_music) {
off_t block_table_offset, channel_table_offset, channel_info_offset;
/* music header */
block_table_offset = read_32bitLE(0x00,streamFile); /* 64b */
ivaud->block_count = read_32bitLE(0x08,streamFile);
ivaud->block_size = read_32bitLE(0x0c,streamFile); /* 64b, uses padded blocks */
channel_table_offset = read_32bitLE(0x14,streamFile); /* 64b */
/* 0x1c(8): block_table_offset again? */
ivaud->channel_count = read_32bitLE(0x24,streamFile);
/* 0x28(4): unknown entries? */
ivaud->stream_offset = read_32bitLE(0x2c,streamFile);
channel_info_offset = channel_table_offset + ivaud->channel_count*0x10;
if ((ivaud->block_count * ivaud->block_size) + ivaud->stream_offset != get_streamfile_size(streamFile)) {
VGM_LOG("IVAUD: bad file size\n");
goto fail;
}
/* channel table (one entry per channel, points to channel info) */
/* 0x00(8): offset within channel_info_offset */
/* 0x08(4): hash */
/* 0x0c(4): size */
/* channel info (one entry per channel) */
/* 0x00(8): offset within data (should be 0) */
/* 0x08(4): hash */
/* 0x0c(4): half num_samples? */
ivaud->num_samples = read_32bitLE(channel_info_offset+0x10,streamFile);
/* 0x14(4): unknown (-1) */
/* 0x18(2): sample rate */
/* 0x1a(2): unknown */
ivaud->codec = read_32bitLE(channel_info_offset+0x1c,streamFile);
/* (when codec is IMA) */
/* 0x20(8): adpcm states offset, 0x38: num states? (reference for seeks?) */
/* rest: unknown data */
/* block table (one entry per block) */
/* 0x00: data size processed up to this block (doesn't count block padding) */
ivaud->sample_rate = read_32bitLE(block_table_offset + 0x04,streamFile);
/* sample_rate should agree with each channel in the channel table */
ivaud->total_subsongs = 1;
ivaud->stream_size = get_streamfile_size(streamFile);
}
else {
off_t stream_table_offset, stream_info_offset, stream_entry_offset;
/* bank header */
stream_table_offset = read_32bitLE(0x00,streamFile); /* 64b */
/* 0x08(8): header size? start offset? */
ivaud->total_subsongs = read_32bitLE(0x10,streamFile);
/* 0x14(4): unknown */
ivaud->stream_offset = read_32bitLE(0x18,streamFile); /* base start_offset */
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > ivaud->total_subsongs || ivaud->total_subsongs < 1) goto fail;
if (stream_table_offset != 0x1c)
goto fail;
stream_info_offset = stream_table_offset + 0x10*ivaud->total_subsongs;
/* stream table (one entry per stream, points to stream info) */
stream_entry_offset = read_32bitLE(stream_table_offset + 0x10*(target_subsong-1) + 0x00,streamFile); /* within stream info */
/* 0x00(8): offset within stream_info_offset */
/* 0x08(4): hash */
/* 0x0c(4): size */
/* stream info (one entry per stream) */
ivaud->stream_offset += read_32bitLE(stream_info_offset+stream_entry_offset+0x00,streamFile); /* 64b, within data */
/* 0x08(4): hash */
/* 0x0c(4): half num_samples? */
ivaud->num_samples = read_32bitLE(stream_info_offset+stream_entry_offset+0x10,streamFile);
/* 0x14(4): unknown (-1) */
ivaud->sample_rate = (uint16_t)read_16bitLE(stream_info_offset+stream_entry_offset+0x18,streamFile);
/* 0x1a(2): unknown */
ivaud->codec = read_32bitLE(stream_info_offset+stream_entry_offset+0x1c,streamFile);
/* (when codec is IMA) */
/* 0x20(8): adpcm states offset, 0x38: num states? (reference for seeks?) */
/* rest: unknown data */
ivaud->channel_count = 1;
/* ghetto size calculator (could substract offsets but streams are not ordered) */
switch(ivaud->codec) {
case 0x0001:
ivaud->stream_size = ivaud->num_samples * 2; /* double 16b PCM */
break;
case 0x0400:
ivaud->stream_size = ivaud->num_samples / 2; /* half nibbles */
break;
default:
break;
}
}
return 1;
fail:
return 0;
}

View File

@ -1,66 +1,52 @@
#include "meta.h"
#include "../util.h"
/* bxaimc - 2009-03-05
- RRDS - found in Ridge Racer DS */
#include "../coding/coding.h"
/* RRDS - from (some) NST games [Ridge Racer (DS), Metroid Prime Hunters - First Hunt (DS)] */
VGMSTREAM * init_vgmstream_nds_rrds(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int channel_count;
int loop_flag;
off_t start_offset;
int loop_flag, channel_count;
/* check extension, case insensitive (made-up extension) */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("rrds",filename_extension(filename))) goto fail;
/* check size */
if ((read_32bitLE(0x0,streamFile)+0x18) != get_streamfile_size(streamFile))
/* checks */
/* .rrds: made-up extension (files come from a bigfile and don't have filenames/extension) */
if (!check_extensions(streamFile, ",rrds"))
goto fail;
/* check type details */
loop_flag = (read_32bitLE(0x14,streamFile) != 0);
if ((read_32bitLE(0x00,streamFile)+0x18) != get_streamfile_size(streamFile))
goto fail;
loop_flag = (read_32bitLE(0x14,streamFile) != 0); //todo not correct for MPH: First Hunt?
channel_count = 1;
start_offset = 0x1c;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x1c;
vgmstream->num_samples = (read_32bitLE(0x0,streamFile)-start_offset) / channel_count * 2;
vgmstream->sample_rate = read_32bitLE(0x8,streamFile);
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
vgmstream->num_samples = ima_bytes_to_samples(read_32bitLE(0x00,streamFile)-start_offset,channel_count);
if (loop_flag) {
vgmstream->loop_start_sample = (read_32bitLE(0x14,streamFile)-start_offset) / channel_count * 2;
vgmstream->loop_start_sample = ima_bytes_to_samples(read_32bitLE(0x14,streamFile)-start_offset,channel_count);
vgmstream->loop_end_sample = vgmstream->num_samples;
}
vgmstream->coding_type = coding_IMA_int;
vgmstream->meta_type = meta_NDS_RRDS;
vgmstream->coding_type = coding_IMA_int;
vgmstream->layout_type = layout_none;
/* open the file for reading */
{
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
vgmstream->ch[0].streamfile = file;
vgmstream->ch[0].channel_start_offset=
vgmstream->ch[0].offset=start_offset;
/* one NDS IMA header for whole stream */
vgmstream->ch[0].adpcm_history1_16 = read_16bitLE(0x18,streamFile);
vgmstream->ch[0].adpcm_step_index = read_16bitLE(0x1a,streamFile);
if (vgmstream->ch[0].adpcm_step_index < 0 || vgmstream->ch[0].adpcm_step_index > 88) goto fail;
if (vgmstream->ch[0].adpcm_step_index < 0 || vgmstream->ch[0].adpcm_step_index > 88)
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

@ -226,6 +226,28 @@ static void gwm_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, vo
}
}
static void mus_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) {
static const uint8_t key[16] = {
0x21,0x4D,0x6F,0x01,0x20,0x4C,0x6E,0x02,0x1F,0x4B,0x6D,0x03,0x20,0x4C,0x6E,0x02
};
size_t bytes_read = size*nmemb;
ogg_vorbis_streamfile * const ov_streamfile = datasource;
int i;
char *header_id = "OggS";
/* bytes are xor'd with key, first "OggS" is changed */
for (i = 0; i < bytes_read; i++) {
if (ov_streamfile->offset+i < 0x04) { /* if decrypted gives "Mus " */
((uint8_t*)ptr)[i] = (uint8_t)header_id[(ov_streamfile->offset + i) % 4];
}
else {
((uint8_t*)ptr)[i] ^= key[(ov_streamfile->offset + i) % sizeof(key)];
}
}
}
/* Ogg Vorbis, by way of libvorbisfile; may contain loop comments */
VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
ogg_vorbis_meta_info_t ovmi = {0};
@ -239,6 +261,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
int is_rpgmvo = 0;
int is_eno = 0;
int is_gwm = 0;
int is_mus = 0;
/* check extension */
@ -262,6 +285,8 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
is_eno = 1;
} else if (check_extensions(streamFile,"gwm")) { /* .gwm: Adagio: Cloudburst (PC) */
is_gwm = 1;
} else if (check_extensions(streamFile,"mus")) { /* .mus: Redux - Dark Matters (PC) */
is_mus = 1;
} else {
goto fail;
}
@ -355,7 +380,6 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
start_offset = 0x01;
}
/* check GWM [Adagio: Cloudburst (PC)], encrypted */
if (is_gwm) {
ovmi.xor_value = 0x5D;
@ -363,6 +387,12 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
ovmi.meta_type = meta_OGG_GWM;
}
/* check .mus [Redux - Dark Matters (PC)], encrypted */
if (is_mus) {
ovmi.decryption_callback = mus_ogg_decryption_callback;
ovmi.meta_type = meta_OGG_MUS;
}
return init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
@ -399,8 +429,8 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callb
/* test if this is a proper Ogg Vorbis file, with the current (from init_x) STREAMFILE */
{
OggVorbis_File temp_ovf;
ogg_vorbis_streamfile temp_streamfile;
OggVorbis_File temp_ovf = {0};
ogg_vorbis_streamfile temp_streamfile = {0};
temp_streamfile.streamfile = streamFile;
@ -414,7 +444,6 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callb
temp_streamfile.xor_value = ovmi->xor_value;
/* open the ogg vorbis file for testing */
memset(&temp_ovf, 0, sizeof(temp_ovf));
if (ov_test_callbacks(&temp_streamfile, &temp_ovf, NULL, 0, *callbacks_p))
goto fail;

View File

@ -41,8 +41,7 @@ VGMSTREAM * init_vgmstream_ogl(STREAMFILE *streamFile) {
#ifdef VGM_USE_VORBIS
{
vorbis_custom_config cfg;
memset(&cfg, 0, sizeof(vorbis_custom_config));
vorbis_custom_config cfg = {0};
vgmstream->layout_type = layout_none;
vgmstream->coding_type = coding_VORBIS_custom;

View File

@ -46,13 +46,12 @@ static VGMSTREAM * init_vgmstream_opus(STREAMFILE *streamFile, meta_t meta_type,
{
uint8_t buf[0x100];
size_t bytes;
ffmpeg_custom_config cfg;
ffmpeg_custom_config cfg = {0};
ffmpeg_codec_data *ffmpeg_data;
bytes = ffmpeg_make_opus_header(buf,0x100, vgmstream->channels, skip, vgmstream->sample_rate);
if (bytes <= 0) goto fail;
memset(&cfg, 0, sizeof(ffmpeg_custom_config));
cfg.type = FFMPEG_SWITCH_OPUS;
ffmpeg_data = init_ffmpeg_config(streamFile, buf,bytes, start_offset,data_size, &cfg);

View File

@ -5,17 +5,14 @@
VGMSTREAM * init_vgmstream_ps2_joe(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int channel_count, loop_flag, sample_rate, num_samples;
size_t file_size, data_size, unknown1, unknown2, interleave;
int loop_flag;
int channel_count;
/* checks */
if (!check_extensions(streamFile, "joe"))
goto fail;
loop_flag = 1;
channel_count = 2;
file_size = get_streamfile_size(streamFile);
data_size = read_32bitLE(0x04,streamFile);
unknown1 = read_32bitLE(0x08,streamFile);
@ -48,14 +45,20 @@ VGMSTREAM * init_vgmstream_ps2_joe(STREAMFILE *streamFile) {
start_offset = file_size - data_size;
channel_count = 2;
sample_rate = read_32bitLE(0x00,streamFile);
num_samples = ps_bytes_to_samples(data_size, channel_count);
/* most songs simply repeat except a few jingles (PS-ADPCM flags are always set) */
loop_flag = (num_samples > 20*sample_rate); /* in seconds */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x00,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count);
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
//todo improve, not working 100% with early .joe
{
@ -103,6 +106,7 @@ VGMSTREAM * init_vgmstream_ps2_joe(STREAMFILE *streamFile) {
}
}
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
vgmstream->meta_type = meta_PS2_JOE;

View File

@ -1,80 +1,57 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
#include "../coding/coding.h"
/* STR: The Bouncer (PS2) */
/* STR - The Bouncer (PS2) */
VGMSTREAM * init_vgmstream_ps2_strlr(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag = 0;
int channel_count;
int i;
int channel_count, loop_flag;
off_t start_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("str",filename_extension(filename))) goto fail;
#if 0
/* checks */
/* .vs: real extension (from .nam container) , .str: partial header id */
if (!check_extensions(streamFile, "vs,str"))
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x5354524C) /* "STRL" */
if (!(read_32bitBE(0x000,streamFile) == 0x5354524C && /* "STRL" */
read_32bitBE(0x800,streamFile) == 0x53545252) && /* "STRR" */
read_32bitBE(0x00,streamFile) != 0x5354524D) /* "STRM" */
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53545252) /* "STRR" */
goto fail;
#endif
/* don't hijack Sonic & Sega All Stars Racing X360 (xma) */
if (read_32bitBE(0x00,streamFile) == 0x52494646)
goto fail; /* "RIFF"*/
/* don't hijack Mad Dash Racing (Xbox) */
if (read_32bitLE(0x0c,streamFile) == 1
&& read_32bitLE(0x010,streamFile) == 0
&& read_32bitLE(0x400,streamFile) == 0
&& read_32bitLE(0x7f0,streamFile) == 0)
goto fail;
loop_flag = 0;
channel_count = 2;
channel_count = (read_32bitBE(0x00,streamFile) == 0x5354524D) ? 1 : 2; /* "STRM"=mono (voices) */
start_offset = 0x00;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x0;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 48000;
vgmstream->sample_rate = 44100;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_blocked_ps2_strlr;
//vgmstream->interleave_block_size = read_32bitLE(0xC, streamFile);
vgmstream->meta_type = meta_PS2_STRLR;
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++)
{
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename, 0x8000);
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
/* Calc num_samples */
block_update_ps2_strlr(start_offset, vgmstream);
vgmstream->num_samples=0;
do
/* calc num_samples */
{
vgmstream->num_samples += vgmstream->current_block_size * 14 / 16;
vgmstream->next_block_offset = start_offset;
do {
block_update_ps2_strlr(vgmstream->next_block_offset,vgmstream);
} while (vgmstream->next_block_offset < get_streamfile_size(streamFile));
vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1);
}
while (vgmstream->next_block_offset < get_streamfile_size(streamFile));
}
block_update_ps2_strlr(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,5 +1,5 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/* VPK */
@ -34,7 +34,7 @@ VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile) {
/* Check for Compression Scheme */
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitLE(0x04,streamFile)/16*28;
vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x04,streamFile),vgmstream->channels);
/* Get loop point values */
if(vgmstream->loop_flag) {
@ -42,7 +42,7 @@ VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = vgmstream->num_samples;
}
vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile)/2;
vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile)/vgmstream->channels;
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_PS2_VPK;

View File

@ -32,8 +32,7 @@ VGMSTREAM * init_vgmstream_sk_aud(STREAMFILE *streamFile) {
#ifdef VGM_USE_VORBIS
{
vorbis_custom_config cfg;
memset(&cfg, 0, sizeof(vorbis_custom_config));
vorbis_custom_config cfg = {0};
vgmstream->layout_type = layout_none;
vgmstream->coding_type = coding_VORBIS_custom;

View File

@ -313,6 +313,7 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
/* ignore non-audio entry (other types seem to have config data) */
if (read_32bit(offset + 0x04, streamFile) != 0x01)
continue;
//;VGM_LOG("SB at %lx\n", offset);
/* weird case when there is no internal substream ID and just seem to rotate every time type changes, joy */
if (sb->has_rotating_ids) { /* assumes certain configs can't happen in this case */
@ -779,6 +780,23 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
return 1;
}
#if 0
/* Far cry: Instincts - Evolution (2006)(Xbox) */
if (sb->version == 0x00170000 && is_sb2) {
sb->section1_entry_size = 0x48;
sb->section2_entry_size = 0x6c;
sb->external_flag_offset = 0;
sb->num_samples_offset = 0x28;
sb->stream_id_offset = 0;
sb->sample_rate_offset = 0x3c;
sb->channels_offset = 0x44;
sb->stream_type_offset = 0x48;
sb->extra_name_offset = 0x58;
return 1;
}
#endif
/* Prince of Persia: Rival Swords (2007)(PSP) */
if (sb->version == 0x00180005 && is_sb5) {

View File

@ -204,7 +204,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
switch(ww.codec) {
case PCM: /* common */
/* normally riff.c has priority but it's needed when .wem is used */
if (ww.fmt_size != 0x10 && ww.fmt_size != 0x18) goto fail; /* old, new */
if (ww.fmt_size != 0x10 && ww.fmt_size != 0x18 && ww.fmt_size != 0x28) goto fail; /* old, new/Limbo (PC) */
if (ww.bits_per_sample != 16) goto fail;
vgmstream->coding_type = (ww.big_endian ? coding_PCM16BE : coding_PCM16LE);

View File

@ -39,8 +39,7 @@ VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile) {
{
/* manually find sample offsets (XMA1 nonsense again) */
ms_sample_data msd;
memset(&msd,0,sizeof(ms_sample_data));
ms_sample_data msd = {0};
msd.xma_version = 1;
msd.channels = channel_count;

View File

@ -68,8 +68,7 @@ VGMSTREAM * init_vgmstream_xma(STREAMFILE *streamFile) {
/* fix samples; for now only XMA1 is fixed, but XMA2 num_samples don't include skip samples and xmaencode.exe doesn't use it */
if (is_xma1) {
ms_sample_data msd;
memset(&msd,0,sizeof(ms_sample_data));
ms_sample_data msd = {0};
msd.xma_version = is_xma1 ? 1 : 2;
msd.channels = channel_count;

View File

@ -19,7 +19,7 @@ VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) {
size_t chunk_size, stream_size;
/* check extension, case insensitive */
if (!check_extensions(streamFile,"xvag"))
if (!check_extensions(streamFile,"xvag,"))
goto fail;
/* check header */

View File

@ -2,16 +2,28 @@
#include "util.h"
#include "streamtypes.h"
const char * filename_extension(const char * filename) {
const char * ext;
const char * filename_extension(const char * pathname) {
const char * filename;
const char * extension;
/* You know what would be nice? strrchrnul().
* Instead I have to do it myself. */
ext = strrchr(filename,'.');
if (ext==NULL) ext=filename+strlen(filename); /* point to null, i.e. an empty string for the extension */
else ext=ext+1; /* skip the dot */
/* get basename + extension */
filename = pathname;
#if 0
//must detect empty extensions in folders with . in the name; not too important and DIR_SEPARATOR could improved
filename = strrchr(pathname, DIR_SEPARATOR);
if (filename == NULL)
filename = pathname; /* pathname has no separators (single filename) */
else
filename++; /* skip the separator */
#endif
return ext;
extension = strrchr(filename,'.');
if (extension==NULL)
extension = filename+strlen(filename); /* point to null, i.e. an empty string for the extension */
else
extension++; /* skip the dot */
return extension;
}
/* unused */

View File

@ -510,7 +510,7 @@ typedef enum {
meta_PS2_MCG, /* Gunvari MCG Files (was name .GCM on disk) */
meta_ZSD, /* Dragon Booster ZSD */
meta_RedSpark, /* "RedSpark" RSD (MadWorld) */
meta_PC_IVAUD, /* .ivaud GTA IV */
meta_IVAUD, /* .ivaud GTA IV */
meta_NDS_HWAS, /* Spider-Man 3, Tony Hawk's Downhill Jam, possibly more... */
meta_NGC_LPS, /* Rave Master (Groove Adventure Rave)(GC) */
meta_NAOMI_ADPCM, /* NAOMI/NAOMI2 ARcade games */
@ -686,6 +686,7 @@ typedef enum {
meta_TA_AAC_VITA, /* tri-Ace AAC (Judas Code) */
meta_OGG_GWM, /* Ogg Vorbis with encryption [Metronomicon (PC)] */
meta_H4M, /* Hudson HVQM4 video [Resident Evil 0 (GC), Tales of Symphonia (GC)] */
meta_OGG_MUS, /* Ogg Vorbis with encryption [Redux - Dark Matters (PC)] */
#ifdef VGM_USE_FFMPEG
meta_FFmpeg,