Merge pull request #140 from bnnm/ac3-xwb-hevag

AC3, XWB, HEVAG
This commit is contained in:
Christopher Snowhill 2017-11-11 20:21:36 -08:00 committed by GitHub
commit fc5bb81ddc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 1367 additions and 1416 deletions

View File

@ -129,7 +129,9 @@ git clean -fd
## Development
### Structure
vgmstream uses C89 when possible (so VS2010 can compile it), and C++ for the foobar2000 and Audacious plugins.
vgmstream uses C (C89 when possible), and C++ for the foobar2000 and Audacious plugins.
C is restricted to features VS2010 can understand. This mainly means means declaring variables at the start of a { .. } block (declare+initialize is fine, as long as it doesn't reference variables declared in that block) and avoiding C99 like variable-length arrays (but others like // comments are fine).
```
./ docs, scripts
@ -162,11 +164,17 @@ Very simplified it goes like this:
### Adding new formats
For new simple formats, assuming existing layout/coding:
- *src/meta/(format-name).c*: create new format parser that reads all needed info from the stream header and inits VGMSTREAM
- *src/meta/meta.h*: register parser's init
- *src/vgmstream.h*: register new meta
- *src/meta/(format-name).c*: create new init_vgmstream_(format-name) parser that reads all needed info from the stream header and inits VGMSTREAM
- *src/meta/meta.h*: define parser's init
- *src/vgmstream.h*: define meta description in the meta_t list
- *src/vgmstream.c*: add parser init to the init list
- *src/formats.c*: add new extension to the format list, add meta description
- *fb2k/foo_filetypes.h*: add new extension to the file register list (optional)
- *src/libvgmstream.vcproj/vcxproj/filters*: add to compile new (format-name).c parser in VS
- if the format needs an external library don't forget to mark optional parts with: *#ifdef VGM_USE_X ... #endif*
A STREAMFILE is passed to init_vgmstream_(format-name) function, and I/O must be done using its functions and not STDIO/FILEs, as this lets plugins do their own I/O. This includes reading data from the header or opening other STREAMFILEs (if the header has companion files that need to be parsed).
When a parser is successful (allocates VGMSTREAM and sets values) it also needs to open and assign to the VGMSTREAM one or several STREAMFILEs (usually reopens the one passed, but could be any other file) to do I/O during decode. The STREAMFILE passed to the meta will be discarded and must not be reused.
If it supports subsongs it should read and handle the stream index (subsong number) in the passed STREAMFILE, and report the number of subsongs in the VGMSTREAM, to signal the plugins this feature. The index is 1-based (first subsong is 1, not 0).

View File

@ -15,7 +15,6 @@
extern "C" {
#include "../src/formats.h"
#include "../src/vgmstream.h"
}
#include "plugin.h"
@ -95,8 +94,8 @@ bool VgmstreamPlugin::is_our_file(const char *filename, VFSFile &file) {
else
ext = ext+1; /* skip the dot */
const char ** ext_list = vgmstream_get_formats();
int ext_list_len = vgmstream_get_formats_length();
size_t ext_list_len = 0;
const char ** ext_list = vgmstream_get_formats(&ext_list_len);
for (int i=0; i < ext_list_len; i++) {
if (!strcasecmp(ext, ext_list[i]))

View File

@ -161,6 +161,7 @@ VGMSTREAM_DECLARE_FILE_TYPE("KOVS", kovs);
VGMSTREAM_DECLARE_FILE_TYPE("KRAW", kraw);
VGMSTREAM_DECLARE_FILE_TYPE("LAAC", laac);
VGMSTREAM_DECLARE_FILE_TYPE("LAC3", lac3);
VGMSTREAM_DECLARE_FILE_TYPE("LEG", leg);
VGMSTREAM_DECLARE_FILE_TYPE("LMP4", lmp4);
VGMSTREAM_DECLARE_FILE_TYPE("LOGG", logg);
@ -282,8 +283,6 @@ VGMSTREAM_DECLARE_FILE_TYPE("SPS", sps);
VGMSTREAM_DECLARE_FILE_TYPE("SPSD", spsd);
VGMSTREAM_DECLARE_FILE_TYPE("SPW", spw);
VGMSTREAM_DECLARE_FILE_TYPE("SS2", ss2);
VGMSTREAM_DECLARE_FILE_TYPE("SS3", ss3);
VGMSTREAM_DECLARE_FILE_TYPE("SS7", ss7);
VGMSTREAM_DECLARE_FILE_TYPE("SSM", ssm);
VGMSTREAM_DECLARE_FILE_TYPE("SSS", sss);
VGMSTREAM_DECLARE_FILE_TYPE("STER", ster);

View File

@ -16,7 +16,6 @@
#include <shared.h>
extern "C" {
#include "../src/formats.h"
#include "../src/vgmstream.h"
}
#include "foo_vgmstream.h"
@ -184,19 +183,19 @@ void input_vgmstream::decode_initialize(t_uint32 p_subsong, unsigned p_flags, ab
bool input_vgmstream::decode_run(audio_chunk & p_chunk,abort_callback & p_abort) {
if (!decoding) return false;
if (!vgmstream) return false;
int max_buffer_samples = sizeof(sample_buffer)/sizeof(sample_buffer[0])/vgmstream->channels;
int l = 0, samples_to_do = max_buffer_samples;
int samples_to_do = max_buffer_samples;
t_size bytes;
if(vgmstream) {
{
bool loop_okay = loop_forever && vgmstream->loop_flag && !ignore_loop && !force_ignore_loop;
if (decode_pos_samples+max_buffer_samples>stream_length_samples && !loop_okay)
samples_to_do=stream_length_samples-decode_pos_samples;
else
samples_to_do=max_buffer_samples;
l = (samples_to_do*vgmstream->channels * sizeof(sample_buffer[0]));
if (samples_to_do /*< DECODE_SIZE*/ == 0) {
decoding = false;
return false;
@ -222,15 +221,14 @@ bool input_vgmstream::decode_run(audio_chunk & p_chunk,abort_callback & p_abort)
}
}
p_chunk.set_data_fixedpoint((char*)sample_buffer, l, vgmstream->sample_rate, vgmstream->channels, 16, audio_chunk::g_guess_channel_config(vgmstream->channels));
bytes = (samples_to_do*vgmstream->channels * sizeof(sample_buffer[0]));
p_chunk.set_data_fixedpoint((char*)sample_buffer, bytes, vgmstream->sample_rate, vgmstream->channels, 16, audio_chunk::g_guess_channel_config(vgmstream->channels));
decode_pos_samples+=samples_to_do;
decode_pos_ms=decode_pos_samples*1000LL/vgmstream->sample_rate;
return samples_to_do==max_buffer_samples;
}
return false;
}
void input_vgmstream::decode_seek(double p_seconds,abort_callback & p_abort) {
@ -295,11 +293,10 @@ void input_vgmstream::retag_commit(abort_callback & p_abort) { /*throw exception
bool input_vgmstream::g_is_our_content_type(const char * p_content_type) {return false;}
bool input_vgmstream::g_is_our_path(const char * p_path,const char * p_extension) {
const char ** ext_list;
int ext_list_len;
size_t ext_list_len;
int i;
ext_list = vgmstream_get_formats();
ext_list_len = vgmstream_get_formats_length();
ext_list = vgmstream_get_formats(&ext_list_len);
for (i=0; i < ext_list_len; i++) {
if (!stricmp_utf8(p_extension, ext_list[i]))

View File

@ -1,4 +1,4 @@
#include "formats.h"
#include "vgmstream.h"
//#define VGM_REGISTER_TYPE(extension) ...
//#define VGM_REGISTER_TYPE_COMMON(extension) ... /* for common extensions like aiff */
@ -154,6 +154,7 @@ static const char* extension_list[] = {
"kraw",
"laac", //fake extension, for AAC (tri-Ace/FFmpeg)
"lac3", //fake extension, for AC3
"leg",
"lmp4", //fake extension, for MP4s
"logg", //fake extension, for OGGs
@ -276,8 +277,6 @@ static const char* extension_list[] = {
"spsd",
"spw",
"ss2",
"ss3",
"ss7",
"ssm",
"sss",
"ster",
@ -374,22 +373,11 @@ static const char* extension_list[] = {
//, NULL //end mark
};
/**
* List of supported formats.
*
* For plugins that need to know (test.exe doesn't use it)
*/
const char ** vgmstream_get_formats() {
const char ** vgmstream_get_formats(size_t * size) {
*size = sizeof(extension_list) / sizeof(char*);
return extension_list;
}
/**
* Number of elements in the list.
*/
int vgmstream_get_formats_length() {
return sizeof(extension_list) / sizeof(char*);
}
/* internal description info */

View File

@ -1,19 +0,0 @@
/*
* formats.h - utils to parse supported formats
*/
#ifndef _FORMATS_H_
#define _FORMATS_H_
#include "vgmstream.h"
/* rough number of chars counting all extensions (actually <1500 and extra space) */
#define VGM_EXTENSION_LIST_CHAR_SIZE 2000
const char ** vgmstream_get_formats();
int vgmstream_get_formats_length();
const char * get_vgmstream_coding_description(coding_t coding_type);
const char * get_vgmstream_layout_description(layout_t layout_type);
const char * get_vgmstream_meta_description(meta_t meta_type);
#endif /* _FORMATS_H_ */

View File

@ -147,10 +147,6 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\formats.h"
>
</File>
<File
RelativePath=".\streamfile.h"
>
@ -662,6 +658,10 @@
RelativePath=".\meta\pc_adp.c"
>
</File>
<File
RelativePath=".\meta\pc_adp_otns.c"
>
</File>
<File
RelativePath=".\meta\pc_al2.c"
>
@ -1122,10 +1122,6 @@
RelativePath=".\meta\sqex_scd.c"
>
</File>
<File
RelativePath=".\meta\ss_stream.c"
>
</File>
<File
RelativePath=".\meta\stm.c"
>

View File

@ -113,7 +113,6 @@
<ClInclude Include="coding\vorbis_custom_data_fsb.h" />
<ClInclude Include="coding\vorbis_custom_data_wwise.h" />
<ClInclude Include="coding\vorbis_custom_decoder.h" />
<ClInclude Include="formats.h" />
<ClInclude Include="streamfile.h" />
<ClInclude Include="streamtypes.h" />
<ClInclude Include="util.h" />
@ -162,6 +161,7 @@
<ClCompile Include="meta\nsw_opus.c" />
<ClCompile Include="meta\nub_vag.c" />
<ClCompile Include="meta\pc_adp.c" />
<ClCompile Include="meta\pc_adp_otns.c" />
<ClCompile Include="meta\pc_ast.c" />
<ClCompile Include="meta\pc_snds.c" />
<ClCompile Include="meta\ps2_2pfs.c" />
@ -388,7 +388,6 @@
<ClCompile Include="meta\sfl.c" />
<ClCompile Include="meta\sli.c" />
<ClCompile Include="meta\spt_spd.c" />
<ClCompile Include="meta\ss_stream.c" />
<ClCompile Include="meta\stm.c" />
<ClCompile Include="meta\str_asr.c" />
<ClCompile Include="meta\str_snds.c" />

View File

@ -47,9 +47,6 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="formats.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="streamfile.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -685,9 +682,6 @@
<ClCompile Include="meta\spt_spd.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ss_stream.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\stm.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
@ -1081,6 +1075,9 @@
<ClCompile Include="meta\pc_adp.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\pc_adp_otns.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\excitebots.c">
<Filter>meta\Source Files</Filter>
</ClCompile>

View File

@ -3,166 +3,166 @@
/* BCSTM - Nintendo 3DS format */
VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
coding_t coding_type;
VGMSTREAM * vgmstream = NULL;
coding_t coding_type;
off_t info_offset = 0, seek_offset = 0, data_offset = 0;
uint16_t temp_id;
int codec_number;
int channel_count, loop_flag;
int i, ima = 0;
off_t start_offset;
int section_count;
off_t info_offset = 0, seek_offset = 0, data_offset = 0;
uint16_t temp_id;
int codec_number;
int channel_count, loop_flag;
int i, ima = 0;
off_t start_offset;
int section_count;
/* check extension, case insensitive */
/* check extension, case insensitive */
if ( !check_extensions(streamFile,"bcstm") )
goto fail;
goto fail;
/* check header */
if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */
goto fail;
/* check header */
if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */
goto fail;
if ((uint16_t)read_16bitLE(4, streamFile) != 0xFEFF)
goto fail;
section_count = read_16bitLE(0x10, streamFile);
for (i = 0; i < section_count; i++) {
temp_id = read_16bitLE(0x14 + i * 0xc, streamFile);
switch(temp_id) {
case 0x4000:
info_offset = read_32bitLE(0x18 + i * 0xc, streamFile);
/* size_t info_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
break;
case 0x4001:
seek_offset = read_32bitLE(0x18 + i * 0xc, streamFile);
/* size_t seek_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
break;
case 0x4002:
data_offset = read_32bitLE(0x18 + i * 0xc, streamFile);
/* size_t data_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
break;
case 0x4003:
/* off_t regn_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */
/* size_t regn_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
break;
case 0x4004:
/* off_t pdat_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */
/* size_t pdat_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
break;
default:
break;
}
}
if ((uint16_t)read_16bitLE(4, streamFile) != 0xFEFF)
goto fail;
section_count = read_16bitLE(0x10, streamFile);
for (i = 0; i < section_count; i++) {
temp_id = read_16bitLE(0x14 + i * 0xc, streamFile);
switch(temp_id) {
case 0x4000:
info_offset = read_32bitLE(0x18 + i * 0xc, streamFile);
/* size_t info_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
break;
case 0x4001:
seek_offset = read_32bitLE(0x18 + i * 0xc, streamFile);
/* size_t seek_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
break;
case 0x4002:
data_offset = read_32bitLE(0x18 + i * 0xc, streamFile);
/* size_t data_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
break;
case 0x4003:
/* off_t regn_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */
/* size_t regn_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
break;
case 0x4004:
/* off_t pdat_offset = read_32bitLE(0x18 + i * 0xc, streamFile); */
/* size_t pdat_size = read_32bitLE(0x1c + i * 0xc, streamFile); */
break;
default:
break;
}
}
if (info_offset == 0) goto fail;
if ((uint32_t)read_32bitBE(info_offset, streamFile) != 0x494E464F) /* "INFO" */
goto fail;
/* check type details */
codec_number = read_8bit(info_offset + 0x20, streamFile);
loop_flag = read_8bit(info_offset + 0x21, streamFile);
channel_count = read_8bit(info_offset + 0x22, streamFile);
switch (codec_number) {
case 0:
coding_type = coding_PCM8;
break;
case 1:
coding_type = coding_PCM16LE;
break;
case 2:
if (seek_offset == 0) goto fail;
if ((uint32_t)read_32bitBE(seek_offset, streamFile) != 0x5345454B) { /* "SEEK" If this header doesn't exist, assuming that the file is IMA */
ima = 1;
coding_type = coding_IMA_int;
}
else
coding_type = coding_NGC_DSP;
break;
default:
goto fail;
}
/* check type details */
codec_number = read_8bit(info_offset + 0x20, streamFile);
loop_flag = read_8bit(info_offset + 0x21, streamFile);
channel_count = read_8bit(info_offset + 0x22, streamFile);
if (channel_count < 1) goto fail;
switch (codec_number) {
case 0:
coding_type = coding_PCM8;
break;
case 1:
coding_type = coding_PCM16LE;
break;
case 2:
if (seek_offset == 0) goto fail;
if ((uint32_t)read_32bitBE(seek_offset, streamFile) != 0x5345454B) { /* "SEEK" If this header doesn't exist, assuming that the file is IMA */
ima = 1;
coding_type = coding_IMA_int;
}
else
coding_type = coding_NGC_DSP;
break;
default:
goto fail;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
if (channel_count < 1) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitLE(info_offset + 0x2c, streamFile);
vgmstream->sample_rate = read_32bitLE(info_offset + 0x24, streamFile);
/* channels and loop flag are set by allocate_vgmstream */
if (ima) //Shift the loop points back slightly to avoid stupid pops in some IMA streams due to DC offsetting
{
vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile);
if (vgmstream->loop_start_sample > 10000)
{
vgmstream->loop_start_sample -= 5000;
vgmstream->loop_end_sample = vgmstream->num_samples - 5000;
}
else
vgmstream->loop_end_sample = vgmstream->num_samples;
}
else
{
vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
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->meta_type = meta_CSTM;
if (ima)
vgmstream->interleave_block_size = 0x200;
else {
vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile);
vgmstream->interleave_smallblock_size = read_32bitLE(info_offset + 0x44, streamFile);
}
if (vgmstream->coding_type == coding_NGC_DSP) {
off_t coef_offset;
off_t tempoffset = info_offset;
int foundcoef = 0;
int i, j;
int coef_spacing = 0x2E;
while (!(foundcoef))
{
if ((uint32_t)read_32bitLE(tempoffset, streamFile) == 0x00004102)
{
coef_offset = read_32bitLE(tempoffset + 4, streamFile) + tempoffset + (channel_count * 8) - 4 - info_offset;
foundcoef++;
break;
}
tempoffset++;
}
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitLE(info_offset + 0x2c, streamFile);
vgmstream->sample_rate = read_32bitLE(info_offset + 0x24, streamFile);
/* channels and loop flag are set by allocate_vgmstream */
if (ima) //Shift the loop points back slightly to avoid stupid pops in some IMA streams due to DC offsetting
{
vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile);
if (vgmstream->loop_start_sample > 10000)
{
vgmstream->loop_start_sample -= 5000;
vgmstream->loop_end_sample = vgmstream->num_samples - 5000;
}
else
vgmstream->loop_end_sample = vgmstream->num_samples;
}
else
{
vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
}
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->meta_type = meta_CSTM;
if (ima)
vgmstream->interleave_block_size = 0x200;
else {
vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile);
vgmstream->interleave_smallblock_size = read_32bitLE(info_offset + 0x44, streamFile);
}
if (vgmstream->coding_type == coding_NGC_DSP) {
off_t coef_offset;
off_t tempoffset = info_offset;
int foundcoef = 0;
int i, j;
int coef_spacing = 0x2E;
while (!(foundcoef))
{
if ((uint32_t)read_32bitLE(tempoffset, streamFile) == 0x00004102)
{
coef_offset = read_32bitLE(tempoffset + 4, streamFile) + tempoffset + (channel_count * 8) - 4 - info_offset;
foundcoef++;
break;
}
tempoffset++;
}
for (j = 0; j<vgmstream->channels; j++) {
for (i = 0; i<16; i++) {
vgmstream->ch[j].adpcm_coef[i] = read_16bitLE(info_offset + coef_offset + j*coef_spacing + i * 2, streamFile);
}
}
}
if (ima) { // No SEEK (ADPC) header, so just start where the SEEK header is supposed to be.
if (seek_offset == 0) goto fail;
start_offset = seek_offset;
} else {
if (data_offset == 0) goto fail;
start_offset = data_offset + 0x20;
}
for (j = 0; j<vgmstream->channels; j++) {
for (i = 0; i<16; i++) {
vgmstream->ch[j].adpcm_coef[i] = read_16bitLE(info_offset + coef_offset + j*coef_spacing + i * 2, streamFile);
}
}
}
if (ima) { // No SEEK (ADPC) header, so just start where the SEEK header is supposed to be.
if (seek_offset == 0) goto fail;
start_offset = seek_offset;
} else {
if (data_offset == 0) goto fail;
start_offset = data_offset + 0x20;
}
/* open the file for reading by each channel */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))

View File

@ -254,7 +254,8 @@ VGMSTREAM * init_vgmstream_fsb_offset(STREAMFILE *streamFile, off_t offset) {
/* sometimes there is garbage at the end or missing bytes due to improper demuxing */
VGM_ASSERT(fsbh.hdrsize + fsbh.shdrsize + fsbh.datasize != streamFile->get_size(streamFile) - offset,
"FSB wrong head/datasize found\n");
"FSB wrong head/datasize found (expected 0x%x vs 0x%lx)\n",
fsbh.hdrsize + fsbh.shdrsize + fsbh.datasize, streamFile->get_size(streamFile) - offset);
/* Loops unless disabled. FMOD default seems full loops (0/num_samples-1) without flags, for repeating tracks
* that should loop and jingles/sfx that shouldn't. We'll try to disable looping is it looks jingly enough. */

View File

@ -3,6 +3,8 @@
#include "../layout/layout.h"
#include "../util.h"
/* known GENH types */
typedef enum {
PSX = 0, /* PSX ADPCM */
@ -28,26 +30,45 @@ typedef enum {
XMA1 = 20, /* raw XMA1 */
XMA2 = 21, /* raw XMA2 */
FFMPEG = 22, /* any headered FFmpeg format */
AC3 = 23, /* AC3/SPDIF */
} genh_type;
typedef struct {
genh_type codec;
int codec_mode;
size_t interleave;
int channels;
int32_t sample_rate;
size_t data_size;
off_t start_offset;
int32_t num_samples;
int32_t loop_start_sample;
int32_t loop_end_sample;
int skip_samples_mode;
int32_t skip_samples;
int loop_flag;
int32_t coef[2];
int32_t coef_splitted[2];
int32_t coef_type;
int32_t coef_interleave_type;
int coef_big_endian;
} genh_header;
static int parse_genh(STREAMFILE * streamFile, genh_header * genh);
/* GENH is an artificial "generic" header for headerless streams */
VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
int channel_count, loop_flag, sample_rate, interleave;
int32_t num_samples = 0, loop_start, loop_end, skip_samples = 0;
int32_t start_offset, header_size;
off_t datasize = 0;
int32_t coef[2];
int32_t coef_splitted[2];
int32_t dsp_interleave_type;
int32_t coef_type;
int skip_samples_mode, atrac3_mode, xma_mode;
genh_header genh = {0};
coding_t coding;
int i, j;
coding_t coding;
genh_type type;
/* check extension, case insensitive */
if (!check_extensions(streamFile,"genh")) goto fail;
@ -55,12 +76,13 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
/* check header magic */
if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail;
channel_count = read_32bitLE(0x4,streamFile);
if (channel_count < 1) goto fail;
/* process the header */
if (!parse_genh(streamFile, &genh))
goto fail;
type = read_32bitLE(0x18,streamFile);
/* type to coding conversion */
switch (type) {
switch (genh.codec) {
case PSX: coding = coding_PSX; break;
case XBOX: coding = coding_XBOX; break;
case NGC_DTK: coding = coding_NGC_DTK; break;
@ -86,68 +108,27 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
case ATRAC3PLUS:
case XMA1:
case XMA2:
case AC3:
case FFMPEG: coding = coding_FFmpeg; break;
#endif
default:
goto fail;
}
start_offset = read_32bitLE(0x1C,streamFile);
header_size = read_32bitLE(0x20,streamFile);
/* HACK to support old genh */
if (header_size == 0) {
start_offset = 0x800;
header_size = 0x800;
}
/* check for audio data start past header end */
if (header_size > start_offset) goto fail;
interleave = read_32bitLE(0x8,streamFile);
sample_rate = read_32bitLE(0xc,streamFile);
loop_start = read_32bitLE(0x10,streamFile);
loop_end = read_32bitLE(0x14,streamFile);
coef[0] = read_32bitLE(0x24,streamFile);
coef[1] = read_32bitLE(0x28,streamFile);
dsp_interleave_type = read_32bitLE(0x2C,streamFile);
/* DSP coefficient variants */
/* bit 0 - split coefs (2 arrays) */
/* bit 1 - little endian coefs */
coef_type = read_32bitLE(0x30,streamFile);
/* when using split coefficients, 2nd array is at: */
coef_splitted[0] = read_32bitLE(0x34,streamFile);
coef_splitted[1] = read_32bitLE(0x38,streamFile);
/* other fields */
num_samples = read_32bitLE(0x40,streamFile);
skip_samples = read_32bitLE(0x44,streamFile); /* for FFmpeg based codecs */
skip_samples_mode = read_8bit(0x48,streamFile); /* 0=autodetect, 1=force manual value @ 0x44 */
atrac3_mode = read_8bit(0x49,streamFile); /* 0=autodetect, 1=force joint stereo, 2=force full stereo */
xma_mode = read_8bit(0x4a,streamFile); /* 0=default (4ch = 2ch + 2ch), 1=single (4ch = 1ch + 1ch + 1ch + 1ch) */
datasize = read_32bitLE(0x50,streamFile);
if (!datasize)
datasize = get_streamfile_size(streamFile)-start_offset;
num_samples = num_samples > 0 ? num_samples : loop_end;
loop_flag = loop_start != -1;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(genh.channels,genh.loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
vgmstream->sample_rate = genh.sample_rate;
vgmstream->num_samples = genh.num_samples;
vgmstream->loop_start_sample = genh.loop_start_sample;
vgmstream->loop_end_sample = genh.loop_end_sample;
/* codec specific */
switch (coding) {
case coding_PCM8_U_int:
vgmstream->layout_type=layout_none;
vgmstream->layout_type = layout_none;
break;
case coding_PCM16LE:
case coding_PCM16BE:
@ -160,14 +141,14 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
case coding_IMA:
case coding_AICA:
case coding_APPLE_IMA4:
vgmstream->interleave_block_size = interleave;
if (channel_count > 1)
vgmstream->interleave_block_size = genh.interleave;
if (vgmstream->channels > 1)
{
if (coding == coding_SDX2) {
coding = coding_SDX2_int;
}
if (vgmstream->interleave_block_size==0xffffffff) {
if (vgmstream->interleave_block_size==0xffffffff) {// || vgmstream->interleave_block_size == 0) {
vgmstream->layout_type = layout_none;
}
else {
@ -179,7 +160,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
}
/* to avoid endless loops */
if (!interleave && (
if (!genh.interleave && (
coding == coding_PSX ||
coding == coding_PSX_badflags ||
coding == coding_IMA_int ||
@ -194,64 +175,61 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
/* setup adpcm */
if (coding == coding_AICA) {
int i;
for (i=0;i<channel_count;i++) {
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].adpcm_step_index = 0x7f;
}
}
break;
case coding_MS_IMA:
if (!interleave) goto fail; /* creates garbage */
if (!genh.interleave) goto fail; /* creates garbage */
vgmstream->interleave_block_size = interleave;
vgmstream->interleave_block_size = genh.interleave;
vgmstream->layout_type = layout_none;
break;
case coding_MSADPCM:
if (channel_count > 2) goto fail;
if (!interleave) goto fail; /* creates garbage */
if (vgmstream->channels > 2) goto fail;
if (!genh.interleave) goto fail; /* creates garbage */
vgmstream->interleave_block_size = interleave;
vgmstream->interleave_block_size = genh.interleave;
vgmstream->layout_type = layout_none;
break;
case coding_XBOX:
vgmstream->layout_type = layout_none;
break;
case coding_NGC_DTK:
if (channel_count != 2) goto fail;
if (vgmstream->channels != 2) goto fail;
vgmstream->layout_type = layout_none;
break;
case coding_NGC_DSP:
if (dsp_interleave_type == 0) {
if (!interleave) goto fail;
if (genh.coef_interleave_type == 0) {
if (!genh.interleave) goto fail;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
} else if (dsp_interleave_type == 1) {
if (!interleave) goto fail;
vgmstream->interleave_block_size = genh.interleave;
} else if (genh.coef_interleave_type == 1) {
if (!genh.interleave) goto fail;
vgmstream->layout_type = layout_interleave_byte;
vgmstream->interleave_block_size = interleave;
} else if (dsp_interleave_type == 2) {
vgmstream->interleave_block_size = genh.interleave;
} else if (genh.coef_interleave_type == 2) {
vgmstream->layout_type = layout_none;
}
}// else {
// goto fail;
//}
/* get coefs */
for (i=0;i<channel_count;i++) {
int16_t (*read_16bit)(off_t , STREAMFILE*);
/* bit 1 - little endian coefs */
if ((coef_type & 2) == 0) {
read_16bit = read_16bitBE;
} else {
read_16bit = read_16bitLE;
}
for (i=0;i<vgmstream->channels;i++) {
int16_t (*read_16bit)(off_t , STREAMFILE*) = genh.coef_big_endian ? read_16bitBE : read_16bitLE;
/* bit 0 - split coefs (2 arrays) */
if ((coef_type & 1) == 0) {
/* normal/split coefs */
if ((genh.coef_type & 1) == 0) { /* bit 0 - split coefs (2 arrays) */
for (j=0;j<16;j++) {
vgmstream->ch[i].adpcm_coef[j] = read_16bit(coef[i]+j*2,streamFile);
vgmstream->ch[i].adpcm_coef[j] = read_16bit(genh.coef[i]+j*2,streamFile);
}
} else {
}
else {
for (j=0;j<8;j++) {
vgmstream->ch[i].adpcm_coef[j*2]=read_16bit(coef[i]+j*2,streamFile);
vgmstream->ch[i].adpcm_coef[j*2+1]=read_16bit(coef_splitted[i]+j*2,streamFile);
vgmstream->ch[i].adpcm_coef[j*2]=read_16bit(genh.coef[i]+j*2,streamFile);
vgmstream->ch[i].adpcm_coef[j*2+1]=read_16bit(genh.coef_splitted[i]+j*2,streamFile);
}
}
}
@ -260,7 +238,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
#ifdef VGM_USE_MPEG
case coding_MPEG_layer3:
vgmstream->layout_type = layout_none;
vgmstream->codec_data = init_mpeg_codec_data(streamFile, start_offset, &coding, vgmstream->channels);
vgmstream->codec_data = init_mpeg_codec_data(streamFile, genh.start_offset, &coding, vgmstream->channels);
if (!vgmstream->codec_data) goto fail;
break;
@ -269,50 +247,53 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
case coding_FFmpeg: {
ffmpeg_codec_data *ffmpeg_data = NULL;
if (type == FFMPEG) {
if (genh.codec == FFMPEG || genh.codec == AC3) {
/* default FFmpeg */
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,datasize);
ffmpeg_data = init_ffmpeg_offset(streamFile, genh.start_offset,genh.data_size);
if ( !ffmpeg_data ) goto fail;
//if (vgmstream->num_samples == 0)
// vgmstream->num_samples = ffmpeg_data->totalSamples; /* sometimes works */
}
else {
/* fake header FFmpeg */
uint8_t buf[200];
int32_t bytes;
if (type == ATRAC3) {
int block_size = interleave;
if (genh.codec == ATRAC3) {
int block_size = genh.interleave;
int joint_stereo;
switch(atrac3_mode) {
case 0: joint_stereo = vgmstream->channels > 1 && interleave/vgmstream->channels==0x60 ? 1 : 0; break; /* autodetect */
switch(genh.codec_mode) {
case 0: joint_stereo = vgmstream->channels > 1 && genh.interleave/vgmstream->channels==0x60 ? 1 : 0; break; /* autodetect */
case 1: joint_stereo = 1; break; /* force joint stereo */
case 2: joint_stereo = 0; break; /* force stereo */
default: goto fail;
}
bytes = ffmpeg_make_riff_atrac3(buf, 200, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, skip_samples);
bytes = ffmpeg_make_riff_atrac3(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, genh.skip_samples);
}
else if (type == ATRAC3PLUS) {
int block_size = interleave;
else if (genh.codec == ATRAC3PLUS) {
int block_size = genh.interleave;
bytes = ffmpeg_make_riff_atrac3plus(buf, 200, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_size, skip_samples);
bytes = ffmpeg_make_riff_atrac3plus(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_size, genh.skip_samples);
}
else if (type == XMA1) {
int xma_stream_mode = xma_mode == 1 ? 1 : 0;
else if (genh.codec == XMA1) {
int xma_stream_mode = genh.codec_mode == 1 ? 1 : 0;
bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
}
else if (type == XMA2) {
int block_size = interleave ? interleave : 2048;
int block_count = datasize / block_size;
else if (genh.codec == XMA2) {
int block_size = genh.interleave ? genh.interleave : 2048;
int block_count = genh.data_size / block_size;
bytes = ffmpeg_make_riff_xma2(buf, 200, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
bytes = ffmpeg_make_riff_xma2(buf, 200, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
}
else {
goto fail;
}
if (bytes <= 0) goto fail;
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,datasize);
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size);
if ( !ffmpeg_data ) goto fail;
}
@ -320,8 +301,8 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none;
/* force encoder delay */
if (skip_samples_mode && skip_samples >= 0) {
ffmpeg_set_skip_samples(ffmpeg_data, skip_samples);
if (genh.skip_samples_mode && genh.skip_samples >= 0) {
ffmpeg_set_skip_samples(ffmpeg_data, genh.skip_samples);
}
break;
@ -335,7 +316,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_GENH;
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) )
if ( !vgmstream_open_stream(vgmstream,streamFile,genh.start_offset) )
goto fail;
return vgmstream;
@ -344,3 +325,60 @@ fail:
close_vgmstream(vgmstream);
return NULL;
}
static int parse_genh(STREAMFILE * streamFile, genh_header * genh) {
size_t header_size;
genh->channels = read_32bitLE(0x4,streamFile);
genh->interleave = read_32bitLE(0x8,streamFile);
genh->sample_rate = read_32bitLE(0xc,streamFile);
genh->loop_start_sample = read_32bitLE(0x10,streamFile);
genh->loop_end_sample = read_32bitLE(0x14,streamFile);
genh->codec = read_32bitLE(0x18,streamFile);
genh->start_offset = read_32bitLE(0x1C,streamFile);
header_size = read_32bitLE(0x20,streamFile);
/* HACK to support old genh */
if (header_size == 0) {
genh->start_offset = 0x800;
header_size = 0x800;
}
/* check for audio data start past header end */
if (header_size > genh->start_offset) goto fail;
genh->coef[0] = read_32bitLE(0x24,streamFile);
genh->coef[1] = read_32bitLE(0x28,streamFile);
genh->coef_interleave_type = read_32bitLE(0x2C,streamFile);
/* DSP coefficient variants */
/* bit 0 - split coefs (2 arrays) */
/* bit 1 - little endian coefs */
genh->coef_type = read_32bitLE(0x30,streamFile);
genh->coef_big_endian = ((genh->coef_type & 2) == 0);
/* when using split coefficients, 2nd array is at: */
genh->coef_splitted[0] = read_32bitLE(0x34,streamFile);
genh->coef_splitted[1] = read_32bitLE(0x38,streamFile);
/* other fields */
genh->num_samples = read_32bitLE(0x40,streamFile);
genh->skip_samples = read_32bitLE(0x44,streamFile); /* for FFmpeg based codecs */
genh->skip_samples_mode = read_8bit(0x48,streamFile); /* 0=autodetect, 1=force manual value @ 0x44 */
if (genh->codec == ATRAC3 || genh->codec == ATRAC3PLUS)
genh->codec_mode = read_8bit(0x49,streamFile); /* 0=autodetect, 1=force joint stereo, 2=force full stereo */
if (genh->codec == XMA1 || genh->codec == XMA2)
genh->codec_mode = read_8bit(0x4a,streamFile); /* 0=default (4ch = 2ch + 2ch), 1=single (4ch = 1ch + 1ch + 1ch + 1ch) */
genh->data_size = read_32bitLE(0x50,streamFile);
if (genh->data_size == 0)
genh->data_size = get_streamfile_size(streamFile) - genh->start_offset;
genh->num_samples = genh->num_samples > 0 ? genh->num_samples : genh->loop_end_sample;
genh->loop_flag = genh->loop_start_sample != -1;
return 1;
fail:
return 0;
}

View File

@ -276,8 +276,6 @@ VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ps2_xa2(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ss_stream(STREAMFILE * streamFile);
//VGMSTREAM * init_vgmstream_idsp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_idsp2(STREAMFILE * streamFile);
@ -581,6 +579,7 @@ VGMSTREAM * init_vgmstream_hyperscan_kvag(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ios_psnd(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_eb_sfx(STREAMFILE* streamFile);

View File

@ -19,11 +19,11 @@ VGMSTREAM * init_vgmstream_nds_strm(STREAMFILE *streamFile) {
if (strcasecmp("strm",filename_extension(filename))) goto fail;
/* check header */
if ((uint32_t)read_32bitBE(0x00,streamFile)!=0x5354524D) /* STRM */
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 */
goto fail;
if ((uint32_t)read_32bitBE(0x04,streamFile)!=0xFFFE0001 && /* Old Header Check */
((uint32_t)read_32bitBE(0x04,streamFile)!=0xFEFF0001)) /* Some newer games have a new flag */
goto fail;

View File

@ -2,17 +2,17 @@
#include "../util.h"
/* .dsp found in:
Hikaru No Go 3 (NGC)
Yu-Gi-Oh! The Falsebound Kingdom (NGC)
Hikaru No Go 3 (NGC)
Yu-Gi-Oh! The Falsebound Kingdom (NGC)
2010-01-31 - added loop stuff and some header checks...
2010-01-31 - added loop stuff and some header checks...
*/
VGMSTREAM * init_vgmstream_dsp_ygo(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag;
int channel_count;
int loop_flag;
int channel_count;
off_t start_offset;
int i;
@ -24,29 +24,29 @@ VGMSTREAM * init_vgmstream_dsp_ygo(STREAMFILE *streamFile) {
if ((read_32bitBE(0x0,streamFile)+0xE0) != (get_streamfile_size(streamFile)))
goto fail;
loop_flag = (uint16_t)(read_16bitBE(0x2C,streamFile) != 0x0);
loop_flag = (uint16_t)(read_16bitBE(0x2C,streamFile) != 0x0);
channel_count = 1;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0xE0;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x28,streamFile);
/* fill in the vital statistics */
start_offset = 0xE0;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x28,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x20,streamFile);
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_DSP_YGO;
if (loop_flag) {
vgmstream->loop_start_sample = (read_32bitBE(0x30,streamFile)*14/16);
vgmstream->loop_end_sample = (read_32bitBE(0x34,streamFile)*14/16);
}
vgmstream->meta_type = meta_DSP_YGO;
if (loop_flag) {
vgmstream->loop_start_sample = (read_32bitBE(0x30,streamFile)*14/16);
vgmstream->loop_end_sample = (read_32bitBE(0x34,streamFile)*14/16);
}
// read coef stuff
{
for (i=0;i<16;i++) {
// read coef stuff
{
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x3C+i*2,streamFile);
}
}

View File

@ -8,63 +8,63 @@
VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamFileDSP = NULL;
char filename[PATH_LIMIT];
char filenameDSP[PATH_LIMIT];
int i;
int channel_count;
int loop_flag;
char filenameDSP[PATH_LIMIT];
int i;
int channel_count;
int loop_flag;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("sck",filename_extension(filename))) goto fail;
strcpy(filenameDSP,filename);
strcpy(filenameDSP+strlen(filenameDSP)-3,"dsp");
strcpy(filenameDSP,filename);
strcpy(filenameDSP+strlen(filenameDSP)-3,"dsp");
streamFileDSP = streamFile->open(streamFile,filenameDSP,STREAMFILE_DEFAULT_BUFFER_SIZE);
streamFileDSP = streamFile->open(streamFile,filenameDSP,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (read_32bitBE(0x5C,streamFile) != 0x60A94000)
goto fail;
if (!streamFile) goto fail;
channel_count = 2;
loop_flag = 0;
if (!streamFile) goto fail;
channel_count = 2;
loop_flag = 0;
/* 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_32bitBE(0x18,streamFile);
vgmstream->num_samples=read_32bitBE(0x14,streamFile)/8/channel_count*14;
vgmstream->coding_type = coding_NGC_DSP;
if(loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitBE(0x10,streamFile)/8/channel_count*14;
}
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x18,streamFile);
vgmstream->num_samples=read_32bitBE(0x14,streamFile)/8/channel_count*14;
vgmstream->coding_type = coding_NGC_DSP;
if (channel_count == 1) {
vgmstream->layout_type = layout_none;
} else if (channel_count == 2) {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size=read_32bitBE(0xC,streamFile);
}
if(loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitBE(0x10,streamFile)/8/channel_count*14;
}
if (channel_count == 1) {
vgmstream->layout_type = layout_none;
} else if (channel_count == 2) {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size=read_32bitBE(0xC,streamFile);
}
vgmstream->meta_type = meta_NGC_SCK_DSP;
/* open the file for reading */
{
for (i=0;i<channel_count;i++) {
/* Not sure, i'll put a fake value here for now */
/* Not sure, i'll put a fake value here for now */
vgmstream->ch[i].streamfile = streamFile->open(streamFileDSP,filenameDSP,0x8000);
vgmstream->ch[i].offset = 0;
@ -74,7 +74,7 @@ VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) {
if (vgmstream->coding_type == coding_NGC_DSP) {
if (vgmstream->coding_type == coding_NGC_DSP) {
int i;
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x2C+i*2,streamFile);
@ -87,7 +87,7 @@ VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) {
}
close_streamfile(streamFileDSP); streamFileDSP=NULL;
close_streamfile(streamFileDSP); streamFileDSP=NULL;
return vgmstream;
/* clean up anything we may have opened */

View File

@ -1,5 +1,4 @@
#include "meta.h"
#include "../util.h"
/* ADP - from Balls of Steel */
VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE *streamFile) {
@ -48,45 +47,3 @@ fail:
close_vgmstream(vgmstream);
return NULL;
}
/* ADP - from Omikron: The Nomad Soul (PC/DC) */
VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset, datasize;
int loop_flag = 0, channel_count, stereo_flag;
if (!check_extensions(streamFile,"adp")) goto fail;
/* no ID, only a basic 0x10 header with filesize and nulls; do some extra checks */
datasize = read_32bitLE(0x00,streamFile) & 0x00FFFFFF; /*24 bit*/
if (datasize + 0x10 != streamFile->get_size(streamFile)
|| read_32bitLE(0x04,streamFile) != 0
|| read_32bitLE(0x08,streamFile) != 0
|| read_32bitLE(0x0c,streamFile) != 0)
goto fail;
stereo_flag = read_8bit(0x03, streamFile);
if (stereo_flag > 1 || stereo_flag < 0) goto fail;
channel_count = stereo_flag ? 2 : 1;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
start_offset = 0x10;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 22050;
vgmstream->num_samples = channel_count== 1 ? datasize*2 : datasize;
vgmstream->coding_type = coding_OTNS_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_OTNS_ADP;
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

43
src/meta/pc_adp_otns.c Normal file
View File

@ -0,0 +1,43 @@
#include "meta.h"
/* ADP - from Omikron: The Nomad Soul (PC/DC) */
VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset, datasize;
int loop_flag = 0, channel_count, stereo_flag;
if (!check_extensions(streamFile,"adp")) goto fail;
/* no ID, only a basic 0x10 header with filesize and nulls; do some extra checks */
datasize = read_32bitLE(0x00,streamFile) & 0x00FFFFFF; /*24 bit*/
if (datasize + 0x10 != streamFile->get_size(streamFile)
|| read_32bitLE(0x04,streamFile) != 0
|| read_32bitLE(0x08,streamFile) != 0
|| read_32bitLE(0x0c,streamFile) != 0)
goto fail;
stereo_flag = read_8bit(0x03, streamFile);
if (stereo_flag > 1 || stereo_flag < 0) goto fail;
channel_count = stereo_flag ? 2 : 1;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
start_offset = 0x10;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 22050;
vgmstream->num_samples = channel_count== 1 ? datasize*2 : datasize;
vgmstream->coding_type = coding_OTNS_IMA;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_OTNS_ADP;
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -4,41 +4,41 @@
/* PCM (from Lunar: Eternal Blue (Sega CD) */
VGMSTREAM * init_vgmstream_pcm_scd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("pcm",filename_extension(filename))) goto fail;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("pcm",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x00020000)
goto fail;
goto fail;
loop_flag = (read_32bitLE(0x02,streamFile)!=0);
channel_count = 1;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
loop_flag = (read_32bitLE(0x02,streamFile)!=0);
channel_count = 1;
/* fill in the vital statistics */
start_offset = 0x200;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 32000;
vgmstream->coding_type = coding_PCM8_SB_int;
vgmstream->num_samples = read_32bitBE(0x06,streamFile)*2;
if(loop_flag) {
vgmstream->loop_start_sample = read_32bitBE(0x02,streamFile)*0x400*2;
vgmstream->loop_end_sample = read_32bitBE(0x06,streamFile)*2;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x1;
vgmstream->meta_type = meta_PCM_SCD;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x200;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 32000;
vgmstream->coding_type = coding_PCM8_SB_int;
vgmstream->num_samples = read_32bitBE(0x06,streamFile)*2;
if(loop_flag) {
vgmstream->loop_start_sample = read_32bitBE(0x02,streamFile)*0x400*2;
vgmstream->loop_end_sample = read_32bitBE(0x06,streamFile)*2;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x1;
vgmstream->meta_type = meta_PCM_SCD;
/* open the file for reading */
{
@ -54,7 +54,7 @@ VGMSTREAM * init_vgmstream_pcm_scd(STREAMFILE *streamFile) {
}
}
return vgmstream;
return vgmstream;
/* clean up anything we may have opened */
fail:
@ -64,41 +64,41 @@ fail:
/* PCM - Custom header from Konami, which contains only loop infos...
found in: Ephemeral Fantasia [Reiselied]
Yu-Gi-Oh! The Duelists of the Roses [Yu-Gi-Oh! Shin Duel Monsters II]
found in: Ephemeral Fantasia [Reiselied]
Yu-Gi-Oh! The Duelists of the Roses [Yu-Gi-Oh! Shin Duel Monsters II]
*/
VGMSTREAM * init_vgmstream_pcm_ps2(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("pcm",filename_extension(filename))) goto fail;
// if ((read_32bitLE(0x00,streamFile)+0x800) != (get_streamfile_size(streamFile)))
// goto fail;
if ((read_32bitLE(0x00,streamFile)) != (read_32bitLE(0x04,streamFile)*4))
goto fail;
// if ((read_32bitLE(0x00,streamFile)+0x800) != (get_streamfile_size(streamFile)))
// goto fail;
if ((read_32bitLE(0x00,streamFile)) != (read_32bitLE(0x04,streamFile)*4))
goto fail;
loop_flag = (read_32bitLE(0x08,streamFile) != 0x0);
loop_flag = (read_32bitLE(0x08,streamFile) != 0x0);
channel_count = 2;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 24000;
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = read_32bitLE(0x0,streamFile)/2/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile);
vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile);
vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile);
vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile);
}
vgmstream->layout_type = layout_interleave;

View File

@ -9,17 +9,17 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
int loop_flag=0;
int channel_count;
off_t start_offset;
off_t check_offset;
int32_t streamSize;
off_t start_offset;
off_t check_offset;
int32_t streamSize;
uint8_t testBuffer[0x10];
uint8_t isPCM = 0;
uint8_t testBuffer[0x10];
uint8_t isPCM = 0;
off_t readOffset = 0;
off_t loopEnd = 0;
off_t readOffset = 0;
off_t loopEnd = 0;
int i;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -35,27 +35,27 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
goto fail;
/* check if file is not corrupt */
/* seems the Gran Turismo 4 ADS files are considered corrupt,*/
/* so I changed it to adapt the stream size if that's the case */
/* instead of failing playing them at all*/
streamSize = read_32bitLE(0x24,streamFile);
/* seems the Gran Turismo 4 ADS files are considered corrupt,*/
/* so I changed it to adapt the stream size if that's the case */
/* instead of failing playing them at all*/
streamSize = read_32bitLE(0x24,streamFile);
if (get_streamfile_size(streamFile) < (size_t)(streamSize + 0x28))
{
streamSize = get_streamfile_size(streamFile) - 0x28;
}
if (get_streamfile_size(streamFile) < (size_t)(streamSize + 0x28))
{
streamSize = get_streamfile_size(streamFile) - 0x28;
}
/* check loop */
if ((read_32bitLE(0x1C,streamFile) == 0xFFFFFFFF) ||
((read_32bitLE(0x18,streamFile) == 0) && (read_32bitLE(0x1C,streamFile) == 0)))
{
loop_flag = 0;
}
else
{
loop_flag = 1;
}
if ((read_32bitLE(0x1C,streamFile) == 0xFFFFFFFF) ||
((read_32bitLE(0x18,streamFile) == 0) && (read_32bitLE(0x1C,streamFile) == 0)))
{
loop_flag = 0;
}
else
{
loop_flag = 1;
}
channel_count=read_32bitLE(0x10,streamFile);
/* build the VGMSTREAM */
@ -70,9 +70,9 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = ((streamSize-0x40)/16*28)/vgmstream->channels;
/* SS2 container with RAW Interleaved PCM */
/* SS2 container with RAW Interleaved PCM */
if (read_32bitLE(0x08,streamFile)!=0x10)
{
{
vgmstream->coding_type=coding_PCM16LE;
vgmstream->num_samples = streamSize/2/vgmstream->channels;
@ -84,100 +84,100 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
/* Get loop point values */
if(vgmstream->loop_flag) {
if((read_32bitLE(0x1C,streamFile)*0x10*vgmstream->channels+0x800)==get_streamfile_size(streamFile))
{
// Search for Loop Value
readOffset=(off_t)get_streamfile_size(streamFile)-(4*vgmstream->interleave_block_size);
if((read_32bitLE(0x1C,streamFile)*0x10*vgmstream->channels+0x800)==get_streamfile_size(streamFile))
{
// Search for Loop Value
readOffset=(off_t)get_streamfile_size(streamFile)-(4*vgmstream->interleave_block_size);
do {
readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile);
// Loop End ...
if(testBuffer[0x01]==0x01) {
if(loopEnd==0) loopEnd = readOffset-0x10;
break;
}
do {
readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile);
} while (streamFile->get_offset(streamFile)<(int32_t)get_streamfile_size(streamFile));
// Loop End ...
if(testBuffer[0x01]==0x01) {
if(loopEnd==0) loopEnd = readOffset-0x10;
break;
}
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (loopEnd/(vgmstream->interleave_block_size)*vgmstream->interleave_block_size)/16*28;
vgmstream->loop_end_sample += (loopEnd%vgmstream->interleave_block_size)/16*28;
vgmstream->loop_end_sample /=vgmstream->channels;
} while (streamFile->get_offset(streamFile)<(int32_t)get_streamfile_size(streamFile));
} else {
if(read_32bitLE(0x1C,streamFile)<=vgmstream->num_samples) {
vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile);
vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile);
} else {
vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*0x10)/16*28/vgmstream->channels;;
vgmstream->loop_end_sample = (read_32bitLE(0x1C,streamFile)*0x10)/16*28/vgmstream->channels;
}
}
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (loopEnd/(vgmstream->interleave_block_size)*vgmstream->interleave_block_size)/16*28;
vgmstream->loop_end_sample += (loopEnd%vgmstream->interleave_block_size)/16*28;
vgmstream->loop_end_sample /=vgmstream->channels;
} else {
if(read_32bitLE(0x1C,streamFile)<=vgmstream->num_samples) {
vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile);
vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile);
} else {
vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*0x10)/16*28/vgmstream->channels;;
vgmstream->loop_end_sample = (read_32bitLE(0x1C,streamFile)*0x10)/16*28/vgmstream->channels;
}
}
}
/* don't know why, but it does happen, in ps2 too :( */
if (vgmstream->loop_end_sample > vgmstream->num_samples)
vgmstream->loop_end_sample = vgmstream->num_samples;
{
start_offset=0x28;
}
{
start_offset=0x28;
}
if ((streamSize * 2) == (get_streamfile_size(streamFile) - 0x18))
{
// True Fortune PS2
streamSize = (read_32bitLE(0x24,streamFile) * 2) - 0x10;
vgmstream->num_samples = streamSize / 16 * 28 / vgmstream->channels;
}
else if(get_streamfile_size(streamFile) - read_32bitLE(0x24,streamFile) >= 0x800)
{
// Hack for files with start_offset = 0x800
start_offset=0x800;
}
if((vgmstream->coding_type == coding_PSX) && (start_offset==0x28))
{
start_offset=0x800;
for(i=0;i<0x1f6;i+=4)
{
if(read_32bitLE(0x28+(i*4),streamFile)!=0)
{
start_offset=0x28;
break;
}
}
}
if ((streamSize * 2) == (get_streamfile_size(streamFile) - 0x18))
{
// True Fortune PS2
streamSize = (read_32bitLE(0x24,streamFile) * 2) - 0x10;
vgmstream->num_samples = streamSize / 16 * 28 / vgmstream->channels;
}
else if(get_streamfile_size(streamFile) - read_32bitLE(0x24,streamFile) >= 0x800)
{
// Hack for files with start_offset = 0x800
start_offset=0x800;
}
// check if we got a real pcm (ex: Clock Tower 3)
if(vgmstream->coding_type==coding_PCM16LE)
{
check_offset=start_offset;
do
{
if(read_8bit(check_offset+1,streamFile)>7)
{
isPCM=1;
break;
}
else
{
check_offset+=0x10;
}
} while (check_offset<get_streamfile_size(streamFile));
if((vgmstream->coding_type == coding_PSX) && (start_offset==0x28))
{
start_offset=0x800;
if(!isPCM)
{
vgmstream->num_samples=(get_streamfile_size(streamFile)-start_offset)/16*28/vgmstream->channels;
vgmstream->coding_type=coding_PSX;
}
}
for(i=0;i<0x1f6;i+=4)
{
if(read_32bitLE(0x28+(i*4),streamFile)!=0)
{
start_offset=0x28;
break;
}
}
}
/* expect pcm format allways start @ 0x800, don't know if it's true :P */
/*if(vgmstream->coding_type == coding_PCM16LE)
start_offset=0x800;*/
// check if we got a real pcm (ex: Clock Tower 3)
if(vgmstream->coding_type==coding_PCM16LE)
{
check_offset=start_offset;
do
{
if(read_8bit(check_offset+1,streamFile)>7)
{
isPCM=1;
break;
}
else
{
check_offset+=0x10;
}
} while (check_offset<get_streamfile_size(streamFile));
if(!isPCM)
{
vgmstream->num_samples=(get_streamfile_size(streamFile)-start_offset)/16*28/vgmstream->channels;
vgmstream->coding_type=coding_PSX;
}
}
/* expect pcm format allways start @ 0x800, don't know if it's true :P */
/*if(vgmstream->coding_type == coding_PCM16LE)
start_offset=0x800;*/
/* open the file for reading by each channel */
{

View File

@ -8,8 +8,8 @@ VGMSTREAM * init_vgmstream_filp(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
int i;
int channel_count;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -18,23 +18,23 @@ VGMSTREAM * init_vgmstream_filp(STREAMFILE *streamFile) {
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x46494C70) /* "FILp" */
goto fail;
if (read_32bitBE(0x100,streamFile) != 0x56414770) /* "VAGp" */
if (read_32bitBE(0x100,streamFile) != 0x56414770) /* "VAGp" */
goto fail;
if (read_32bitBE(0x130,streamFile) != 0x56414770) /* "VAGp" */
if (read_32bitBE(0x130,streamFile) != 0x56414770) /* "VAGp" */
goto fail;
if (get_streamfile_size(streamFile) != read_32bitLE(0xC,streamFile))
goto fail;
if (get_streamfile_size(streamFile) != read_32bitLE(0xC,streamFile))
goto fail;
loop_flag = (read_32bitLE(0x34,streamFile) == 0);
channel_count = read_32bitLE(0x4,streamFile);
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
/* fill in the vital statistics */
start_offset = 0x0;
vgmstream->channels = channel_count;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x110,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_filp_blocked;
@ -47,9 +47,9 @@ VGMSTREAM * init_vgmstream_filp(STREAMFILE *streamFile) {
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
}
}
}
}
filp_block_update(start_offset,vgmstream);
vgmstream->num_samples = read_32bitLE(0x10C,streamFile)/16*28;
if (loop_flag) {
@ -57,7 +57,7 @@ VGMSTREAM * init_vgmstream_filp(STREAMFILE *streamFile) {
vgmstream->loop_end_sample = vgmstream->num_samples;
}
return vgmstream;
/* clean up anything we may have opened */

View File

@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_ps2_gcm(STREAMFILE *streamFile) {
off_t start_offset;
int loop_flag;
int channel_count;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -17,19 +17,19 @@ VGMSTREAM * init_vgmstream_ps2_gcm(STREAMFILE *streamFile) {
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x4D434700) /* "MCG" */
goto fail;
if (read_32bitBE(0x20,streamFile) != 0x56414770) /* "VAGp" */
if (read_32bitBE(0x20,streamFile) != 0x56414770) /* "VAGp" */
goto fail;
loop_flag = 0;
channel_count= 2;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
/* fill in the vital statistics */
start_offset = 0x80;
vgmstream->channels = channel_count;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x30,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitLE(0x10,streamFile)*28/32;

View File

@ -8,14 +8,14 @@ VGMSTREAM * init_vgmstream_ps2_hsf(STREAMFILE *streamFile)
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
size_t fileLength;
size_t frequencyFlag;
int channel_count;
size_t fileLength;
size_t frequencyFlag;
#if 0
off_t readOffset = 0;
uint8_t testBuffer[0x10];
off_t loopEndOffset;
off_t readOffset = 0;
uint8_t testBuffer[0x10];
off_t loopEndOffset;
#endif
/* check extension, case insensitive */
@ -26,56 +26,56 @@ VGMSTREAM * init_vgmstream_ps2_hsf(STREAMFILE *streamFile)
if (read_32bitBE(0x00,streamFile) != 0x48534600) // "HSF"
goto fail;
loop_flag = 0;
loop_flag = 0;
channel_count = 2;
fileLength = get_streamfile_size(streamFile);
frequencyFlag = read_32bitLE(0x08, streamFile);
frequencyFlag = read_32bitLE(0x08, streamFile);
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x10;
vgmstream->channels = channel_count;
/* fill in the vital statistics */
start_offset = 0x10;
vgmstream->channels = channel_count;
if (frequencyFlag == 0x0EB3)
{
vgmstream->sample_rate = 44100;
}
else if (frequencyFlag == 0x1000)
{
vgmstream->sample_rate = 48000;
}
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = ((fileLength - 0x10) / 16 * 28) / vgmstream->channels;
if (frequencyFlag == 0x0EB3)
{
vgmstream->sample_rate = 44100;
}
else if (frequencyFlag == 0x1000)
{
vgmstream->sample_rate = 48000;
}
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = ((fileLength - 0x10) / 16 * 28) / vgmstream->channels;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x0C, streamFile);
vgmstream->meta_type = meta_PS2_HSF;
if (vgmstream->loop_flag)
{
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
if (vgmstream->loop_flag)
{
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
#if 0
readOffset = fileLength - 0x10;
readOffset = fileLength - 0x10;
do
{
readOffset -=(off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile);
do
{
readOffset -=(off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile);
if (testBuffer[1] == 0x07)
{
loopEndOffset = readOffset + 0x10;
vgmstream->loop_end_sample = ((loopEndOffset - 0x10) / 16 * 28) / vgmstream->channels;
break;
}
if (testBuffer[1] == 0x07)
{
loopEndOffset = readOffset + 0x10;
vgmstream->loop_end_sample = ((loopEndOffset - 0x10) / 16 * 28) / vgmstream->channels;
break;
}
} while (readOffset > 0);
} while (readOffset > 0);
#endif
}
}
/* open the file for reading */
{

View File

@ -7,7 +7,7 @@ VGMSTREAM * init_vgmstream_ps2_ild(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag=0;
int channel_count;
int channel_count;
off_t start_offset;
int i;
@ -19,33 +19,33 @@ VGMSTREAM * init_vgmstream_ps2_ild(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x494C4400)
goto fail;
/* check loop */
loop_flag = (read_32bitLE(0x2C,streamFile)!=0);
/* check loop */
loop_flag = (read_32bitLE(0x2C,streamFile)!=0);
channel_count=read_32bitLE(0x04,streamFile);
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = read_32bitLE(0x04,streamFile);
/* fill in the vital statistics */
vgmstream->channels = read_32bitLE(0x04,streamFile);
vgmstream->sample_rate = read_32bitLE(0x28,streamFile);
/* Check for Compression Scheme */
vgmstream->coding_type = coding_PSX;
/* Check for Compression Scheme */
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitLE(0x0C,streamFile)/16*28/vgmstream->channels;
/* Get loop point values */
if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x2C,streamFile)/16*28;
vgmstream->loop_end_sample = read_32bitLE(0x30,streamFile)/16*28;
}
/* Get loop point values */
if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x2C,streamFile)/16*28;
vgmstream->loop_end_sample = read_32bitLE(0x30,streamFile)/16*28;
}
vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile)/2;
vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile)/2;
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_PS2_ILD;
start_offset = (off_t)read_32bitLE(0x08,streamFile);
start_offset = (off_t)read_32bitLE(0x08,streamFile);
/* open the file for reading by each channel */
{

View File

@ -7,7 +7,7 @@ VGMSTREAM * init_vgmstream_ps2_mcg(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -16,31 +16,31 @@ VGMSTREAM * init_vgmstream_ps2_mcg(STREAMFILE *streamFile) {
/* check header */
if (!((read_32bitBE(0x00,streamFile) == 0x4D434700) &&
(read_32bitBE(0x20,streamFile) == 0x56414770) &&
(read_32bitBE(0x50,streamFile) == 0x56414770)))
(read_32bitBE(0x50,streamFile) == 0x56414770)))
goto fail;
loop_flag = (read_32bitLE(0x34,streamFile)!=0);
loop_flag = (read_32bitLE(0x34,streamFile)!=0);
channel_count = 2;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x80;
vgmstream->channels = channel_count;
/* fill in the vital statistics */
start_offset = 0x80;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x30,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitBE(0x2C,streamFile)/16*14*channel_count;
vgmstream->num_samples = read_32bitBE(0x2C,streamFile)/16*14*channel_count;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile);
vgmstream->meta_type = meta_PS2_MCG;
if (vgmstream->loop_flag)
{
vgmstream->loop_start_sample = read_32bitLE(0x34,streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
}
if (vgmstream->loop_flag)
{
vgmstream->loop_start_sample = read_32bitLE(0x34,streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
}
/* open the file for reading */
{

View File

@ -6,9 +6,9 @@ VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int mib_blocks;
int mib_blocks;
int loop_flag = 0;
int channel_count;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -17,18 +17,18 @@ VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE *streamFile) {
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x40000000)
goto fail;
mib_blocks = read_32bitLE(0x14,streamFile);
mib_blocks = read_32bitLE(0x14,streamFile);
loop_flag = 0;
channel_count = read_32bitLE(0x08,streamFile);
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
/* fill in the vital statistics */
start_offset = 0x40;
vgmstream->channels = channel_count;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x0C,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = ((read_32bitLE(0x10,streamFile))*mib_blocks)*28/16;

View File

@ -14,20 +14,20 @@ VGMSTREAM * init_vgmstream_ps2_npsf(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x4E505346) /* "NPSF" */
goto fail;
loop_flag = (read_32bitLE(0x14,streamFile) != 0xFFFFFFFF);
loop_flag = (read_32bitLE(0x14,streamFile) != 0xFFFFFFFF);
channel_count = read_32bitLE(0x0C,streamFile);
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->channels = read_32bitLE(0x0C,streamFile);
vgmstream->channels = read_32bitLE(0x0C,streamFile);
vgmstream->sample_rate = read_32bitLE(0x18,streamFile);
vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x08,streamFile), 1); /* single channel data */
if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile);
vgmstream->loop_end_sample = ps_bytes_to_samples(read_32bitLE(0x08,streamFile), 1);
}
if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile);
vgmstream->loop_end_sample = ps_bytes_to_samples(read_32bitLE(0x08,streamFile), 1);
}
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;

View File

@ -186,30 +186,30 @@ VGMSTREAM * init_vgmstream_ps2_rxw(STREAMFILE *streamFile) {
/* check RXWS/FORM Header */
if (!((read_32bitBE(0x00,streamFile) == 0x52585753) &&
(read_32bitBE(0x10,streamFile) == 0x464F524D)))
(read_32bitBE(0x10,streamFile) == 0x464F524D)))
goto fail;
loop_flag = (read_32bitLE(0x3C,streamFile)!=0xFFFFFFFF);
channel_count=2; /* Always stereo files */
loop_flag = (read_32bitLE(0x3C,streamFile)!=0xFFFFFFFF);
channel_count=2; /* Always stereo files */
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x2E,streamFile);
vgmstream->num_samples = (read_32bitLE(0x38,streamFile)*28/16)/2;
/* Get loop point values */
if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x3C,streamFile)/16*14;
vgmstream->loop_end_sample = read_32bitLE(0x38,streamFile)/16*14;
}
/* Get loop point values */
if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x3C,streamFile)/16*14;
vgmstream->loop_end_sample = read_32bitLE(0x38,streamFile)/16*14;
}
vgmstream->interleave_block_size = read_32bitLE(0x1c,streamFile)+0x10;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_PS2_RXWS;
start_offset = 0x40;
start_offset = 0x40;
/* open the file for reading */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))

View File

@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -18,28 +18,28 @@ VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x544B3553)
goto fail;
loop_flag = (read_32bitLE(0x0C,streamFile)!=0);
loop_flag = (read_32bitLE(0x0C,streamFile)!=0);
channel_count = 2;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 48000;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 48000;
vgmstream->coding_type = coding_PSX_badflags;
vgmstream->num_samples = ((get_streamfile_size(streamFile)-0x800))/16*28/2;
vgmstream->num_samples = ((get_streamfile_size(streamFile)-0x800))/16*28/2;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10;
vgmstream->meta_type = meta_PS2_TK5;
if (vgmstream->loop_flag)
{
vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28;
vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28);
}
if (vgmstream->loop_flag)
{
vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28;
vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28);
}
/* open the file for reading */
{
@ -71,7 +71,7 @@ VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -81,28 +81,28 @@ VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x544B3553)
goto fail;
loop_flag = (read_32bitLE(0x0C,streamFile)!=0);
loop_flag = (read_32bitLE(0x0C,streamFile)!=0);
channel_count = 2;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 44100;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 44100;
vgmstream->coding_type = coding_PSX_badflags;
vgmstream->num_samples = read_32bitLE(0x08,streamFile)/16*28;
vgmstream->num_samples = read_32bitLE(0x08,streamFile)/16*28;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10;
vgmstream->meta_type = meta_PS2_TK1;
if (vgmstream->loop_flag)
{
vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28;
vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28);
}
if (vgmstream->loop_flag)
{
vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28;
vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28);
}
/* open the file for reading */
{

View File

@ -79,13 +79,16 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) {
/* channels are usually at 0x1e, but not in Ukiyo no Roushi which has some kind
* of loop-like values instead (who designs this crap?) */
if (read_32bitBE(0x18,streamFile) != 0 || read_32bitBE(0x1c,streamFile) > 0x20) {
channel_count = 1;
} else {
if (read_32bitBE(0x18,streamFile) == 0
&& (read_32bitBE(0x1c,streamFile) & 0xFFFF00FF) == 0
&& read_8bit(0x1e,streamFile) < 16) {
channel_count = read_8bit(0x1e,streamFile);
if (channel_count == 0)
channel_count = 1; /* ex. early Vita vag (Lumines) */
}
else {
channel_count = 1;
}
}
else {
loop_flag = vag_find_loop_offsets(streamFile, 0x30, &loopStart, &loopEnd);

View File

@ -9,15 +9,15 @@ VGMSTREAM * init_vgmstream_ps2_vgs(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
size_t fileLength;
off_t readOffset = 0;
off_t start_offset;
off_t loop_start_offset = 0;
off_t loop_end_offset = 0;
size_t fileLength;
off_t readOffset = 0;
off_t start_offset;
off_t loop_start_offset = 0;
off_t loop_end_offset = 0;
uint8_t testBuffer[0x10];
int loop_flag = 0;
int channel_count;
uint8_t testBuffer[0x10];
int loop_flag = 0;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -27,71 +27,71 @@ VGMSTREAM * init_vgmstream_ps2_vgs(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x56475300)
goto fail;
// get file length
fileLength = get_streamfile_size(streamFile);
// get file length
fileLength = get_streamfile_size(streamFile);
// Find loop start
do {
readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile);
// Loop Start ...
if(testBuffer[0x01] == 0x06)
{
loop_start_offset = readOffset - 0x10;
break;
}
// Find loop start
do {
readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile);
} while (streamFile->get_offset(streamFile)<((int32_t)fileLength));
// Loop Start ...
if(testBuffer[0x01] == 0x06)
{
loop_start_offset = readOffset - 0x10;
break;
}
// start at last line of file and move up
readOffset = (int32_t)fileLength - 0x10;
// Find loop end
do {
readOffset -= (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile);
// Loop End ...
if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77))
{
loop_end_offset = readOffset + 0x20;
break;
}
} while (readOffset > 0);
} while (streamFile->get_offset(streamFile)<((int32_t)fileLength));
// setup loops
if (loop_start_offset > 0)
{
loop_flag = 1;
// if we have a start loop, use EOF if end loop is not found
if (loop_end_offset == 0)
{
loop_end_offset = (int32_t)fileLength - 0x10;
}
}
else
{
loop_flag = 0;
}
// start at last line of file and move up
readOffset = (int32_t)fileLength - 0x10;
// Find loop end
do {
readOffset -= (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile);
// Loop End ...
if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77))
{
loop_end_offset = readOffset + 0x20;
break;
}
} while (readOffset > 0);
// setup loops
if (loop_start_offset > 0)
{
loop_flag = 1;
// if we have a start loop, use EOF if end loop is not found
if (loop_end_offset == 0)
{
loop_end_offset = (int32_t)fileLength - 0x10;
}
}
else
{
loop_flag = 0;
}
channel_count = 2;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x30;
vgmstream->channels = channel_count;
/* fill in the vital statistics */
start_offset = 0x30;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x10,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = ((get_streamfile_size(streamFile)-0x30)/16/channel_count*28);
vgmstream->num_samples = ((get_streamfile_size(streamFile)-0x30)/16/channel_count*28);
if (loop_flag)
{
vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28;
vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28;
}
if (loop_flag)
{
vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28;
vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x04,streamFile)*0x1000;

View File

@ -7,9 +7,9 @@ VGMSTREAM * init_vgmstream_ps2_vms(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
int header_size;
int loop_flag = 0;
int channel_count;
int header_size;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -19,27 +19,27 @@ VGMSTREAM * init_vgmstream_ps2_vms(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x564D5320)
goto fail;
loop_flag = 1;
channel_count = read_8bit(0x08,streamFile);
header_size = read_32bitLE(0x1C, streamFile);
loop_flag = 1;
channel_count = read_8bit(0x08,streamFile);
header_size = read_32bitLE(0x1C, 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 = header_size;
vgmstream->channels = channel_count;
/* fill in the vital statistics */
start_offset = header_size;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x14,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = ((get_streamfile_size(streamFile) - header_size)/16/ channel_count * 28);
vgmstream->num_samples = ((get_streamfile_size(streamFile) - header_size)/16/ channel_count * 28);
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile);
vgmstream->meta_type = meta_PS2_VMS;
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (get_streamfile_size(streamFile))/16/ channel_count * 28;
vgmstream->meta_type = meta_PS2_VMS;
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (get_streamfile_size(streamFile))/16/ channel_count * 28;
/* open the file for reading */
{

View File

@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
int loop_flag=0;
int channel_count;
int channel_count;
off_t start_offset;
int i;
@ -20,33 +20,33 @@ VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x204B5056)
goto fail;
/* check loop */
loop_flag = (read_32bitLE(0x7FC,streamFile)!=0);
/* check loop */
loop_flag = (read_32bitLE(0x7FC,streamFile)!=0);
channel_count=read_32bitLE(0x14,streamFile);
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = read_32bitLE(0x14,streamFile);
/* fill in the vital statistics */
vgmstream->channels = read_32bitLE(0x14,streamFile);
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
/* Check for Compression Scheme */
vgmstream->coding_type = coding_PSX;
/* Check for Compression Scheme */
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitLE(0x04,streamFile)/16*28;
/* Get loop point values */
if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x7FC,streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
}
/* Get loop point values */
if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x7FC,streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
}
vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile)/2;
vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile)/2;
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_PS2_VPK;
start_offset = (off_t)read_32bitLE(0x08,streamFile);
start_offset = (off_t)read_32bitLE(0x08,streamFile);
/* open the file for reading by each channel */
{

View File

@ -2,19 +2,19 @@
#include "../util.h"
/* IVAG
- The Idolm@ster: Gravure For You! Vol. 3 (PS3)
- The Idolm@ster: Gravure For You! Vol. 3 (PS3)
Appears to be two VAGp streams interleaved.
Appears to be two VAGp streams interleaved.
*/
VGMSTREAM * init_vgmstream_ps3_ivag(STREAMFILE *streamFile)
{
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
off_t start_offset;
int loop_flag = 0;
int channel_count;
int loop_flag = 0;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -24,34 +24,34 @@ VGMSTREAM * init_vgmstream_ps3_ivag(STREAMFILE *streamFile)
if (read_32bitBE(0x00,streamFile) != 0x49564147) // "IVAG"
goto fail;
// channel count
channel_count = read_32bitBE(0x08, streamFile);
// channel count
channel_count = read_32bitBE(0x08, streamFile);
// header size
start_offset = 0x40 + (0x40 * channel_count);
// header size
start_offset = 0x40 + (0x40 * channel_count);
// loop flag
if ((read_32bitBE(0x14, streamFile) != 0 ||
(read_32bitBE(0x18, streamFile) != 0)))
{
loop_flag = 1;
}
// loop flag
if ((read_32bitBE(0x14, streamFile) != 0 ||
(read_32bitBE(0x18, streamFile) != 0)))
{
loop_flag = 1;
}
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x0C,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitBE(0x10,streamFile);
vgmstream->num_samples = read_32bitBE(0x10,streamFile);
if (loop_flag)
{
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile);
}
if (loop_flag)
{
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile);
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x1C,streamFile);
@ -64,15 +64,15 @@ VGMSTREAM * init_vgmstream_ps3_ivag(STREAMFILE *streamFile)
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++)
{
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;

View File

@ -7,15 +7,15 @@ VGMSTREAM * init_vgmstream_ps3_klbs(STREAMFILE *streamFile)
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
size_t fileLength;
off_t readOffset = 0;
off_t start_offset;
off_t loop_start_offset = 0;
off_t loop_end_offset = 0;
size_t fileLength;
off_t readOffset = 0;
off_t start_offset;
off_t loop_start_offset = 0;
off_t loop_end_offset = 0;
uint8_t testBuffer[0x10];
int loop_flag = 0;
int channel_count;
uint8_t testBuffer[0x10];
int loop_flag = 0;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -25,77 +25,77 @@ VGMSTREAM * init_vgmstream_ps3_klbs(STREAMFILE *streamFile)
if (read_32bitBE(0x20,streamFile) != 0x6B6C4253)
goto fail;
// get file length
fileLength = get_streamfile_size(streamFile);
// get file length
fileLength = get_streamfile_size(streamFile);
// Find loop start
start_offset = read_32bitBE(0x10,streamFile);
readOffset = start_offset;
// Find loop start
start_offset = read_32bitBE(0x10,streamFile);
readOffset = start_offset;
do {
readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile);
// Loop Start ...
if(testBuffer[0x01] == 0x06)
{
loop_start_offset = readOffset - 0x10;
break;
}
do {
readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile);
} while (streamFile->get_offset(streamFile)<((int32_t)fileLength));
// Loop Start ...
if(testBuffer[0x01] == 0x06)
{
loop_start_offset = readOffset - 0x10;
break;
}
// start at last line of file and move up
readOffset = (int32_t)fileLength - 0x10;
// Find loop end
do {
readOffset -= (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile);
// Loop End ...
if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77))
{
loop_end_offset = readOffset + 0x20;
break;
}
} while (readOffset > 0);
} while (streamFile->get_offset(streamFile)<((int32_t)fileLength));
// setup loops
if (loop_start_offset > 0)
{
loop_flag = 1;
// if we have a start loop, use EOF if end loop is not found
if (loop_end_offset == 0)
{
loop_end_offset = (int32_t)fileLength - 0x10;
}
}
else
{
loop_flag = 0;
}
// start at last line of file and move up
readOffset = (int32_t)fileLength - 0x10;
// Find loop end
do {
readOffset -= (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile);
// Loop End ...
if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77))
{
loop_end_offset = readOffset + 0x20;
break;
}
} while (readOffset > 0);
// setup loops
if (loop_start_offset > 0)
{
loop_flag = 1;
// if we have a start loop, use EOF if end loop is not found
if (loop_end_offset == 0)
{
loop_end_offset = (int32_t)fileLength - 0x10;
}
}
else
{
loop_flag = 0;
}
channel_count = 2;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
/* fill in the vital statistics */
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x90, streamFile);
vgmstream->meta_type = meta_PS3_KLBS;
vgmstream->channels = channel_count;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 48000;
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = ((vgmstream->interleave_block_size * channel_count)/16/channel_count*28);
vgmstream->num_samples = ((vgmstream->interleave_block_size * channel_count)/16/channel_count*28);
if (loop_flag)
{
vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28;
vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28;
}
if (loop_flag)
{
vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28;
vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28;
}
/* open the file for reading */
{

View File

@ -7,7 +7,7 @@ VGMSTREAM * init_vgmstream_psx_fag(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -15,27 +15,27 @@ VGMSTREAM * init_vgmstream_psx_fag(STREAMFILE *streamFile) {
/* check header */
/* Look if there's more than 1 one file... */
/* Look if there's more than 1 one file... */
if (read_32bitBE(0x00,streamFile) != 0x01000000)
goto fail;
loop_flag = 0;
loop_flag = 0;
channel_count = 2;
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = read_32bitLE(0x04,streamFile);
vgmstream->channels = channel_count;
/* fill in the vital statistics */
start_offset = read_32bitLE(0x04,streamFile);
vgmstream->channels = channel_count;
vgmstream->sample_rate = 24000;
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = (read_32bitLE(0x08,streamFile))/channel_count/32*28;
vgmstream->num_samples = (read_32bitLE(0x08,streamFile))/channel_count/32*28;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(0x08,streamFile))/channel_count/32*28;
}
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x8000;

View File

@ -1,203 +0,0 @@
#include "meta.h"
#include "../util.h"
/* SS_STREAM
SS_STREAM is format used by various UBI Soft Games
2008-11-15 - Fastelbja : First version ...
Some infos, sorry for messing up the meta (regards, manako)
Splinter Cell - *.SS0; PC (except Music_*.SS0)
Splinter Cell: Pandora Tomorrow - *.SS0, *.LS0; PC
Splinter Cell: Chaos Theory - *.SS0, *.LS0; PC
Splinter Cell: Double Agent - *.SS0, *.LS0; PC
UbiSoft Old Simple Stream (version 3)
UbiSoft Simple Stream (version 5)
UbiSoft Old Interleaved Stream (version 2)
UbiSoft Interleaved Stream (version 8 )
Note: if the version number is 3, then all values in this file are big-endian. If the version is 5, then all values are little-endian.
Header:
byte {1} - Version number (3 or 5)
byte {3} - Unknown
byte {4} - Unknown
uint32 {4} - Unknown
uint16 {2} - Unknown
uint16 {2} - Number of extra uncompressed samples before the data (always 10)
int16 {2} - First left sample for decompression
byte {1} - First left index for decompression
byte {1} - Unknown
int16 {2} - First right sample for decompression
byte {1} - First right index for decompression
byte {1} - Unknown
byte {4} - Unknown
Extra Uncompressed Samples:
if the sound is mono:
int16 {Number of extra uncompressed samples * 2} - Uncompressed samples
if the sound is stereo:
int16 {Number of extra uncompressed samples * 4} - Uncompressed samples
Data:
byte {?} - Compressed data
And here is the format of the old interleaved streams:
Code:
Little-endian
uint32 {4} - Signature (2)
uint32 {4} - Number of Layers (always 3)
uint32 {4} - Total File Size
uint32 {4} - Unknown (always 20)
uint32 {4} - Unknown (always 1104)
uint32 {4} - Average Block Size (always 361)
For Each Block: {
uint32 {4} - Block Index (begins at 1)
uint32 {4} - Unknown (always 20)
For Each Layer (Chunk): {
uint32 {4} - Layer Chunk Size
}
For Each Layer (Chunk): {
uint32 {Layer Chunk Size} - Chunk of an Encapsulated UbiSoft Old Simple Stream
}
}
And the new interleaved streams:
Code:
Little-endian
uint16 {2} - Signature (8)
uint16 {2} - Unknown
uint32 {4} - Unknown
uint32 {4} - Number of Layers
uint32 {4} - Number of Blocks
uint32 {4} - Number of Bytes after This to the Headers
uint32 {4} - The Sum of (Number of Layers * 4) Plus the Header Lengths
uint32 {4} - Average Sum of Chunk Data Lengths
For Each Layer: {
uint32 {4} - Layer Header Size
}
For Each Layer: {
uint32 {Layer Header Size} - Header of an Encapsulated Stream (PCM, UbiSoft Simple Stream, Ogg Vorbis)
}
For Each Block: {
uint32 {4} - Signature (3)
uint32 {4} - Number of bytes from the start of this block to the next block, 0 if no more blocks
For Each Layer (Chunk): {
uint32 {4} - Layer Chunk Size
}
For Each Layer (Chunk): {
uint32 {Layer Chunk Size} - Chunk of an Encapsulated Stream (PCM, UbiSoft Simple Stream, Ogg Vorbis)
}
}
*/
VGMSTREAM * init_vgmstream_ss_stream(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag=0;
int channels;
int channel_count;
off_t start_offset;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("ss3",filename_extension(filename)) &&
strcasecmp("ss7",filename_extension(filename))) goto fail;
loop_flag = 0;
//freq_flag = read_8bit(0x08,streamFile);
if (read_8bit(0x0C,streamFile) == 0) {
channels = 1;
} else {
channels = read_8bit(0x0C,streamFile)*2;
}
channel_count = channels;
/* 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 = 48000;
#if 0
if (!strcasecmp("ss3",filename_extension(filename))) {
vgmstream->sample_rate = 32000;
} else if (!strcasecmp("ss7",filename_extension(filename))) {
vgmstream->sample_rate = 48000;
}
#endif
start_offset = (read_8bit(0x07,streamFile)+5);
#if 0
if (channel_count == 1){
start_offset = 0x3C;
} else if (channel_count == 2) {
start_offset = 0x44;
}
#endif
if(channel_count==1)
vgmstream->coding_type = coding_IMA;
else
vgmstream->coding_type = coding_EACS_IMA;
vgmstream->num_samples = (int32_t)((get_streamfile_size(streamFile)-start_offset)* 2 / vgmstream->channels);
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_XBOX_WAVM;
vgmstream->get_high_nibble=0;
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
if (channel_count == 1){
vgmstream->ch[i].offset = start_offset;
} else if (channel_count == 2) {
vgmstream->ch[i].offset = start_offset;
}
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
vgmstream->ch[i].adpcm_history1_32=(int32_t)read_16bitLE(0x10+i*4,streamFile);
vgmstream->ch[i].adpcm_step_index =(int)read_8bit(0x12+i*4,streamFile);
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -8,93 +8,93 @@ VGMSTREAM * init_vgmstream_ta_aac_x360(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
size_t sampleRate, numSamples, startSample, dataSize, blockSize, blockCount; // A mess
size_t sampleRate, numSamples, startSample, dataSize, blockSize, blockCount; // A mess
/* check extension, case insensitive */
/* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */
/* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */
if ( !check_extensions(streamFile,"aac,laac,ace"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x41414320) /* "AAC " */
goto fail;
/* Ok, let's check what's behind door number 1 */
if (read_32bitBE(0x1000, streamFile) == 0x41534320) /* "ASC " */
{
loop_flag = read_32bitBE(0x1118, streamFile);
/* Ok, let's check what's behind door number 1 */
if (read_32bitBE(0x1000, streamFile) == 0x41534320) /* "ASC " */
{
loop_flag = read_32bitBE(0x1118, streamFile);
/*Funky Channel Count Checking */
if (read_32bitBE(0x1184, streamFile) == 0x7374726D)
channel_count = 6;
else if (read_32bitBE(0x1154, streamFile) == 0x7374726D)
channel_count = 4;
else
channel_count = read_8bit(0x1134, streamFile);
/*Funky Channel Count Checking */
if (read_32bitBE(0x1184, streamFile) == 0x7374726D)
channel_count = 6;
else if (read_32bitBE(0x1154, streamFile) == 0x7374726D)
channel_count = 4;
else
channel_count = read_8bit(0x1134, streamFile);
sampleRate = read_32bitBE(0x10F4, streamFile);
numSamples = read_32bitBE(0x10FC, streamFile);
startSample = read_32bitBE(0x10F8, streamFile);
dataSize = read_32bitBE(0x10F0, streamFile);
blockSize = read_32bitBE(0x1100, streamFile);
blockCount = read_32bitBE(0x110C, streamFile);
}
else if (read_32bitBE(0x1000, streamFile) == 0x57415645) /* "WAVE" */
{
loop_flag = read_32bitBE(0x1048, streamFile);
sampleRate = read_32bitBE(0x10F4, streamFile);
numSamples = read_32bitBE(0x10FC, streamFile);
startSample = read_32bitBE(0x10F8, streamFile);
dataSize = read_32bitBE(0x10F0, streamFile);
blockSize = read_32bitBE(0x1100, streamFile);
blockCount = read_32bitBE(0x110C, streamFile);
}
else if (read_32bitBE(0x1000, streamFile) == 0x57415645) /* "WAVE" */
{
loop_flag = read_32bitBE(0x1048, streamFile);
/*Funky Channel Count Checking */
if (read_32bitBE(0x10B0, streamFile) == 0x7374726D)
channel_count = 6;
else if (read_32bitBE(0x1080, streamFile) == 0x7374726D)
channel_count = 4;
else
channel_count = read_8bit(0x1060, streamFile);
/*Funky Channel Count Checking */
if (read_32bitBE(0x10B0, streamFile) == 0x7374726D)
channel_count = 6;
else if (read_32bitBE(0x1080, streamFile) == 0x7374726D)
channel_count = 4;
else
channel_count = read_8bit(0x1060, streamFile);
sampleRate = read_32bitBE(0x1024, streamFile);
numSamples = read_32bitBE(0x102C, streamFile);
startSample = read_32bitBE(0x1028, streamFile);
dataSize = read_32bitBE(0x1020, streamFile);
blockSize = read_32bitBE(0x1030, streamFile);
blockCount = read_32bitBE(0x103C, streamFile);
}
else if (read_32bitBE(0x1000, streamFile) == 0x00000000) /* some like to be special */
{
loop_flag = read_32bitBE(0x6048, streamFile);
sampleRate = read_32bitBE(0x1024, streamFile);
numSamples = read_32bitBE(0x102C, streamFile);
startSample = read_32bitBE(0x1028, streamFile);
dataSize = read_32bitBE(0x1020, streamFile);
blockSize = read_32bitBE(0x1030, streamFile);
blockCount = read_32bitBE(0x103C, streamFile);
}
else if (read_32bitBE(0x1000, streamFile) == 0x00000000) /* some like to be special */
{
loop_flag = read_32bitBE(0x6048, streamFile);
/*Funky Channel Count Checking */
if (read_32bitBE(0x60B0, streamFile) == 0x7374726D)
channel_count = 6;
else if (read_32bitBE(0x6080, streamFile) == 0x7374726D)
channel_count = 4;
else
channel_count = read_8bit(0x6060, streamFile);
/*Funky Channel Count Checking */
if (read_32bitBE(0x60B0, streamFile) == 0x7374726D)
channel_count = 6;
else if (read_32bitBE(0x6080, streamFile) == 0x7374726D)
channel_count = 4;
else
channel_count = read_8bit(0x6060, streamFile);
sampleRate = read_32bitBE(0x6024, streamFile);
numSamples = read_32bitBE(0x602C, streamFile);
startSample = read_32bitBE(0x6028, streamFile);
dataSize = read_32bitBE(0x6020, streamFile);
blockSize = read_32bitBE(0x6030, streamFile);
blockCount = read_32bitBE(0x603C, streamFile);
}
else
goto fail; //cuz I don't know if there are other variants
sampleRate = read_32bitBE(0x6024, streamFile);
numSamples = read_32bitBE(0x602C, streamFile);
startSample = read_32bitBE(0x6028, streamFile);
dataSize = read_32bitBE(0x6020, streamFile);
blockSize = read_32bitBE(0x6030, streamFile);
blockCount = read_32bitBE(0x603C, streamFile);
}
else
goto fail; //cuz I don't know if there are other variants
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
if (read_32bitBE(0x1000, streamFile) == 0x00000000)
start_offset = 0x7000;
else
start_offset = 0x2000;
if (read_32bitBE(0x1000, streamFile) == 0x00000000)
start_offset = 0x7000;
else
start_offset = 0x2000;
vgmstream->sample_rate = sampleRate;
vgmstream->channels = channel_count;
vgmstream->num_samples = numSamples;
if (loop_flag) {
vgmstream->loop_start_sample = startSample;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
if (loop_flag) {
vgmstream->loop_start_sample = startSample;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
vgmstream->meta_type = meta_TA_AAC_X360;
#ifdef VGM_USE_FFMPEG
@ -103,9 +103,9 @@ VGMSTREAM * init_vgmstream_ta_aac_x360(STREAMFILE *streamFile) {
uint8_t buf[100];
size_t bytes, datasize, block_size, block_count;
block_count = blockCount;
block_size = blockSize;
datasize = dataSize;
block_count = blockCount;
block_size = blockSize;
datasize = dataSize;
bytes = ffmpeg_make_riff_xma2(buf,100, vgmstream->num_samples, datasize, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
if (bytes <= 0) goto fail;
@ -132,79 +132,79 @@ fail:
/* PlayStation 3 Variants (Star Ocean International, Resonance of Fate) */
VGMSTREAM * init_vgmstream_ta_aac_ps3(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
uint32_t data_size, loop_start, loop_end, codec_id;
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
uint32_t data_size, loop_start, loop_end, codec_id;
/* check extension, case insensitive */
/* .aac: expected, .laac/ace: for players to avoid hijacking MP4/AAC */
if (!check_extensions(streamFile, "aac,laac,ace"))
goto fail;
/* 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_32bitBE(0x00, streamFile) != 0x41414320) /* "AAC " */
goto fail;
if (read_32bitBE(0x00, streamFile) != 0x41414320) /* "AAC " */
goto fail;
/* Haven't Found a codec flag yet. Let's just use this for now */
if (read_32bitBE(0x10000, streamFile) != 0x41534320) /* "ASC " */
goto fail;
/* Haven't Found a codec flag yet. Let's just use this for now */
if (read_32bitBE(0x10000, streamFile) != 0x41534320) /* "ASC " */
goto fail;
if (read_32bitBE(0x10104, streamFile) != 0xFFFFFFFF)
loop_flag = 1;
else
loop_flag = 0;
if (read_32bitBE(0x10104, streamFile) != 0xFFFFFFFF)
loop_flag = 1;
else
loop_flag = 0;
channel_count = read_32bitBE(0x100F4, streamFile);
codec_id = read_32bitBE(0x100F0, streamFile);
channel_count = read_32bitBE(0x100F4, streamFile);
codec_id = read_32bitBE(0x100F0, streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
/* Useless header, let's play the guessing game */
start_offset = 0x10110;
vgmstream->sample_rate = read_32bitBE(0x100FC, streamFile);
vgmstream->channels = channel_count;
vgmstream->meta_type = meta_TA_AAC_PS3;
data_size = read_32bitBE(0x100F8, streamFile);
loop_start = read_32bitBE(0x10104, streamFile);
loop_end = read_32bitBE(0x10108, streamFile);
/* Useless header, let's play the guessing game */
start_offset = 0x10110;
vgmstream->sample_rate = read_32bitBE(0x100FC, streamFile);
vgmstream->channels = channel_count;
vgmstream->meta_type = meta_TA_AAC_PS3;
data_size = read_32bitBE(0x100F8, streamFile);
loop_start = read_32bitBE(0x10104, streamFile);
loop_end = read_32bitBE(0x10108, streamFile);
#ifdef VGM_USE_FFMPEG
{
ffmpeg_codec_data *ffmpeg_data = NULL;
uint8_t buf[100];
int32_t bytes, samples_size = 1024, block_size, encoder_delay, joint_stereo, max_samples;
block_size = (codec_id == 4 ? 0x60 : (codec_id == 5 ? 0x98 : 0xC0)) * vgmstream->channels;
max_samples = (data_size / block_size) * samples_size;
encoder_delay = 0x0;
joint_stereo = 0;
{
ffmpeg_codec_data *ffmpeg_data = NULL;
uint8_t buf[100];
int32_t bytes, samples_size = 1024, block_size, encoder_delay, joint_stereo, max_samples;
block_size = (codec_id == 4 ? 0x60 : (codec_id == 5 ? 0x98 : 0xC0)) * vgmstream->channels;
max_samples = (data_size / block_size) * samples_size;
encoder_delay = 0x0;
joint_stereo = 0;
/* make a fake riff so FFmpeg can parse the ATRAC3 */
bytes = ffmpeg_make_riff_atrac3(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay);
if (bytes <= 0) goto fail;
bytes = ffmpeg_make_riff_atrac3(buf, 100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, encoder_delay);
if (bytes <= 0) goto fail;
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, 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 = max_samples;
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf, bytes, start_offset, 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 = max_samples;
if (loop_flag) {
vgmstream->loop_start_sample = (loop_start / block_size) * samples_size;
vgmstream->loop_end_sample = (loop_end / block_size) * samples_size;
}
if (loop_flag) {
vgmstream->loop_start_sample = (loop_start / block_size) * samples_size;
vgmstream->loop_end_sample = (loop_end / block_size) * samples_size;
}
}
}
#endif
/* open the file for reading */
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
/* open the file for reading */
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -7,74 +7,74 @@
VGMSTREAM * init_vgmstream_thp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
char filename[PATH_LIMIT];
off_t start_offset;
uint32_t maxAudioSize=0;
uint32_t maxAudioSize=0;
uint32_t numComponents;
off_t componentTypeOffset;
off_t componentDataOffset;
char thpVersion;
uint32_t numComponents;
off_t componentTypeOffset;
off_t componentDataOffset;
int loop_flag;
int channel_count=-1;
int i;
char thpVersion;
int loop_flag;
int channel_count=-1;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("thp",filename_extension(filename)) &&
strcasecmp("dsp",filename_extension(filename))) goto fail;
strcasecmp("dsp",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x54485000)
goto fail;
maxAudioSize = read_32bitBE(0x0C,streamFile);
thpVersion = read_8bit(0x06,streamFile);
maxAudioSize = read_32bitBE(0x0C,streamFile);
thpVersion = read_8bit(0x06,streamFile);
if(maxAudioSize==0) // no sound
goto fail;
if(maxAudioSize==0) // no sound
goto fail;
loop_flag = 0; // allways unloop
/* fill in the vital statistics */
if(thpVersion==0x10) {
start_offset = read_32bitBE(0x24,streamFile);
/* No idea what's up with this */
if (start_offset == 0)
start_offset = read_32bitBE(0x28,streamFile);
} else
start_offset = read_32bitBE(0x28,streamFile);
/* fill in the vital statistics */
if(thpVersion==0x10) {
start_offset = read_32bitBE(0x24,streamFile);
/* No idea what's up with this */
if (start_offset == 0)
start_offset = read_32bitBE(0x28,streamFile);
} else
start_offset = read_32bitBE(0x28,streamFile);
// Get info from the first block
componentTypeOffset = read_32bitBE(0x20,streamFile);
numComponents = read_32bitBE(componentTypeOffset ,streamFile);
componentDataOffset=componentTypeOffset+0x14;
componentTypeOffset+=4;
// Get info from the first block
componentTypeOffset = read_32bitBE(0x20,streamFile);
numComponents = read_32bitBE(componentTypeOffset ,streamFile);
componentDataOffset=componentTypeOffset+0x14;
componentTypeOffset+=4;
for(i=0;i<numComponents;i++) {
if(read_8bit(componentTypeOffset+i,streamFile)==1) {
channel_count=read_32bitBE(componentDataOffset,streamFile);
for(i=0;i<numComponents;i++) {
if(read_8bit(componentTypeOffset+i,streamFile)==1) {
channel_count=read_32bitBE(componentDataOffset,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->channels=channel_count;
vgmstream->sample_rate=read_32bitBE(componentDataOffset+4,streamFile);
vgmstream->num_samples=read_32bitBE(componentDataOffset+8,streamFile);
break;
} else {
if(thpVersion==0x10)
componentDataOffset+=0x0c;
else
componentDataOffset+=0x08;
}
}
vgmstream->channels=channel_count;
vgmstream->sample_rate=read_32bitBE(componentDataOffset+4,streamFile);
vgmstream->num_samples=read_32bitBE(componentDataOffset+8,streamFile);
break;
} else {
if(thpVersion==0x10)
componentDataOffset+=0x0c;
else
componentDataOffset+=0x08;
}
}
/* open the file for reading */
{
@ -87,10 +87,10 @@ VGMSTREAM * init_vgmstream_thp(STREAMFILE *streamFile) {
}
}
vgmstream->thpNextFrameSize=read_32bitBE(0x18,streamFile);
thp_block_update(start_offset,vgmstream);
vgmstream->thpNextFrameSize=read_32bitBE(0x18,streamFile);
thp_block_update(start_offset,vgmstream);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_thp_blocked;
vgmstream->meta_type = meta_THP;

View File

@ -7,7 +7,7 @@ VGMSTREAM * init_vgmstream_tun(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
off_t start_offset;
int channel_count;
int loop_flag;
int loop_flag;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -17,8 +17,8 @@ VGMSTREAM * init_vgmstream_tun(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x414C5020) /* "ALP " */
goto fail;
channel_count = 2;
loop_flag = 0;
channel_count = 2;
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);

View File

@ -30,11 +30,12 @@ typedef enum {
XMA1 = 20, /* raw XMA1 */
XMA2 = 21, /* raw XMA2 */
FFMPEG = 22, /* any headered FFmpeg format */
AC3 = 23, /* AC3/SPDIF */
} txth_type;
typedef struct {
txth_type codec;
txth_type codec_mode;
uint32_t codec_mode;
uint32_t interleave;
uint32_t id_value;
@ -60,11 +61,12 @@ typedef struct {
uint32_t coef_offset;
uint32_t coef_spacing;
uint32_t coef_mode;
uint32_t coef_big_endian;
uint32_t coef_mode;
} txth_header;
static STREAMFILE * open_txth(STREAMFILE * streamFile);
static int parse_txth(STREAMFILE * streamFile, STREAMFILE * streamText, txth_header * txth);
static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_header * txth, const char * key, const char * val);
static int parse_num(STREAMFILE * streamFile, const char * val, uint32_t * out_value);
@ -76,44 +78,16 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes);
VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamText = NULL;
txth_header txth;
txth_header txth = {0};
coding_t coding;
int i, j;
/* no need for ID or ext checks -- if a .TXTH exists all is good
* (player still needs to accept the ext, so at worst rename to .vgmstream) */
{
char filename[PATH_LIMIT];
char fileext[PATH_LIMIT];
/* try "(path/)(name.ext).txth" */
if (!get_streamfile_name(streamFile,filename,PATH_LIMIT)) goto fail;
strcat(filename, ".txth");
streamText = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (streamText) goto found;
/* try "(path/)(.ext).txth" */
if (!get_streamfile_path(streamFile,filename,PATH_LIMIT)) goto fail;
if (!get_streamfile_ext(streamFile,fileext,PATH_LIMIT)) goto fail;
strcat(filename,".");
strcat(filename, fileext);
strcat(filename, ".txth");
streamText = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (streamText) goto found;
/* try "(path/).txth" */
if (!get_streamfile_path(streamFile,filename,PATH_LIMIT)) goto fail;
strcat(filename, ".txth");
streamText = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (streamText) goto found;
/* not found */
goto fail;
}
found:
streamText = open_txth(streamFile);
if (!streamText) goto fail;
/* process the text file */
memset(&txth,0,sizeof(txth_header));
if (!parse_txth(streamFile, streamText, &txth))
goto fail;
@ -145,6 +119,7 @@ found:
case ATRAC3PLUS:
case XMA1:
case XMA2:
case AC3:
case FFMPEG: coding = coding_FFmpeg; break;
#endif
default:
@ -261,7 +236,8 @@ found:
for (j=0;j<16;j++) {
vgmstream->ch[i].adpcm_coef[j] = read_16bit(txth.coef_offset + i*txth.coef_spacing + j*2,streamFile);
}
} else {
}
else {
goto fail; //IDK what is this
/*
for (j=0;j<8;j++) {
@ -285,7 +261,7 @@ found:
case coding_FFmpeg: {
ffmpeg_codec_data *ffmpeg_data = NULL;
if (txth.codec == FFMPEG) {
if (txth.codec == FFMPEG || txth.codec == AC3) {
/* default FFmpeg */
ffmpeg_data = init_ffmpeg_offset(streamFile, txth.start_offset,txth.data_size);
if ( !ffmpeg_data ) goto fail;
@ -390,6 +366,38 @@ fail:
return NULL;
}
static STREAMFILE * open_txth(STREAMFILE * streamFile) {
char filename[PATH_LIMIT];
char fileext[PATH_LIMIT];
STREAMFILE * streamText;
/* try "(path/)(name.ext).txth" */
if (!get_streamfile_name(streamFile,filename,PATH_LIMIT)) goto fail;
strcat(filename, ".txth");
streamText = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (streamText) return streamText;
/* try "(path/)(.ext).txth" */
if (!get_streamfile_path(streamFile,filename,PATH_LIMIT)) goto fail;
if (!get_streamfile_ext(streamFile,fileext,PATH_LIMIT)) goto fail;
strcat(filename,".");
strcat(filename, fileext);
strcat(filename, ".txth");
streamText = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (streamText) return streamText;
/* try "(path/).txth" */
if (!get_streamfile_path(streamFile,filename,PATH_LIMIT)) goto fail;
strcat(filename, ".txth");
streamText = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (streamText) return streamText;
fail:
/* not found */
return 0;
}
/* Simple text parser of "key = value" lines.
* The code is meh and error handling not exactly the best. */
static int parse_txth(STREAMFILE * streamFile, STREAMFILE * streamText, txth_header * txth) {
@ -472,6 +480,7 @@ static int parse_keyval(STREAMFILE * streamFile, STREAMFILE * streamText, txth_h
else if (0==strcmp(val,"XMA1")) txth->codec = XMA1;
else if (0==strcmp(val,"XMA2")) txth->codec = XMA2;
else if (0==strcmp(val,"FFMPEG")) txth->codec = FFMPEG;
else if (0==strcmp(val,"AC3")) txth->codec = AC3;
else goto fail;
}
else if (0==strcmp(key,"codec_mode")) {
@ -663,6 +672,10 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) {
case XMA2:
return bytes; /* preserve */
case AC3:
if (!txth->interleave) return 0;
return bytes / txth->interleave * 256 * txth->channels;
/* untested */
case IMA:
case DVI_IMA:

View File

@ -34,6 +34,8 @@ typedef struct {
size_t stream_id_offset;
int has_short_channels;
int has_internal_names;
int has_extra_name_flag;
int has_rotating_ids;
/* derived */
size_t main_size;
@ -73,8 +75,6 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
/* check extension (number represents the platform, see later) */
if ( !check_extensions(streamFile,"sb0,sb1,sb2,sb3,sb4,sb5,sb6,sb7") )
goto fail;
//memset(&sb,0,sizeof(ubi_sb_header)); //todo test for VC2010's init = {0} above (should be C89 but...)
if (sb.flag1 != 0 || sb.codec!=0 || sb.stream_samples != 0) { VGM_LOG("UBI SB: not init ok\n"); goto fail; }
/* .sb0 (sound bank) is a small multisong format (loaded in memory?) that contains SFX data
@ -119,7 +119,7 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
start_offset = sb.main_size + sb.section1_size + sb.section2_size + sb.extra_size + sb.section3_size;
start_offset += sb.stream_offset;
}
;VGM_LOG("so=%lx, main=%x, s1=%x, s2=%x, ex=%x, s3=%x, so=%lx\n", start_offset, sb.main_size, sb.section1_size, sb.section2_size, sb.extra_size, sb.section3_size, sb.stream_offset);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(sb.channels,loop_flag);
@ -131,7 +131,7 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
switch(sb.codec) {
case UBI_ADPCM: { //todo move to its own decoder
case UBI_ADPCM: {
vgmstream->coding_type = coding_UBI_IMA;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = ubi_ima_bytes_to_samples(sb.stream_size, sb.channels, streamData, start_offset);
@ -139,11 +139,10 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
}
case RAW_PCM:
vgmstream->coding_type = coding_PCM16LE;
vgmstream->coding_type = coding_PCM16LE; /* always LE even on Wii */
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02;
vgmstream->num_samples = pcm_bytes_to_samples(sb.stream_size, sb.channels, 16);
if (sb.channels > 1) { VGM_LOG("UBI SB: >1 channel\n"); goto fail; } //todo
break;
case RAW_PSX:
@ -183,7 +182,8 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = sb.stream_size / sb.channels;
vgmstream->num_samples = ps_bytes_to_samples(sb.stream_size, sb.channels) ;
vgmstream->num_samples = ps_bytes_to_samples(sb.stream_size, sb.channels);
if (sb.channels > 1) { VGM_LOG("UBI SB: >1 channel\n"); goto fail; } //todo
break;
@ -264,7 +264,7 @@ fail:
static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
int i, ok;
int i, ok, current_type = -1, current_id = -1;
int target_stream = streamFile->stream_index;
if (target_stream == 0) target_stream = 1;
@ -284,7 +284,7 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
sb->section1_num = read_32bit(0x04, streamFile); /* group headers? */
sb->section2_num = read_32bit(0x08, streamFile); /* streams headers (internal or external) */
sb->section3_num = read_32bit(0x0c, streamFile); /* internal streams table */
sb->extra_size = read_32bit(0x10, streamFile); /* extra table, unknown except with DSP = coefs */
sb->extra_size = read_32bit(0x10, streamFile); /* extra table, unknown (config for non-audio types) except with DSP = coefs */
sb->flag1 = read_32bit(0x14, streamFile); /* unknown, usually -1 but can be others (0/1/2/etc) */
sb->flag2 = read_32bit(0x18, streamFile); /* unknown, usually -1 but can be others */
@ -307,11 +307,39 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
if (read_32bit(offset + 0x04, streamFile) != 0x01)
continue;
/* weird case when there is no internal substream ID and just seem to rotate every time type changes, joy */
if (sb->has_rotating_ids) { /* assumes certain configs can't happen in this case */
int current_is_external = 0;
int type = read_32bit(offset + sb->stream_type_offset, streamFile);
if (current_type == -1)
current_type = type;
if (current_id == -1) /* use first ID in section3 */
current_id = read_32bit(sb->main_size + sb->section1_size + sb->section2_size + sb->extra_size + 0x00, streamFile);
if (sb->external_flag_offset) {
current_is_external = read_32bit(offset + sb->external_flag_offset, streamFile);
} else if (sb->has_extra_name_flag && read_32bit(offset + sb->extra_name_offset, streamFile) != 0xFFFFFFFF) {
current_is_external = 1; /* -1 in extra_name means internal */
}
if (!current_is_external) {
if (current_type != type) {
current_type = type;
current_id++; /* rotate */
if (current_id >= sb->section3_num)
current_id = 0; /* reset */
}
}
}
/* update streams (total_stream also doubles as current) */
sb->total_streams++;
if (sb->total_streams != target_stream)
continue;
;VGM_LOG("target at offset=%lx (size=%x)\n", offset, sb->section2_entry_size);
//;VGM_LOG("target at offset=%lx (size=%x)\n", offset, sb->section2_entry_size);
sb->header_id = read_32bit(offset + 0x00, streamFile); /* 16b+16b group+sound id */
sb->header_type = read_32bit(offset + 0x04, streamFile);
@ -327,8 +355,11 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
if (sb->num_samples_offset)
sb->stream_samples = read_32bit(offset + sb->num_samples_offset, streamFile);
if (sb->stream_id_offset)
if (sb-> has_rotating_ids) {
sb->stream_id = current_id;
} else if (sb->stream_id_offset) {
sb->stream_id = read_32bit(offset + sb->stream_id_offset, streamFile);
}
/* external stream name can be found in the header (first versions) or the extra table (later versions) */
if (sb->stream_name_offset) {
@ -341,6 +372,8 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
/* not always set and must be derived */
if (sb->external_flag_offset) {
sb->is_external = read_32bit(offset + sb->external_flag_offset, streamFile);
} else if (sb->has_extra_name_flag && read_32bit(offset + sb->extra_name_offset, streamFile) != 0xFFFFFFFF) {
sb->is_external = 1; /* -1 in extra_name means internal */
} else if (sb->section3_num == 0) {
sb->is_external = 1;
} else {
@ -361,7 +394,7 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
goto fail;
}
if (!sb->stream_id_offset && sb->section3_num > 1) {
if (!(sb->stream_id_offset || sb->has_rotating_ids) && sb->section3_num > 1) {
VGM_LOG("UBI SB: unexpected number of internal streams %i\n", sb->section3_num);
goto fail;
}
@ -392,6 +425,10 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
}
break;
case 0x01: /* PCM (Wii, rarely used) */
sb->codec = RAW_PCM;
break;
case 0x03: /* Ubi ADPCM (main external stream codec, has subtypes) */
sb->codec = UBI_ADPCM;
break;
@ -404,7 +441,6 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
sb->codec = FMT_AT3;
break;
case 0x01: /* PCM? (Wii, rarely used) */
default:
VGM_LOG("UBI SB: unknown stream_type %x\n", sb->stream_type);
goto fail;
@ -413,12 +449,11 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
/* uncommon but possible */
//VGM_ASSERT(sb->is_external && sb->section3_num != 0, "UBI SS: mixed external and internal streams\n");
/* seems can be safely ignored */
/* seems that can be safely ignored */
//VGM_ASSERT(sb->is_external && sb->stream_id_offset && sb->stream_id > 0, "UBI SB: unexpected external stream with stream id\n");
//todo fix, wrong
/* section 3: substreams within the file, adjust stream offset (rarely used but table is always present) */
if (!sb->is_external && sb->stream_id_offset && sb->section3_num > 1) {
if (!sb->is_external && (sb->stream_id_offset || sb->has_rotating_ids) && sb->section3_num > 1) {
for (i = 0; i < sb->section3_num; i++) {
off_t offset = sb->main_size + sb->section1_size + sb->section2_size + sb->extra_size + sb->section3_entry_size * i;
@ -620,13 +655,14 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
sb->section2_entry_size = 0x78;
sb->external_flag_offset = 0x2c;
sb->stream_id_offset = 0x34;//todo test
sb->stream_id_offset = 0x34;
sb->num_samples_offset = 0x40;
sb->sample_rate_offset = 0x54;
sb->channels_offset = 0x5c;
sb->stream_type_offset = 0x60;
sb->extra_name_offset = 0x64;
sb->has_extra_name_flag = 1;
return 1;
}
@ -635,13 +671,14 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
sb->section1_entry_size = 0x48;
sb->section2_entry_size = 0x5c;
sb->external_flag_offset = 0; /* no apparent flag */
sb->external_flag_offset = 0;
sb->channels_offset = 0x2c;
sb->sample_rate_offset = 0x30;
sb->num_samples_offset = 0x3c;
sb->extra_name_offset = 0x4c;
sb->stream_type_offset = 0x50;
sb->has_extra_name_flag = 1;
return 1;
}
@ -650,15 +687,16 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
sb->section1_entry_size = 0x48;
sb->section2_entry_size = 0x58;
sb->external_flag_offset = 0; /* no apparent flag */
sb->external_flag_offset = 0;
sb->num_samples_offset = 0x28;
sb->stream_id_offset = 0x34;//todo test
sb->stream_id_offset = 0;
sb->sample_rate_offset = 0x3c;
sb->channels_offset = 0x44;
sb->stream_type_offset = 0x48;
sb->extra_name_offset = 0x4c;
sb->has_internal_names = 1;
sb->has_extra_name_flag = 1;
sb->has_rotating_ids = 1;
return 1;
}
@ -677,18 +715,34 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
return 1;
}
/* Red Steel (2006)(Wii) */
if (sb->version == 0x00180006 && is_sb7) { /* same as 0x00150000 */
sb->section1_entry_size = 0x68;
sb->section2_entry_size = 0x6c;
sb->external_flag_offset = 0x28; /* maybe 0x2c */
sb->num_samples_offset = 0x3c;
sb->sample_rate_offset = 0x50;
sb->channels_offset = 0x58;
sb->stream_type_offset = 0x5c;
sb->extra_name_offset = 0x60;
return 1;
}
/* Prince of Persia: Rival Swords (2007)(PSP) */
if (sb->version == 0x00180005 && is_sb5) {
sb->section1_entry_size = 0x48;
sb->section2_entry_size = 0x54;
sb->external_flag_offset = 0; /* no apparent flag */
sb->external_flag_offset = 0;
sb->channels_offset = 0x28;
sb->sample_rate_offset = 0x2c;
//sb->num_samples_offset = 0x34 or 0x3c /* varies */
sb->extra_name_offset = 0x44;
sb->stream_type_offset = 0x48;
sb->has_extra_name_flag = 1;
return 1;
}
@ -699,7 +753,7 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
sb->external_flag_offset = 0x28; /* maybe 0x2c */
sb->channels_offset = 0x3c;
sb->sample_rate_offset = 0x44;
sb->sample_rate_offset = 0x40;
sb->num_samples_offset = 0x48;
sb->extra_name_offset = 0x58;
sb->stream_type_offset = 0x5c;

View File

@ -7,7 +7,7 @@ VGMSTREAM * init_vgmstream_wpd(STREAMFILE *streamFile) {
char filename[PATH_LIMIT];
off_t start_offset;
int channel_count;
int loop_flag;
int loop_flag;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
@ -17,8 +17,8 @@ VGMSTREAM * init_vgmstream_wpd(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x20445057) /* " DPW" */
goto fail;
channel_count = read_32bitLE(0x4,streamFile);
loop_flag = 0;
channel_count = read_32bitLE(0x4,streamFile);
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);

View File

@ -128,8 +128,8 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
}
/* other Wwise specific: */
//"JUNK": optional padding so that raw data starts in an offset multiple of 0x10 (0-size JUNK exists too)
//"akd ": unknown (IMA/PCM; "audiokinetic data"?)
//"JUNK": optional padding for usually aligment (0-size JUNK exists too)
//"akd ": seem to store extra info for Wwise editor (wave peaks/loudness/HDR envelope?)
}
/* format to codec */
@ -158,7 +158,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
ww.codec = DSP;
}
/* Some Wwise files (ex. Oddworld PSV, Bayonetta 2 WiiU sfx) are truncated mirrors of another file.
/* Some Wwise files (ex. Oddworld PSV, Bayonetta 2 WiiU, often in BGM.bnk) are truncated mirrors of another file.
* They come in RAM banks, probably to play the beginning while the rest of the real stream loads.
* We'll add basic support to avoid complaints of this or that .wem not playing */
if (ww.data_size > ww.file_size) {
@ -560,50 +560,50 @@ fail:
0x00 (4): num_samples
0x04 (4): skip samples?
0x08 (4): ? (small if loop, 0 otherwise)
0x0c (4): loop offset after seek table+setup (offset after setup if file doesn't loop)
0x0c (4): data start offset after seek table+setup, or loop start when "smpl" is present
0x10 (4): ? (small, 0..~0x400)
0x14 (4): approximate data size without seek table? (almost setup+packets)
0x18 (4): setup_offset within data (0 = no seek table)
0x1c (4): audio_offset within data
0x20 (4): biggest packet size (not including header)?
0x24 (4): ? (mid, 0~0x5000)
0x28 (4): ? (mid, 0~0x5000)
0x2c (4): parent bank/event id? (shared by several .wem a game, but not all need to share it)
0x20 (2): biggest packet size (not including header)?
0x22 (2): ? (small, N..~0x100) uLastGranuleExtra?
0x24 (4): ? (mid, 0~0x5000) dwDecodeAllocSize?
0x28 (4): ? (mid, 0~0x5000) dwDecodeX64AllocSize?
0x2c (4): parent bank/event id? uHashCodebook? (shared by several .wem a game, but not all need to share it)
0x30 (1): blocksize_1_exp (small)
0x31 (1): blocksize_0_exp (large)
0x32 (2): empty
"vorb" size 0x28 / 0x2a
0x00 (4): num_samples
0x04 (4): loop offset after seek table+setup (offset after setup if file doesn't loop)
0x08 (4): data size without seek table (setup+packets)
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)
0x10 (4): setup_offset within data (0 = no seek table)
0x14 (4): audio_offset within data
0x18 (2): ? (small, 0..~0x400)
0x1a (2): ? (small, N..~0x100)
0x1c (4): ? (mid, 0~0x5000)
0x20 (4): ? (mid, 0~0x5000)
0x24 (4): parent bank/event id? (shared by several .wem a game, but not all need to share it)
0x28 (1): blocksize_1_exp (small) [removed when size is 0x28]
0x29 (1): blocksize_0_exp (large) [removed when size is 0x28]
0x18 (2): biggest packet size (not including header)?
0x1a (2): ? (small, N..~0x100) uLastGranuleExtra?
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)
0x28 (1): blocksize_1_exp (small) [removed when size is 0x28]
0x29 (1): blocksize_0_exp (large) [removed when size is 0x28]
- new format:
"fmt" size 0x42, extra size 0x30
0x12 (2): flag? (00,10,18): not related to seek table, codebook type, chunk count, looping, etc
0x14 (4): channel config
0x18 (4): num_samples
0x1c (4): loop offset after seek table+setup (offset after setup if file doesn't loop)
0x20 (4): data size without seek table (setup+packets)
0x1c (4): data start offset after seek table+setup, or loop start when "smpl" is present
0x20 (4): data end offset after seek table (setup+packets), or loop end when "smpl" is present
0x24 (2): ?1 (small, 0..~0x400)
0x26 (2): ?2 (small, N..~0x100): not related to seek table, codebook type, chunk count, looping, packet size, samples, etc
0x28 (4): setup offset within data (0 = no seek table)
0x2c (4): audio offset within data
0x30 (2): biggest packet size (not including header)
0x32 (2): ?4 (small, 0..~0x100): may be same than ?2 (something related to the avg bitrate?)
0x34 (4): bitrate config? (mid, 0~0x5000)
0x38 (4): bitrate config? (mid, 0~0x5000) (2 byte with max/min?)
0x32 (2): (small, 0..~0x100) uLastGranuleExtra?
0x34 (4): ? (mid, 0~0x5000) dwDecodeAllocSize?
0x38 (4): ? (mid, 0~0x5000) dwDecodeX64AllocSize?
0x40 (1): blocksize_1_exp (small)
0x41 (1): blocksize_0_exp (large)

View File

@ -25,7 +25,7 @@ static const int wma_block_align_index[17] = {
};
typedef enum { PCM, XBOX_ADPCM, MS_ADPCM, XMA1, XMA2, WMA, XWMA, ATRAC3 } xact_codec;
typedef enum { PCM, XBOX_ADPCM, MS_ADPCM, XMA1, XMA2, WMA, XWMA, ATRAC3, OGG } xact_codec;
typedef struct {
int little_endian;
int version;
@ -124,8 +124,6 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
/* for Techland's XWB with no data */
if (xwb.base_offset == 0) goto fail;
/* some BlazBlue Centralfiction songs have padding after data size */
if (xwb.data_offset + xwb.data_size > get_streamfile_size(streamFile)) goto fail;
/* read base entry (WAVEBANKDATA) */
off = xwb.base_offset;
@ -168,8 +166,6 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
xwb.loop_start = (uint32_t)read_32bit(off+0x0c, streamFile);
xwb.loop_end = (uint32_t)read_32bit(off+0x10, streamFile);//length
xwb.loop_flag = (xwb.loop_end > 0 || xwb.loop_end_sample > xwb.loop_start);
}
else {
uint32_t entry_info = (uint32_t)read_32bit(off+0x00, streamFile);
@ -190,9 +186,6 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
xwb.loop_start_sample = (uint32_t)read_32bit(off+0x10, streamFile);
xwb.loop_end_sample = (uint32_t)read_32bit(off+0x14, streamFile) + xwb.loop_start_sample;
}
xwb.loop_flag = (xwb.loop_end > 0 || xwb.loop_end_sample > xwb.loop_start)
&& !(xwb.entry_flags & WAVEBANKENTRY_FLAGS_IGNORELOOP);
}
@ -231,14 +224,17 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
case 1: xwb.codec = XBOX_ADPCM; break;
default: goto fail;
}
} else if (xwb.version <= XACT1_1_MAX) {
}
else if (xwb.version <= XACT1_1_MAX) {
switch(xwb.tag){
case 0: xwb.codec = PCM; break;
case 1: xwb.codec = XBOX_ADPCM; break;
case 2: xwb.codec = WMA; break;
case 3: xwb.codec = OGG; break; /* extension */
default: goto fail;
}
} else if (xwb.version <= XACT2_2_MAX) {
}
else if (xwb.version <= XACT2_2_MAX) {
switch(xwb.tag) {
case 0: xwb.codec = PCM; break;
/* Table Tennis (v34): XMA1, Prey (v38): XMA2, v35/36/37: ? */
@ -246,7 +242,8 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
case 2: xwb.codec = MS_ADPCM; break;
default: goto fail;
}
} else {
}
else {
switch(xwb.tag) {
case 0: xwb.codec = PCM; break;
case 1: xwb.codec = XMA2; break;
@ -267,6 +264,26 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
xwb.num_samples = atrac3_bytes_to_samples(xwb.stream_size, xwb.block_align * xwb.channels);
}
/* Oddworld: Stranger's Wrath iOS/Android format hijack, with changed meanings */
if (xwb.codec == OGG) {
xwb.num_samples = xwb.stream_size / (2 * xwb.channels); /* uncompressed bytes */
xwb.stream_size = xwb.loop_end;
xwb.loop_start = 0;
xwb.loop_end = 0;
}
/* test loop after the above fixes */
xwb.loop_flag = (xwb.loop_end > 0 || xwb.loop_end_sample > xwb.loop_start)
&& !(xwb.entry_flags & WAVEBANKENTRY_FLAGS_IGNORELOOP);
if (xwb.codec != OGG) {
/* for Oddworld OGG the data_size value is size of uncompressed bytes instead */
/* some BlazBlue Centralfiction songs have padding after data size (maybe wrong rip?) */
if (xwb.data_offset + xwb.data_size > get_streamfile_size(streamFile))
goto fail;
}
/* fix samples */
if (xwb.version <= XACT2_2_MAX && xwb.codec == PCM) {
@ -435,7 +452,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
break;
}
case ATRAC3: { /* Techland extension */
case ATRAC3: { /* Techland PS3 extension */
uint8_t buf[200];
int bytes;
@ -452,6 +469,15 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none;
break;
}
case OGG: { /* Oddworld: Strangers Wrath iOS/Android extension */
vgmstream->codec_data = init_ffmpeg_offset(streamFile, xwb.stream_offset, xwb.stream_size);
if ( !vgmstream->codec_data ) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
break;
}
#endif
default:

View File

@ -5,7 +5,6 @@
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "formats.h"
#include "vgmstream.h"
#include "meta/meta.h"
#include "layout/layout.h"
@ -202,7 +201,6 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
init_vgmstream_wii_smp,
init_vgmstream_emff_ps2,
init_vgmstream_emff_ngc,
init_vgmstream_ss_stream,
init_vgmstream_thp,
init_vgmstream_wii_sts,
init_vgmstream_ps2_p2bt,

View File

@ -1147,6 +1147,7 @@ typedef struct {
/* do format detection, return pointer to a usable VGMSTREAM, or NULL on failure */
VGMSTREAM * init_vgmstream(const char * const filename);
/* init with custom IO via streamfile */
VGMSTREAM * init_vgmstream_from_STREAMFILE(STREAMFILE *streamFile);
/* reset a VGMSTREAM to start of stream */
@ -1169,6 +1170,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length);
* stream. Compares files by absolute paths. */
int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream);
/* List of supported formats and elements in the list, for plugins that need to know. */
const char ** vgmstream_get_formats(size_t * size);
/* -------------------------------------------------------------------------*/
/* vgmstream "private" API */
/* -------------------------------------------------------------------------*/
@ -1203,4 +1207,9 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream);
* returns 0 on failure */
int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t start_offset);
/* get description info */
const char * get_vgmstream_coding_description(coding_t coding_type);
const char * get_vgmstream_layout_description(layout_t layout_type);
const char * get_vgmstream_meta_description(meta_t meta_type);
#endif

View File

@ -14,8 +14,9 @@ REM #TODO: escape & ! % in file/folder names
setlocal enableDelayedExpansion
REM #-------------------------------------------------------------------------
REM #options
REM #-------------------------------------------------------------------------
REM # -vo <exe> -vn <exe>: path to old/new exe
set OP_CMD_OLD=test_old.exe
set OP_CMD_NEW=test.exe
@ -27,6 +28,8 @@ REM # -nd: don't delete compared files
set OP_NODELETE=
REM # -nc: don't report correct files
set OP_NOCORRECT=
REM # -p: performance test (decode with new exe and no comparison done)
set OP_PERFORMANCE=
REM # parse options
@ -38,6 +41,7 @@ if "%~1"=="-f" set OP_SEARCH=%2
if "%~1"=="-r" set OP_RECURSIVE=/s
if "%~1"=="-nd" set OP_NODELETE=true
if "%~1"=="-nc" set OP_NOCORRECT=true
if "%~1"=="-p" set OP_PERFORMANCE=true
shift
goto set_options
:end_options
@ -61,7 +65,8 @@ if %OP_SEARCH%=="" (
)
REM # process start
echo VRTS: start @%time%
set TIME_START=%time%
echo VRTS: start @%TIME_START%
REM # search for files
set CMD_DIR=dir /a:-d /b %OP_RECURSIVE% %OP_SEARCH%
@ -70,18 +75,39 @@ set CMD_FIND=findstr /i /v "\.exe$ \.dll$ \.zip$ \.7z$ \.rar$ \.bat$ \.sh$ \.txt
REM # process files
for /f "delims=" %%x in ('%CMD_DIR% ^| %CMD_FIND%') do (
set CMD_FILE=%%x
call :process_file "!CMD_FILE!"
if "%OP_PERFORMANCE%" == "" (
call :process_file "!CMD_FILE!"
) else (
call :performance_file "!CMD_FILE!"
)
)
REM # find time elapsed
set TIME_END=%time%
for /F "tokens=1-4 delims=:.," %%a in ("%TIME_START%") do (
set /A "TIME_START_S=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100"
)
for /F "tokens=1-4 delims=:.," %%a in ("%TIME_END%") do (
set /A "TIME_END_S=(((%%a*60)+1%%b %% 100)*60+1%%c %% 100)*100+1%%d %% 100"
)
set /A TIME_ELAPSED_S=(TIME_END_S-TIME_START_S)/100
set /A TIME_ELAPSED_C=(TIME_END_S-TIME_START_S)%%100
REM # process end (ok)
goto done
echo VRTS: done @%TIME_END% (%TIME_ELAPSED_S%,%TIME_ELAPSED_C%s)
goto exit
REM # ########################################################################
REM # test a single file
REM # ########################################################################
:process_file outer
REM # ignore files starting with dot (no filename)
set CMD_SHORTNAME=%~n1
if "%CMD_SHORTNAME%" == "" goto continue
if "%CMD_SHORTNAME%" == "" goto process_file_continue
REM # get file
set CMD_FILE=%1
@ -105,7 +131,7 @@ REM # test a single file
REM echo VRTS: nothing created for file %CMD_FILE%
if exist "%TXT_NEW%" del /a:a "%TXT_NEW%"
if exist "%TXT_OLD%" del /a:a "%TXT_OLD%"
goto continue
goto process_file_continue
)
)
@ -146,12 +172,42 @@ REM # test a single file
if exist "%TXT_NEW%" del /a:a "%TXT_NEW%"
)
:continue
:process_file_continue
exit /B
REM :process_file end, continue from last call
REM # ########################################################################
REM # decode only (no comparisons done), for performance testing
REM # ########################################################################
:performance_file
REM # ignore files starting with dot (no filename)
set CMD_SHORTNAME=%~n1
if "%CMD_SHORTNAME%" == "" goto performance_file_continue
REM # get file
set CMD_FILE=%1
set CMD_FILE=%CMD_FILE:"=%
REM echo VTRS: file %CMD_FILE%
REM # new temp output
set WAV_NEW=%CMD_FILE%.test.wav
set CMD_VGM_NEW="%OP_CMD_NEW%" -o "%WAV_NEW%" "%CMD_FILE%"
%CMD_VGM_NEW% 1> nul 2>&1 & REM || goto error
call :echo_color %C_O% "%CMD_FILE%" "done"
REM # ignore output
if exist "%WAV_NEW%" del /a:a "%WAV_NEW%"
:performance_file_continue
exit /B
REM :performance_file end, continue from last call
REM # ########################################################################
REM # hack to get colored output in Windows CMD using findstr + temp file
REM # ########################################################################
:echo_color
set TEMP_FILE=%2-result
set TEMP_FILE=%TEMP_FILE:"=%
@ -165,14 +221,10 @@ exit /B
REM :echo_color end, continue from last call
:done
echo VRTS: done @%time%
goto exit
REM # ########################################################################
:error
echo VRTS: error @%time%
echo VRTS: error
goto exit
:exit

View File

@ -5,8 +5,9 @@
/* Normally Winamp opens unicode files by their DOS 8.3 name. #define this to use wchar_t filenames,
* which must be opened with _wfopen in a WINAMP_STREAMFILE (needed for dual files like .pos).
* Only for Winamp paths, other parts would need #define UNICODE for Windows. */
//#define UNICODE_INPUT_PLUGIN
#ifdef VGM_WINAMP_UNICODE
#define UNICODE_INPUT_PLUGIN
#endif
#ifdef _MSC_VER
#define _CRT_SECURE_NO_DEPRECATE
@ -19,7 +20,6 @@
#include <string.h>
#include <ctype.h>
#include "../src/formats.h"
#include "../src/vgmstream.h"
#include "in2.h"
#include "wa_ipc.h"
@ -68,7 +68,7 @@ In_Module input_module;
DWORD WINAPI __stdcall decode(void *arg);
/* Winamp Play extension list, needed to accept/play and associate extensions in Windows */
#define EXTENSION_LIST_SIZE VGM_EXTENSION_LIST_CHAR_SIZE * 6
#define EXTENSION_LIST_SIZE (0x2000 * 6)
#define EXT_BUFFER_SIZE 200
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
@ -463,14 +463,13 @@ static void add_extension(int length, char * dst, const char * ext) {
* Each extension must be in this format: "extension\0Description\0" */
static void build_extension_list() {
const char ** ext_list;
int ext_list_len;
size_t ext_list_len;
int i;
working_extension_list[0]='\0';
working_extension_list[1]='\0';
ext_list = vgmstream_get_formats();
ext_list_len = vgmstream_get_formats_length();
ext_list = vgmstream_get_formats(&ext_list_len);
for (i=0; i < ext_list_len; i++) {
add_extension(EXTENSION_LIST_SIZE, working_extension_list, ext_list[i]);

View File

@ -11,7 +11,6 @@
#include <string.h>
#include <ctype.h>
#include "../src/formats.h"
#include "../src/vgmstream.h"
#include "xmpin.h"
@ -27,7 +26,7 @@
/* XMPlay extension list, only needed to associate extensions in Windows */
/* todo: as of v3.8.2.17, any more than ~1000 will crash XMplay's file list screen (but not using the non-native Winamp plugin...) */
#define EXTENSION_LIST_SIZE 1000 /*VGM_EXTENSION_LIST_CHAR_SIZE * 2*/
#define EXTENSION_LIST_SIZE 1000 /* (0x2000 * 2) */
#define XMPLAY_MAX_PATH 32768
/* XMPlay function library */
@ -205,13 +204,12 @@ static int add_extension(int length, char * dst, const char * ext) {
* Extensions must be in this format: "Description\0extension1/.../extensionN" */
static void build_extension_list() {
const char ** ext_list;
int ext_list_len;
size_t ext_list_len;
int i, written;
written = sprintf(working_extension_list, "%s%c", "vgmstream files",'\0');
ext_list = vgmstream_get_formats();
ext_list_len = vgmstream_get_formats_length();
ext_list = vgmstream_get_formats(&ext_list_len);
for (i=0; i < ext_list_len; i++) {
written += add_extension(EXTENSION_LIST_SIZE-written, working_extension_list + written, ext_list[i]);