mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-14 18:47:39 +01:00
Merge pull request #207 from bnnm/yamaha-layouts-fixes
Yamaha, layouts, fixes
This commit is contained in:
commit
16423580a2
@ -154,7 +154,7 @@ void input_vgmstream::get_info(t_uint32 p_subsong, file_info & p_info, abort_cal
|
||||
if (get_description_tag(temp,description,"encoding: ")) p_info.info_set("codec",temp);
|
||||
if (get_description_tag(temp,description,"layout: ")) p_info.info_set("layout",temp);
|
||||
if (get_description_tag(temp,description,"interleave: ",' ')) p_info.info_set("interleave",temp);
|
||||
if (get_description_tag(temp,description,"last block interleave:",' ')) p_info.info_set("interleave_last_block",temp);
|
||||
if (get_description_tag(temp,description,"interleave last block:",' ')) p_info.info_set("interleave_last_block",temp);
|
||||
|
||||
if (get_description_tag(temp,description,"block size: ")) p_info.info_set("block_size",temp);
|
||||
if (get_description_tag(temp,description,"metadata from: ")) p_info.info_set("metadata_source",temp);
|
||||
|
@ -1,50 +0,0 @@
|
||||
#include "../util.h"
|
||||
#include "coding.h"
|
||||
|
||||
/* fixed point (.8) amount to scale the current step size by */
|
||||
/* part of the same series as used in MS ADPCM "ADPCMTable" */
|
||||
static const unsigned int scale_step[16] =
|
||||
{
|
||||
230, 230, 230, 230, 307, 409, 512, 614,
|
||||
230, 230, 230, 230, 307, 409, 512, 614
|
||||
};
|
||||
|
||||
/* expand an unsigned four bit delta to a wider signed range */
|
||||
static const int scale_delta[16] =
|
||||
{
|
||||
1, 3, 5, 7, 9, 11, 13, 15,
|
||||
-1, -3, -5, -7, -9,-11,-13,-15
|
||||
};
|
||||
|
||||
/* Yamaha AICA ADPCM (as seen in Dreamcast) */
|
||||
|
||||
void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
int i;
|
||||
int32_t sample_count;
|
||||
int32_t hist1 = stream->adpcm_history1_16;
|
||||
uint32_t step_size = stream->adpcm_step_index;
|
||||
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
int sample_nibble =
|
||||
(
|
||||
(unsigned)read_8bit(stream->offset+i/2,stream->streamfile) >>
|
||||
(i&1?4:0)
|
||||
)&0xf;
|
||||
|
||||
int32_t sample_delta = (int32_t)step_size * scale_delta[sample_nibble];
|
||||
int32_t new_sample;
|
||||
|
||||
new_sample = hist1 + sample_delta/8;
|
||||
|
||||
outbuf[sample_count] = clamp16(new_sample);
|
||||
|
||||
hist1 = outbuf[sample_count];
|
||||
|
||||
step_size = (step_size * scale_step[sample_nibble])/0x100;
|
||||
if (step_size < 0x7f) step_size = 0x7f;
|
||||
if (step_size > 0x6000) step_size = 0x6000;
|
||||
}
|
||||
|
||||
stream->adpcm_history1_16 = hist1;
|
||||
stream->adpcm_step_index = step_size;
|
||||
}
|
@ -17,8 +17,9 @@ void g72x_init_state(struct g72x_state *state_ptr);
|
||||
/* ima_decoder */
|
||||
void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||
void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||
void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_xbox_ima_mch(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_standard_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo, int is_high_first);
|
||||
void decode_3ds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
@ -116,8 +117,11 @@ void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first
|
||||
void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do);
|
||||
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels);
|
||||
|
||||
/* aica_decoder */
|
||||
/* yamaha_decoder */
|
||||
void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_yamaha(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_yamaha_nxap(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
size_t yamaha_bytes_to_samples(size_t bytes, int channels);
|
||||
|
||||
/* nds_procyon_decoder */
|
||||
void decode_nds_procyon(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
|
@ -389,8 +389,9 @@ void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * o
|
||||
/* ************************************ */
|
||||
|
||||
/* MS-IMA with fixed frame size, and outputs an even number of samples per frame (skips last nibble).
|
||||
* Defined in Xbox's SDK. Multichannel interleaves 2ch*N/2, or 1ch*N with odd num_channels. */
|
||||
void decode_xbox_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
* Defined in Xbox's SDK. Multichannel interleaves 2ch*N/2, or 1ch*N with odd num_channels
|
||||
* (seen in some Koei .wav, could be simplified as interleaved stereo) --unsure if official. */
|
||||
void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
int i, sample_count = 0;
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_index = stream->adpcm_step_index;
|
||||
@ -434,7 +435,51 @@ void decode_xbox_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample *
|
||||
|
||||
/* internal interleave: increment offset on complete frame */
|
||||
if (i == block_samples) {
|
||||
stream->offset += 0x24*vgmstream->channels;
|
||||
stream->offset += 0x24*channelspacing;
|
||||
}
|
||||
|
||||
stream->adpcm_history1_32 = hist1;
|
||||
stream->adpcm_step_index = step_index;
|
||||
}
|
||||
|
||||
/* Multichannel XBOX-IMA ADPCM, with all channels mixed in the same block (equivalent to multichannel MS-IMA; seen in .rsd XADP). */
|
||||
void decode_xbox_ima_mch(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
int i, sample_count = 0, num_frame;
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_index = stream->adpcm_step_index;
|
||||
|
||||
/* external interleave (fixed size), multichannel */
|
||||
int block_samples = (0x24 - 0x4) * 2;
|
||||
num_frame = first_sample / block_samples;
|
||||
first_sample = first_sample % block_samples;
|
||||
|
||||
/* normal header (hist+step+reserved), multichannel */
|
||||
if (first_sample == 0) {
|
||||
off_t header_offset = stream->offset + 0x24*channelspacing*num_frame + 0x04*channel;
|
||||
|
||||
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
|
||||
step_index = read_8bit(header_offset+0x02,stream->streamfile);
|
||||
if (step_index < 0) step_index=0;
|
||||
if (step_index > 88) step_index=88;
|
||||
|
||||
/* write header sample (even samples per block, skips last nibble) */
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
sample_count += channelspacing;
|
||||
first_sample += 1;
|
||||
samples_to_do -= 1;
|
||||
}
|
||||
|
||||
/* decode nibbles (layout: alternates 4 bytes/4*2 nibbles per channel) */
|
||||
for (i = first_sample; i < first_sample + samples_to_do; i++) {
|
||||
off_t byte_offset = (stream->offset + 0x24*channelspacing*num_frame + 0x04*channelspacing) + 0x04*channel + 0x04*channelspacing*((i-1)/8) + ((i-1)%8)/2;
|
||||
int nibble_shift = ((i-1)&1?4:0); /* low nibble first */
|
||||
|
||||
/* must skip last nibble per spec, rarely needed though */
|
||||
if (i < block_samples) {
|
||||
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
sample_count += channelspacing;
|
||||
}
|
||||
}
|
||||
|
||||
stream->adpcm_history1_32 = hist1;
|
||||
@ -613,6 +658,7 @@ void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channel
|
||||
stream->adpcm_step_index = step_index;
|
||||
}
|
||||
|
||||
/* Apple's IMA4, a.k.a QuickTime IMA. 2 byte header and header sample is not written (setup only). */
|
||||
void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
int i, sample_count, num_frame;
|
||||
int16_t hist1 = stream->adpcm_history1_16;//todo unneeded 16?
|
||||
|
149
src/coding/yamaha_decoder.c
Normal file
149
src/coding/yamaha_decoder.c
Normal file
@ -0,0 +1,149 @@
|
||||
#include "../util.h"
|
||||
#include "coding.h"
|
||||
|
||||
/* fixed point (.8) amount to scale the current step size by */
|
||||
/* part of the same series as used in MS ADPCM "ADPCMTable" */
|
||||
static const unsigned int scale_step[16] = {
|
||||
230, 230, 230, 230, 307, 409, 512, 614,
|
||||
230, 230, 230, 230, 307, 409, 512, 614
|
||||
};
|
||||
|
||||
/* expand an unsigned four bit delta to a wider signed range */
|
||||
static const int scale_delta[16] = {
|
||||
1, 3, 5, 7, 9, 11, 13, 15,
|
||||
-1, -3, -5, -7, -9,-11,-13,-15
|
||||
};
|
||||
|
||||
|
||||
/* Yamaha AICA ADPCM, as seen in Dreamcast. Possibly like RIFF codec 0x20 or used in older arcade sound chips. */
|
||||
void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
int i, sample_count;
|
||||
|
||||
int32_t hist1 = stream->adpcm_history1_16;
|
||||
int step_size = stream->adpcm_step_index;
|
||||
|
||||
/* no header (external setup), pre-clamp for wrong values */
|
||||
if (step_size < 0x7f) step_size = 0x7f;
|
||||
if (step_size > 0x6000) step_size = 0x6000;
|
||||
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
int sample_nibble, sample_decoded, sample_delta;
|
||||
off_t byte_offset = (stream->offset) + i/2;
|
||||
int nibble_shift = (i&1?4:0); /* low nibble first */
|
||||
|
||||
/* Yamaha/AICA expand, but same result as IMA's (((delta * 2 + 1) * step) >> 3) */
|
||||
sample_nibble = ((read_8bit(byte_offset,stream->streamfile) >> nibble_shift))&0xf;
|
||||
sample_delta = (step_size * scale_delta[sample_nibble]) / 8;
|
||||
sample_decoded = hist1 + sample_delta;
|
||||
|
||||
outbuf[sample_count] = clamp16(sample_decoded);
|
||||
hist1 = outbuf[sample_count];
|
||||
|
||||
step_size = (step_size * scale_step[sample_nibble]) >> 8;
|
||||
if (step_size < 0x7f) step_size = 0x7f;
|
||||
if (step_size > 0x6000) step_size = 0x6000;
|
||||
}
|
||||
|
||||
stream->adpcm_history1_16 = hist1;
|
||||
stream->adpcm_step_index = step_size;
|
||||
}
|
||||
|
||||
/* Yamaha ADPCM, in headered frames like MS-IMA. Possibly originated from Yamaha's SMAF tools
|
||||
* (Windows ACM encoder/decoder was given in their site). Some info from Rockbox's yamaha_adpcm.c */
|
||||
void decode_yamaha(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
int i, sample_count, num_frame;
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_size = stream->adpcm_step_index;
|
||||
|
||||
/* external interleave */
|
||||
int block_samples = (0x40 - 0x04*channelspacing) * 2 / channelspacing;
|
||||
num_frame = first_sample / block_samples;
|
||||
first_sample = first_sample % block_samples;
|
||||
|
||||
/* header (hist+step) */
|
||||
if (first_sample == 0) {
|
||||
off_t header_offset = stream->offset + 0x40*num_frame + 0x04*channel;
|
||||
|
||||
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
|
||||
step_size = read_16bitLE(header_offset+0x02,stream->streamfile);
|
||||
if (step_size < 0x7f) step_size = 0x7f;
|
||||
if (step_size > 0x6000) step_size = 0x6000;
|
||||
}
|
||||
|
||||
/* decode nibbles (layout: varies) */
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
int sample_nibble, sample_decoded, sample_delta;
|
||||
off_t byte_offset = (channelspacing == 2) ?
|
||||
(stream->offset + 0x40*num_frame + 0x04*channelspacing) + i : /* stereo: one nibble per channel */
|
||||
(stream->offset + 0x40*num_frame + 0x04*channelspacing) + i/2; /* mono: consecutive nibbles */
|
||||
int nibble_shift = (channelspacing == 2) ?
|
||||
(!(channel&1) ? 0:4) :
|
||||
(!(i&1) ? 0:4); /* even = low, odd = high */
|
||||
|
||||
/* Yamaha/AICA expand, but same result as IMA's (((delta * 2 + 1) * step) >> 3) */
|
||||
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
|
||||
sample_delta = (step_size * scale_delta[sample_nibble]) / 8;
|
||||
sample_decoded = hist1 + sample_delta;
|
||||
|
||||
outbuf[sample_count] = clamp16(sample_decoded);
|
||||
hist1 = outbuf[sample_count];
|
||||
|
||||
step_size = (step_size * scale_step[sample_nibble]) >> 8;
|
||||
if (step_size < 0x7f) step_size = 0x7f;
|
||||
if (step_size > 0x6000) step_size = 0x6000;
|
||||
}
|
||||
|
||||
stream->adpcm_history1_32 = hist1;
|
||||
stream->adpcm_step_index = step_size;
|
||||
}
|
||||
|
||||
/* Yamaha ADPCM with unknown expand variation (noisy), step size is double of normal Yamaha? */
|
||||
void decode_yamaha_nxap(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
int i, sample_count, num_frame;
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_size = stream->adpcm_step_index;
|
||||
|
||||
/* external interleave */
|
||||
int block_samples = (0x40 - 0x4) * 2;
|
||||
num_frame = first_sample / block_samples;
|
||||
first_sample = first_sample % block_samples;
|
||||
|
||||
/* header (hist+step) */
|
||||
if (first_sample == 0) {
|
||||
off_t header_offset = stream->offset + 0x40*num_frame;
|
||||
|
||||
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
|
||||
step_size = read_16bitLE(header_offset+0x02,stream->streamfile);
|
||||
if (step_size < 0x7f) step_size = 0x7f;
|
||||
if (step_size > 0x6000) step_size = 0x6000;
|
||||
}
|
||||
|
||||
/* decode nibbles (layout: all nibbles from one channel) */
|
||||
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||
int sample_nibble, sample_decoded, sample_delta;
|
||||
off_t byte_offset = (stream->offset + 0x40*num_frame + 0x04) + i/2;
|
||||
int nibble_shift = (i&1?4:0); /* low nibble first */
|
||||
|
||||
/* Yamaha expand? */
|
||||
sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf;
|
||||
sample_delta = (step_size * scale_delta[sample_nibble] / 4) / 8; //todo not ok
|
||||
sample_decoded = hist1 + sample_delta;
|
||||
|
||||
outbuf[sample_count] = clamp16(sample_decoded);
|
||||
hist1 = outbuf[sample_count];
|
||||
|
||||
step_size = (step_size * scale_step[sample_nibble]) >> 8;
|
||||
if (step_size < 0x7f) step_size = 0x7f;
|
||||
if (step_size > 0x6000) step_size = 0x6000;
|
||||
}
|
||||
|
||||
stream->adpcm_history1_32 = hist1;
|
||||
stream->adpcm_step_index = step_size;
|
||||
}
|
||||
|
||||
size_t yamaha_bytes_to_samples(size_t bytes, int channels) {
|
||||
int block_align = 0x40;
|
||||
|
||||
return (bytes / block_align) * (block_align - 0x04*channels) * 2 / channels
|
||||
+ ((bytes % block_align) ? ((bytes % block_align) - 0x04*channels) * 2 / channels : 0);
|
||||
}
|
@ -166,6 +166,7 @@ static const char* extension_list[] = {
|
||||
"ktss",
|
||||
"kvs",
|
||||
|
||||
"l",
|
||||
"laac", //fake extension, for AAC (tri-Ace/FFmpeg)
|
||||
"lac3", //fake extension, for AC3
|
||||
"leg",
|
||||
@ -240,6 +241,7 @@ static const char* extension_list[] = {
|
||||
"psnd",
|
||||
"psw",
|
||||
|
||||
"r",
|
||||
"rac", //txth/reserved [Manhunt (Xbox)]
|
||||
"rak",
|
||||
"ras",
|
||||
@ -291,6 +293,7 @@ static const char* extension_list[] = {
|
||||
"sli",
|
||||
"smp",
|
||||
"smpl", //fake extension (to be removed)
|
||||
"smv",
|
||||
"snd",
|
||||
"snds",
|
||||
"sng",
|
||||
@ -479,6 +482,7 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_3DS_IMA, "3DS IMA 4-bit ADPCM"},
|
||||
{coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"},
|
||||
{coding_XBOX_IMA, "XBOX 4-bit IMA ADPCM"},
|
||||
{coding_XBOX_IMA_mch, "XBOX 4-bit IMA ADPCM (multichannel)"},
|
||||
{coding_XBOX_IMA_int, "XBOX 4-bit IMA ADPCM (mono/interleave)"},
|
||||
{coding_NDS_IMA, "NDS-style 4-bit IMA ADPCM"},
|
||||
{coding_DAT4_IMA, "Eurocom DAT4 4-bit IMA ADPCM"},
|
||||
@ -496,6 +500,8 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_MSADPCM, "Microsoft 4-bit ADPCM"},
|
||||
{coding_WS, "Westwood Studios VBR ADPCM"},
|
||||
{coding_AICA, "Yamaha AICA 4-bit ADPCM"},
|
||||
{coding_YAMAHA, "Yamaha 4-bit ADPCM"},
|
||||
{coding_YAMAHA_NXAP, "Yamaha NXAP 4-bit ADPCM"},
|
||||
{coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"},
|
||||
{coding_L5_555, "Level-5 0x555 4-bit ADPCM"},
|
||||
{coding_SASSC, "Activision / EXAKT SASSC 8-bit DPCM"},
|
||||
@ -548,7 +554,11 @@ static const coding_info coding_info_list[] = {
|
||||
static const layout_info layout_info_list[] = {
|
||||
{layout_none, "flat (no layout)"},
|
||||
{layout_interleave, "interleave"},
|
||||
{layout_interleave_shortblock, "interleave with short last block"},
|
||||
|
||||
{layout_segmented, "segmented"},
|
||||
{layout_aix, "AIX interleave, internally 18-byte interleaved"},
|
||||
{layout_scd_int, "SCD multistream interleave"},
|
||||
|
||||
{layout_mxch_blocked, "MxCh blocked"},
|
||||
{layout_ast_blocked, "AST blocked"},
|
||||
{layout_halpst_blocked, "HALPST blocked"},
|
||||
@ -556,7 +566,7 @@ static const layout_info layout_info_list[] = {
|
||||
{layout_blocked_ea_schl, "blocked (EA SCHl)"},
|
||||
{layout_blocked_ea_1snh, "blocked (EA 1SNh)"},
|
||||
{layout_blocked_caf, "blocked (CAF)"},
|
||||
{layout_wsi_blocked, ".wsi blocked"},
|
||||
{layout_blocked_wsi, "blocked (WSI)"},
|
||||
{layout_xvas_blocked, ".xvas blocked"},
|
||||
{layout_str_snds_blocked, ".str SNDS blocked"},
|
||||
{layout_ws_aud_blocked, "Westwood Studios .aud blocked"},
|
||||
@ -577,17 +587,11 @@ static const layout_info layout_info_list[] = {
|
||||
{layout_blocked_rws, "blocked (RWS)"},
|
||||
{layout_blocked_hwas, "blocked (HWAS)"},
|
||||
{layout_tra_blocked, "TRA blocked"},
|
||||
{layout_aix, "AIX interleave, internally 18-byte interleaved"},
|
||||
{layout_segmented, "segmented"},
|
||||
{layout_scd_int, "SCD multistream interleave"},
|
||||
{layout_blocked_ea_sns, "blocked (EA SNS)"},
|
||||
{layout_blocked_awc, "blocked (AWC)"},
|
||||
{layout_blocked_vgs, "blocked (VGS)"},
|
||||
{layout_blocked_vawx, "blocked (VAWX)"},
|
||||
{layout_blocked_xvag_subsong, "blocked (XVAG subsong)"},
|
||||
#ifdef VGM_USE_VORBIS
|
||||
{layout_ogg_vorbis, "Ogg"},
|
||||
#endif
|
||||
};
|
||||
|
||||
static const meta_info meta_info_list[] = {
|
||||
@ -653,7 +657,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_DSP_SADB, "Procyon Studio SADB header"},
|
||||
{meta_SADL, "Procyon Studio SADL header"},
|
||||
{meta_PS2_BMDX, "Beatmania .bmdx header"},
|
||||
{meta_DSP_WSI, ".wsi header"},
|
||||
{meta_DSP_WSI, "Alone in the Dark .WSI header"},
|
||||
{meta_AIFC, "Audio Interchange File Format AIFF-C"},
|
||||
{meta_AIFF, "Audio Interchange File Format"},
|
||||
{meta_STR_SNDS, ".str SNDS SHDR chunk"},
|
||||
@ -707,7 +711,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_XNB, "Microsoft XNA Game Studio 4.0 header"},
|
||||
{meta_SCD_PCM, "Lunar: Eternal Blue .PCM header"},
|
||||
{meta_PS2_PCM, "Konami KCEJ East .PCM header"},
|
||||
{meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV Header"},
|
||||
{meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV PS2 header"},
|
||||
{meta_PS2_PSW, "Rayman Raving Rabbids Riff Container File"},
|
||||
{meta_PS2_VAS, "Pro Baseball Spirits 5 VAS Header"},
|
||||
{meta_PS2_TEC, "assumed TECMO badflagged stream by .tec extension"},
|
||||
@ -729,23 +733,24 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_PS2_MIHB, "MIH+MIB header"},
|
||||
{meta_DSP_WII_MUS, "mus header"},
|
||||
{meta_WII_SNG, "SNG DSP Header"},
|
||||
{meta_RSD2VAG, "RSD2/VAG Header"},
|
||||
{meta_RSD2PCMB, "RSD2/PCMB Header"},
|
||||
{meta_RSD2XADP, "RSD2/XADP Header"},
|
||||
{meta_RSD3VAG, "RSD3/VAG Header"},
|
||||
{meta_RSD3GADP, "RSD3/GADP Header"},
|
||||
{meta_RSD3PCM, "RSD3/PCM Header"},
|
||||
{meta_RSD3PCMB, "RSD3/PCMB Header"},
|
||||
{meta_RSD4PCMB, "RSD4/PCMB Header"},
|
||||
{meta_RSD4PCM, "RSD4/PCM Header"},
|
||||
{meta_RSD4RADP, "RSD4/RADP Header"},
|
||||
{meta_RSD4VAG, "RSD4/VAG Header"},
|
||||
{meta_RSD6XADP, "RSD6/XADP Header"},
|
||||
{meta_RSD6VAG, "RSD6/VAG Header"},
|
||||
{meta_RSD6WADP, "RSD6/WADP Header"},
|
||||
{meta_RSD6RADP, "RSD6/RADP Header"},
|
||||
{meta_RSD6XMA, "RSD6/XMA Header"},
|
||||
{meta_RSD6AT3P, "RSD6/AT3+ Header"},
|
||||
{meta_RSD2VAG, "Radical RSD2/VAG header"},
|
||||
{meta_RSD2PCMB, "Radical RSD2/PCMB header"},
|
||||
{meta_RSD2XADP, "Radical RSD2/XADP header"},
|
||||
{meta_RSD3VAG, "Radical RSD3/VAG header"},
|
||||
{meta_RSD3GADP, "Radical RSD3/GADP header"},
|
||||
{meta_RSD3PCM, "Radical RSD3/PCM header"},
|
||||
{meta_RSD3PCMB, "Radical RSD3/PCMB header"},
|
||||
{meta_RSD4PCMB, "Radical RSD4/PCMB header"},
|
||||
{meta_RSD4PCM, "Radical RSD4/PCM header"},
|
||||
{meta_RSD4RADP, "Radical RSD4/RADP header"},
|
||||
{meta_RSD4VAG, "Radical RSD4/VAG header"},
|
||||
{meta_RSD6XADP, "Radical RSD6/XADP header"},
|
||||
{meta_RSD6VAG, "Radical RSD6/VAG header"},
|
||||
{meta_RSD6WADP, "Radical RSD6/WADP header"},
|
||||
{meta_RSD6RADP, "Radical RSD6/RADP header"},
|
||||
{meta_RSD6XMA, "Radical RSD6/XMA header"},
|
||||
{meta_RSD6AT3P, "Radical RSD6/AT3+ header"},
|
||||
{meta_RSD6WMA, "Radical RSD6/WMA header"},
|
||||
{meta_DC_ASD, "ASD Header"},
|
||||
{meta_NAOMI_SPSD, "SPSD Header"},
|
||||
{meta_FFXI_BGW, "BGW BGMStream header"},
|
||||
@ -835,7 +840,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_PS2_MSA, "Psyvariar -Complete Edition- MSA header"},
|
||||
{meta_PC_SMP, "Ghostbusters .smp Header"},
|
||||
{meta_NGC_PDT, "PDT DSP header"},
|
||||
{meta_NGC_BO2, "Blood Omen 2 DSP header"},
|
||||
{meta_NGC_RKV, "Legacy of Kain - Blood Omen 2 RKV GC header"},
|
||||
{meta_DSP_DDSP, ".DDSP header"},
|
||||
{meta_P3D, "Radical P3D header"},
|
||||
{meta_PS2_TK1, "Tekken TK5STRM1 Header"},
|
||||
@ -922,7 +927,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_GTD, "GTD/GHS header"},
|
||||
{meta_TA_AAC_X360, "tri-Ace AAC (X360) header"},
|
||||
{meta_TA_AAC_PS3, "tri-Ace AAC (PS3) header"},
|
||||
{meta_TA_AAC_VORBIS, "tri-Ace AAC (Mobile Vorbis) header"},
|
||||
{meta_TA_AAC_MOBILE, "tri-Ace AAC (Mobile) header"},
|
||||
{meta_PS3_MTA2, "Konami MTA2 header"},
|
||||
{meta_NGC_ULW, "Criterion ULW raw header"},
|
||||
{meta_PC_XA30, "Reflections XA30 PC header"},
|
||||
@ -964,6 +969,8 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_WAF, "KID WAF header"},
|
||||
{meta_WAVE, "EngineBlack .WAVE header"},
|
||||
{meta_WAVE_segmented, "EngineBlack .WAVE header (segmented)"},
|
||||
{meta_SMV, "Cho Aniki Zero .SMV header"},
|
||||
{meta_NXAP, "Nex NXAP header"},
|
||||
|
||||
#ifdef VGM_USE_MP4V2
|
||||
{meta_MP4, "AAC header"},
|
||||
|
@ -89,8 +89,8 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
|
||||
case layout_blocked_caf:
|
||||
block_update_caf(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_wsi_blocked:
|
||||
wsi_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
case layout_blocked_wsi:
|
||||
block_update_wsi(vgmstream->next_block_offset,vgmstream);
|
||||
break;
|
||||
case layout_str_snds_blocked:
|
||||
str_snds_block_update(vgmstream->next_block_offset,vgmstream);
|
||||
|
21
src/layout/blocked_wsi.c
Normal file
21
src/layout/blocked_wsi.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include "layout.h"
|
||||
#include "../vgmstream.h"
|
||||
|
||||
/* .wsi - headered blocks with a single channel */
|
||||
void block_update_wsi(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
|
||||
int i;
|
||||
off_t channel_block_size;
|
||||
|
||||
|
||||
/* assume that all channels have the same size for this block */
|
||||
channel_block_size = read_32bitBE(block_offset, streamFile);
|
||||
|
||||
vgmstream->current_block_offset = block_offset;
|
||||
vgmstream->current_block_size = channel_block_size - 0x10; /* remove header */
|
||||
vgmstream->next_block_offset = block_offset + channel_block_size*vgmstream->channels;
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
vgmstream->ch[i].offset = block_offset + channel_block_size*i + 0x10;
|
||||
}
|
||||
}
|
@ -10,12 +10,12 @@ void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREA
|
||||
|
||||
samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame;
|
||||
|
||||
if (vgmstream->layout_type == layout_interleave_shortblock &&
|
||||
if (vgmstream->interleave_last_block_size && vgmstream->channels > 1 &&
|
||||
vgmstream->current_sample - vgmstream->samples_into_block + samples_this_block> vgmstream->num_samples) {
|
||||
frame_size = get_vgmstream_shortframe_size(vgmstream);
|
||||
samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream);
|
||||
|
||||
samples_this_block = vgmstream->interleave_smallblock_size / frame_size * samples_per_frame;
|
||||
samples_this_block = vgmstream->interleave_last_block_size / frame_size * samples_per_frame;
|
||||
}
|
||||
|
||||
while (samples_written<sample_count) {
|
||||
@ -23,7 +23,7 @@ void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREA
|
||||
|
||||
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
|
||||
/* we assume that the loop is not back into a short block */
|
||||
if (vgmstream->layout_type == layout_interleave_shortblock) {
|
||||
if (vgmstream->interleave_last_block_size && vgmstream->channels > 1) {
|
||||
frame_size = get_vgmstream_frame_size(vgmstream);
|
||||
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
|
||||
samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame;
|
||||
@ -45,14 +45,14 @@ void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREA
|
||||
|
||||
if (vgmstream->samples_into_block==samples_this_block) {
|
||||
int chan;
|
||||
if (vgmstream->layout_type == layout_interleave_shortblock &&
|
||||
if (vgmstream->interleave_last_block_size && vgmstream->channels > 1 &&
|
||||
vgmstream->current_sample + samples_this_block > vgmstream->num_samples) {
|
||||
frame_size = get_vgmstream_shortframe_size(vgmstream);
|
||||
samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream);
|
||||
|
||||
samples_this_block = vgmstream->interleave_smallblock_size / frame_size * samples_per_frame;
|
||||
samples_this_block = vgmstream->interleave_last_block_size / frame_size * samples_per_frame;
|
||||
for (chan=0;chan<vgmstream->channels;chan++)
|
||||
vgmstream->ch[chan].offset+=vgmstream->interleave_block_size*(vgmstream->channels-chan)+vgmstream->interleave_smallblock_size*chan;
|
||||
vgmstream->ch[chan].offset+=vgmstream->interleave_block_size*(vgmstream->channels-chan)+vgmstream->interleave_last_block_size*chan;
|
||||
} else {
|
||||
|
||||
for (chan=0;chan<vgmstream->channels;chan++)
|
||||
|
@ -18,8 +18,7 @@ void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_ea_1snh(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_caf(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void wsi_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_wsi(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
void str_snds_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
#include "layout.h"
|
||||
#include "../vgmstream.h"
|
||||
|
||||
/* set up for the block at the given offset */
|
||||
void wsi_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
int i;
|
||||
|
||||
/* assume that all channels have the same size for this block */
|
||||
|
||||
vgmstream->current_block_offset = block_offset;
|
||||
/* current_block_size is the data size in this block, so subtract header */
|
||||
vgmstream->current_block_size = read_32bitBE(
|
||||
vgmstream->current_block_offset,
|
||||
vgmstream->ch[0].streamfile) - 0x10;
|
||||
vgmstream->next_block_offset =
|
||||
vgmstream->current_block_offset +
|
||||
(vgmstream->current_block_size + 0x10) * vgmstream->channels;
|
||||
|
||||
for (i=0;i<vgmstream->channels;i++) {
|
||||
vgmstream->ch[i].offset = vgmstream->current_block_offset +
|
||||
0x10 + (vgmstream->current_block_size+0x10)*i;
|
||||
}
|
||||
}
|
@ -610,10 +610,6 @@
|
||||
RelativePath=".\meta\ngc_bh2pcm.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\ngc_bo2.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\caf.c"
|
||||
>
|
||||
@ -662,6 +658,10 @@
|
||||
RelativePath=".\meta\ngc_ssm.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\ngc_str_cauldron.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\ngc_tydsp.c"
|
||||
>
|
||||
@ -698,6 +698,10 @@
|
||||
RelativePath=".\meta\nwa.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\nxap.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\ogg_vorbis.c"
|
||||
>
|
||||
@ -1186,6 +1190,10 @@
|
||||
RelativePath=".\meta\sli.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\smv.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\sps_n1.c"
|
||||
>
|
||||
@ -1471,7 +1479,7 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\aica_decoder.c"
|
||||
RelativePath=".\coding\yamaha_decoder.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
@ -1815,7 +1823,7 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\layout\wsi_blocked.c"
|
||||
RelativePath=".\layout\blocked_wsi.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
|
@ -258,7 +258,6 @@
|
||||
<ClCompile Include="meta\nds_swav.c" />
|
||||
<ClCompile Include="meta\ngc_adpdtk.c" />
|
||||
<ClCompile Include="meta\ngc_bh2pcm.c" />
|
||||
<ClCompile Include="meta\ngc_bo2.c" />
|
||||
<ClCompile Include="meta\caf.c" />
|
||||
<ClCompile Include="meta\ngc_dsp_konami.c" />
|
||||
<ClCompile Include="meta\ngc_dsp_mpds.c" />
|
||||
@ -271,12 +270,14 @@
|
||||
<ClCompile Include="meta\ngc_pdt.c" />
|
||||
<ClCompile Include="meta\ngc_sck_dsp.c" />
|
||||
<ClCompile Include="meta\ngc_ssm.c" />
|
||||
<ClCompile Include="meta\ngc_str_cauldron.c" />
|
||||
<ClCompile Include="meta\ngc_tydsp.c" />
|
||||
<ClCompile Include="meta\ngc_ymf.c" />
|
||||
<ClCompile Include="meta\ngc_ulw.c" />
|
||||
<ClCompile Include="meta\ngc_vid1.c" />
|
||||
<ClCompile Include="meta\nub_xma.c" />
|
||||
<ClCompile Include="meta\nwa.c" />
|
||||
<ClCompile Include="meta\nxap.c" />
|
||||
<ClCompile Include="meta\ogg_vorbis.c" />
|
||||
<ClCompile Include="meta\ogl.c" />
|
||||
<ClCompile Include="meta\omu.c" />
|
||||
@ -380,6 +381,7 @@
|
||||
<ClCompile Include="meta\sdt.c" />
|
||||
<ClCompile Include="meta\sfl.c" />
|
||||
<ClCompile Include="meta\sli.c" />
|
||||
<ClCompile Include="meta\smv.c" />
|
||||
<ClCompile Include="meta\sps_n1.c" />
|
||||
<ClCompile Include="meta\spt_spd.c" />
|
||||
<ClCompile Include="meta\stm.c" />
|
||||
@ -430,7 +432,7 @@
|
||||
<ClCompile Include="meta\zwdsp.c" />
|
||||
<ClCompile Include="coding\acm_decoder.c" />
|
||||
<ClCompile Include="coding\adx_decoder.c" />
|
||||
<ClCompile Include="coding\aica_decoder.c" />
|
||||
<ClCompile Include="coding\yamaha_decoder.c" />
|
||||
<ClCompile Include="coding\ea_mt_decoder.c" />
|
||||
<ClCompile Include="coding\ea_xa_decoder.c" />
|
||||
<ClCompile Include="coding\ea_xas_decoder.c" />
|
||||
@ -498,7 +500,7 @@
|
||||
<ClCompile Include="layout\thp_blocked.c" />
|
||||
<ClCompile Include="layout\vs_blocked.c" />
|
||||
<ClCompile Include="layout\ws_aud_blocked.c" />
|
||||
<ClCompile Include="layout\wsi_blocked.c" />
|
||||
<ClCompile Include="layout\blocked_wsi.c" />
|
||||
<ClCompile Include="layout\xa_blocked.c" />
|
||||
<ClCompile Include="layout\xvas_block.c" />
|
||||
<ClCompile Include="..\ext_libs\clHCA.c" />
|
||||
|
@ -358,9 +358,6 @@
|
||||
<ClCompile Include="meta\ngc_bh2pcm.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\ngc_bo2.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\caf.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -397,6 +394,9 @@
|
||||
<ClCompile Include="meta\ngc_ssm.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\ngc_str_cauldron.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\ngc_tydsp.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -415,6 +415,9 @@
|
||||
<ClCompile Include="meta\nwa.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\nxap.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\ogg_vorbis.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -724,6 +727,9 @@
|
||||
<ClCompile Include="meta\sli.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\smv.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\sps_n1.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -868,7 +874,7 @@
|
||||
<ClCompile Include="coding\adx_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coding\aica_decoder.c">
|
||||
<ClCompile Include="coding\yamaha_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coding\ea_mt_decoder.c">
|
||||
@ -1069,7 +1075,7 @@
|
||||
<ClCompile Include="layout\ws_aud_blocked.c">
|
||||
<Filter>layout\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="layout\wsi_blocked.c">
|
||||
<ClCompile Include="layout\blocked_wsi.c">
|
||||
<Filter>layout\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="layout\xa_blocked.c">
|
||||
|
251
src/meta/akb.c
251
src/meta/akb.c
@ -3,7 +3,7 @@
|
||||
|
||||
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
|
||||
/* AKB (AAC only) - found in SQEX iOS games */
|
||||
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * init_vgmstream_akb_mp4(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
|
||||
size_t filesize;
|
||||
@ -34,74 +34,99 @@ fail:
|
||||
|
||||
|
||||
/* AKB - found in SQEX iOS games */
|
||||
VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset, extra_data_offset = 0;
|
||||
size_t file_size, header_size, extra_header_size = 0, extra_data_size = 0;
|
||||
int loop_flag = 0, channel_count, codec;
|
||||
off_t start_offset, extradata_offset = 0;
|
||||
size_t stream_size, header_size, subheader_size = 0, extradata_size = 0;
|
||||
int loop_flag = 0, channel_count, codec, sample_rate;
|
||||
int num_samples, loop_start, loop_end;
|
||||
|
||||
/* check extensions */
|
||||
|
||||
/* checks */
|
||||
/* .akb.bytes is the usual extension in later games */
|
||||
if ( !check_extensions(streamFile, "akb") )
|
||||
if ( !check_extensions(streamFile, "akb,bytes") )
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x414B4220) /* "AKB " */
|
||||
goto fail;
|
||||
if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
|
||||
channel_count = read_8bit(0x0d,streamFile);
|
||||
loop_flag = read_32bitLE(0x18,streamFile) > 0; /* loop end */
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* 0x04 (2): version (iPad/IPhone?) */
|
||||
/* 0x04(2): version? (iPad/IPhone?) */
|
||||
header_size = read_16bitLE(0x06,streamFile);
|
||||
file_size = read_32bitLE(0x08,streamFile);
|
||||
codec = read_8bit(0x0c,streamFile);
|
||||
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x0e,streamFile);
|
||||
vgmstream->num_samples = read_32bitLE(0x10,streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(0x18,streamFile);
|
||||
vgmstream->meta_type = meta_AKB;
|
||||
|
||||
/* should be ok but not exact (probably more complex, see AKB2) */
|
||||
if ( header_size >= 0x44) { /* v2 */
|
||||
/* 0x10+: config? (pan, volume), 0x24: file_id? */
|
||||
extra_data_size = read_16bitLE(0x1c,streamFile);
|
||||
extra_header_size = read_16bitLE(0x28,streamFile);
|
||||
extra_data_offset = header_size + extra_header_size;
|
||||
start_offset = extra_data_offset + extra_data_size;
|
||||
/* ~num_samples at extra_data_offset + 0x04/0x0c? */
|
||||
codec = read_8bit(0x0c,streamFile);
|
||||
channel_count = read_8bit(0x0d,streamFile);
|
||||
sample_rate = (uint16_t)read_16bitLE(0x0e,streamFile);
|
||||
num_samples = read_32bitLE(0x10,streamFile);
|
||||
loop_start = read_32bitLE(0x14,streamFile);
|
||||
loop_end = read_32bitLE(0x18,streamFile);
|
||||
|
||||
/* possibly more complex, see AKB2 */
|
||||
if (header_size >= 0x44) { /* v2 */
|
||||
extradata_size = read_16bitLE(0x1c,streamFile);
|
||||
subheader_size = read_16bitLE(0x28,streamFile);
|
||||
/* 0x20+: config? (pan, volume), 0x24: file_id? */
|
||||
extradata_offset = header_size + subheader_size;
|
||||
start_offset = extradata_offset + extradata_size;
|
||||
}
|
||||
else { /* v0 */
|
||||
start_offset = header_size;
|
||||
}
|
||||
|
||||
stream_size = get_streamfile_size(streamFile) - start_offset;
|
||||
loop_flag = read_32bitLE(0x18,streamFile) > 0; /* loop end */
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->meta_type = meta_AKB;
|
||||
|
||||
|
||||
switch (codec) {
|
||||
case 0x02: { /* MSAPDCM [various SFX] */
|
||||
case 0x02: { /* MSAPDCM [Dragon Quest II (iOS) sfx] */
|
||||
vgmstream->coding_type = coding_MSADPCM;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = read_16bitLE(extra_data_offset + 0x02,streamFile);
|
||||
vgmstream->interleave_block_size = read_16bitLE(extradata_offset + 0x02,streamFile);
|
||||
|
||||
/* adjusted samples; bigger or smaller than base samples, but seems more accurate
|
||||
* (base samples may have more than possible and read over file size otherwise, very strange)
|
||||
* loop_end seems to exist even with loop disabled */
|
||||
vgmstream->num_samples = read_32bitLE(extra_data_offset + 0x04, streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(extra_data_offset + 0x08, streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(extra_data_offset + 0x0c, streamFile);
|
||||
vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, streamFile);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case 0x05: { /* Ogg Vorbis [Final Fantasy VI, Dragon Quest II-VI] */
|
||||
/* Starting from an offset in the current libvorbis code is a bit hard so just use FFmpeg.
|
||||
* Decoding seems to produce the same output with (inaudible) +-1 lower byte differences due to rounding. */
|
||||
#ifdef VGM_USE_VORBIS
|
||||
case 0x05: { /* Ogg Vorbis [Final Fantasy VI (iOS), Dragon Quest II-VI (iOS)] */
|
||||
VGMSTREAM *ogg_vgmstream = NULL;
|
||||
ogg_vorbis_meta_info_t ovmi = {0};
|
||||
|
||||
ovmi.meta_type = vgmstream->meta_type;
|
||||
ovmi.stream_size = stream_size;
|
||||
|
||||
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
|
||||
if (ogg_vgmstream) {
|
||||
close_vgmstream(vgmstream);
|
||||
return ogg_vgmstream;
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#elif defined(VGM_USE_FFMPEG)
|
||||
/* Alt decoding without libvorbis (minor number of beginning samples difference).
|
||||
* Otherwise same output with (inaudible) +-1 lower byte differences due to rounding. */
|
||||
case 0x05: { /* Ogg Vorbis [Final Fantasy VI (iOS), Dragon Quest II-VI (iOS)] */
|
||||
ffmpeg_codec_data *ffmpeg_data;
|
||||
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,file_size-start_offset);
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
|
||||
if ( !ffmpeg_data ) goto fail;
|
||||
|
||||
vgmstream->codec_data = ffmpeg_data;
|
||||
@ -109,20 +134,30 @@ VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
/* These oggs have loop info in the comments, too */
|
||||
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case 0x06: { /* aac [The World Ends with You (iPad)] */
|
||||
/* init_vgmstream_akb above has priority, but this works fine too */
|
||||
/* init_vgmstream_akb_mp4 above has priority, but this works fine too */
|
||||
ffmpeg_codec_data *ffmpeg_data;
|
||||
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,file_size-start_offset);
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size-start_offset);
|
||||
if ( !ffmpeg_data ) goto fail;
|
||||
|
||||
vgmstream->codec_data = ffmpeg_data;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
|
||||
/* remove encoder delay from the "global" sample values */
|
||||
vgmstream->num_samples -= ffmpeg_data->skipSamples;
|
||||
vgmstream->loop_start_sample -= ffmpeg_data->skipSamples;
|
||||
@ -149,80 +184,134 @@ fail:
|
||||
|
||||
|
||||
/* AKB2 - found in later SQEX iOS games */
|
||||
VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset, header_offset;
|
||||
size_t datasize;
|
||||
int loop_flag = 0, channel_count, codec;
|
||||
int akb_header_size, sound_index = 0, sound_offset_data, sound, sound_header_size, material_offset_data, material_index = 0, material, extradata, encryption_flag;
|
||||
off_t start_offset, material_offset, extradata_offset;
|
||||
size_t material_size, extradata_size, stream_size;
|
||||
int loop_flag = 0, channel_count, encryption_flag, codec, sample_rate, num_samples, loop_start, loop_end;
|
||||
int total_subsongs, target_subsong = streamFile->stream_index;
|
||||
|
||||
/* check extensions */
|
||||
/* .akb.bytes is the usual extension in later games */
|
||||
if ( !check_extensions(streamFile, "akb") )
|
||||
if ( !check_extensions(streamFile, "akb,bytes") )
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
/* checks */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x414B4232) /* "AKB2" */
|
||||
goto fail;
|
||||
if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
|
||||
akb_header_size = read_16bitLE(0x06, streamFile);
|
||||
sound_offset_data = akb_header_size + sound_index * 0x10;
|
||||
sound = read_32bitLE(sound_offset_data + 0x04, streamFile);
|
||||
sound_header_size = read_16bitLE(sound + 0x02, streamFile);
|
||||
material_offset_data = sound + sound_header_size + material_index * 0x10;
|
||||
material = sound + read_32bitLE(material_offset_data + 0x04, streamFile);
|
||||
encryption_flag = read_8bit(material + 0x03, streamFile) & 0x08;
|
||||
extradata = material + read_16bitLE(material + 0x04, streamFile);
|
||||
/* parse tables */
|
||||
{
|
||||
off_t table_offset;
|
||||
size_t table_size, entry_size;
|
||||
off_t akb_header_size = read_16bitLE(0x06, streamFile);
|
||||
int table_count = read_8bit(0x0c, streamFile);
|
||||
|
||||
start_offset = material + read_16bitLE(material + 0x04, streamFile) + read_32bitLE(material + 0x18, streamFile);
|
||||
header_offset = material;
|
||||
/* probably each table has its type somewhere, but only seen last table = sound table */
|
||||
if (table_count > 2) /* 2 only seen in some Mobius FF sound banks */
|
||||
goto fail;
|
||||
entry_size = 0x10; /* technically every entry/table has its own size but to simplify... */
|
||||
|
||||
table_offset = read_32bitLE(akb_header_size + (table_count-1)*entry_size + 0x04, streamFile);
|
||||
table_size = read_16bitLE(table_offset + 0x02, streamFile);
|
||||
|
||||
total_subsongs = read_8bit(table_offset + 0x0f, streamFile); /* can contain 0 entries too */
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
|
||||
|
||||
material_offset = table_offset + read_32bitLE(table_offset + table_size + (target_subsong-1)*entry_size + 0x04, streamFile);
|
||||
}
|
||||
|
||||
/** stream header **/
|
||||
/* 0x00: 0? */
|
||||
codec = read_8bit(material_offset+0x01,streamFile);
|
||||
channel_count = read_8bit(material_offset+0x02,streamFile);
|
||||
encryption_flag = read_8bit(material_offset+0x03,streamFile);
|
||||
material_size = read_16bitLE(material_offset+0x04,streamFile);
|
||||
sample_rate = (uint16_t)read_16bitLE(material_offset+0x06,streamFile);
|
||||
stream_size = read_32bitLE(material_offset+0x08,streamFile);
|
||||
num_samples = read_32bitLE(material_offset+0x0c,streamFile);
|
||||
|
||||
loop_start = read_32bitLE(material_offset+0x10,streamFile);
|
||||
loop_end = read_32bitLE(material_offset+0x14,streamFile);
|
||||
extradata_size = read_32bitLE(material_offset+0x18,streamFile);
|
||||
/* rest: ? (empty or 0x3f80) */
|
||||
|
||||
loop_flag = (loop_end > 0);
|
||||
extradata_offset = material_offset + material_size;
|
||||
start_offset = material_offset + material_size + extradata_size;
|
||||
|
||||
channel_count = read_8bit(header_offset+0x02,streamFile);
|
||||
loop_flag = read_32bitLE(header_offset+0x14,streamFile) > 0; /* loop end */
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* 0x04: version? 0x08: filesize, 0x28: file_id?, others: no idea */
|
||||
codec = read_8bit(header_offset+0x01,streamFile);
|
||||
datasize = read_32bitLE(header_offset+0x08,streamFile);
|
||||
vgmstream->sample_rate = (uint16_t)read_16bitLE(header_offset+0x06,streamFile);
|
||||
/* When loop_flag num_samples may be much larger than real num_samples (it's fine when looping is off)
|
||||
* Actual num_samples would be loop_end_sample+1, but more testing is needed */
|
||||
vgmstream->num_samples = read_32bitLE(header_offset+0x0c,streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(header_offset+0x10,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(header_offset+0x14,streamFile);
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_streams = total_subsongs;
|
||||
vgmstream->stream_size = stream_size;
|
||||
|
||||
vgmstream->meta_type = meta_AKB;
|
||||
|
||||
switch (codec) {
|
||||
case 0x02: { /* MSAPDCM [The Irregular at Magic High School Lost Zero (Android)] */
|
||||
if (encryption_flag) goto fail;
|
||||
case 0x02: { /* MSADPCM [The Irregular at Magic High School Lost Zero (Android)] */
|
||||
if (encryption_flag & 0x08) goto fail;
|
||||
vgmstream->coding_type = coding_MSADPCM;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = read_16bitLE(extradata + 0x02, streamFile);
|
||||
vgmstream->interleave_block_size = read_16bitLE(extradata_offset + 0x02, streamFile);
|
||||
|
||||
/* adjusted samples; bigger or smaller than base samples, but seems more accurate
|
||||
* (base samples may have more than possible and read over file size otherwise, very strange)
|
||||
* loop_end seems to exist even with loop disabled */
|
||||
vgmstream->num_samples = read_32bitLE(extradata + 0x04, streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(extradata + 0x08, streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(extradata + 0x0c, streamFile);
|
||||
vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, streamFile);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case 0x05: { /* ogg vorbis [The World Ends with You (iPhone / latest update)] */
|
||||
#ifdef VGM_USE_VORBIS
|
||||
case 0x05: { /* Ogg Vorbis [The World Ends with You (iOS / latest update)] */
|
||||
VGMSTREAM *ogg_vgmstream = NULL;
|
||||
ogg_vorbis_meta_info_t ovmi = {0};
|
||||
|
||||
ovmi.meta_type = vgmstream->meta_type;
|
||||
ovmi.total_subsongs = total_subsongs;
|
||||
ovmi.stream_size = stream_size;
|
||||
|
||||
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
|
||||
if (ogg_vgmstream) {
|
||||
ogg_vgmstream->num_streams = vgmstream->num_streams;
|
||||
ogg_vgmstream->stream_size = vgmstream->stream_size;
|
||||
|
||||
close_vgmstream(vgmstream);
|
||||
return ogg_vgmstream;
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#elif defined(VGM_USE_FFMPEG)
|
||||
/* Alt decoding without libvorbis (minor number of beginning samples difference).
|
||||
* Otherwise same output with (inaudible) +-1 lower byte differences due to rounding. */
|
||||
case 0x05: { /* Ogg Vorbis [The World Ends with You (iOS / latest update)] */
|
||||
ffmpeg_codec_data *ffmpeg_data;
|
||||
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,datasize);
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
|
||||
if ( !ffmpeg_data ) goto fail;
|
||||
|
||||
vgmstream->codec_data = ffmpeg_data;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
/* When loop_flag num_samples may be much larger than real num_samples (it's fine when looping is off)
|
||||
* Actual num_samples would be loop_end_sample+1, but more testing is needed */
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -145,10 +145,8 @@ VGMSTREAM * init_vgmstream_apple_caff(STREAMFILE *streamFile) {
|
||||
break;
|
||||
|
||||
default: /* "aac " "alac" etc: probably parsed by FFMpeg... */
|
||||
VGM_LOG("CAFF: unknown codec %x\n", codec);
|
||||
goto fail;
|
||||
}
|
||||
goto fail;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
|
@ -9,16 +9,16 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) {
|
||||
VGMSTREAM *vgmstream = NULL;
|
||||
STREAMFILE *temp_streamFile = NULL;
|
||||
int total_subsongs, target_subsong = streamFile->stream_index;
|
||||
int type, big_endian = 0;
|
||||
int type, big_endian = 0, entries;
|
||||
atsl_codec codec;
|
||||
const char* fake_ext;
|
||||
off_t subfile_offset;
|
||||
size_t subfile_size, header_size;
|
||||
off_t subfile_offset = 0;
|
||||
size_t subfile_size = 0, header_size;
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
|
||||
|
||||
|
||||
/* check extensions
|
||||
* .atsl: header id (for G1L extractions), .atsl3: PS3 games, .atsl4: PS4 games */
|
||||
/* checks */
|
||||
/* .atsl: header id (for G1L extractions), .atsl3: PS3 games, .atsl4: PS4 games */
|
||||
if ( !check_extensions(streamFile,"atsl,atsl3,atsl4"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4154534C) /* "ATSL" */
|
||||
@ -27,17 +27,11 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) {
|
||||
/* main header (LE) */
|
||||
header_size = read_32bitLE(0x04,streamFile);
|
||||
/* 0x08/0c: flags?, 0x10: fixed? (0x03E8) */
|
||||
total_subsongs = read_32bitLE(0x14,streamFile);
|
||||
entries = read_32bitLE(0x14,streamFile);
|
||||
/* 0x18: 0x28, or 0x30 (rarer) */
|
||||
/* 0x1c: null, 0x20: subheader size, 0x24/28: null */
|
||||
|
||||
//todo: sometimes entries are repeated/dummy and point to the first entry
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail;
|
||||
|
||||
|
||||
/* Type byte may be wrong (could need header id tests instead).
|
||||
* Example flags at 0x08/0x0c:
|
||||
/* Type byte may be wrong (could need header id tests instead). Example flags at 0x08/0x0c:
|
||||
* - 00010101 00020001 .atsl3 from One Piece Pirate Warriors (PS3)[ATRAC3]
|
||||
* - 00000201 00020001 .atsl3 from Fist of North Star: Ken's Rage 2 (PS3)[ATRAC3]
|
||||
* 00000301 00020101 (same)
|
||||
@ -68,12 +62,47 @@ VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) {
|
||||
read_32bit = big_endian ? read_32bitBE : read_32bitLE;
|
||||
|
||||
|
||||
/* entry header (machine endianness) */
|
||||
/* 0x00: id */
|
||||
subfile_offset = read_32bit(header_size + (target_subsong-1)*0x28 + 0x04,streamFile);
|
||||
subfile_size = read_32bit(header_size + (target_subsong-1)*0x28 + 0x08,streamFile);
|
||||
/* 0x08+: sample rate/num_samples/loop_start/etc, matching subfile header */
|
||||
/* some kind of seek/switch table follows (optional, found in .atsl3) */
|
||||
/* entries can point to the same file, count unique only */
|
||||
{
|
||||
int i,j;
|
||||
|
||||
total_subsongs = 0;
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
|
||||
/* parse entry header (in machine endianness) */
|
||||
for (i = 0; i < entries; i++) {
|
||||
int is_unique = 1;
|
||||
|
||||
off_t entry_offset = read_32bit(header_size + i*0x28 + 0x04,streamFile);
|
||||
size_t entry_size = read_32bit(header_size + i*0x28 + 0x08,streamFile);
|
||||
/* 0x00: id?, 0x08+: sample rate/num_samples/loop_start/etc, matching subfile header */
|
||||
|
||||
/* check if current entry was repeated in a prev entry */
|
||||
for (j = 0; j < i; j++) {
|
||||
off_t prev_offset = read_32bit(header_size + j*0x28 + 0x04,streamFile);
|
||||
if (prev_offset == entry_offset) {
|
||||
is_unique = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_unique)
|
||||
continue;
|
||||
|
||||
total_subsongs++;
|
||||
|
||||
/* target GET, but keep going to count subsongs */
|
||||
if (!subfile_offset && target_subsong == total_subsongs) {
|
||||
subfile_offset = entry_offset;
|
||||
subfile_size = entry_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail;
|
||||
if (!subfile_offset || !subfile_size) goto fail;
|
||||
|
||||
|
||||
/* some kind of seek/switch table may follow (optional, found in .atsl3) */
|
||||
|
||||
|
||||
temp_streamFile = setup_atsl_streamfile(streamFile, subfile_offset,subfile_size, fake_ext);
|
||||
if (!temp_streamFile) goto fail;
|
||||
|
@ -49,7 +49,7 @@ static STREAMFILE* setup_atx_streamfile(STREAMFILE *streamFile) {
|
||||
num_segments = read_16bitLE(0x1e,streamFile);
|
||||
|
||||
/* expected segment name: X_XXX_XXX_0n.ATX, starting from n=1 */
|
||||
get_streamfile_name(streamFile, filename,PATH_LIMIT);
|
||||
get_streamfile_filename(streamFile, filename,PATH_LIMIT);
|
||||
filename_len = strlen(filename);
|
||||
if (filename_len < 7 || filename[filename_len - 5] != '1') goto fail;
|
||||
|
||||
@ -96,12 +96,16 @@ static STREAMFILE* setup_atx_streamfile(STREAMFILE *streamFile) {
|
||||
if (!new_streamFile) goto fail;
|
||||
temp_streamFile = new_streamFile;
|
||||
|
||||
/* if all this worked we'll have this frankenstein streamfile:
|
||||
* fakename( clamp( multifile( segment0=clamp(standard(FILE)), segment1=clamp(standard(FILE)) ) ) ) */
|
||||
|
||||
return temp_streamFile;
|
||||
|
||||
fail:
|
||||
if (!temp_streamFile) {
|
||||
for (i = 0; i < num_segments; i++)
|
||||
for (i = 0; i < num_segments; i++) {
|
||||
close_streamfile(segment_streamFiles[i]);
|
||||
}
|
||||
} else {
|
||||
close_streamfile(temp_streamFile); /* closes all segments */
|
||||
}
|
||||
|
@ -112,22 +112,14 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
vgmstream->coding_type = coding_type;
|
||||
if (channel_count == 1)
|
||||
vgmstream->layout_type = layout_none;
|
||||
else
|
||||
{
|
||||
if (ima)
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
else
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
}
|
||||
vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
|
||||
vgmstream->meta_type = meta_CSTM;
|
||||
|
||||
if (ima)
|
||||
if (ima) {
|
||||
vgmstream->interleave_block_size = 0x200;
|
||||
else {
|
||||
} else {
|
||||
vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile);
|
||||
vgmstream->interleave_smallblock_size = read_32bitLE(info_offset + 0x44, streamFile);
|
||||
vgmstream->interleave_last_block_size = read_32bitLE(info_offset + 0x44, streamFile);
|
||||
}
|
||||
|
||||
if (vgmstream->coding_type == coding_NGC_DSP) {
|
||||
|
@ -121,22 +121,14 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
vgmstream->coding_type = coding_type;
|
||||
if (channel_count == 1)
|
||||
vgmstream->layout_type = layout_none;
|
||||
else
|
||||
{
|
||||
if (ima)
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
else
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
}
|
||||
vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
|
||||
vgmstream->meta_type = meta_FSTM;
|
||||
|
||||
if (ima)
|
||||
vgmstream->interleave_block_size = 0x200;
|
||||
else {
|
||||
vgmstream->interleave_block_size = read_32bit(info_offset + 0x34, streamFile);
|
||||
vgmstream->interleave_smallblock_size = read_32bit(info_offset + 0x44, streamFile);
|
||||
vgmstream->interleave_last_block_size = read_32bit(info_offset + 0x44, streamFile);
|
||||
}
|
||||
|
||||
if (vgmstream->coding_type == coding_NGC_DSP) {
|
||||
|
@ -123,15 +123,10 @@ VGMSTREAM * init_vgmstream_bfwav(STREAMFILE *streamFile) {
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i<channel_count; i++) {
|
||||
if (vgmstream->layout_type == layout_interleave_shortblock)
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
|
||||
vgmstream->interleave_block_size);
|
||||
else if (vgmstream->layout_type == layout_interleave)
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
|
||||
STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (vgmstream->layout_type == layout_interleave)
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
else
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
|
||||
0x1000);
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,0x1000);
|
||||
|
||||
if (!vgmstream->ch[i].streamfile) goto fail;
|
||||
|
||||
|
@ -91,10 +91,7 @@ VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile) {
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->coding_type = coding_type;
|
||||
if (channel_count==1)
|
||||
vgmstream->layout_type = layout_none;
|
||||
else
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave;
|
||||
vgmstream->meta_type = meta_RSTM;
|
||||
if (atlus_shrunken_head)
|
||||
vgmstream->meta_type = meta_RSTM_shrunken;
|
||||
@ -105,7 +102,7 @@ VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
vgmstream->interleave_block_size = read_32bitBE(head_offset+0x38,streamFile);
|
||||
vgmstream->interleave_smallblock_size = read_32bitBE(head_offset+0x48,streamFile);
|
||||
vgmstream->interleave_last_block_size = read_32bitBE(head_offset+0x48,streamFile);
|
||||
|
||||
if (vgmstream->coding_type == coding_NGC_DSP) {
|
||||
off_t coef_offset;
|
||||
@ -139,12 +136,7 @@ VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile) {
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
if (vgmstream->layout_type==layout_interleave_shortblock)
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
|
||||
vgmstream->interleave_block_size);
|
||||
else
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
|
||||
0x1000);
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
|
||||
if (!vgmstream->ch[i].streamfile) goto fail;
|
||||
|
||||
|
@ -5,9 +5,12 @@
|
||||
VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
size_t data_size;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
/* check extension (.dvi: original, .idvi: renamed to header id) */
|
||||
|
||||
/* checks*/
|
||||
/* .dvi: original, .idvi: renamed to header id */
|
||||
if ( !check_extensions(streamFile,"dvi,idvi") )
|
||||
goto fail;
|
||||
|
||||
@ -18,28 +21,24 @@ VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
|
||||
loop_flag = (read_32bitLE(0x0C,streamFile) != 0);
|
||||
channel_count = read_32bitLE(0x04,streamFile); /* always 2? */
|
||||
start_offset = 0x800;
|
||||
data_size = get_streamfile_size(streamFile) - start_offset;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
|
||||
vgmstream->num_samples = ima_bytes_to_samples(get_streamfile_size(streamFile) - start_offset, channel_count);
|
||||
vgmstream->num_samples = ima_bytes_to_samples(data_size, channel_count);
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile);
|
||||
vgmstream->loop_end_sample = ima_bytes_to_samples(get_streamfile_size(streamFile) - start_offset, channel_count);
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
vgmstream->meta_type = meta_DC_IDVI;
|
||||
|
||||
/* Calculating the short block... */
|
||||
if (channel_count > 1) {
|
||||
vgmstream->interleave_block_size = 0x400;
|
||||
vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%(vgmstream->channels*vgmstream->interleave_block_size))/vgmstream->channels;
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
} else {
|
||||
vgmstream->layout_type = layout_none;
|
||||
}
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x400;
|
||||
if (vgmstream->interleave_block_size)
|
||||
vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
|
||||
|
||||
/* open the file for reading */
|
||||
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||
|
126
src/meta/idsp.c
126
src/meta/idsp.c
@ -1,16 +1,16 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* "idsp/IDSP"
|
||||
Soul Calibur Legends (Wii)
|
||||
Sky Crawlers: Innocent Aces (Wii)
|
||||
/* "idsp/IDSP"
|
||||
Soul Calibur Legends (Wii)
|
||||
Sky Crawlers: Innocent Aces (Wii)
|
||||
*/
|
||||
VGMSTREAM * init_vgmstream_idsp2(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
int loop_flag;
|
||||
int channel_count;
|
||||
int i, j;
|
||||
int channel_count;
|
||||
int i, j;
|
||||
off_t start_offset;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
@ -20,60 +20,53 @@ VGMSTREAM * init_vgmstream_idsp2(STREAMFILE *streamFile) {
|
||||
/* check header */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x69647370 || /* "idsp" */
|
||||
read_32bitBE(0xBC,streamFile) != 0x49445350) /* IDSP */
|
||||
goto fail;
|
||||
goto fail;
|
||||
|
||||
loop_flag = read_32bitBE(0x20,streamFile);
|
||||
channel_count = read_32bitBE(0xC4,streamFile);
|
||||
|
||||
if (channel_count > 8)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
goto fail;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
start_offset = (channel_count * 0x60) + 0x100;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitBE(0xC8,streamFile);
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->num_samples = (read_32bitBE(0x14,streamFile))*14/8/channel_count;
|
||||
start_offset = (channel_count * 0x60) + 0x100;
|
||||
vgmstream->sample_rate = read_32bitBE(0xC8,streamFile);
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->num_samples = (read_32bitBE(0x14,streamFile))*14/8/channel_count;
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = (read_32bitBE(0xD0,streamFile));
|
||||
vgmstream->loop_end_sample = (read_32bitBE(0xD4,streamFile));
|
||||
}
|
||||
|
||||
if (channel_count == 1)
|
||||
{
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
if (channel_count == 1) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
}
|
||||
else if (channel_count > 1)
|
||||
{
|
||||
if (read_32bitBE(0xD8,streamFile) == 0)
|
||||
{
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = (get_streamfile_size(streamFile)-start_offset)/2;
|
||||
else if (channel_count > 1) {
|
||||
if (read_32bitBE(0xD8,streamFile) == 0) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = (get_streamfile_size(streamFile)-start_offset)/2;
|
||||
}
|
||||
else if (read_32bitBE(0xD8,streamFile) > 0)
|
||||
{
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitBE(0xD8,streamFile);
|
||||
else if (read_32bitBE(0xD8,streamFile) > 0) {
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitBE(0xD8,streamFile);
|
||||
}
|
||||
}
|
||||
|
||||
vgmstream->meta_type = meta_IDSP;
|
||||
vgmstream->meta_type = meta_IDSP;
|
||||
|
||||
{
|
||||
if (vgmstream->coding_type == coding_NGC_DSP) {
|
||||
off_t coef_table[8] = {0x118,0x178,0x1D8,0x238,0x298,0x2F8,0x358,0x3B8};
|
||||
for (j=0;j<vgmstream->channels;j++) {
|
||||
for (i=0;i<16;i++) {
|
||||
vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile);
|
||||
}
|
||||
{
|
||||
if (vgmstream->coding_type == coding_NGC_DSP) {
|
||||
off_t coef_table[8] = {0x118,0x178,0x1D8,0x238,0x298,0x2F8,0x358,0x3B8};
|
||||
for (j=0;j<vgmstream->channels;j++) {
|
||||
for (i=0;i<16;i++) {
|
||||
vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* open the file for reading */
|
||||
@ -121,17 +114,13 @@ VGMSTREAM * init_vgmstream_idsp3(STREAMFILE *streamFile) {
|
||||
channel_count = read_32bitBE(0x24,streamFile);
|
||||
|
||||
if (channel_count > 8)
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
goto fail;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
start_offset = (channel_count*0x60)+0xC;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitBE(0x14,streamFile);
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->num_samples = read_32bitBE(0x0C,streamFile);
|
||||
@ -141,9 +130,9 @@ VGMSTREAM * init_vgmstream_idsp3(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
vgmstream->interleave_block_size = read_32bitBE(0x04,streamFile);
|
||||
vgmstream->interleave_smallblock_size = ((vgmstream->num_samples/7*8)%(vgmstream->interleave_block_size)/vgmstream->channels);
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
|
||||
vgmstream->interleave_last_block_size = ((vgmstream->num_samples/7*8)%(vgmstream->interleave_block_size)/vgmstream->channels);
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
|
||||
vgmstream->meta_type = meta_IDSP;
|
||||
|
||||
if (vgmstream->coding_type == coding_NGC_DSP) {
|
||||
@ -170,7 +159,6 @@ VGMSTREAM * init_vgmstream_idsp3(STREAMFILE *streamFile) {
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=start_offset+
|
||||
vgmstream->interleave_block_size*i;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,7 +175,7 @@ VGMSTREAM * init_vgmstream_idsp4(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
int loop_flag = 0;
|
||||
int channel_count;
|
||||
int channel_count;
|
||||
off_t start_offset;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
@ -201,17 +189,13 @@ VGMSTREAM * init_vgmstream_idsp4(STREAMFILE *streamFile) {
|
||||
channel_count = read_32bitBE(0x0C,streamFile);
|
||||
|
||||
if (channel_count > 2) // Refuse everything else for now
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
goto fail;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
start_offset = 0x70;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitBE(0x08,streamFile);
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->num_samples = read_32bitBE(0x04,streamFile)/channel_count/8*14;
|
||||
@ -220,27 +204,25 @@ VGMSTREAM * init_vgmstream_idsp4(STREAMFILE *streamFile) {
|
||||
vgmstream->loop_end_sample = read_32bitBE(0x04,streamFile)/channel_count/8*14;
|
||||
}
|
||||
|
||||
if (channel_count == 1)
|
||||
{
|
||||
vgmstream->layout_type = layout_none;
|
||||
if (channel_count == 1) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
}
|
||||
else
|
||||
{
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitBE(0x10,streamFile);
|
||||
else {
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitBE(0x10,streamFile);
|
||||
}
|
||||
|
||||
vgmstream->meta_type = meta_IDSP;
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<16;i++)
|
||||
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x14+i*2,streamFile);
|
||||
if (channel_count == 2) {
|
||||
for (i=0;i<16;i++)
|
||||
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x42+i*2,streamFile);
|
||||
}
|
||||
}
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<16;i++)
|
||||
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x14+i*2,streamFile);
|
||||
if (channel_count == 2) {
|
||||
for (i=0;i<16;i++)
|
||||
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x42+i*2,streamFile);
|
||||
}
|
||||
}
|
||||
|
||||
/* open the file for reading */
|
||||
{
|
||||
|
@ -95,7 +95,6 @@ typedef struct {
|
||||
int loop_end_found;
|
||||
int32_t loop_end;
|
||||
meta_t meta_type;
|
||||
layout_t layout_type;
|
||||
|
||||
off_t stream_size;
|
||||
int total_subsongs;
|
||||
@ -106,9 +105,9 @@ typedef struct {
|
||||
off_t scd_xor_length;
|
||||
uint32_t sngw_xor;
|
||||
|
||||
} vgm_vorbis_info_t;
|
||||
} ogg_vorbis_meta_info_t;
|
||||
|
||||
VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks, off_t other_header_bytes, const vgm_vorbis_info_t *vgm_inf);
|
||||
VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callbacks *callbacks, off_t other_header_bytes, const ogg_vorbis_meta_info_t *ovmi);
|
||||
|
||||
VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE * streamFile);
|
||||
#endif
|
||||
@ -126,7 +125,7 @@ VGMSTREAM * init_vgmstream_mp4_aac_ffmpeg(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_mp4_aac(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_mp4_aac_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size);
|
||||
|
||||
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_akb_mp4(STREAMFILE *streamFile);
|
||||
#endif
|
||||
|
||||
VGMSTREAM * init_vgmstream_sfl(STREAMFILE * streamFile);
|
||||
@ -308,6 +307,7 @@ VGMSTREAM * init_vgmstream_rsd6radp(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE* streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd6xma(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_rsd6wma(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_dc_asd(STREAMFILE * streamFile);
|
||||
|
||||
@ -477,7 +477,7 @@ VGMSTREAM * init_vgmstream_ps2_khv(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_pc_smp(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ngc_bo2(STREAMFILE* streamFile);
|
||||
VGMSTREAM * init_vgmstream_ngc_rkv(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_dsp_ddsp(STREAMFILE* streamFile);
|
||||
|
||||
@ -622,8 +622,8 @@ VGMSTREAM * init_vgmstream_x360_cxs(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_dsp_adx(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile);
|
||||
|
||||
@ -646,6 +646,7 @@ VGMSTREAM * init_vgmstream_gtd(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_ta_aac_x360(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_ta_aac_ps3(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_ta_aac_mobile_vorbis(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps3_mta2(STREAMFILE *streamFile);
|
||||
|
||||
@ -711,4 +712,9 @@ VGMSTREAM * init_vgmstream_waf(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_wave(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_smv(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_nxap(STREAMFILE * streamFile);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
@ -1,9 +1,9 @@
|
||||
/*
|
||||
2017-12-10: Preliminary MOGG Support. As long as the stream is unencrypted, this should be fine.
|
||||
This will also work on unconventional 5 channel Vorbis streams but some sound cards might not like it.
|
||||
TODO (Eventually): Add decryption for encrypted MOGG types (Rock Band, etc.)
|
||||
This will also work on unconventional 5 channel Vorbis streams but some sound cards might not like it.
|
||||
TODO (Eventually): Add decryption for encrypted MOGG types (Rock Band, etc.)
|
||||
|
||||
-bxaimc
|
||||
-bxaimc
|
||||
*/
|
||||
|
||||
#include "meta.h"
|
||||
@ -12,31 +12,28 @@
|
||||
/* MOGG - Harmonix Music Systems (Guitar Hero)[Unencrypted Type] */
|
||||
VGMSTREAM * init_vgmstream_mogg(STREAMFILE *streamFile) {
|
||||
#ifdef VGM_USE_VORBIS
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset;
|
||||
off_t start_offset;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile, filename, sizeof(filename));
|
||||
if (strcasecmp("mogg", filename_extension(filename))) goto fail;
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "mogg"))
|
||||
goto fail;
|
||||
|
||||
{
|
||||
vgm_vorbis_info_t inf;
|
||||
VGMSTREAM * result = NULL;
|
||||
{
|
||||
ogg_vorbis_meta_info_t ovmi = {0};
|
||||
VGMSTREAM * result = NULL;
|
||||
|
||||
memset(&inf, 0, sizeof(inf));
|
||||
inf.layout_type = layout_ogg_vorbis;
|
||||
inf.meta_type = meta_MOGG;
|
||||
ovmi.meta_type = meta_MOGG;
|
||||
|
||||
start_offset = read_32bitLE(0x04, streamFile);
|
||||
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf);
|
||||
start_offset = read_32bitLE(0x04, streamFile);
|
||||
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
|
||||
|
||||
if (result != NULL) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (result != NULL) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
/* clean up anything we may have opened */
|
||||
/* clean up anything we may have opened */
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,88 +1,55 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* SPSD (Guilty Gear X [NAOMI GD-ROM]) */
|
||||
/* SPSD - Naomi GD-ROM streams [Guilty Gear X (Naomi), Crazy Taxi (Naomi), Virtua Tennis 2 (Naomi)] */
|
||||
VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset;
|
||||
int coding;
|
||||
int loop_flag;
|
||||
int channel_count;
|
||||
size_t data_size;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("spsd",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check header */
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "spsd"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x53505344) /* "SPSD" */
|
||||
goto fail;
|
||||
|
||||
loop_flag = 0;
|
||||
channel_count = 2;
|
||||
|
||||
|
||||
start_offset = 0x40;
|
||||
data_size = get_streamfile_size(streamFile) - start_offset;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
start_offset = 0x40;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x2A,streamFile);
|
||||
|
||||
switch (read_8bit(0x8,streamFile))
|
||||
{
|
||||
case 0x01:
|
||||
coding = coding_PCM8;
|
||||
break;
|
||||
case 0x03:
|
||||
coding = coding_AICA;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
vgmstream->coding_type = coding;
|
||||
vgmstream->num_samples = read_32bitLE(0x0C,streamFile);
|
||||
|
||||
#if 0
|
||||
if (loop_flag)
|
||||
{
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile);
|
||||
}
|
||||
#endif
|
||||
|
||||
vgmstream->interleave_block_size = 0x2000;
|
||||
if (channel_count > 1) {
|
||||
vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%(vgmstream->channels*vgmstream->interleave_block_size))/vgmstream->channels;
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
} else {
|
||||
vgmstream->layout_type = layout_none;
|
||||
}
|
||||
|
||||
vgmstream->meta_type = meta_NAOMI_SPSD;
|
||||
|
||||
/* open the file for reading */
|
||||
{
|
||||
int i;
|
||||
STREAMFILE * file;
|
||||
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!file) goto fail;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = file;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=start_offset+
|
||||
vgmstream->interleave_block_size*i;
|
||||
vgmstream->ch[i].adpcm_step_index = 0x7f; /* AICA */
|
||||
}
|
||||
switch (read_8bit(0x08,streamFile)) {
|
||||
case 0x01: /* [Virtua Tennis 2 (Naomi)] */
|
||||
vgmstream->coding_type = coding_PCM8;
|
||||
break;
|
||||
case 0x03:
|
||||
vgmstream->coding_type = coding_AICA;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x2000;
|
||||
if (vgmstream->interleave_block_size)
|
||||
vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
|
||||
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -4,103 +4,66 @@
|
||||
/* STRM - common Nintendo NDS streaming format */
|
||||
VGMSTREAM * init_vgmstream_nds_strm(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
|
||||
coding_t coding_type;
|
||||
|
||||
int codec_number;
|
||||
int channel_count;
|
||||
int loop_flag;
|
||||
|
||||
off_t start_offset;
|
||||
int channel_count, loop_flag, codec;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("strm",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check header */
|
||||
if ((uint32_t)read_32bitBE(0x00,streamFile)!=0x5354524D) /* STRM */
|
||||
goto fail;
|
||||
if ((uint32_t)read_32bitBE(0x04,streamFile)!=0xFFFE0001 && /* Old Header Check */
|
||||
((uint32_t)read_32bitBE(0x04,streamFile)!=0xFEFF0001)) /* Some newer games have a new flag */
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "strm"))
|
||||
goto fail;
|
||||
|
||||
|
||||
|
||||
/* check for HEAD section */
|
||||
if ((uint32_t)read_32bitBE(0x10,streamFile)!=0x48454144 && /* "HEAD" */
|
||||
(uint32_t)read_32bitLE(0x14,streamFile)!=0x50) /* 0x50-sized head is all I've seen */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x5354524D) /* "STRM" */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x04,streamFile) != 0xFFFE0001 && /* Old Header Check */
|
||||
(read_32bitBE(0x04,streamFile) != 0xFEFF0001)) /* Some newer games have a new flag */
|
||||
goto fail;
|
||||
|
||||
/* check type details */
|
||||
codec_number = read_8bit(0x18,streamFile);
|
||||
if (read_32bitBE(0x10,streamFile) != 0x48454144 && /* "HEAD" */
|
||||
read_32bitLE(0x14,streamFile) != 0x50) /* 0x50-sized head is all I've seen */
|
||||
goto fail;
|
||||
|
||||
codec = read_8bit(0x18,streamFile);
|
||||
loop_flag = read_8bit(0x19,streamFile);
|
||||
channel_count = read_8bit(0x1a,streamFile);
|
||||
if (channel_count > 2) goto fail;
|
||||
|
||||
switch (codec_number) {
|
||||
case 0:
|
||||
coding_type = coding_PCM8;
|
||||
start_offset = read_32bitLE(0x28,streamFile);
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x1c,streamFile);
|
||||
vgmstream->num_samples = read_32bitLE(0x24,streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile);
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->meta_type = meta_STRM;
|
||||
|
||||
switch (codec) {
|
||||
case 0x00: /* [Bleach - Dark Souls (DS)] */
|
||||
vgmstream->coding_type = coding_PCM8;
|
||||
break;
|
||||
case 1:
|
||||
coding_type = coding_PCM16LE;
|
||||
case 0x01:
|
||||
vgmstream->coding_type = coding_PCM16LE;
|
||||
break;
|
||||
case 2:
|
||||
coding_type = coding_NDS_IMA;
|
||||
case 0x02: /* [SaGa 2 (DS)] */
|
||||
vgmstream->coding_type = coding_NDS_IMA;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* TODO: only mono and stereo supported */
|
||||
if (channel_count < 1 || channel_count > 2) goto fail;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->num_samples = read_32bitLE(0x24,streamFile);
|
||||
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x1c,streamFile);
|
||||
/* channels and loop flag are set by allocate_vgmstream */
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile);
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->coding_type = coding_type;
|
||||
vgmstream->meta_type = meta_STRM;
|
||||
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitLE(0x30,streamFile);
|
||||
vgmstream->interleave_smallblock_size = read_32bitLE(0x38,streamFile);
|
||||
vgmstream->interleave_last_block_size = read_32bitLE(0x38,streamFile);
|
||||
|
||||
if (coding_type==coding_PCM8 || coding_type==coding_PCM16LE)
|
||||
vgmstream->layout_type = layout_none;
|
||||
else
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
|
||||
start_offset = read_32bitLE(0x28,streamFile);
|
||||
|
||||
/* open the file for reading by each channel */
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
if (vgmstream->layout_type==layout_interleave_shortblock)
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
|
||||
vgmstream->interleave_block_size);
|
||||
else
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
|
||||
0x1000);
|
||||
if (!vgmstream->ch[i].streamfile) goto fail;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=
|
||||
start_offset + i*vgmstream->interleave_block_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,100 +0,0 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* BO2 (Blood Omen 2 NGC) */
|
||||
VGMSTREAM * init_vgmstream_ngc_bo2(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
int loop_flag;
|
||||
int channels;
|
||||
int channel_count;
|
||||
off_t start_offset;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("bo2",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x0) /* "IDSP" */
|
||||
goto fail;
|
||||
|
||||
switch (read_32bitBE(0x10,streamFile))
|
||||
{
|
||||
case 0x0:
|
||||
channels = 1;
|
||||
break;
|
||||
case 0x1:
|
||||
channels = 2;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((get_streamfile_size(streamFile)) < ((read_32bitBE(0x0C,streamFile)/14*8*channels)+0x800))
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
channel_count = channels;
|
||||
loop_flag = (read_32bitBE(0x08,streamFile) != 0xFFFFFFFF);
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
start_offset = 0x800;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitBE(0x04,streamFile);
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->num_samples = read_32bitBE(0x0C,streamFile);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitBE(0x08,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile);
|
||||
}
|
||||
|
||||
if (channel_count == 1)
|
||||
{
|
||||
vgmstream->layout_type = layout_none;
|
||||
}
|
||||
else
|
||||
{
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x400;
|
||||
}
|
||||
|
||||
vgmstream->meta_type = meta_NGC_BO2;
|
||||
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<16;i++)
|
||||
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x24+i*2,streamFile);
|
||||
if (channel_count == 2) {
|
||||
for (i=0;i<16;i++)
|
||||
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x52+i*2,streamFile);
|
||||
}
|
||||
}
|
||||
|
||||
/* open the file for reading */
|
||||
{
|
||||
int i;
|
||||
STREAMFILE * file;
|
||||
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!file) goto fail;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = file;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=start_offset+
|
||||
vgmstream->interleave_block_size*i;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -24,6 +24,7 @@ struct dsp_header {
|
||||
uint16_t loop_ps;
|
||||
int16_t loop_hist1;
|
||||
int16_t loop_hist2;
|
||||
/* later/mdsp extension */
|
||||
int16_t channel_count;
|
||||
int16_t block_size;
|
||||
};
|
||||
@ -158,8 +159,10 @@ VGMSTREAM * init_vgmstream_ngc_dsp_std(STREAMFILE *streamFile) {
|
||||
int i;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
/* .dsp: standard, .adp: Dr. Muto (GC) mono files */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("dsp",filename_extension(filename))) goto fail;
|
||||
if (strcasecmp("dsp",filename_extension(filename)) &&
|
||||
strcasecmp("adp", filename_extension(filename))) goto fail;
|
||||
|
||||
if (read_dsp_header(&header, 0, streamFile)) goto fail;
|
||||
|
||||
@ -301,11 +304,11 @@ VGMSTREAM * init_vgmstream_ngc_mdsp_std(STREAMFILE *streamFile) {
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave_shortblock;
|
||||
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave;
|
||||
vgmstream->meta_type = meta_DSP_STD;
|
||||
vgmstream->interleave_block_size = header.block_size * 8;
|
||||
if (vgmstream->interleave_block_size)
|
||||
vgmstream->interleave_smallblock_size = (header.nibble_count / 2 % vgmstream->interleave_block_size + 7) / 8 * 8;
|
||||
vgmstream->interleave_last_block_size = (header.nibble_count / 2 % vgmstream->interleave_block_size + 7) / 8 * 8;
|
||||
|
||||
for (i = 0; i < channel_count; i++) {
|
||||
if (read_dsp_header(&header, header_size * i, streamFile)) goto fail;
|
||||
@ -581,67 +584,6 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* str: a very simple header format with implicit loop values
|
||||
* it's allways in interleaved stereo format
|
||||
*/
|
||||
VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
|
||||
const off_t start_offset = 0x60;
|
||||
int i;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("str",filename_extension(filename))) goto fail;
|
||||
|
||||
/* always 0xFAAF0001 @ offset 0 */
|
||||
if (read_32bitBE(0x00,streamFile)!=0xFAAF0001) goto fail;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
/* always loop & stereo */
|
||||
vgmstream = allocate_vgmstream(2,1);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->num_samples = read_32bitBE(0x08,streamFile);
|
||||
vgmstream->sample_rate = read_32bitBE(0x04,streamFile);
|
||||
|
||||
/* always loop to the beginning */
|
||||
vgmstream->loop_start_sample=0;
|
||||
vgmstream->loop_end_sample=vgmstream->num_samples;
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitBE(0x0C,streamFile);
|
||||
vgmstream->meta_type = meta_DSP_STR;
|
||||
|
||||
/* coeffs */
|
||||
for (i=0;i<16;i++) {
|
||||
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x10+(i*2),streamFile);
|
||||
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x30+(i*2),streamFile);
|
||||
}
|
||||
|
||||
/* open the file for reading */
|
||||
for (i=0;i<2;i++) {
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
|
||||
vgmstream->interleave_block_size);
|
||||
|
||||
if (!vgmstream->ch[i].streamfile) goto fail;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=start_offset+
|
||||
vgmstream->interleave_block_size*i;
|
||||
}
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
/* clean up anything we may have opened */
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* a bunch of formats that are identical except for file extension,
|
||||
* but have different interleaves */
|
||||
VGMSTREAM * init_vgmstream_ngc_dsp_std_int(STREAMFILE *streamFile) {
|
||||
@ -882,7 +824,6 @@ fail:
|
||||
#define SADB_MAX_CHANNELS 2
|
||||
/* sadb - Procyon Studio header + interleaved dsp [Shiren the Wanderer 3 (Wii), Disaster: Day of Crisis (Wii)] */
|
||||
VGMSTREAM * init_vgmstream_sadb(STREAMFILE *streamFile) {
|
||||
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset, header_offset;
|
||||
size_t header_spacing, interleave;
|
||||
@ -936,180 +877,103 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* .wsi as found in Alone in the Dark for Wii */
|
||||
/* These appear to be standard .dsp, but interleaved in a blocked format */
|
||||
|
||||
#define WSI_MAX_CHANNELS 2
|
||||
/* .wsi - blocked dsp [Alone in the Dark (Wii)] */
|
||||
VGMSTREAM * init_vgmstream_wsi(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
struct dsp_header header[2];
|
||||
off_t start_offset[2];
|
||||
|
||||
off_t start_offset, header_offset;
|
||||
size_t header_spacing;
|
||||
struct dsp_header ch_header[WSI_MAX_CHANNELS];
|
||||
int channel_count;
|
||||
size_t est_block_size = 0;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("wsi",filename_extension(filename))) goto fail;
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "wsi"))
|
||||
goto fail;
|
||||
|
||||
/* I don't know if this is actually the channel count, or a block type
|
||||
for the first block. Won't know until I see a mono .wsi */
|
||||
* for the first block. Won't know until I see a mono .wsi */
|
||||
channel_count = read_32bitBE(0x04,streamFile);
|
||||
|
||||
/* I've only allocated two headers, and I want to be alerted if a mono
|
||||
.wsi shows up */
|
||||
if (channel_count != 2) goto fail;
|
||||
|
||||
/* check for consistent block headers */
|
||||
{
|
||||
off_t check_offset;
|
||||
off_t block_offset;
|
||||
off_t block_size_has_been;
|
||||
int i;
|
||||
|
||||
check_offset = read_32bitBE(0x0,streamFile);
|
||||
if (check_offset < 8) goto fail;
|
||||
block_offset = read_32bitBE(0x00,streamFile);
|
||||
if (block_offset < 0x08) goto fail;
|
||||
|
||||
block_size_has_been = check_offset;
|
||||
block_size_has_been = block_offset;
|
||||
|
||||
/* check 4 blocks, to get an idea */
|
||||
for (i=0;i<4*channel_count;i++) {
|
||||
off_t block_size;
|
||||
block_size = read_32bitBE(check_offset,streamFile);
|
||||
for (i = 0; i < 4*channel_count; i++) {
|
||||
off_t block_size = read_32bitBE(block_offset,streamFile);
|
||||
|
||||
/* expect at least the block header */
|
||||
if (block_size < 0x10) goto fail;
|
||||
if (block_size < 0x10)
|
||||
goto fail; /* expect at least the block header */
|
||||
if (i%channel_count+1 != read_32bitBE(block_offset+0x08,streamFile))
|
||||
goto fail; /* expect the channel numbers to alternate */
|
||||
|
||||
/* expect the channel numbers to alternate */
|
||||
if (i%channel_count+1 != read_32bitBE(check_offset+8,streamFile)) goto fail;
|
||||
if (i%channel_count==0)
|
||||
block_size_has_been = block_size;
|
||||
else if (block_size != block_size_has_been)
|
||||
goto fail; /* expect every block in a set of channels to have the same size */
|
||||
|
||||
/* expect every block in a set of channels to have the same size */
|
||||
if (i%channel_count==0) block_size_has_been = block_size;
|
||||
else if (block_size != block_size_has_been) goto fail;
|
||||
|
||||
/* get an estimate of block size for buffer sizing */
|
||||
if (block_size > est_block_size) est_block_size = block_size;
|
||||
|
||||
check_offset += block_size;
|
||||
block_offset += block_size;
|
||||
}
|
||||
}
|
||||
|
||||
/* look at DSP headers */
|
||||
start_offset = read_32bitBE(0x00, streamFile);
|
||||
header_offset = start_offset + 0x10;
|
||||
header_spacing = read_32bitBE(start_offset,streamFile);
|
||||
|
||||
{
|
||||
off_t check_offset;
|
||||
int i;
|
||||
|
||||
check_offset = read_32bitBE(0x0,streamFile);
|
||||
|
||||
for (i=0;i<channel_count;i++) {
|
||||
off_t block_size;
|
||||
|
||||
block_size = read_32bitBE(check_offset,streamFile);
|
||||
|
||||
/* make sure block is actually big enough to hold the dsp header
|
||||
and beginning of first frame */
|
||||
if (block_size < 0x61+0x10) goto fail;
|
||||
if (read_dsp_header(&header[i], check_offset+0x10, streamFile)) goto fail;
|
||||
|
||||
start_offset[i] = check_offset + 0x60+0x10;
|
||||
|
||||
/* check initial predictor/scale */
|
||||
if (header[i].initial_ps != (uint8_t)read_8bit(check_offset+0x60+0x10,streamFile))
|
||||
goto fail;
|
||||
|
||||
/* check type==0 and gain==0 */
|
||||
if (header[i].format || header[i].gain)
|
||||
goto fail;
|
||||
|
||||
#if 0
|
||||
/* difficult to use this with blocks, but might be worth doing */
|
||||
if (header[i].loop_flag) {
|
||||
off_t loop_off;
|
||||
/* check loop predictor/scale */
|
||||
loop_off = header[i].loop_start_offset/16*8;
|
||||
if (header[i].loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile))
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
check_offset += block_size;
|
||||
}
|
||||
} /* done looking at headers */
|
||||
|
||||
/* check for agreement (two channels only) */
|
||||
if (
|
||||
header[0].sample_count != header[1].sample_count ||
|
||||
header[0].nibble_count != header[1].nibble_count ||
|
||||
header[0].sample_rate != header[1].sample_rate ||
|
||||
header[0].loop_flag != header[1].loop_flag ||
|
||||
header[0].loop_start_offset != header[1].loop_start_offset ||
|
||||
header[0].loop_end_offset != header[1].loop_end_offset
|
||||
) goto fail;
|
||||
/* read dsp */
|
||||
if (!dsp_load_header(ch_header, channel_count, streamFile,header_offset,header_spacing)) goto fail;
|
||||
if (!check_dsp_format(ch_header, channel_count)) goto fail;
|
||||
if (!check_dsp_samples(ch_header, channel_count)) goto fail;
|
||||
//if (!check_dsp_initial_ps(ch_header, channel_count, streamFile,start_offset,interleave)) goto fail;
|
||||
//if (!check_dsp_loop_ps(ch_header, channel_count, streamFile,start_offset,interleave)) goto fail;
|
||||
|
||||
|
||||
vgmstream = allocate_vgmstream(channel_count,header[0].loop_flag);
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,ch_header[0].loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
/* incomplete last frame is missing */
|
||||
vgmstream->num_samples = header[0].sample_count/14*14;
|
||||
vgmstream->sample_rate = header[0].sample_rate;
|
||||
vgmstream->sample_rate = ch_header[0].sample_rate;
|
||||
|
||||
vgmstream->loop_start_sample = dsp_nibbles_to_samples(
|
||||
header[0].loop_start_offset);
|
||||
vgmstream->loop_end_sample = dsp_nibbles_to_samples(
|
||||
header[0].loop_end_offset)+1;
|
||||
|
||||
/* don't know why, but it does happen*/
|
||||
if (vgmstream->loop_end_sample > vgmstream->num_samples)
|
||||
vgmstream->num_samples = ch_header[0].sample_count / 14 * 14; /* remove incomplete last frame */
|
||||
vgmstream->loop_start_sample = dsp_nibbles_to_samples(ch_header[0].loop_start_offset);
|
||||
vgmstream->loop_end_sample = dsp_nibbles_to_samples(ch_header[0].loop_end_offset)+1;
|
||||
if (vgmstream->loop_end_sample > vgmstream->num_samples) /* don't know why, but it does happen*/
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_wsi_blocked;
|
||||
vgmstream->meta_type = meta_DSP_WSI;
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_blocked_wsi;
|
||||
|
||||
/* coeffs */
|
||||
{
|
||||
int i,j;
|
||||
for (j=0;j<channel_count;j++) {
|
||||
for (i=0;i<16;i++) {
|
||||
vgmstream->ch[j].adpcm_coef[i] = header[j].coef[i];
|
||||
}
|
||||
|
||||
/* initial history */
|
||||
/* always 0 that I've ever seen, but for completeness... */
|
||||
vgmstream->ch[j].adpcm_history1_16 = header[j].initial_hist1;
|
||||
vgmstream->ch[j].adpcm_history2_16 = header[j].initial_hist2;
|
||||
}
|
||||
}
|
||||
setup_vgmstream_dsp(vgmstream, ch_header);
|
||||
|
||||
|
||||
/* open the file for reading */
|
||||
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,est_block_size*4);
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
|
||||
if (!vgmstream->ch[0].streamfile) goto fail;
|
||||
|
||||
wsi_block_update(read_32bitBE(0,streamFile),vgmstream);
|
||||
block_update_wsi(start_offset,vgmstream);
|
||||
|
||||
/* first block has DSP header */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = vgmstream->ch[0].streamfile;
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=start_offset[i];
|
||||
vgmstream->current_block_size -= 0x60;
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
vgmstream->ch[i].offset += 0x60;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* first block isn't full of musics */
|
||||
vgmstream->current_block_size -= 0x60;
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
/* clean up anything we may have opened */
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1970,119 +1834,60 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* dual dsp header with additional "iadp" header, found in Dr. Muto (NGC) */
|
||||
#define IADP_MAX_CHANNELS 2
|
||||
/* iadp - custom header + interleaved dsp [Dr. Muto (GC)] */
|
||||
VGMSTREAM * init_vgmstream_ngc_dsp_iadp(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
struct dsp_header ch0_header,ch1_header;
|
||||
off_t ch1_header_start, ch2_header_start, ch1_start, ch2_start;
|
||||
off_t start_offset, header_offset;
|
||||
size_t header_spacing, interleave;
|
||||
int channel_count;
|
||||
int i;
|
||||
struct dsp_header ch_header[IADP_MAX_CHANNELS];
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("iadp",filename_extension(filename)))
|
||||
|
||||
/* checks */
|
||||
/* .adp: actual extension, .iadp: header id */
|
||||
if (!check_extensions(streamFile, "adp,iadp"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x69616470) /* "iadp" */
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_32bitBE(0x0,streamFile) != 0x69616470) /* iadp */
|
||||
goto fail;
|
||||
|
||||
channel_count = read_32bitBE(0x4,streamFile);
|
||||
|
||||
if (channel_count != 0x2)
|
||||
goto fail;
|
||||
channel_count = read_32bitBE(0x04,streamFile);
|
||||
if (channel_count != IADP_MAX_CHANNELS) goto fail;
|
||||
|
||||
|
||||
ch1_header_start = 0x20;
|
||||
ch2_header_start = 0x80;
|
||||
ch1_start = read_32bitBE(0x1C,streamFile);
|
||||
ch2_start = ch1_start + read_32bitBE(0x8,streamFile);
|
||||
header_offset = 0x20;
|
||||
header_spacing = 0x60;
|
||||
start_offset = read_32bitBE(0x1C,streamFile);
|
||||
interleave = read_32bitBE(0x08,streamFile);
|
||||
|
||||
/* get DSP headers */
|
||||
if (read_dsp_header(&ch0_header, ch1_header_start, streamFile)) goto fail;
|
||||
if (read_dsp_header(&ch1_header, ch2_header_start, streamFile)) goto fail;
|
||||
|
||||
/* check initial predictor/scale */
|
||||
if (ch0_header.initial_ps != (uint8_t)read_8bit(ch1_start, streamFile))
|
||||
goto fail;
|
||||
if (ch1_header.initial_ps != (uint8_t)read_8bit(ch2_start, streamFile))
|
||||
goto fail;
|
||||
|
||||
/* check type==0 and gain==0 */
|
||||
if (ch0_header.format || ch0_header.gain)
|
||||
goto fail;
|
||||
if (ch1_header.format || ch1_header.gain)
|
||||
goto fail;
|
||||
|
||||
/* check for agreement */
|
||||
if (
|
||||
ch0_header.sample_count != ch1_header.sample_count ||
|
||||
ch0_header.nibble_count != ch1_header.nibble_count ||
|
||||
ch0_header.sample_rate != ch1_header.sample_rate ||
|
||||
ch0_header.loop_flag != ch1_header.loop_flag ||
|
||||
ch0_header.loop_start_offset != ch1_header.loop_start_offset ||
|
||||
ch0_header.loop_end_offset != ch1_header.loop_end_offset
|
||||
) goto fail;
|
||||
|
||||
if (ch0_header.loop_flag)
|
||||
{
|
||||
off_t loop_off;
|
||||
/* check loop predictor/scale */
|
||||
loop_off = ch0_header.loop_start_offset/16*8;
|
||||
|
||||
if (ch0_header.loop_ps != (uint8_t)read_8bit(ch1_start+loop_off,streamFile))
|
||||
goto fail;
|
||||
if (ch1_header.loop_ps != (uint8_t)read_8bit(ch2_start+loop_off,streamFile))
|
||||
goto fail;
|
||||
}
|
||||
/* read dsp */
|
||||
if (!dsp_load_header(ch_header, channel_count, streamFile,header_offset,header_spacing)) goto fail;
|
||||
if (!check_dsp_format(ch_header, channel_count)) goto fail;
|
||||
if (!check_dsp_samples(ch_header, channel_count)) goto fail;
|
||||
if (!check_dsp_initial_ps(ch_header, channel_count, streamFile,start_offset,interleave)) goto fail;
|
||||
if (!check_dsp_loop_ps(ch_header, channel_count, streamFile,start_offset,interleave)) goto fail;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,ch0_header.loop_flag);
|
||||
vgmstream = allocate_vgmstream(channel_count,ch_header[0].loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->num_samples = ch0_header.sample_count;
|
||||
vgmstream->sample_rate = ch0_header.sample_rate;
|
||||
|
||||
vgmstream->loop_start_sample = dsp_nibbles_to_samples(ch0_header.loop_start_offset);
|
||||
vgmstream->loop_end_sample = dsp_nibbles_to_samples(ch0_header.loop_end_offset)+1;
|
||||
vgmstream->sample_rate = ch_header[0].sample_rate;
|
||||
vgmstream->num_samples = ch_header[0].sample_count;
|
||||
vgmstream->loop_start_sample = dsp_nibbles_to_samples(ch_header[0].loop_start_offset);
|
||||
vgmstream->loop_end_sample = dsp_nibbles_to_samples(ch_header[0].loop_end_offset)+1;
|
||||
|
||||
vgmstream->meta_type = meta_NGC_DSP_IADP;
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->interleave_block_size = read_32bitBE(0x8,streamFile);
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->meta_type = meta_NGC_DSP_IADP;
|
||||
setup_vgmstream_dsp(vgmstream, ch_header);
|
||||
|
||||
/* coeffs */
|
||||
for (i=0;i<16;i++) {
|
||||
vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i];
|
||||
vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i];
|
||||
}
|
||||
|
||||
/* initial history */
|
||||
/* always 0 that I've ever seen, but for completeness... */
|
||||
vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1;
|
||||
vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2;
|
||||
vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1;
|
||||
vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2;
|
||||
|
||||
/* open the file for reading */
|
||||
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!vgmstream->ch[0].streamfile)
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start;
|
||||
|
||||
vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!vgmstream->ch[1].streamfile)
|
||||
goto fail;
|
||||
vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset=ch2_start;
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
/* clean up anything we may have opened */
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
46
src/meta/ngc_str_cauldron.c
Normal file
46
src/meta/ngc_str_cauldron.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* .str - Cauldron/Conan mini-header + interleaved dsp data [Conan (GC)] */
|
||||
VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int channel_count, loop_flag;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "str"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0xFAAF0001) /* header id */
|
||||
goto fail;
|
||||
|
||||
channel_count = 2; /* always loop & stereo */
|
||||
loop_flag = 1;
|
||||
start_offset = 0x60;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = read_32bitBE(0x04,streamFile);
|
||||
vgmstream->num_samples = read_32bitBE(0x08,streamFile);
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->meta_type = meta_DSP_STR;
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitBE(0x0C,streamFile);
|
||||
|
||||
dsp_read_coefs_be(vgmstream, streamFile, 0x10, 0x20);
|
||||
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -14,29 +14,20 @@ VGMSTREAM * init_vgmstream_ngc_ulw(STREAMFILE *streamFile) {
|
||||
|
||||
/* raw data, the info is in the filename (really!) */
|
||||
{
|
||||
char* path;
|
||||
char basename[PATH_LIMIT];
|
||||
char filename[PATH_LIMIT];
|
||||
char filename[PATH_LIMIT] = {0};
|
||||
|
||||
/* get base name */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
path = strrchr(filename,DIR_SEPARATOR);
|
||||
if (path!=NULL)
|
||||
path = path+1;
|
||||
else
|
||||
path = filename;
|
||||
strcpy(basename,path);
|
||||
get_streamfile_filename(streamFile, filename,PATH_LIMIT);
|
||||
|
||||
/* first letter gives the channels */
|
||||
if (basename[0]=='M') /* Mono */
|
||||
if (filename[0]=='M') /* Mono */
|
||||
channel_count = 1;
|
||||
else if (basename[0]=='S' || basename[0]=='D') /* Stereo/Dolby */
|
||||
else if (filename[0]=='S' || filename[0]=='D') /* Stereo/Dolby */
|
||||
channel_count = 2;
|
||||
else
|
||||
goto fail;
|
||||
|
||||
/* not very robust but meh (other tracks don't loop) */
|
||||
if (strcmp(basename,"MMenu.ulw")==0 || strcmp(basename,"DMenu.ulw")==0) {
|
||||
if (strcmp(filename,"MMenu.ulw")==0 || strcmp(filename,"DMenu.ulw")==0) {
|
||||
loop_flag = 1;
|
||||
}
|
||||
}
|
||||
|
49
src/meta/nxap.c
Normal file
49
src/meta/nxap.c
Normal file
@ -0,0 +1,49 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* NXAP - Nex Entertainment header [Time Crisis 4 (PS3), Time Crisis Razing Storm (PS3)] */
|
||||
VGMSTREAM * init_vgmstream_nxap(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "adp"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4E584150) /* "NXAP" */
|
||||
goto fail;
|
||||
if (read_32bitLE(0x14,streamFile) != 0x40 || /* expected frame size? */
|
||||
read_32bitLE(0x18,streamFile) != 0x40) /* expected interleave? */
|
||||
goto fail;
|
||||
|
||||
start_offset = read_32bitLE(0x04,streamFile);
|
||||
channel_count = read_32bitLE(0x0c,streamFile);
|
||||
loop_flag = 0; //(read_32bitLE(0x24,streamFile) > 0); //todo
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = read_32bitLE(0x10, streamFile);
|
||||
vgmstream->num_samples = read_32bitLE(0x1c,streamFile) * (0x40-0x04)*2 / channel_count; /* number of frames */
|
||||
|
||||
/* unknown loop format, also 0x28/2c values seem related */
|
||||
//vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile) * (0x40-0x04)*2 / channel_count;
|
||||
//vgmstream->loop_end_sample = read_32bitLE(0x24,streamFile) * (0x40-0x04)*2 / channel_count;
|
||||
//vgmstream->loop_end_sample = vgmstream->loop_start_sample + vgmstream->loop_end_sample;
|
||||
|
||||
vgmstream->meta_type = meta_NXAP;
|
||||
vgmstream->coding_type = coding_YAMAHA_NXAP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x40;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -179,8 +179,7 @@ static void l2sd_ogg_decryption_callback(void *ptr, size_t size, size_t nmemb, v
|
||||
|
||||
/* Ogg Vorbis, by way of libvorbisfile; may contain loop comments */
|
||||
VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
|
||||
char filename[PATH_LIMIT];
|
||||
vgm_vorbis_info_t inf = {0};
|
||||
ogg_vorbis_meta_info_t ovmi = {0};
|
||||
off_t start_offset = 0;
|
||||
|
||||
int is_ogg = 0;
|
||||
@ -210,7 +209,6 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
|
||||
} else {
|
||||
goto fail;
|
||||
}
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
|
||||
/* check standard Ogg Vorbis */
|
||||
if (is_ogg) {
|
||||
@ -218,11 +216,11 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
|
||||
/* check Psychic Software obfuscation (Darkwind: War on Wheels PC) */
|
||||
if (read_32bitBE(0x00,streamFile) == 0x2c444430) {
|
||||
is_psychic = 1;
|
||||
inf.decryption_callback = psychic_ogg_decryption_callback;
|
||||
ovmi.decryption_callback = psychic_ogg_decryption_callback;
|
||||
}
|
||||
else if (read_32bitBE(0x00,streamFile) == 0x4C325344) { /* "L2SD" [Lineage II Chronicle 4 (PC)] */
|
||||
is_l2sd = 1;
|
||||
inf.decryption_callback = l2sd_ogg_decryption_callback;
|
||||
ovmi.decryption_callback = l2sd_ogg_decryption_callback;
|
||||
}
|
||||
else if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */
|
||||
goto fail; /* not known (ex. Wwise) */
|
||||
@ -232,7 +230,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
|
||||
/* check "Ultramarine3" (???), may be encrypted */
|
||||
if (is_um3) {
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */
|
||||
inf.decryption_callback = um3_ogg_decryption_callback;
|
||||
ovmi.decryption_callback = um3_ogg_decryption_callback;
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,9 +239,9 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4b4f5653) { /* "KOVS" */
|
||||
goto fail;
|
||||
}
|
||||
inf.loop_start = read_32bitLE(0x08,streamFile);
|
||||
inf.loop_flag = (inf.loop_start != 0);
|
||||
inf.decryption_callback = kovs_ogg_decryption_callback;
|
||||
ovmi.loop_start = read_32bitLE(0x08,streamFile);
|
||||
ovmi.loop_flag = (ovmi.loop_start != 0);
|
||||
ovmi.decryption_callback = kovs_ogg_decryption_callback;
|
||||
|
||||
start_offset = 0x20;
|
||||
}
|
||||
@ -251,14 +249,14 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
|
||||
/* check SNGW (Capcom's MT Framework PC games), may be encrypted */
|
||||
if (is_sngw) {
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4f676753) { /* "OggS" */
|
||||
inf.sngw_xor = read_32bitBE(0x00,streamFile);
|
||||
inf.decryption_callback = sngw_ogg_decryption_callback;
|
||||
ovmi.sngw_xor = read_32bitBE(0x00,streamFile);
|
||||
ovmi.decryption_callback = sngw_ogg_decryption_callback;
|
||||
}
|
||||
}
|
||||
|
||||
/* check ISD (Gunvolt PC) */
|
||||
if (is_isd) {
|
||||
inf.decryption_callback = isd_ogg_decryption_callback;
|
||||
ovmi.decryption_callback = isd_ogg_decryption_callback;
|
||||
|
||||
//todo looping unknown, not in Ogg comments
|
||||
// game has sound/GV_steam.* files with info about sound/stream/*.isd
|
||||
@ -271,42 +269,41 @@ VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) {
|
||||
|
||||
|
||||
if (is_um3) {
|
||||
inf.meta_type = meta_OGG_UM3;
|
||||
ovmi.meta_type = meta_OGG_UM3;
|
||||
} else if (is_kovs) {
|
||||
inf.meta_type = meta_OGG_KOVS;
|
||||
ovmi.meta_type = meta_OGG_KOVS;
|
||||
} else if (is_psychic) {
|
||||
inf.meta_type = meta_OGG_PSYCHIC;
|
||||
ovmi.meta_type = meta_OGG_PSYCHIC;
|
||||
} else if (is_sngw) {
|
||||
inf.meta_type = meta_OGG_SNGW;
|
||||
ovmi.meta_type = meta_OGG_SNGW;
|
||||
} else if (is_isd) {
|
||||
inf.meta_type = meta_OGG_ISD;
|
||||
ovmi.meta_type = meta_OGG_ISD;
|
||||
} else if (is_l2sd) {
|
||||
inf.meta_type = meta_OGG_L2SD;
|
||||
ovmi.meta_type = meta_OGG_L2SD;
|
||||
} else {
|
||||
inf.meta_type = meta_OGG_VORBIS;
|
||||
ovmi.meta_type = meta_OGG_VORBIS;
|
||||
}
|
||||
inf.layout_type = layout_ogg_vorbis;
|
||||
|
||||
return init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf);
|
||||
return init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
|
||||
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks_p, off_t start, const vgm_vorbis_info_t *vgm_inf) {
|
||||
VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callbacks *callbacks_p, off_t start, const ogg_vorbis_meta_info_t *ovmi) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
ogg_vorbis_codec_data * data = NULL;
|
||||
OggVorbis_File *ovf = NULL;
|
||||
vorbis_info *vi;
|
||||
|
||||
int loop_flag = vgm_inf->loop_flag;
|
||||
int32_t loop_start = vgm_inf->loop_start;
|
||||
int loop_length_found = vgm_inf->loop_length_found;
|
||||
int32_t loop_length = vgm_inf->loop_length;
|
||||
int loop_end_found = vgm_inf->loop_end_found;
|
||||
int32_t loop_end = vgm_inf->loop_end;
|
||||
size_t stream_size = vgm_inf->stream_size ?
|
||||
vgm_inf->stream_size :
|
||||
int loop_flag = ovmi->loop_flag;
|
||||
int32_t loop_start = ovmi->loop_start;
|
||||
int loop_length_found = ovmi->loop_length_found;
|
||||
int32_t loop_length = ovmi->loop_length;
|
||||
int loop_end_found = ovmi->loop_end_found;
|
||||
int32_t loop_end = ovmi->loop_end;
|
||||
size_t stream_size = ovmi->stream_size ?
|
||||
ovmi->stream_size :
|
||||
get_streamfile_size(streamFile) - start;
|
||||
|
||||
ov_callbacks default_callbacks;
|
||||
@ -331,10 +328,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
|
||||
temp_streamfile.offset = 0;
|
||||
temp_streamfile.size = stream_size;
|
||||
|
||||
temp_streamfile.decryption_callback = vgm_inf->decryption_callback;
|
||||
temp_streamfile.scd_xor = vgm_inf->scd_xor;
|
||||
temp_streamfile.scd_xor_length = vgm_inf->scd_xor_length;
|
||||
temp_streamfile.sngw_xor = vgm_inf->sngw_xor;
|
||||
temp_streamfile.decryption_callback = ovmi->decryption_callback;
|
||||
temp_streamfile.scd_xor = ovmi->scd_xor;
|
||||
temp_streamfile.scd_xor_length = ovmi->scd_xor_length;
|
||||
temp_streamfile.sngw_xor = ovmi->sngw_xor;
|
||||
|
||||
/* open the ogg vorbis file for testing */
|
||||
memset(&temp_ovf, 0, sizeof(temp_ovf));
|
||||
@ -348,9 +345,12 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
|
||||
|
||||
/* proceed to init codec_data and reopen a STREAMFILE for this stream */
|
||||
{
|
||||
char filename[PATH_LIMIT];
|
||||
|
||||
data = calloc(1,sizeof(ogg_vorbis_codec_data));
|
||||
if (!data) goto fail;
|
||||
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
data->ov_streamfile.streamfile = streamFile->open(streamFile,filename, STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!data->ov_streamfile.streamfile) goto fail;
|
||||
|
||||
@ -358,10 +358,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
|
||||
data->ov_streamfile.offset = 0;
|
||||
data->ov_streamfile.size = stream_size;
|
||||
|
||||
data->ov_streamfile.decryption_callback = vgm_inf->decryption_callback;
|
||||
data->ov_streamfile.scd_xor = vgm_inf->scd_xor;
|
||||
data->ov_streamfile.scd_xor_length = vgm_inf->scd_xor_length;
|
||||
data->ov_streamfile.sngw_xor = vgm_inf->sngw_xor;
|
||||
data->ov_streamfile.decryption_callback = ovmi->decryption_callback;
|
||||
data->ov_streamfile.scd_xor = ovmi->scd_xor;
|
||||
data->ov_streamfile.scd_xor_length = ovmi->scd_xor_length;
|
||||
data->ov_streamfile.sngw_xor = ovmi->sngw_xor;
|
||||
|
||||
/* open the ogg vorbis file for real */
|
||||
if (ov_open_callbacks(&data->ov_streamfile, &data->ogg_vorbis_file, NULL, 0, *callbacks_p))
|
||||
@ -441,7 +441,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
|
||||
vgmstream->codec_data = data; /* store our fun extra datas */
|
||||
vgmstream->channels = vi->channels;
|
||||
vgmstream->sample_rate = vi->rate;
|
||||
vgmstream->num_streams = vgm_inf->total_subsongs;
|
||||
vgmstream->num_streams = ovmi->total_subsongs;
|
||||
vgmstream->stream_size = stream_size;
|
||||
|
||||
vgmstream->num_samples = ov_pcm_total(ovf,-1); /* let libvorbisfile find total samples */
|
||||
@ -460,8 +460,8 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
|
||||
}
|
||||
|
||||
vgmstream->coding_type = coding_OGG_VORBIS;
|
||||
vgmstream->layout_type = vgm_inf->layout_type;
|
||||
vgmstream->meta_type = vgm_inf->meta_type;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->meta_type = ovmi->meta_type;
|
||||
|
||||
return vgmstream;
|
||||
|
||||
|
@ -1,79 +1,53 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* SND (Warriors of Might and Magic Heroes of M&M:Dragonbone Staff) */
|
||||
/* SND - Might and Magic games [Warriors of M&M (PS2), Heroes of M&M: Quest for the DragonBone Staff (PS2)] */
|
||||
VGMSTREAM * init_vgmstream_ps2_snd(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
size_t data_size;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset;
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "snd"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x53534E44) /* "SSND" */
|
||||
goto fail;
|
||||
|
||||
int loop_flag;
|
||||
int channel_count;
|
||||
start_offset = read_32bitLE(0x04,streamFile)+0x08;
|
||||
data_size = get_streamfile_size(streamFile) - start_offset;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("snd",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_32bitBE(0x0,streamFile) !=0x53534e44) goto fail;
|
||||
|
||||
/* Force Loop 0->end */
|
||||
loop_flag = 1;
|
||||
loop_flag = 1; /* force full Loop */
|
||||
channel_count = read_16bitLE(0x0a,streamFile);
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
start_offset = read_32bitLE(0x04,streamFile)+8;
|
||||
vgmstream->sample_rate = (uint16_t)read_16bitLE(0xe,streamFile);
|
||||
|
||||
if(read_8bit(0x08,streamFile)==1) {
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
}
|
||||
else
|
||||
vgmstream->coding_type = coding_PCM16LE;
|
||||
|
||||
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x0e,streamFile);
|
||||
vgmstream->num_samples = read_32bitLE(0x16,streamFile);
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->interleave_block_size = (uint16_t)read_16bitLE(0x12,streamFile);
|
||||
|
||||
if((get_streamfile_size(streamFile)-start_offset)%vgmstream->interleave_block_size)
|
||||
{
|
||||
/* not sure if this is right ... */
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%vgmstream->interleave_block_size)/vgmstream->channels;
|
||||
} else {
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
}
|
||||
vgmstream->meta_type = meta_PS2_SND;
|
||||
|
||||
if(loop_flag) {
|
||||
vgmstream->loop_start_sample=0;
|
||||
vgmstream->loop_end_sample=vgmstream->num_samples;
|
||||
}
|
||||
if (read_8bit(0x08,streamFile)==1) {
|
||||
vgmstream->coding_type = coding_DVI_IMA_int; /* Warriors of M&M DragonBone */
|
||||
}
|
||||
else {
|
||||
vgmstream->coding_type = coding_PCM16LE; /* Heroes of M&M */
|
||||
}
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = (uint16_t)read_16bitLE(0x12,streamFile);
|
||||
if (vgmstream->interleave_block_size)
|
||||
vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
|
||||
|
||||
/* open the file for reading */
|
||||
{
|
||||
int i;
|
||||
STREAMFILE * file;
|
||||
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!file) goto fail;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = file;
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=start_offset+
|
||||
vgmstream->interleave_block_size*i;
|
||||
|
||||
}
|
||||
}
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,85 +1,53 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* SVAG
|
||||
|
||||
PS2 SVAG format is an interleaved format found in many konami Games
|
||||
The header start with a Svag id and have the sentence :
|
||||
"ALL RIGHTS RESERVED.KONAMITYO Sound Design Dept. "
|
||||
or "ALL RIGHTS RESERVED.KCE-Tokyo Sound Design Dept. "
|
||||
|
||||
2008-05-13 - Fastelbja : First version ...
|
||||
Thx to HCS for his awesome work on shortblock interleave
|
||||
*/
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* SVAG - from Konami Tokyo games [OZ (PS2), Neo Contra (PS2)]] */
|
||||
VGMSTREAM * init_vgmstream_ps2_svag(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset;
|
||||
size_t data_size;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
int loop_flag=0;
|
||||
int channel_count;
|
||||
int i;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("svag",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check SVAG Header */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x53766167)
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "svag"))
|
||||
goto fail;
|
||||
|
||||
/* check loop */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x53766167) /* "Svag" */
|
||||
goto fail;
|
||||
|
||||
channel_count = read_16bitLE(0x0C,streamFile); /* always 2? ("S"tereo vag?) */
|
||||
loop_flag = (read_32bitLE(0x14,streamFile)==1);
|
||||
|
||||
channel_count=read_16bitLE(0x0C,streamFile);
|
||||
start_offset = 0x800; /* header repeated at 0x400 too */
|
||||
data_size = read_32bitLE(0x04,streamFile);
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->channels = read_16bitLE(0x0C,streamFile);
|
||||
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
|
||||
|
||||
/* Compression Scheme */
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->num_samples = read_32bitLE(0x04,streamFile)/16*28/vgmstream->channels;
|
||||
|
||||
/* Get loop point values */
|
||||
vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x04,streamFile), vgmstream->channels);
|
||||
if(vgmstream->loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile)/16*28;
|
||||
vgmstream->loop_end_sample = read_32bitLE(0x04,streamFile)/16*28/vgmstream->channels;
|
||||
vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitLE(0x18,streamFile)*vgmstream->channels, vgmstream->channels);
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
}
|
||||
|
||||
vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile);
|
||||
if (channel_count > 1) {
|
||||
vgmstream->interleave_smallblock_size = (read_32bitLE(0x04,streamFile)%(vgmstream->channels*vgmstream->interleave_block_size))/vgmstream->channels;
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
} else {
|
||||
vgmstream->layout_type = layout_none;
|
||||
}
|
||||
vgmstream->meta_type = meta_PS2_SVAG;
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile);
|
||||
if (vgmstream->interleave_block_size)
|
||||
vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
|
||||
|
||||
/* open the file for reading by each channel */
|
||||
{
|
||||
for (i=0;i<channel_count;i++) {
|
||||
if (channel_count > 1)
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size);
|
||||
else
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
|
||||
if (!vgmstream->ch[i].streamfile) goto fail;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=
|
||||
(off_t)(0x800+vgmstream->interleave_block_size*i);
|
||||
}
|
||||
}
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -17,8 +17,9 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) {
|
||||
int channel_count = 0;
|
||||
int is_swag = 0;
|
||||
|
||||
/* check extension (.swag: Frantix PSP, .str: Ben10 Galactic Racing, .vig: MX vs. ATV Untamed PS2) */
|
||||
if ( !check_extensions(streamFile,"vag,swag,str,vig") )
|
||||
/* checks */
|
||||
/* .swag: Frantix (PSP), .str: Ben10 Galactic Racing, .vig: MX vs. ATV Untamed (PS2) .l/r: Crash Nitro Kart (PS2) */
|
||||
if ( !check_extensions(streamFile,"vag,swag,str,vig,l,r") )
|
||||
goto fail;
|
||||
|
||||
/* check VAG Header */
|
||||
|
@ -838,15 +838,13 @@ static VGMSTREAM *parse_riff_ogg(STREAMFILE * streamFile, off_t start_offset, si
|
||||
{
|
||||
VGMSTREAM *vgmstream = NULL;
|
||||
STREAMFILE *custom_streamFile = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
vgm_vorbis_info_t inf = {0};
|
||||
ogg_vorbis_meta_info_t ovmi = {0};
|
||||
riff_ogg_io_data io_data = {0};
|
||||
size_t io_data_size = sizeof(riff_ogg_io_data);
|
||||
|
||||
|
||||
inf.layout_type = layout_ogg_vorbis;
|
||||
inf.meta_type = meta_RIFF_WAVE;
|
||||
inf.stream_size = real_size;
|
||||
ovmi.meta_type = meta_RIFF_WAVE;
|
||||
ovmi.stream_size = real_size;
|
||||
//inf.loop_flag = 0; /* not observed */
|
||||
|
||||
io_data.patch_offset = patch_offset;
|
||||
@ -854,8 +852,7 @@ static VGMSTREAM *parse_riff_ogg(STREAMFILE * streamFile, off_t start_offset, si
|
||||
custom_streamFile = open_io_streamfile(open_wrap_streamfile(streamFile), &io_data,io_data_size, riff_ogg_io_read);
|
||||
if (!custom_streamFile) return NULL;
|
||||
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
vgmstream = init_vgmstream_ogg_vorbis_callbacks(custom_streamFile, filename, NULL, start_offset, &inf);
|
||||
vgmstream = init_vgmstream_ogg_vorbis_callbacks(custom_streamFile, NULL, start_offset, &ovmi);
|
||||
|
||||
close_streamfile(custom_streamFile);
|
||||
|
||||
|
152
src/meta/rkv.c
152
src/meta/rkv.c
@ -1,77 +1,115 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* RKV (from Legacy of Kain - Blood Omen 2) */
|
||||
/* RKV - from Legacy of Kain - Blood Omen 2 (PS2) */
|
||||
VGMSTREAM * init_vgmstream_ps2_rkv(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset=0;
|
||||
int loop_flag;
|
||||
int channel_count;
|
||||
off_t start_offset, header_offset;
|
||||
size_t data_size;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("rkv",filename_extension(filename))) goto fail;
|
||||
|
||||
// Some RKV got info @ offset 0
|
||||
// Some other @ offset 4
|
||||
if(read_32bitLE(0,streamFile)==0)
|
||||
start_offset=4;
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "rkv"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x24,streamFile) != 0x00) /* quick test vs GC rkv (coef position) */
|
||||
goto fail;
|
||||
|
||||
loop_flag = (read_32bitLE(start_offset+4,streamFile)!=0xFFFFFFFF);
|
||||
channel_count = read_32bitLE(start_offset+0x0c,streamFile)+1;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
/* some RKV got info at offset 0x00, some other at 0x0 4 */
|
||||
if (read_32bitLE(0x00,streamFile)==0)
|
||||
header_offset = 0x04;
|
||||
else
|
||||
header_offset = 0x00;
|
||||
|
||||
switch (read_32bitLE(header_offset+0x0c,streamFile)) {
|
||||
case 0x00: channel_count = 1; break;
|
||||
case 0x01: channel_count = 2; break;
|
||||
default: goto fail;
|
||||
}
|
||||
loop_flag = (read_32bitLE(header_offset+0x04,streamFile) != 0xFFFFFFFF);
|
||||
start_offset = 0x800;
|
||||
data_size = get_streamfile_size(streamFile) - start_offset;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitLE(start_offset,streamFile);
|
||||
vgmstream->sample_rate = read_32bitLE(header_offset,streamFile);
|
||||
vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count);
|
||||
//vgmstream->num_samples = read_32bitLE(header_offset+0x08,streamFile); /* sometimes not set */
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitLE(header_offset+0x04,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(header_offset+0x08,streamFile);
|
||||
}
|
||||
|
||||
vgmstream->meta_type = meta_PS2_RKV;
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x400;
|
||||
if (vgmstream->interleave_block_size)
|
||||
vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size*vgmstream->channels)) / vgmstream->channels;
|
||||
|
||||
// sometimes sample count is not set on the header
|
||||
vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)/16*28/channel_count;
|
||||
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitLE(start_offset+4,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(start_offset+8,streamFile);
|
||||
}
|
||||
|
||||
start_offset = 0x800;
|
||||
|
||||
if((get_streamfile_size(streamFile)-0x800)%0x400)
|
||||
{
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
vgmstream->interleave_smallblock_size=((get_streamfile_size(streamFile)-0x800)%0x400)/channel_count;
|
||||
} else {
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
}
|
||||
|
||||
vgmstream->interleave_block_size = 0x400;
|
||||
vgmstream->meta_type = meta_PS2_RKV;
|
||||
/* open the file for reading */
|
||||
{
|
||||
int i;
|
||||
STREAMFILE * file;
|
||||
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (!file) goto fail;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = file;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=start_offset+
|
||||
vgmstream->interleave_block_size*i;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* RKV - from Legacy of Kain - Blood Omen 2 (GC) */
|
||||
VGMSTREAM * init_vgmstream_ngc_rkv(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
|
||||
/* checks */
|
||||
/* "": empty (files have names but no extensions), .rkv: container bigfile extension, .bo2: fake extension */
|
||||
if (!check_extensions(streamFile, ",rkv,bo2"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x00)
|
||||
goto fail;
|
||||
if (read_32bitBE(0x24,streamFile) == 0x00) /* quick test vs GC rkv (coef position) */
|
||||
goto fail;
|
||||
|
||||
switch (read_32bitBE(0x10,streamFile)) {
|
||||
case 0x00: channel_count = 1; break;
|
||||
case 0x01: channel_count = 2; break;
|
||||
default: goto fail;
|
||||
}
|
||||
loop_flag = (read_32bitBE(0x08,streamFile) != 0xFFFFFFFF);
|
||||
start_offset = 0x800;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = read_32bitBE(0x04,streamFile);
|
||||
vgmstream->num_samples = read_32bitBE(0x0C,streamFile);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitBE(0x08,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile);
|
||||
}
|
||||
|
||||
vgmstream->meta_type = meta_NGC_RKV;
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x400;
|
||||
|
||||
dsp_read_coefs_be(vgmstream,streamFile,0x24,0x2e);
|
||||
/* hist at 0x44/0x72? */
|
||||
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,81 +1,54 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* .dsp w/ RS03 header - from Metroid Prime 2 */
|
||||
|
||||
/* RS03 - from Metroid Prime 2 (GC) */
|
||||
VGMSTREAM * init_vgmstream_rs03(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
|
||||
int channel_count;
|
||||
int loop_flag;
|
||||
off_t start_offset;
|
||||
int i;
|
||||
size_t data_size;
|
||||
int channel_count, loop_flag;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("dsp",filename_extension(filename))) goto fail;
|
||||
|
||||
/* check header */
|
||||
if ((uint32_t)read_32bitBE(0,streamFile)!=0x52530003) /* "RS03" */
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "dsp"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x52530003) /* "RS03" */
|
||||
goto fail;
|
||||
|
||||
channel_count = read_32bitBE(4,streamFile);
|
||||
channel_count = read_32bitBE(0x04,streamFile);
|
||||
if (channel_count != 1 && channel_count != 2) goto fail;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
|
||||
loop_flag = read_16bitBE(0x14,streamFile);
|
||||
|
||||
start_offset = 0x60;
|
||||
data_size = (get_streamfile_size(streamFile) - start_offset);
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->num_samples = read_32bitBE(8,streamFile);
|
||||
vgmstream->sample_rate = read_32bitBE(0xc,streamFile);
|
||||
|
||||
vgmstream->num_samples = read_32bitBE(8,streamFile);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = read_32bitBE(0x18,streamFile)/8*14;
|
||||
vgmstream->loop_end_sample = read_32bitBE(0x1c,streamFile)/8*14;
|
||||
}
|
||||
|
||||
start_offset = 0x60;
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
if (channel_count == 2) {
|
||||
vgmstream->layout_type = layout_interleave_shortblock;
|
||||
vgmstream->interleave_block_size = 0x8f00;
|
||||
vgmstream->interleave_smallblock_size = (((get_streamfile_size(streamFile)-start_offset)%(0x8f00*2))/2+7)/8*8;
|
||||
} else
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->meta_type = meta_DSP_RS03;
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x8f00;
|
||||
if (vgmstream->interleave_block_size)
|
||||
vgmstream->interleave_last_block_size = ((data_size % (vgmstream->interleave_block_size*vgmstream->channels))/2+7)/8*8;
|
||||
|
||||
for (i=0;i<16;i++)
|
||||
vgmstream->ch[0].adpcm_coef[i]=read_16bitBE(0x20+i*2,streamFile);
|
||||
if (channel_count==2) {
|
||||
for (i=0;i<16;i++)
|
||||
vgmstream->ch[1].adpcm_coef[i]=read_16bitBE(0x40+i*2,streamFile);
|
||||
}
|
||||
dsp_read_coefs_be(vgmstream,streamFile,0x20,0x20);
|
||||
|
||||
/* open the file for reading by each channel */
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8f00);
|
||||
|
||||
if (!vgmstream->ch[i].streamfile) goto fail;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=
|
||||
start_offset+0x8f00*i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -903,12 +903,11 @@ fail:
|
||||
/* RSD6OGG */
|
||||
VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE *streamFile) {
|
||||
#ifdef VGM_USE_VORBIS
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("rsd",filename_extension(filename))) goto fail;
|
||||
/* check extension */
|
||||
if (!check_extensions(streamFile, "rsd"))
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */
|
||||
@ -917,15 +916,13 @@ VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE *streamFile) {
|
||||
goto fail;
|
||||
|
||||
{
|
||||
vgm_vorbis_info_t inf;
|
||||
ogg_vorbis_meta_info_t ovmi = {0};
|
||||
VGMSTREAM * result = NULL;
|
||||
|
||||
memset(&inf, 0, sizeof(inf));
|
||||
inf.layout_type = layout_ogg_vorbis;
|
||||
inf.meta_type = meta_RSD6OOGV;
|
||||
ovmi.meta_type = meta_RSD6OOGV;
|
||||
|
||||
start_offset = 0x800;
|
||||
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf);
|
||||
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
|
||||
|
||||
if (result != NULL) {
|
||||
return result;
|
||||
@ -938,7 +935,7 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* RSD6XADP - from Crash Tag Team Racing (Xbox) */
|
||||
/* RSD6XADP - from Crash Tag Team Racing (Xbox), Scarface (Xbox) */
|
||||
VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
@ -966,9 +963,10 @@ VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE *streamFile) {
|
||||
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
|
||||
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
|
||||
|
||||
vgmstream->coding_type = coding_XBOX_IMA;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->meta_type = meta_RSD6XADP;
|
||||
vgmstream->coding_type = (channel_count > 2) ? coding_XBOX_IMA_mch : coding_XBOX_IMA;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
|
||||
goto fail;
|
||||
@ -1082,7 +1080,6 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* RSD6AT3+ [Crash of the Titans (PSP)] */
|
||||
VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
@ -1096,13 +1093,13 @@ VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE *streamFile) {
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_32bitBE(0x0, streamFile) != 0x52534436) /* "RSD6" */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x52534436) /* "RSD6" */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x04,streamFile) != 0x4154332B) /* "AT3+" */
|
||||
goto fail;
|
||||
|
||||
loop_flag = 0;
|
||||
channel_count = read_32bitLE(0x8, streamFile);
|
||||
channel_count = read_32bitLE(0x08, streamFile);
|
||||
start_offset = 0x800;
|
||||
data_size = get_streamfile_size(streamFile) - start_offset;
|
||||
|
||||
@ -1117,7 +1114,7 @@ VGMSTREAM * init_vgmstream_rsd6at3p(STREAMFILE *streamFile) {
|
||||
{
|
||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
||||
|
||||
/* full RIFF header at start_offset/post_meta_offset (same) */
|
||||
/* full RIFF header at start_offset */
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,data_size);
|
||||
if (!ffmpeg_data) goto fail;
|
||||
vgmstream->codec_data = ffmpeg_data;
|
||||
@ -1154,3 +1151,60 @@ fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* RSD6WMA [Scarface (Xbox)] */
|
||||
VGMSTREAM * init_vgmstream_rsd6wma(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
size_t data_size;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile,"rsd"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x52534436) /* "RSD6" */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x04,streamFile) != 0x574D4120) /* "WMA " */
|
||||
goto fail;
|
||||
|
||||
loop_flag = 0;
|
||||
channel_count = read_32bitLE(0x08, streamFile);
|
||||
start_offset = 0x800;
|
||||
data_size = get_streamfile_size(streamFile) - start_offset;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_RSD6WMA;
|
||||
//vgmstream->num_samples = read_32bitLE(start_offset + 0x00, streamFile); /* ? */
|
||||
vgmstream->sample_rate = read_32bitLE(start_offset + 0x04, streamFile);
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
{
|
||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
||||
|
||||
/* mini header + WMA header at start_offset */
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset+0x08,data_size);
|
||||
if (!ffmpeg_data) goto fail;
|
||||
vgmstream->codec_data = ffmpeg_data;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
vgmstream->num_samples = (int32_t)ffmpeg_data->totalSamples; /* probably an estimation */
|
||||
|
||||
#else
|
||||
goto fail;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
50
src/meta/smv.c
Normal file
50
src/meta/smv.c
Normal file
@ -0,0 +1,50 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* .SMV - from Cho Aniki Zero (PSP) */
|
||||
VGMSTREAM * init_vgmstream_smv(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count;
|
||||
size_t channel_size, loop_start;
|
||||
|
||||
|
||||
/* check extension */
|
||||
if (!check_extensions(streamFile, "smv"))
|
||||
goto fail;
|
||||
|
||||
channel_size = read_32bitLE(0x00,streamFile);
|
||||
/* 0x08: number of full interleave blocks */
|
||||
channel_count = read_16bitLE(0x0a,streamFile);
|
||||
loop_start = read_32bitLE(0x18,streamFile);
|
||||
loop_flag = (loop_start != -1);
|
||||
start_offset = 0x800;
|
||||
|
||||
if (channel_size * channel_count + start_offset != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
|
||||
channel_size -= 0x10; /* last value has SPU end frame without flag 0x7 as it should */
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = read_32bitLE(0x10, streamFile);
|
||||
vgmstream->num_samples = ps_bytes_to_samples(channel_size*channel_count, channel_count);
|
||||
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start*channel_count, channel_count);
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->meta_type = meta_SMV;
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitLE(0x04, streamFile);
|
||||
vgmstream->interleave_last_block_size = read_32bitLE(0x0c, streamFile);
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -12,8 +12,8 @@ static void scd_ogg_v3_decryption_callback(void *ptr, size_t size, size_t nmemb,
|
||||
VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset, tables_offset, meta_offset, post_meta_offset, name_offset = 0;
|
||||
int32_t stream_size, subheader_size, loop_start, loop_end;
|
||||
off_t start_offset, tables_offset, meta_offset, extradata_offset, name_offset = 0;
|
||||
int32_t stream_size, extradata_size, loop_start, loop_end;
|
||||
|
||||
int loop_flag = 0, channel_count, codec, sample_rate;
|
||||
int version, target_entry, aux_chunk_count;
|
||||
@ -113,13 +113,13 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
|
||||
loop_start = read_32bit(meta_offset+0x10,streamFile);
|
||||
loop_end = read_32bit(meta_offset+0x14,streamFile);
|
||||
subheader_size = read_32bit(meta_offset+0x18,streamFile);
|
||||
extradata_size = read_32bit(meta_offset+0x18,streamFile);
|
||||
aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile);
|
||||
/* 0x01e(2): unknown, seen in some FF XIV sfx (MSADPCM) */
|
||||
|
||||
loop_flag = (loop_end > 0);
|
||||
post_meta_offset = meta_offset + 0x20;
|
||||
start_offset = post_meta_offset + subheader_size;
|
||||
extradata_offset = meta_offset + 0x20;
|
||||
start_offset = extradata_offset + extradata_size;
|
||||
|
||||
/* only "MARK" chunk is known (some FF XIV PS3 have "STBL" but it's not counted) */
|
||||
if (aux_chunk_count > 1 && aux_chunk_count < 0xFFFF) { /* some FF XIV Heavensward IMA sfx have 0x01000000 */
|
||||
@ -128,8 +128,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
/* skips aux chunks, sometimes needed (Lightning Returns X360, FF XIV PC) */
|
||||
if (aux_chunk_count && read_32bitBE(post_meta_offset, streamFile) == 0x4D41524B) { /* "MARK" */
|
||||
post_meta_offset += read_32bit(post_meta_offset+0x04, streamFile);
|
||||
if (aux_chunk_count && read_32bitBE(extradata_offset, streamFile) == 0x4D41524B) { /* "MARK" */
|
||||
extradata_offset += read_32bit(extradata_offset+0x04, streamFile);
|
||||
}
|
||||
|
||||
/* find name if possible */
|
||||
@ -151,41 +151,40 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
if (codec == 0x06) {
|
||||
VGMSTREAM *ogg_vgmstream;
|
||||
uint8_t ogg_version, ogg_byte;
|
||||
vgm_vorbis_info_t inf = {0};
|
||||
ogg_vorbis_meta_info_t ovmi = {0};
|
||||
|
||||
inf.layout_type = layout_ogg_vorbis;
|
||||
inf.meta_type = meta_SQEX_SCD;
|
||||
inf.total_subsongs = total_subsongs;
|
||||
ovmi.meta_type = meta_SQEX_SCD;
|
||||
ovmi.total_subsongs = total_subsongs;
|
||||
/* loop values are in bytes, let init_vgmstream_ogg_vorbis find loop comments instead */
|
||||
|
||||
ogg_version = read_8bit(post_meta_offset + 0x00, streamFile);
|
||||
ogg_version = read_8bit(extradata_offset + 0x00, streamFile);
|
||||
/* 0x01(1): 0x20 in v2/3, this ogg miniheader size? */
|
||||
ogg_byte = read_8bit(post_meta_offset + 0x02, streamFile);
|
||||
ogg_byte = read_8bit(extradata_offset + 0x02, streamFile);
|
||||
/* 0x03(1): ? in v3 */
|
||||
|
||||
if (ogg_version == 0) { /* 0x10? header, then custom Vorbis header before regular Ogg (FF XIV PC v1) */
|
||||
inf.stream_size = stream_size;
|
||||
ovmi.stream_size = stream_size;
|
||||
}
|
||||
else { /* 0x20 header, then seek table */
|
||||
size_t seek_table_size = read_32bit(post_meta_offset+0x10, streamFile);
|
||||
size_t vorb_header_size = read_32bit(post_meta_offset+0x14, streamFile);
|
||||
size_t seek_table_size = read_32bit(extradata_offset+0x10, streamFile);
|
||||
size_t vorb_header_size = read_32bit(extradata_offset+0x14, streamFile);
|
||||
/* 0x18(4): ? (can be 0) */
|
||||
|
||||
if ((post_meta_offset-meta_offset) + seek_table_size + vorb_header_size != subheader_size)
|
||||
if ((extradata_offset-meta_offset) + seek_table_size + vorb_header_size != extradata_size)
|
||||
goto fail;
|
||||
|
||||
inf.stream_size = vorb_header_size + stream_size;
|
||||
start_offset = post_meta_offset + 0x20 + seek_table_size; /* subheader_size skips vorb_header */
|
||||
ovmi.stream_size = vorb_header_size + stream_size;
|
||||
start_offset = extradata_offset + 0x20 + seek_table_size; /* extradata_size skips vorb_header */
|
||||
|
||||
if (ogg_version == 2) { /* header is XOR'ed using byte (FF XIV PC) */
|
||||
inf.decryption_callback = scd_ogg_v2_decryption_callback;
|
||||
inf.scd_xor = ogg_byte;
|
||||
inf.scd_xor_length = vorb_header_size;
|
||||
ovmi.decryption_callback = scd_ogg_v2_decryption_callback;
|
||||
ovmi.scd_xor = ogg_byte;
|
||||
ovmi.scd_xor_length = vorb_header_size;
|
||||
}
|
||||
else if (ogg_version == 3) { /* file is XOR'ed using table (FF XIV Heavensward PC) */
|
||||
inf.decryption_callback = scd_ogg_v3_decryption_callback;
|
||||
inf.scd_xor = stream_size & 0xFF; /* ogg_byte not used? */
|
||||
inf.scd_xor_length = vorb_header_size + stream_size;
|
||||
ovmi.decryption_callback = scd_ogg_v3_decryption_callback;
|
||||
ovmi.scd_xor = stream_size & 0xFF; /* ogg_byte not used? */
|
||||
ovmi.scd_xor_length = vorb_header_size + stream_size;
|
||||
}
|
||||
else {
|
||||
VGM_LOG("SCD: unknown ogg_version 0x%x\n", ogg_version);
|
||||
@ -193,7 +192,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
/* actual Ogg init */
|
||||
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf);
|
||||
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
|
||||
if (ogg_vgmstream && name_offset)
|
||||
read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile);
|
||||
return ogg_vgmstream;
|
||||
@ -270,8 +269,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
case 0x0C: /* MS ADPCM [Final Fantasy XIV (PC) sfx] */
|
||||
vgmstream->coding_type = coding_MSADPCM;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = read_16bit(post_meta_offset+0x0c,streamFile);
|
||||
/* in post_meta_offset is a WAVEFORMATEX (including coefs and all) */
|
||||
vgmstream->interleave_block_size = read_16bit(extradata_offset+0x0c,streamFile);
|
||||
/* in extradata_offset is a WAVEFORMATEX (including coefs and all) */
|
||||
|
||||
vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->interleave_block_size, vgmstream->channels);
|
||||
if (loop_flag) {
|
||||
@ -346,8 +345,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
uint8_t buf[200];
|
||||
int32_t bytes;
|
||||
|
||||
/* post_meta_offset+0x00: fmt0x166 header (BE), post_meta_offset+0x34: seek table */
|
||||
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, post_meta_offset,0x34, stream_size, streamFile, 1);
|
||||
/* extradata_offset+0x00: fmt0x166 header (BE), extradata_offset+0x34: seek table */
|
||||
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, extradata_offset,0x34, stream_size, streamFile, 1);
|
||||
if (bytes <= 0) goto fail;
|
||||
|
||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size);
|
||||
@ -365,7 +364,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
case 0x0E: { /* ATRAC3/ATRAC3plus [Lord of Arcana (PSP), Final Fantasy Type-0] */
|
||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
||||
|
||||
/* full RIFF header at start_offset/post_meta_offset (same) */
|
||||
/* full RIFF header at start_offset/extradata_offset (same) */
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
|
||||
if (!ffmpeg_data) goto fail;
|
||||
vgmstream->codec_data = ffmpeg_data;
|
||||
@ -401,17 +400,17 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
|
||||
/* post header has various typical ATRAC9 values */
|
||||
cfg.channels = vgmstream->channels;
|
||||
cfg.config_data = read_32bit(post_meta_offset+0x0c,streamFile);
|
||||
cfg.encoder_delay = read_32bit(post_meta_offset+0x18,streamFile);
|
||||
cfg.config_data = read_32bit(extradata_offset+0x0c,streamFile);
|
||||
cfg.encoder_delay = read_32bit(extradata_offset+0x18,streamFile);
|
||||
|
||||
vgmstream->codec_data = init_atrac9(&cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_ATRAC9;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
vgmstream->num_samples = read_32bit(post_meta_offset+0x10,streamFile); /* loop values above are also weird and ignored */
|
||||
vgmstream->loop_start_sample = read_32bit(post_meta_offset+0x20, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_start
|
||||
vgmstream->loop_end_sample = read_32bit(post_meta_offset+0x24, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_end
|
||||
vgmstream->num_samples = read_32bit(extradata_offset+0x10,streamFile); /* loop values above are also weird and ignored */
|
||||
vgmstream->loop_start_sample = read_32bit(extradata_offset+0x20, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_start
|
||||
vgmstream->loop_end_sample = read_32bit(extradata_offset+0x24, streamFile) - (loop_flag ? cfg.encoder_delay : 0); //loop_end
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -187,19 +187,15 @@ VGMSTREAM * init_vgmstream_sqex_sead(STREAMFILE * streamFile) {
|
||||
#ifdef VGM_USE_VORBIS
|
||||
case 0x03: { /* OGG [Final Fantasy XV Benchmark sfx (PC)] */
|
||||
VGMSTREAM *ogg_vgmstream = NULL;
|
||||
vgm_vorbis_info_t inf = {0};
|
||||
ogg_vorbis_meta_info_t ovmi = {0};
|
||||
off_t subfile_offset = extradata_offset + extradata_size;
|
||||
char filename[PATH_LIMIT];
|
||||
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
|
||||
inf.layout_type = layout_ogg_vorbis;
|
||||
inf.meta_type = vgmstream->meta_type;
|
||||
inf.total_subsongs = total_subsongs;
|
||||
inf.stream_size = stream_size;
|
||||
ovmi.meta_type = vgmstream->meta_type;
|
||||
ovmi.total_subsongs = total_subsongs;
|
||||
ovmi.stream_size = stream_size;
|
||||
/* post header has some kind of repeated values, config/table? */
|
||||
|
||||
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, subfile_offset, &inf);
|
||||
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, subfile_offset, &ovmi);
|
||||
if (ogg_vgmstream) {
|
||||
ogg_vgmstream->num_streams = vgmstream->num_streams;
|
||||
ogg_vgmstream->stream_size = vgmstream->stream_size;
|
||||
|
@ -210,13 +210,11 @@ fail:
|
||||
}
|
||||
|
||||
/* Android/iOS Variants (Star Ocean Anamnesis (APK v1.9.2), Heaven x Inferno (iOS)) */
|
||||
VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * init_vgmstream_ta_aac_mobile_vorbis(STREAMFILE *streamFile) {
|
||||
#ifdef VGM_USE_VORBIS
|
||||
off_t start_offset;
|
||||
char filename[PATH_LIMIT];
|
||||
int8_t codec_id;
|
||||
|
||||
streamFile->get_name(streamFile, filename, sizeof(filename));
|
||||
/* check extension, case insensitive */
|
||||
/* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */
|
||||
if (!check_extensions(streamFile, "aac,laac,ace"))
|
||||
@ -231,19 +229,17 @@ VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile) {
|
||||
codec_id = read_8bit(0x104, streamFile);
|
||||
if (codec_id == 0xe) /* Vorbis */
|
||||
{
|
||||
vgm_vorbis_info_t inf;
|
||||
ogg_vorbis_meta_info_t ovmi = {0};
|
||||
VGMSTREAM * result = NULL;
|
||||
|
||||
memset(&inf, 0, sizeof(inf));
|
||||
inf.layout_type = layout_ogg_vorbis;
|
||||
inf.meta_type = meta_TA_AAC_VORBIS;
|
||||
inf.loop_start = read_32bitLE(0x140, streamFile);
|
||||
inf.loop_end = read_32bitLE(0x144, streamFile);
|
||||
inf.loop_flag = inf.loop_end > inf.loop_start;
|
||||
inf.loop_end_found = inf.loop_flag;
|
||||
ovmi.meta_type = meta_TA_AAC_MOBILE;
|
||||
ovmi.loop_start = read_32bitLE(0x140, streamFile);
|
||||
ovmi.loop_end = read_32bitLE(0x144, streamFile);
|
||||
ovmi.loop_flag = ovmi.loop_end > ovmi.loop_start;
|
||||
ovmi.loop_end_found = ovmi.loop_flag;
|
||||
|
||||
start_offset = read_32bitLE(0x120, streamFile);
|
||||
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf);
|
||||
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
|
||||
|
||||
if (result != NULL) {
|
||||
return result;
|
||||
@ -255,3 +251,65 @@ fail:
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Android/iOS Variants, before they switched to Vorbis (Star Ocean Anamnesis (Android), Heaven x Inferno (iOS)) */
|
||||
VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int channel_count, loop_flag, codec;
|
||||
size_t data_size;
|
||||
|
||||
|
||||
/* check extension, case insensitive */
|
||||
/* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */
|
||||
if (!check_extensions(streamFile, "aac,laac,ace"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitLE(0x00, streamFile) != 0x41414320) /* "AAC " */
|
||||
goto fail;
|
||||
|
||||
if (read_32bitLE(0xf0, streamFile) != 0x57415645) /* "WAVE" */
|
||||
goto fail;
|
||||
|
||||
codec = read_8bit(0x104, streamFile);
|
||||
channel_count = read_8bit(0x105, streamFile);
|
||||
/* 0x106: 0x01?, 0x107: 0x10? */
|
||||
data_size = read_32bitLE(0x10c, streamFile); /* usable data only, cuts last frame */
|
||||
start_offset = read_32bitLE(0x120, streamFile);
|
||||
/* 0x124: full data size */
|
||||
loop_flag = (read_32bitLE(0x134, streamFile) > 0);
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = read_32bitLE(0x108, streamFile);
|
||||
vgmstream->meta_type = meta_TA_AAC_MOBILE;
|
||||
|
||||
switch(codec) {
|
||||
case 0x0d:
|
||||
if (read_32bitLE(0x144, streamFile) != 0x40) goto fail; /* frame size */
|
||||
if (read_32bitLE(0x148, streamFile) != (0x40-0x04*channel_count)*2 / channel_count) goto fail; /* frame samples */
|
||||
if (channel_count > 2) goto fail; /* unknown data layout */
|
||||
|
||||
vgmstream->coding_type = coding_YAMAHA;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
vgmstream->num_samples = yamaha_bytes_to_samples(data_size, channel_count);
|
||||
vgmstream->loop_start_sample = yamaha_bytes_to_samples(read_32bitLE(0x130, streamFile), channel_count);;
|
||||
vgmstream->loop_end_sample = yamaha_bytes_to_samples(read_32bitLE(0x134, streamFile), channel_count);;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -5,12 +5,12 @@
|
||||
VGMSTREAM * init_vgmstream_waf(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
|
||||
/* check extension */
|
||||
if (!check_extensions(streamFile, "waf"))
|
||||
goto fail;
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "waf"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x00,streamFile) != 0x57414600) /* "WAF\0" "*/
|
||||
goto fail;
|
||||
@ -21,7 +21,7 @@ VGMSTREAM * init_vgmstream_waf(STREAMFILE *streamFile) {
|
||||
loop_flag = 0;
|
||||
start_offset = 0x38;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
@ -33,8 +33,8 @@ VGMSTREAM * init_vgmstream_waf(STREAMFILE *streamFile) {
|
||||
vgmstream->num_samples = msadpcm_bytes_to_samples(read_32bitLE(0x34,streamFile), vgmstream->interleave_block_size, channel_count);
|
||||
/* 0x04: null?, 0x0c: avg br, 0x12: bps, 0x14: s_p_f, 0x16~34: count + standard MSADPCM coefs (a modified RIFF fmt) */
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#define MAX_SEGMENTS 4
|
||||
|
||||
/* .WAVE - WayForward "EngineBlack" games, segmented [Shantae and the Pirate's Curse (PC/3DS), TMNT: Danger of the Ooze (PS3/3DS)] */
|
||||
/* .WAVE - "EngineBlack" games, segmented [Shantae and the Pirate's Curse (PC/3DS), TMNT: Danger of the Ooze (PS3/3DS)] */
|
||||
VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t segments_offset;
|
||||
@ -135,18 +135,15 @@ VGMSTREAM * init_vgmstream_wave_segmented(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
case 0x04: { /* "vorbis" */
|
||||
char filename[PATH_LIMIT];
|
||||
vgm_vorbis_info_t ovi = {0};
|
||||
ogg_vorbis_meta_info_t ovmi = {0};
|
||||
|
||||
segment_offset = read_32bit(table_offset, streamFile);
|
||||
segment_size = read_32bitBE(segment_offset, streamFile); /* always BE */
|
||||
|
||||
ovi.layout_type = layout_ogg_vorbis;
|
||||
ovi.meta_type = meta_WAVE;
|
||||
ovi.stream_size = segment_size;
|
||||
ovmi.meta_type = meta_WAVE;
|
||||
ovmi.stream_size = segment_size;
|
||||
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
data->segments[i] = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, segment_offset+0x04, &ovi);
|
||||
data->segments[i] = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, segment_offset+0x04, &ovmi);
|
||||
if (!data->segments[i]) goto fail;
|
||||
|
||||
if (data->segments[i]->num_samples != segment_samples) {
|
||||
|
@ -9,12 +9,10 @@ VGMSTREAM * init_vgmstream_wii_04sw(STREAMFILE *streamFile) {
|
||||
size_t file_size, data_size;
|
||||
|
||||
|
||||
/* check extension, case insensitive */
|
||||
/* checks */
|
||||
/* ".04sw" is just the ID, the real filename inside the file uses .XA */
|
||||
if (!check_extensions(streamFile,"xa,04sw"))
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x30345357) /* "04SW" */
|
||||
goto fail;
|
||||
|
||||
@ -39,9 +37,9 @@ VGMSTREAM * init_vgmstream_wii_04sw(STREAMFILE *streamFile) {
|
||||
vgmstream->num_samples = read_32bitBE(0x04,streamFile);
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave_shortblock;
|
||||
vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x8000;
|
||||
vgmstream->interleave_smallblock_size = (read_32bitBE(0x08,streamFile) / 2 % vgmstream->interleave_block_size + 7) / 8 * 8;
|
||||
vgmstream->interleave_last_block_size = (read_32bitBE(0x08,streamFile) / 2 % vgmstream->interleave_block_size + 7) / 8 * 8;
|
||||
|
||||
dsp_read_coefs_be(vgmstream,streamFile,0x20, 0x60);
|
||||
/* the initial history offset seems different thatn standard DSP and possibly always zero */
|
||||
@ -50,10 +48,8 @@ VGMSTREAM * init_vgmstream_wii_04sw(STREAMFILE *streamFile) {
|
||||
/* the rest of the header has unknown values (several repeats) and the filename */
|
||||
|
||||
|
||||
/* open the file for reading */
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
|
@ -1,20 +1,17 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* RAS (from Donkey Kong Country Returns) */
|
||||
/* RAS_ - from Donkey Kong Country Returns (Wii) */
|
||||
VGMSTREAM * init_vgmstream_wii_ras(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset;
|
||||
|
||||
int loop_flag;
|
||||
int channel_count;
|
||||
int loop_flag, channel_count;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||
if (strcasecmp("ras",filename_extension(filename))) goto fail;
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "ras"))
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x5241535F) /* "RAS_" */
|
||||
goto fail;
|
||||
|
||||
@ -26,63 +23,32 @@ VGMSTREAM * init_vgmstream_wii_ras(STREAMFILE *streamFile) {
|
||||
loop_flag = 1;
|
||||
}
|
||||
channel_count = 2;
|
||||
start_offset = read_32bitBE(0x18,streamFile);
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
start_offset = read_32bitBE(0x18,streamFile);
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = read_32bitBE(0x14,streamFile);
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->num_samples = read_32bitBE(0x1c,streamFile)/channel_count/8*14;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitBE(0x20,streamFile);
|
||||
vgmstream->meta_type = meta_WII_RAS;
|
||||
|
||||
if (loop_flag) {
|
||||
// loop is block + samples into block
|
||||
vgmstream->loop_start_sample =
|
||||
read_32bitBE(0x30,streamFile)*vgmstream->interleave_block_size/8*14 +
|
||||
read_32bitBE(0x34,streamFile);
|
||||
vgmstream->loop_end_sample =
|
||||
read_32bitBE(0x38,streamFile)*vgmstream->interleave_block_size/8*14 +
|
||||
read_32bitBE(0x3C,streamFile);
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitBE(0x20,streamFile);
|
||||
|
||||
vgmstream->num_samples = read_32bitBE(0x1c,streamFile)/channel_count/8*14;
|
||||
if (loop_flag) { /* loop is block + samples into block */
|
||||
vgmstream->loop_start_sample = read_32bitBE(0x30,streamFile)*vgmstream->interleave_block_size/8*14 +
|
||||
read_32bitBE(0x34,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitBE(0x38,streamFile)*vgmstream->interleave_block_size/8*14 +
|
||||
read_32bitBE(0x3C,streamFile);
|
||||
}
|
||||
|
||||
if (vgmstream->coding_type == coding_NGC_DSP) {
|
||||
int i;
|
||||
for (i=0;i<16;i++) {
|
||||
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x40+i*2,streamFile);
|
||||
}
|
||||
if (channel_count == 2) {
|
||||
for (i=0;i<16;i++)
|
||||
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x70+i*2,streamFile);
|
||||
}
|
||||
} else {
|
||||
dsp_read_coefs_be(vgmstream,streamFile,0x40,0x30);
|
||||
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* open the file for reading */
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
if (vgmstream->layout_type==layout_interleave_shortblock)
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
|
||||
vgmstream->interleave_block_size);
|
||||
else
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
|
||||
0x1000);
|
||||
|
||||
if (!vgmstream->ch[i].streamfile) goto fail;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=
|
||||
start_offset + i*vgmstream->interleave_block_size;
|
||||
}
|
||||
}
|
||||
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
|
@ -229,8 +229,8 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
|
||||
/* older Wwise (~<2012) */
|
||||
|
||||
switch(vorb_size) {
|
||||
//case 0x2C: /* early (~2009), some EVE Online Apocrypha files? */
|
||||
case 0x28: /* early (~2009), ex. The Lord of the Rings: Conquest PC */
|
||||
case 0x2C: /* earliest (~2009), ex. UFC Undisputed 2009 (PS3), some EVE Online Apocrypha files? */
|
||||
case 0x28: /* early (~2009), ex. The Lord of the Rings: Conquest (PC) */
|
||||
data_offsets = 0x18;
|
||||
block_offsets = 0; /* no need, full headers are present */
|
||||
cfg.header_type = WWV_TYPE_8;
|
||||
@ -589,15 +589,15 @@ fail:
|
||||
0x31 (1): blocksize_0_exp (large)
|
||||
0x32 (2): empty
|
||||
|
||||
"vorb" size 0x28 / 0x2a
|
||||
"vorb" size 0x28 / 0x2c / 0x2a
|
||||
0x00 (4): num_samples
|
||||
0x04 (4): data start offset after seek table+setup, or loop start when "smpl" is present
|
||||
0x08 (4): data end offset after seek table (setup+packets), or loop end when "smpl" is present
|
||||
0x0c (2): ? (small, 0..~0x400)
|
||||
0x0c (2): ? (small, 0..~0x400) [(4) when size is 0x2C]
|
||||
0x10 (4): setup_offset within data (0 = no seek table)
|
||||
0x14 (4): audio_offset within data
|
||||
0x18 (2): biggest packet size (not including header)?
|
||||
0x1a (2): ? (small, N..~0x100) uLastGranuleExtra?
|
||||
0x1a (2): ? (small, N..~0x100) uLastGranuleExtra? [(4) when size is 0x2C]
|
||||
0x1c (4): ? (mid, 0~0x5000) dwDecodeAllocSize?
|
||||
0x20 (4): ? (mid, 0~0x5000) dwDecodeX64AllocSize?
|
||||
0x24 (4): parent bank/event id? uHashCodebook? (shared by several .wem a game, but not all need to share it)
|
||||
|
112
src/meta/xwb.c
112
src/meta/xwb.c
@ -35,6 +35,11 @@ typedef struct {
|
||||
size_t base_size;
|
||||
off_t entry_offset;
|
||||
size_t entry_size;
|
||||
off_t names_offset;
|
||||
size_t names_size;
|
||||
size_t names_entry_size;
|
||||
off_t extra_offset;
|
||||
size_t extra_size;
|
||||
off_t data_offset;
|
||||
size_t data_size;
|
||||
|
||||
@ -63,7 +68,7 @@ typedef struct {
|
||||
uint32_t loop_end_sample;
|
||||
} xwb_header;
|
||||
|
||||
static void get_xsb_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile);
|
||||
static void get_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile);
|
||||
|
||||
|
||||
/* XWB - XACT Wave Bank (Microsoft SDK format for XBOX/XBOX360/Windows) */
|
||||
@ -100,12 +105,20 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||
/* read segment offsets (SEGIDX) */
|
||||
if (xwb.version <= XACT1_0_MAX) {
|
||||
xwb.total_subsongs = read_32bit(0x0c, streamFile);
|
||||
/* 0x10: bank name */
|
||||
/* 0x10: bank name (size 0x10) */
|
||||
xwb.base_offset = 0;
|
||||
xwb.base_size = 0;
|
||||
xwb.entry_offset = 0x50;
|
||||
xwb.entry_size = xwb.entry_elem_size * xwb.total_subsongs;
|
||||
xwb.entry_elem_size = 0x14;
|
||||
xwb.entry_offset= 0x50;
|
||||
xwb.entry_size = xwb.entry_elem_size * xwb.total_subsongs;
|
||||
xwb.data_offset = xwb.entry_offset + xwb.entry_size;
|
||||
xwb.data_size = get_streamfile_size(streamFile) - xwb.data_offset;
|
||||
xwb.data_offset = xwb.entry_offset + xwb.entry_size;
|
||||
xwb.data_size = get_streamfile_size(streamFile) - xwb.data_offset;
|
||||
|
||||
xwb.names_offset = 0;
|
||||
xwb.names_size = 0;
|
||||
xwb.names_entry_size= 0;
|
||||
xwb.extra_offset = 0;
|
||||
xwb.extra_size = 0;
|
||||
}
|
||||
else {
|
||||
off = xwb.version <= XACT2_2_MAX ? 0x08 : 0x0c;
|
||||
@ -113,10 +126,32 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||
xwb.base_size = read_32bit(off+0x04, streamFile);
|
||||
xwb.entry_offset= read_32bit(off+0x08, streamFile);//ENTRYMETADATA
|
||||
xwb.entry_size = read_32bit(off+0x0c, streamFile);
|
||||
/* go to last segment (XACT2/3 have 5 segments, XACT1 4) */
|
||||
//0x10: XACT1/2: ENTRYNAMES, XACT3: SEEKTABLES
|
||||
//0x14: XACT1: none (ENTRYWAVEDATA), XACT2: EXTRA, XACT3: ENTRYNAMES
|
||||
suboff = xwb.version <= XACT1_1_MAX ? 0x08 : 0x08+0x08;
|
||||
|
||||
/* read extra segments (values can be 0 == no segment) */
|
||||
if (xwb.version <= XACT1_1_MAX) {
|
||||
xwb.names_offset = read_32bit(off+0x10, streamFile);//ENTRYNAMES
|
||||
xwb.names_size = read_32bit(off+0x14, streamFile);
|
||||
xwb.names_entry_size= 0x40;
|
||||
xwb.extra_offset = 0;
|
||||
xwb.extra_size = 0;
|
||||
suboff = 0x04*2;
|
||||
}
|
||||
else if (xwb.version <= XACT2_1_MAX) {
|
||||
xwb.names_offset = read_32bit(off+0x10, streamFile);//ENTRYNAMES
|
||||
xwb.names_size = read_32bit(off+0x14, streamFile);
|
||||
xwb.names_entry_size= 0x40;
|
||||
xwb.extra_offset = read_32bit(off+0x18, streamFile);//EXTRA
|
||||
xwb.extra_size = read_32bit(off+0x1c, streamFile);
|
||||
suboff = 0x04*2 + 0x04*2;
|
||||
} else {
|
||||
xwb.extra_offset = read_32bit(off+0x10, streamFile);//SEEKTABLES
|
||||
xwb.extra_size = read_32bit(off+0x14, streamFile);
|
||||
xwb.names_offset = read_32bit(off+0x18, streamFile);//ENTRYNAMES
|
||||
xwb.names_size = read_32bit(off+0x1c, streamFile);
|
||||
xwb.names_entry_size= 0x40;
|
||||
suboff = 0x04*2 + 0x04*2;
|
||||
}
|
||||
|
||||
xwb.data_offset = read_32bit(off+0x10+suboff, streamFile);//ENTRYWAVEDATA
|
||||
xwb.data_size = read_32bit(off+0x14+suboff, streamFile);
|
||||
|
||||
@ -127,7 +162,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||
off = xwb.base_offset;
|
||||
xwb.base_flags = (uint32_t)read_32bit(off+0x00, streamFile);
|
||||
xwb.total_subsongs = read_32bit(off+0x04, streamFile);
|
||||
/* 0x08 bank_name */
|
||||
/* 0x08: bank name (size 0x40) */
|
||||
suboff = 0x08 + (xwb.version <= XACT1_1_MAX ? 0x10 : 0x40);
|
||||
xwb.entry_elem_size = read_32bit(off+suboff+0x00, streamFile);
|
||||
/* suboff+0x04: meta name entry size */
|
||||
@ -315,8 +350,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||
else if (xwb.version <= XACT2_1_MAX && (xwb.codec == XMA1 || xwb.codec == XMA2) && xwb.loop_flag) {
|
||||
/* v38: byte offset, v40+: sample offset, v39: ? */
|
||||
/* need to manually find sample offsets, thanks to Microsoft dumb headers */
|
||||
ms_sample_data msd;
|
||||
memset(&msd,0,sizeof(ms_sample_data));
|
||||
ms_sample_data msd = {0};
|
||||
|
||||
msd.xma_version = xwb.codec == XMA1 ? 1 : 2;
|
||||
msd.channels = xwb.channels;
|
||||
@ -360,7 +394,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||
vgmstream->num_streams = xwb.total_subsongs;
|
||||
vgmstream->stream_size = xwb.stream_size;
|
||||
vgmstream->meta_type = meta_XWB;
|
||||
get_xsb_name(vgmstream->stream_name,STREAM_NAME_SIZE, target_subsong, &xwb, streamFile);
|
||||
get_name(vgmstream->stream_name,STREAM_NAME_SIZE, target_subsong, &xwb, streamFile);
|
||||
|
||||
switch(xwb.codec) {
|
||||
case PCM: /* Unreal Championship (Xbox)[PCM8], KOF2003 (Xbox)[PCM16LE], Otomedius (X360)[PCM16BE] */
|
||||
@ -496,6 +530,24 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
/* ****************************************************************************** */
|
||||
|
||||
/* try to get the stream name in the .xwb, though they are very rarely included */
|
||||
static int get_xwb_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile) {
|
||||
int read;
|
||||
|
||||
if (!xwb->names_offset || !xwb->names_size || xwb->names_entry_size > maxsize)
|
||||
goto fail;
|
||||
|
||||
read = read_string(buf,xwb->names_entry_size, xwb->names_offset + xwb->names_entry_size*(target_subsong-1),streamFile);
|
||||
if (read <= 0) goto fail;
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ****************************************************************************** */
|
||||
/* XSB parsing from xwb_split (mostly untouched), could be improved */
|
||||
|
||||
@ -539,24 +591,19 @@ typedef struct {
|
||||
|
||||
|
||||
/* try to find the stream name in a companion XSB file, a comically complex cue format. */
|
||||
static void get_xsb_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamXwb) {
|
||||
static int get_xsb_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamXwb) {
|
||||
STREAMFILE *streamFile = NULL;
|
||||
int i,j, start_sound, cfg__start_sound = 0, cfg__selected_wavebank = 0;
|
||||
int xsb_version;
|
||||
off_t off, suboff, name_offset = 0;
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
|
||||
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
|
||||
xsb_header xsb;
|
||||
|
||||
memset(&xsb,0,sizeof(xsb_header)); /* before any "fail"! */
|
||||
xsb_header xsb = {0};
|
||||
|
||||
|
||||
streamFile = open_stream_ext(streamXwb, "xsb");
|
||||
if (!streamFile) goto fail;
|
||||
|
||||
//todo try common names (xwb and xsb often are named slightly differently using a common convention)
|
||||
|
||||
|
||||
/* check header */
|
||||
if ((read_32bitBE(0x00,streamFile) != 0x5344424B) && /* "SDBK" (LE) */
|
||||
(read_32bitBE(0x00,streamFile) != 0x4B424453)) /* "KBDS" (BE) */
|
||||
@ -817,6 +864,25 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_subsong, xwb_hea
|
||||
fail:
|
||||
free(xsb.xsb_sounds);
|
||||
free(xsb.xsb_wavebanks);
|
||||
if (streamFile) close_streamfile(streamFile);
|
||||
return;
|
||||
close_streamfile(streamFile);
|
||||
|
||||
return (name_offset);
|
||||
}
|
||||
|
||||
static void get_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile) {
|
||||
int name_found;
|
||||
|
||||
/* try inside this xwb */
|
||||
name_found = get_xwb_name(buf, maxsize, target_subsong, xwb, streamFile);
|
||||
if (name_found) return;
|
||||
|
||||
/* try again in external .xsb */
|
||||
get_xsb_name(buf, maxsize, target_subsong, xwb, streamFile);
|
||||
|
||||
|
||||
//todo try again with common names (xwb and xsb often are named slightly differently using a common convention):
|
||||
// InGameMusic.xwb + ingamemusic.xsb
|
||||
// UIMusicBank.xwb + UISoundBank.xsb
|
||||
// NB_BGM_m0100_WB.xwb + NB_BGM_m0100_SB.xsb
|
||||
// Wave Bank.xwb + Sound Bank.xsb
|
||||
}
|
||||
|
@ -628,8 +628,9 @@ fail:
|
||||
static void multifile_close(MULTIFILE_STREAMFILE *streamfile) {
|
||||
int i;
|
||||
for (i = 0; i < streamfile->inner_sfs_size; i++) {
|
||||
for (i = 0; i < streamfile->inner_sfs_size; i++)
|
||||
for (i = 0; i < streamfile->inner_sfs_size; i++) {
|
||||
close_streamfile(streamfile->inner_sfs[i]);
|
||||
}
|
||||
}
|
||||
free(streamfile->inner_sfs);
|
||||
free(streamfile->sizes);
|
||||
|
@ -69,7 +69,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_mp4_aac,
|
||||
#endif
|
||||
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
|
||||
init_vgmstream_akb,
|
||||
init_vgmstream_akb_mp4,
|
||||
#endif
|
||||
init_vgmstream_sadb,
|
||||
init_vgmstream_ps2_bmdx,
|
||||
@ -257,7 +257,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_ps2_voi,
|
||||
init_vgmstream_ps2_khv,
|
||||
init_vgmstream_pc_smp,
|
||||
init_vgmstream_ngc_bo2,
|
||||
init_vgmstream_ngc_rkv,
|
||||
init_vgmstream_dsp_ddsp,
|
||||
init_vgmstream_p3d,
|
||||
init_vgmstream_ps2_tk1,
|
||||
@ -330,8 +330,8 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_ps2_vds_vdm,
|
||||
init_vgmstream_x360_cxs,
|
||||
init_vgmstream_dsp_adx,
|
||||
init_vgmstream_akb_multi,
|
||||
init_vgmstream_akb2_multi,
|
||||
init_vgmstream_akb,
|
||||
init_vgmstream_akb2,
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
init_vgmstream_mp4_aac_ffmpeg,
|
||||
#endif
|
||||
@ -350,6 +350,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_ta_aac_x360,
|
||||
init_vgmstream_ta_aac_ps3,
|
||||
init_vgmstream_ta_aac_mobile,
|
||||
init_vgmstream_ta_aac_mobile_vorbis,
|
||||
init_vgmstream_ps3_mta2,
|
||||
init_vgmstream_ngc_ulw,
|
||||
init_vgmstream_pc_xa30,
|
||||
@ -383,6 +384,9 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_wave,
|
||||
init_vgmstream_wave_segmented,
|
||||
init_vgmstream_rsd6at3p,
|
||||
init_vgmstream_rsd6wma,
|
||||
init_vgmstream_smv,
|
||||
init_vgmstream_nxap,
|
||||
|
||||
init_vgmstream_txth, /* should go at the end (lower priority) */
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
@ -884,12 +888,8 @@ void vgmstream_force_loop(VGMSTREAM* vgmstream, int loop_flag, int loop_start_sa
|
||||
void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
|
||||
switch (vgmstream->layout_type) {
|
||||
case layout_interleave:
|
||||
case layout_interleave_shortblock:
|
||||
render_vgmstream_interleave(buffer,sample_count,vgmstream);
|
||||
break;
|
||||
#ifdef VGM_USE_VORBIS
|
||||
case layout_ogg_vorbis:
|
||||
#endif
|
||||
case layout_none:
|
||||
render_vgmstream_nolayout(buffer,sample_count,vgmstream);
|
||||
break;
|
||||
@ -900,7 +900,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
|
||||
case layout_blocked_ea_schl:
|
||||
case layout_blocked_ea_1snh:
|
||||
case layout_blocked_caf:
|
||||
case layout_wsi_blocked:
|
||||
case layout_blocked_wsi:
|
||||
case layout_str_snds_blocked:
|
||||
case layout_ws_aud_blocked:
|
||||
case layout_matx_blocked:
|
||||
@ -1006,6 +1006,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
case coding_3DS_IMA:
|
||||
return 2;
|
||||
case coding_XBOX_IMA:
|
||||
case coding_XBOX_IMA_mch:
|
||||
case coding_XBOX_IMA_int:
|
||||
case coding_FSB_IMA:
|
||||
case coding_WWISE_IMA:
|
||||
@ -1048,6 +1049,10 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
return vgmstream->ws_output_size;
|
||||
case coding_AICA:
|
||||
return 2;
|
||||
case coding_YAMAHA:
|
||||
return (0x40-0x04*vgmstream->channels) * 2 / vgmstream->channels;
|
||||
case coding_YAMAHA_NXAP:
|
||||
return (0x40-0x04) * 2;
|
||||
case coding_NDS_PROCYON:
|
||||
return 30;
|
||||
case coding_L5_555:
|
||||
@ -1175,9 +1180,11 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
//todo should be 0x48 when stereo, but blocked/interleave layout don't understand stereo codecs
|
||||
return 0x24; //vgmstream->channels==1 ? 0x24 : 0x48;
|
||||
case coding_XBOX_IMA_int:
|
||||
case coding_FSB_IMA:
|
||||
case coding_WWISE_IMA:
|
||||
return 0x24;
|
||||
case coding_XBOX_IMA_mch:
|
||||
case coding_FSB_IMA:
|
||||
return 0x24 * vgmstream->channels;
|
||||
case coding_APPLE_IMA4:
|
||||
return 0x22;
|
||||
|
||||
@ -1208,6 +1215,9 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
return vgmstream->current_block_size;
|
||||
case coding_AICA:
|
||||
return 0x01;
|
||||
case coding_YAMAHA:
|
||||
case coding_YAMAHA_NXAP:
|
||||
return 0x40;
|
||||
case coding_NDS_PROCYON:
|
||||
return 0x10;
|
||||
case coding_L5_555:
|
||||
@ -1251,7 +1261,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) {
|
||||
switch (vgmstream->coding_type) {
|
||||
case coding_NDS_IMA:
|
||||
return (vgmstream->interleave_smallblock_size-4)*2;
|
||||
return (vgmstream->interleave_last_block_size-4)*2;
|
||||
default:
|
||||
return get_vgmstream_samples_per_frame(vgmstream);
|
||||
}
|
||||
@ -1259,7 +1269,7 @@ int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) {
|
||||
int get_vgmstream_shortframe_size(VGMSTREAM * vgmstream) {
|
||||
switch (vgmstream->coding_type) {
|
||||
case coding_NDS_IMA:
|
||||
return vgmstream->interleave_smallblock_size;
|
||||
return vgmstream->interleave_last_block_size;
|
||||
default:
|
||||
return get_vgmstream_frame_size(vgmstream);
|
||||
}
|
||||
@ -1433,7 +1443,14 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
break;
|
||||
case coding_XBOX_IMA:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_xbox_ima(vgmstream,&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
decode_xbox_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
samples_to_do,chan);
|
||||
}
|
||||
break;
|
||||
case coding_XBOX_IMA_mch:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_xbox_ima_mch(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
samples_to_do,chan);
|
||||
}
|
||||
@ -1799,6 +1816,20 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
samples_to_do);
|
||||
}
|
||||
break;
|
||||
case coding_YAMAHA:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_yamaha(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
samples_to_do, chan);
|
||||
}
|
||||
break;
|
||||
case coding_YAMAHA_NXAP:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_yamaha_nxap(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
samples_to_do);
|
||||
}
|
||||
break;
|
||||
case coding_NDS_PROCYON:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_nds_procyon(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
@ -2109,17 +2140,16 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
||||
"\n");
|
||||
concatn(length,desc,temp);
|
||||
|
||||
if (vgmstream->layout_type == layout_interleave
|
||||
|| vgmstream->layout_type == layout_interleave_shortblock) {
|
||||
if (vgmstream->layout_type == layout_interleave) {
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"interleave: %#x bytes\n",
|
||||
(int32_t)vgmstream->interleave_block_size);
|
||||
concatn(length,desc,temp);
|
||||
|
||||
if (vgmstream->layout_type == layout_interleave_shortblock) {
|
||||
if (vgmstream->interleave_last_block_size) {
|
||||
snprintf(temp,TEMPSIZE,
|
||||
"last block interleave: %#x bytes\n",
|
||||
(int32_t)vgmstream->interleave_smallblock_size);
|
||||
"interleave last block: %#x bytes\n",
|
||||
(int32_t)vgmstream->interleave_last_block_size);
|
||||
concatn(length,desc,temp);
|
||||
}
|
||||
}
|
||||
@ -2192,7 +2222,8 @@ static void try_dual_file_stereo(VGMSTREAM * opened_vgmstream, STREAMFILE *strea
|
||||
{"l","r"},
|
||||
{"left","right"},
|
||||
{"Left","Right"},
|
||||
{".V0",".V1"},
|
||||
{".V0",".V1"}, /* Homura (PS2) */
|
||||
{".L",".R"}, /* Crash Nitro Racing (PS2) */
|
||||
{"_0","_1"}, //unneeded?
|
||||
};
|
||||
char new_filename[PATH_LIMIT];
|
||||
@ -2269,7 +2300,7 @@ static void try_dual_file_stereo(VGMSTREAM * opened_vgmstream, STREAMFILE *strea
|
||||
/* check even if the layout doesn't use them, because it is
|
||||
* difficult to determine when it does, and they should be zero otherwise, anyway */
|
||||
new_vgmstream->interleave_block_size == opened_vgmstream->interleave_block_size &&
|
||||
new_vgmstream->interleave_smallblock_size == opened_vgmstream->interleave_smallblock_size)) {
|
||||
new_vgmstream->interleave_last_block_size == opened_vgmstream->interleave_last_block_size)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -128,6 +128,7 @@ typedef enum {
|
||||
coding_3DS_IMA, /* 3DS IMA ADPCM */
|
||||
coding_MS_IMA, /* Microsoft IMA ADPCM */
|
||||
coding_XBOX_IMA, /* XBOX IMA ADPCM */
|
||||
coding_XBOX_IMA_mch, /* XBOX IMA ADPCM (multichannel) */
|
||||
coding_XBOX_IMA_int, /* XBOX IMA ADPCM (interleaved/mono) */
|
||||
coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */
|
||||
coding_DAT4_IMA, /* Eurocom 'DAT4' IMA ADPCM */
|
||||
@ -145,6 +146,8 @@ typedef enum {
|
||||
coding_MSADPCM, /* Microsoft ADPCM */
|
||||
coding_WS, /* Westwood Studios VBR ADPCM */
|
||||
coding_AICA, /* Yamaha AICA ADPCM */
|
||||
coding_YAMAHA, /* Yamaha ADPCM */
|
||||
coding_YAMAHA_NXAP, /* Yamaha ADPCM (NXAP variation) */
|
||||
coding_NDS_PROCYON, /* Procyon Studio ADPCM */
|
||||
coding_L5_555, /* Level-5 0x555 ADPCM */
|
||||
coding_SASSC, /* Activision EXAKT SASSC DPCM */
|
||||
@ -212,7 +215,6 @@ typedef enum {
|
||||
|
||||
/* interleave */
|
||||
layout_interleave, /* equal interleave throughout the stream */
|
||||
layout_interleave_shortblock, /* interleave with a short last block */
|
||||
|
||||
/* headered blocks */
|
||||
layout_ast_blocked,
|
||||
@ -221,7 +223,7 @@ typedef enum {
|
||||
layout_blocked_ea_schl,
|
||||
layout_blocked_ea_1snh,
|
||||
layout_blocked_caf,
|
||||
layout_wsi_blocked,
|
||||
layout_blocked_wsi,
|
||||
layout_str_snds_blocked,
|
||||
layout_ws_aud_blocked,
|
||||
layout_matx_blocked,
|
||||
@ -254,9 +256,6 @@ typedef enum {
|
||||
layout_segmented, /* song divided in segments, each a complete VGMSTREAM */
|
||||
layout_scd_int, /* deinterleave done by the SCDINTSTREAMFILE */
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
layout_ogg_vorbis, /* ogg vorbis file */
|
||||
#endif
|
||||
} layout_t;
|
||||
|
||||
/* The meta type specifies how we know what we know about the file.
|
||||
@ -371,7 +370,7 @@ typedef enum {
|
||||
meta_PS2_PSH, /* Dawn of Mana - Seiken Densetsu 4 */
|
||||
meta_SCD_PCM, /* Lunar - Eternal Blue */
|
||||
meta_PS2_PCM, /* Konami KCEJ East: Ephemeral Fantasia, Yu-Gi-Oh! The Duelists of the Roses, 7 Blades */
|
||||
meta_PS2_RKV, /* Legacy of Kain - Blood Omen 2 */
|
||||
meta_PS2_RKV, /* Legacy of Kain - Blood Omen 2 (PS2) */
|
||||
meta_PS2_PSW, /* Rayman Raving Rabbids */
|
||||
meta_PS2_VAS, /* Pro Baseball Spirits 5 */
|
||||
meta_PS2_TEC, /* TECMO badflagged stream */
|
||||
@ -428,6 +427,7 @@ typedef enum {
|
||||
meta_RSD6OOGV, /* RSD6OOGV */
|
||||
meta_RSD6XMA, /* RSD6XMA */
|
||||
meta_RSD6AT3P, /* RSD6AT3+ */
|
||||
meta_RSD6WMA, /* RSD6WMA */
|
||||
|
||||
meta_PS2_ASS, /* ASS */
|
||||
meta_PS2_SEG, /* Eragon */
|
||||
@ -535,7 +535,7 @@ typedef enum {
|
||||
meta_P3D, /* Prototype P3D */
|
||||
meta_PS2_TK1, /* Tekken (NamCollection) */
|
||||
meta_PS2_ADSC, /* Kenka Bancho 2: Full Throttle */
|
||||
meta_NGC_BO2, /* Blood Omen 2 (NGC) */
|
||||
meta_NGC_RKV, /* Legacy of Kain - Blood Omen 2 (GC) */
|
||||
meta_DSP_DDSP, /* Various (2 dsp files stuck together */
|
||||
meta_NGC_DSP_MPDS, /* Big Air Freestyle, Terminator 3 */
|
||||
meta_DSP_STR_IG, /* Micro Machines, Superman Superman: Shadow of Apokolis */
|
||||
@ -617,7 +617,7 @@ typedef enum {
|
||||
meta_GTD, /* Knights Contract (X360/PS3), Valhalla Knights 3 (PSV) */
|
||||
meta_TA_AAC_X360, /* tri-Ace AAC (Star Ocean 4, End of Eternity, Infinite Undiscovery) */
|
||||
meta_TA_AAC_PS3, /* tri-Ace AAC (Star Ocean International, Resonance of Fate) */
|
||||
meta_TA_AAC_VORBIS, /* tri-Ace AAC (Star Ocean Anamnesis, Heaven x Inferno) */
|
||||
meta_TA_AAC_MOBILE, /* tri-Ace AAC (Star Ocean Anamnesis, Heaven x Inferno) */
|
||||
meta_PS3_MTA2, /* Metal Gear Solid 4 MTA2 */
|
||||
meta_NGC_ULW, /* Burnout 1 (GC only) */
|
||||
meta_PC_XA30, /* Driver - Parallel Lines (PC) */
|
||||
@ -656,8 +656,10 @@ typedef enum {
|
||||
meta_SQEX_MAB, /* Square-Enix newest middleware (music) */
|
||||
meta_OGG_L2SD, /* Ogg Vorbis with obfuscation [Lineage II Chronicle 4 (PC)] */
|
||||
meta_WAF, /* KID WAF [Ever 17 (PC)] */
|
||||
meta_WAVE, /* WayForward "EngineBlack" games [Mighty Switch Force! (3DS)] */
|
||||
meta_WAVE_segmented, /* WayForward "EngineBlack" games, segmented [Shantae and the Pirate's Curse (PC)] */
|
||||
meta_WAVE, /* EngineBlack games [Mighty Switch Force! (3DS)] */
|
||||
meta_WAVE_segmented, /* EngineBlack games, segmented [Shantae and the Pirate's Curse (PC)] */
|
||||
meta_SMV, /* Cho Aniki Zero (PSP) */
|
||||
meta_NXAP, /* Nex Entertainment games [Time Crisis 4 (PS3), Time Crisis Razing Storm (PS3)] */
|
||||
|
||||
#ifdef VGM_USE_MP4V2
|
||||
meta_MP4, /* AAC (iOS) */
|
||||
@ -745,7 +747,7 @@ typedef struct {
|
||||
|
||||
/* layouts/block */
|
||||
size_t interleave_block_size; /* interleave, or block/frame size (depending on the codec) */
|
||||
size_t interleave_smallblock_size; /* smaller interleave for last block */
|
||||
size_t interleave_last_block_size; /* smaller interleave for last block */
|
||||
|
||||
/* channel state */
|
||||
VGMSTREAMCHANNEL * ch; /* pointer to array of channels */
|
||||
|
Loading…
Reference in New Issue
Block a user