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 ## Development
### Structure ### 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 ./ docs, scripts
@ -162,11 +164,17 @@ Very simplified it goes like this:
### Adding new formats ### Adding new formats
For new simple formats, assuming existing layout/coding: 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/(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*: register parser's init - *src/meta/meta.h*: define parser's init
- *src/vgmstream.h*: register new meta - *src/vgmstream.h*: define meta description in the meta_t list
- *src/vgmstream.c*: add parser init to the init list - *src/vgmstream.c*: add parser init to the init list
- *src/formats.c*: add new extension to the format list, add meta description - *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) - *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 - *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* - 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" { extern "C" {
#include "../src/formats.h"
#include "../src/vgmstream.h" #include "../src/vgmstream.h"
} }
#include "plugin.h" #include "plugin.h"
@ -95,8 +94,8 @@ bool VgmstreamPlugin::is_our_file(const char *filename, VFSFile &file) {
else else
ext = ext+1; /* skip the dot */ ext = ext+1; /* skip the dot */
const char ** ext_list = vgmstream_get_formats(); size_t ext_list_len = 0;
int ext_list_len = vgmstream_get_formats_length(); const char ** ext_list = vgmstream_get_formats(&ext_list_len);
for (int i=0; i < ext_list_len; i++) { for (int i=0; i < ext_list_len; i++) {
if (!strcasecmp(ext, ext_list[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("KRAW", kraw);
VGMSTREAM_DECLARE_FILE_TYPE("LAAC", laac); VGMSTREAM_DECLARE_FILE_TYPE("LAAC", laac);
VGMSTREAM_DECLARE_FILE_TYPE("LAC3", lac3);
VGMSTREAM_DECLARE_FILE_TYPE("LEG", leg); VGMSTREAM_DECLARE_FILE_TYPE("LEG", leg);
VGMSTREAM_DECLARE_FILE_TYPE("LMP4", lmp4); VGMSTREAM_DECLARE_FILE_TYPE("LMP4", lmp4);
VGMSTREAM_DECLARE_FILE_TYPE("LOGG", logg); 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("SPSD", spsd);
VGMSTREAM_DECLARE_FILE_TYPE("SPW", spw); VGMSTREAM_DECLARE_FILE_TYPE("SPW", spw);
VGMSTREAM_DECLARE_FILE_TYPE("SS2", ss2); 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("SSM", ssm);
VGMSTREAM_DECLARE_FILE_TYPE("SSS", sss); VGMSTREAM_DECLARE_FILE_TYPE("SSS", sss);
VGMSTREAM_DECLARE_FILE_TYPE("STER", ster); VGMSTREAM_DECLARE_FILE_TYPE("STER", ster);

View File

@ -16,7 +16,6 @@
#include <shared.h> #include <shared.h>
extern "C" { extern "C" {
#include "../src/formats.h"
#include "../src/vgmstream.h" #include "../src/vgmstream.h"
} }
#include "foo_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) { bool input_vgmstream::decode_run(audio_chunk & p_chunk,abort_callback & p_abort) {
if (!decoding) return false; if (!decoding) return false;
if (!vgmstream) return false;
int max_buffer_samples = sizeof(sample_buffer)/sizeof(sample_buffer[0])/vgmstream->channels; 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; 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) if (decode_pos_samples+max_buffer_samples>stream_length_samples && !loop_okay)
samples_to_do=stream_length_samples-decode_pos_samples; samples_to_do=stream_length_samples-decode_pos_samples;
else else
samples_to_do=max_buffer_samples; samples_to_do=max_buffer_samples;
l = (samples_to_do*vgmstream->channels * sizeof(sample_buffer[0]));
if (samples_to_do /*< DECODE_SIZE*/ == 0) { if (samples_to_do /*< DECODE_SIZE*/ == 0) {
decoding = false; decoding = false;
return 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_samples+=samples_to_do;
decode_pos_ms=decode_pos_samples*1000LL/vgmstream->sample_rate; decode_pos_ms=decode_pos_samples*1000LL/vgmstream->sample_rate;
return samples_to_do==max_buffer_samples; return samples_to_do==max_buffer_samples;
} }
return false;
} }
void input_vgmstream::decode_seek(double p_seconds,abort_callback & p_abort) { 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_content_type(const char * p_content_type) {return false;}
bool input_vgmstream::g_is_our_path(const char * p_path,const char * p_extension) { bool input_vgmstream::g_is_our_path(const char * p_path,const char * p_extension) {
const char ** ext_list; const char ** ext_list;
int ext_list_len; size_t ext_list_len;
int i; int i;
ext_list = vgmstream_get_formats(); ext_list = vgmstream_get_formats(&ext_list_len);
ext_list_len = vgmstream_get_formats_length();
for (i=0; i < ext_list_len; i++) { for (i=0; i < ext_list_len; i++) {
if (!stricmp_utf8(p_extension, ext_list[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(extension) ...
//#define VGM_REGISTER_TYPE_COMMON(extension) ... /* for common extensions like aiff */ //#define VGM_REGISTER_TYPE_COMMON(extension) ... /* for common extensions like aiff */
@ -154,6 +154,7 @@ static const char* extension_list[] = {
"kraw", "kraw",
"laac", //fake extension, for AAC (tri-Ace/FFmpeg) "laac", //fake extension, for AAC (tri-Ace/FFmpeg)
"lac3", //fake extension, for AC3
"leg", "leg",
"lmp4", //fake extension, for MP4s "lmp4", //fake extension, for MP4s
"logg", //fake extension, for OGGs "logg", //fake extension, for OGGs
@ -276,8 +277,6 @@ static const char* extension_list[] = {
"spsd", "spsd",
"spw", "spw",
"ss2", "ss2",
"ss3",
"ss7",
"ssm", "ssm",
"sss", "sss",
"ster", "ster",
@ -374,22 +373,11 @@ static const char* extension_list[] = {
//, NULL //end mark //, NULL //end mark
}; };
/** const char ** vgmstream_get_formats(size_t * size) {
* List of supported formats. *size = sizeof(extension_list) / sizeof(char*);
*
* For plugins that need to know (test.exe doesn't use it)
*/
const char ** vgmstream_get_formats() {
return extension_list; return extension_list;
} }
/**
* Number of elements in the list.
*/
int vgmstream_get_formats_length() {
return sizeof(extension_list) / sizeof(char*);
}
/* internal description info */ /* 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" Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
> >
<File
RelativePath=".\formats.h"
>
</File>
<File <File
RelativePath=".\streamfile.h" RelativePath=".\streamfile.h"
> >
@ -662,6 +658,10 @@
RelativePath=".\meta\pc_adp.c" RelativePath=".\meta\pc_adp.c"
> >
</File> </File>
<File
RelativePath=".\meta\pc_adp_otns.c"
>
</File>
<File <File
RelativePath=".\meta\pc_al2.c" RelativePath=".\meta\pc_al2.c"
> >
@ -1122,10 +1122,6 @@
RelativePath=".\meta\sqex_scd.c" RelativePath=".\meta\sqex_scd.c"
> >
</File> </File>
<File
RelativePath=".\meta\ss_stream.c"
>
</File>
<File <File
RelativePath=".\meta\stm.c" RelativePath=".\meta\stm.c"
> >

View File

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

View File

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

View File

@ -3,166 +3,166 @@
/* BCSTM - Nintendo 3DS format */ /* BCSTM - Nintendo 3DS format */
VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
coding_t coding_type; coding_t coding_type;
off_t info_offset = 0, seek_offset = 0, data_offset = 0; off_t info_offset = 0, seek_offset = 0, data_offset = 0;
uint16_t temp_id; uint16_t temp_id;
int codec_number; int codec_number;
int channel_count, loop_flag; int channel_count, loop_flag;
int i, ima = 0; int i, ima = 0;
off_t start_offset; off_t start_offset;
int section_count; int section_count;
/* check extension, case insensitive */ /* check extension, case insensitive */
if ( !check_extensions(streamFile,"bcstm") ) if ( !check_extensions(streamFile,"bcstm") )
goto fail; goto fail;
/* check header */ /* check header */
if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */ if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */
goto fail; 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 (info_offset == 0) goto fail;
if ((uint32_t)read_32bitBE(info_offset, streamFile) != 0x494E464F) /* "INFO" */ if ((uint32_t)read_32bitBE(info_offset, streamFile) != 0x494E464F) /* "INFO" */
goto fail; 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) { /* check type details */
case 0: codec_number = read_8bit(info_offset + 0x20, streamFile);
coding_type = coding_PCM8; loop_flag = read_8bit(info_offset + 0x21, streamFile);
break; channel_count = read_8bit(info_offset + 0x22, streamFile);
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;
}
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 */ if (channel_count < 1) goto fail;
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* build the VGMSTREAM */
vgmstream->num_samples = read_32bitLE(info_offset + 0x2c, streamFile); vgmstream = allocate_vgmstream(channel_count, loop_flag);
vgmstream->sample_rate = read_32bitLE(info_offset + 0x24, streamFile); if (!vgmstream) goto fail;
/* 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; /* fill in the vital statistics */
if (channel_count == 1) vgmstream->num_samples = read_32bitLE(info_offset + 0x2c, streamFile);
vgmstream->layout_type = layout_none; vgmstream->sample_rate = read_32bitLE(info_offset + 0x24, streamFile);
else /* 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
if (ima) {
vgmstream->layout_type = layout_interleave; vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile);
else if (vgmstream->loop_start_sample > 10000)
vgmstream->layout_type = layout_interleave_shortblock; {
} vgmstream->loop_start_sample -= 5000;
vgmstream->meta_type = meta_CSTM; vgmstream->loop_end_sample = vgmstream->num_samples - 5000;
}
if (ima) else
vgmstream->interleave_block_size = 0x200; vgmstream->loop_end_sample = vgmstream->num_samples;
else { }
vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile); else
vgmstream->interleave_smallblock_size = read_32bitLE(info_offset + 0x44, streamFile); {
} vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
if (vgmstream->coding_type == coding_NGC_DSP) { }
off_t coef_offset;
off_t tempoffset = info_offset; vgmstream->coding_type = coding_type;
int foundcoef = 0; if (channel_count == 1)
int i, j; vgmstream->layout_type = layout_none;
int coef_spacing = 0x2E; else
{
while (!(foundcoef)) if (ima)
{ vgmstream->layout_type = layout_interleave;
if ((uint32_t)read_32bitLE(tempoffset, streamFile) == 0x00004102) else
{ vgmstream->layout_type = layout_interleave_shortblock;
coef_offset = read_32bitLE(tempoffset + 4, streamFile) + tempoffset + (channel_count * 8) - 4 - info_offset; }
foundcoef++; vgmstream->meta_type = meta_CSTM;
break;
} if (ima)
tempoffset++; 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 */ /* open the file for reading by each channel */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) 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 */ /* 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, 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 /* 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. */ * 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 "../layout/layout.h"
#include "../util.h" #include "../util.h"
/* known GENH types */ /* known GENH types */
typedef enum { typedef enum {
PSX = 0, /* PSX ADPCM */ PSX = 0, /* PSX ADPCM */
@ -28,26 +30,45 @@ typedef enum {
XMA1 = 20, /* raw XMA1 */ XMA1 = 20, /* raw XMA1 */
XMA2 = 21, /* raw XMA2 */ XMA2 = 21, /* raw XMA2 */
FFMPEG = 22, /* any headered FFmpeg format */ FFMPEG = 22, /* any headered FFmpeg format */
AC3 = 23, /* AC3/SPDIF */
} genh_type; } 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 */ /* GENH is an artificial "generic" header for headerless streams */
VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
genh_header genh = {0};
int channel_count, loop_flag, sample_rate, interleave; coding_t coding;
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;
int i, j; int i, j;
coding_t coding;
genh_type type;
/* check extension, case insensitive */ /* check extension, case insensitive */
if (!check_extensions(streamFile,"genh")) goto fail; if (!check_extensions(streamFile,"genh")) goto fail;
@ -55,12 +76,13 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
/* check header magic */ /* check header magic */
if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail; if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail;
channel_count = read_32bitLE(0x4,streamFile); /* process the header */
if (channel_count < 1) goto fail; if (!parse_genh(streamFile, &genh))
goto fail;
type = read_32bitLE(0x18,streamFile);
/* type to coding conversion */ /* type to coding conversion */
switch (type) { switch (genh.codec) {
case PSX: coding = coding_PSX; break; case PSX: coding = coding_PSX; break;
case XBOX: coding = coding_XBOX; break; case XBOX: coding = coding_XBOX; break;
case NGC_DTK: coding = coding_NGC_DTK; break; case NGC_DTK: coding = coding_NGC_DTK; break;
@ -86,68 +108,27 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
case ATRAC3PLUS: case ATRAC3PLUS:
case XMA1: case XMA1:
case XMA2: case XMA2:
case AC3:
case FFMPEG: coding = coding_FFmpeg; break; case FFMPEG: coding = coding_FFmpeg; break;
#endif #endif
default: default:
goto fail; 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 */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(genh.channels,genh.loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate; vgmstream->sample_rate = genh.sample_rate;
vgmstream->num_samples = num_samples; vgmstream->num_samples = genh.num_samples;
vgmstream->loop_start_sample = loop_start; vgmstream->loop_start_sample = genh.loop_start_sample;
vgmstream->loop_end_sample = loop_end; vgmstream->loop_end_sample = genh.loop_end_sample;
/* codec specific */ /* codec specific */
switch (coding) { switch (coding) {
case coding_PCM8_U_int: case coding_PCM8_U_int:
vgmstream->layout_type=layout_none; vgmstream->layout_type = layout_none;
break; break;
case coding_PCM16LE: case coding_PCM16LE:
case coding_PCM16BE: case coding_PCM16BE:
@ -160,14 +141,14 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
case coding_IMA: case coding_IMA:
case coding_AICA: case coding_AICA:
case coding_APPLE_IMA4: case coding_APPLE_IMA4:
vgmstream->interleave_block_size = interleave; vgmstream->interleave_block_size = genh.interleave;
if (channel_count > 1) if (vgmstream->channels > 1)
{ {
if (coding == coding_SDX2) { if (coding == coding_SDX2) {
coding = coding_SDX2_int; 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; vgmstream->layout_type = layout_none;
} }
else { else {
@ -179,7 +160,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
} }
/* to avoid endless loops */ /* to avoid endless loops */
if (!interleave && ( if (!genh.interleave && (
coding == coding_PSX || coding == coding_PSX ||
coding == coding_PSX_badflags || coding == coding_PSX_badflags ||
coding == coding_IMA_int || coding == coding_IMA_int ||
@ -194,64 +175,61 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
/* setup adpcm */ /* setup adpcm */
if (coding == coding_AICA) { if (coding == coding_AICA) {
int i; int i;
for (i=0;i<channel_count;i++) { for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].adpcm_step_index = 0x7f; vgmstream->ch[i].adpcm_step_index = 0x7f;
} }
} }
break; break;
case coding_MS_IMA: 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; vgmstream->layout_type = layout_none;
break; break;
case coding_MSADPCM: case coding_MSADPCM:
if (channel_count > 2) goto fail; if (vgmstream->channels > 2) goto fail;
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; vgmstream->layout_type = layout_none;
break; break;
case coding_XBOX: case coding_XBOX:
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
break; break;
case coding_NGC_DTK: case coding_NGC_DTK:
if (channel_count != 2) goto fail; if (vgmstream->channels != 2) goto fail;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
break; break;
case coding_NGC_DSP: case coding_NGC_DSP:
if (dsp_interleave_type == 0) { if (genh.coef_interleave_type == 0) {
if (!interleave) goto fail; if (!genh.interleave) goto fail;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave; vgmstream->interleave_block_size = genh.interleave;
} else if (dsp_interleave_type == 1) { } else if (genh.coef_interleave_type == 1) {
if (!interleave) goto fail; if (!genh.interleave) goto fail;
vgmstream->layout_type = layout_interleave_byte; vgmstream->layout_type = layout_interleave_byte;
vgmstream->interleave_block_size = interleave; vgmstream->interleave_block_size = genh.interleave;
} else if (dsp_interleave_type == 2) { } else if (genh.coef_interleave_type == 2) {
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
} }// else {
// goto fail;
//}
/* get coefs */ /* get coefs */
for (i=0;i<channel_count;i++) { for (i=0;i<vgmstream->channels;i++) {
int16_t (*read_16bit)(off_t , STREAMFILE*); int16_t (*read_16bit)(off_t , STREAMFILE*) = genh.coef_big_endian ? read_16bitBE : read_16bitLE;
/* bit 1 - little endian coefs */
if ((coef_type & 2) == 0) {
read_16bit = read_16bitBE;
} else {
read_16bit = read_16bitLE;
}
/* bit 0 - split coefs (2 arrays) */ /* normal/split coefs */
if ((coef_type & 1) == 0) { if ((genh.coef_type & 1) == 0) { /* bit 0 - split coefs (2 arrays) */
for (j=0;j<16;j++) { 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++) { 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]=read_16bit(genh.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+1]=read_16bit(genh.coef_splitted[i]+j*2,streamFile);
} }
} }
} }
@ -260,7 +238,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
#ifdef VGM_USE_MPEG #ifdef VGM_USE_MPEG
case coding_MPEG_layer3: case coding_MPEG_layer3:
vgmstream->layout_type = layout_none; 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; if (!vgmstream->codec_data) goto fail;
break; break;
@ -269,50 +247,53 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
case coding_FFmpeg: { case coding_FFmpeg: {
ffmpeg_codec_data *ffmpeg_data = NULL; ffmpeg_codec_data *ffmpeg_data = NULL;
if (type == FFMPEG) { if (genh.codec == FFMPEG || genh.codec == AC3) {
/* default FFmpeg */ /* 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 ( !ffmpeg_data ) goto fail;
//if (vgmstream->num_samples == 0)
// vgmstream->num_samples = ffmpeg_data->totalSamples; /* sometimes works */
} }
else { else {
/* fake header FFmpeg */ /* fake header FFmpeg */
uint8_t buf[200]; uint8_t buf[200];
int32_t bytes; int32_t bytes;
if (type == ATRAC3) { if (genh.codec == ATRAC3) {
int block_size = interleave; int block_size = genh.interleave;
int joint_stereo; int joint_stereo;
switch(atrac3_mode) { switch(genh.codec_mode) {
case 0: joint_stereo = vgmstream->channels > 1 && interleave/vgmstream->channels==0x60 ? 1 : 0; break; /* autodetect */ 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 1: joint_stereo = 1; break; /* force joint stereo */
case 2: joint_stereo = 0; break; /* force stereo */ case 2: joint_stereo = 0; break; /* force stereo */
default: goto fail; 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) { else if (genh.codec == ATRAC3PLUS) {
int block_size = interleave; 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) { else if (genh.codec == XMA1) {
int xma_stream_mode = xma_mode == 1 ? 1 : 0; 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) { else if (genh.codec == XMA2) {
int block_size = interleave ? interleave : 2048; int block_size = genh.interleave ? genh.interleave : 2048;
int block_count = datasize / block_size; 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 { else {
goto fail; goto fail;
} }
if (bytes <= 0) 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; if ( !ffmpeg_data ) goto fail;
} }
@ -320,8 +301,8 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
/* force encoder delay */ /* force encoder delay */
if (skip_samples_mode && skip_samples >= 0) { if (genh.skip_samples_mode && genh.skip_samples >= 0) {
ffmpeg_set_skip_samples(ffmpeg_data, skip_samples); ffmpeg_set_skip_samples(ffmpeg_data, genh.skip_samples);
} }
break; break;
@ -335,7 +316,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_GENH; vgmstream->meta_type = meta_GENH;
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) ) if ( !vgmstream_open_stream(vgmstream,streamFile,genh.start_offset) )
goto fail; goto fail;
return vgmstream; return vgmstream;
@ -344,3 +325,60 @@ fail:
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; 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_ps2_xa2(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ss_stream(STREAMFILE * streamFile);
//VGMSTREAM * init_vgmstream_idsp(STREAMFILE * streamFile); //VGMSTREAM * init_vgmstream_idsp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_idsp2(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_ios_psnd(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_pc_adp_bos(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_pc_adp_otns(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_eb_sfx(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; if (strcasecmp("strm",filename_extension(filename))) goto fail;
/* check header */ /* 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; 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" #include "../util.h"
/* .dsp found in: /* .dsp found in:
Hikaru No Go 3 (NGC) Hikaru No Go 3 (NGC)
Yu-Gi-Oh! The Falsebound Kingdom (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 * init_vgmstream_dsp_ygo(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
int loop_flag; int loop_flag;
int channel_count; int channel_count;
off_t start_offset; off_t start_offset;
int i; int i;
@ -24,29 +24,29 @@ VGMSTREAM * init_vgmstream_dsp_ygo(STREAMFILE *streamFile) {
if ((read_32bitBE(0x0,streamFile)+0xE0) != (get_streamfile_size(streamFile))) if ((read_32bitBE(0x0,streamFile)+0xE0) != (get_streamfile_size(streamFile)))
goto fail; goto fail;
loop_flag = (uint16_t)(read_16bitBE(0x2C,streamFile) != 0x0); loop_flag = (uint16_t)(read_16bitBE(0x2C,streamFile) != 0x0);
channel_count = 1; channel_count = 1;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
start_offset = 0xE0; start_offset = 0xE0;
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x28,streamFile); vgmstream->sample_rate = read_32bitBE(0x28,streamFile);
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x20,streamFile); vgmstream->num_samples = read_32bitBE(0x20,streamFile);
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_DSP_YGO; vgmstream->meta_type = meta_DSP_YGO;
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample = (read_32bitBE(0x30,streamFile)*14/16); vgmstream->loop_start_sample = (read_32bitBE(0x30,streamFile)*14/16);
vgmstream->loop_end_sample = (read_32bitBE(0x34,streamFile)*14/16); vgmstream->loop_end_sample = (read_32bitBE(0x34,streamFile)*14/16);
} }
// read coef stuff // read coef stuff
{ {
for (i=0;i<16;i++) { for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x3C+i*2,streamFile); 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 * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamFileDSP = NULL; STREAMFILE * streamFileDSP = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
char filenameDSP[PATH_LIMIT]; char filenameDSP[PATH_LIMIT];
int i; int i;
int channel_count; int channel_count;
int loop_flag; int loop_flag;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("sck",filename_extension(filename))) goto fail; if (strcasecmp("sck",filename_extension(filename))) goto fail;
strcpy(filenameDSP,filename); strcpy(filenameDSP,filename);
strcpy(filenameDSP+strlen(filenameDSP)-3,"dsp"); 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) if (read_32bitBE(0x5C,streamFile) != 0x60A94000)
goto fail; goto fail;
if (!streamFile) goto fail; if (!streamFile) goto fail;
channel_count = 2; channel_count = 2;
loop_flag = 0; loop_flag = 0;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x18,streamFile); vgmstream->sample_rate = read_32bitBE(0x18,streamFile);
vgmstream->num_samples=read_32bitBE(0x14,streamFile)/8/channel_count*14; vgmstream->num_samples=read_32bitBE(0x14,streamFile)/8/channel_count*14;
vgmstream->coding_type = coding_NGC_DSP; 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;
}
if (channel_count == 1) { if(loop_flag) {
vgmstream->layout_type = layout_none; vgmstream->loop_start_sample = 0;
} else if (channel_count == 2) { vgmstream->loop_end_sample = read_32bitBE(0x10,streamFile)/8/channel_count*14;
vgmstream->layout_type = layout_interleave; }
vgmstream->interleave_block_size=read_32bitBE(0xC,streamFile);
} 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; vgmstream->meta_type = meta_NGC_SCK_DSP;
/* open the file for reading */ /* open the file for reading */
{ {
for (i=0;i<channel_count;i++) { 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].streamfile = streamFile->open(streamFileDSP,filenameDSP,0x8000);
vgmstream->ch[i].offset = 0; 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; int i;
for (i=0;i<16;i++) { for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x2C+i*2,streamFile); 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; return vgmstream;
/* clean up anything we may have opened */ /* clean up anything we may have opened */

View File

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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@ VGMSTREAM * init_vgmstream_ps2_ild(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
int loop_flag=0; int loop_flag=0;
int channel_count; int channel_count;
off_t start_offset; off_t start_offset;
int i; int i;
@ -19,33 +19,33 @@ VGMSTREAM * init_vgmstream_ps2_ild(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x494C4400) if (read_32bitBE(0x00,streamFile) != 0x494C4400)
goto fail; goto fail;
/* check loop */ /* check loop */
loop_flag = (read_32bitLE(0x2C,streamFile)!=0); loop_flag = (read_32bitLE(0x2C,streamFile)!=0);
channel_count=read_32bitLE(0x04,streamFile); channel_count=read_32bitLE(0x04,streamFile);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
vgmstream->channels = read_32bitLE(0x04,streamFile); vgmstream->channels = read_32bitLE(0x04,streamFile);
vgmstream->sample_rate = read_32bitLE(0x28,streamFile); vgmstream->sample_rate = read_32bitLE(0x28,streamFile);
/* Check for Compression Scheme */ /* Check for Compression Scheme */
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitLE(0x0C,streamFile)/16*28/vgmstream->channels; vgmstream->num_samples = read_32bitLE(0x0C,streamFile)/16*28/vgmstream->channels;
/* Get loop point values */ /* Get loop point values */
if(vgmstream->loop_flag) { if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x2C,streamFile)/16*28; vgmstream->loop_start_sample = read_32bitLE(0x2C,streamFile)/16*28;
vgmstream->loop_end_sample = read_32bitLE(0x30,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->layout_type = layout_interleave;
vgmstream->meta_type = meta_PS2_ILD; 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 */ /* 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]; char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
int loop_flag = 0; int loop_flag = 0;
int channel_count; int channel_count;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
@ -16,31 +16,31 @@ VGMSTREAM * init_vgmstream_ps2_mcg(STREAMFILE *streamFile) {
/* check header */ /* check header */
if (!((read_32bitBE(0x00,streamFile) == 0x4D434700) && if (!((read_32bitBE(0x00,streamFile) == 0x4D434700) &&
(read_32bitBE(0x20,streamFile) == 0x56414770) && (read_32bitBE(0x20,streamFile) == 0x56414770) &&
(read_32bitBE(0x50,streamFile) == 0x56414770))) (read_32bitBE(0x50,streamFile) == 0x56414770)))
goto fail; goto fail;
loop_flag = (read_32bitLE(0x34,streamFile)!=0); loop_flag = (read_32bitLE(0x34,streamFile)!=0);
channel_count = 2; channel_count = 2;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
start_offset = 0x80; start_offset = 0x80;
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x30,streamFile); vgmstream->sample_rate = read_32bitBE(0x30,streamFile);
vgmstream->coding_type = coding_PSX; 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->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile); vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile);
vgmstream->meta_type = meta_PS2_MCG; vgmstream->meta_type = meta_PS2_MCG;
if (vgmstream->loop_flag) if (vgmstream->loop_flag)
{ {
vgmstream->loop_start_sample = read_32bitLE(0x34,streamFile); vgmstream->loop_start_sample = read_32bitLE(0x34,streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
} }
/* open the file for reading */ /* open the file for reading */
{ {

View File

@ -6,9 +6,9 @@ VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
int mib_blocks; int mib_blocks;
int loop_flag = 0; int loop_flag = 0;
int channel_count; int channel_count;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
@ -17,18 +17,18 @@ VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE *streamFile) {
/* check header */ /* check header */
if (read_32bitBE(0x00,streamFile) != 0x40000000) if (read_32bitBE(0x00,streamFile) != 0x40000000)
goto fail; goto fail;
mib_blocks = read_32bitLE(0x14,streamFile); mib_blocks = read_32bitLE(0x14,streamFile);
loop_flag = 0; loop_flag = 0;
channel_count = read_32bitLE(0x08,streamFile); channel_count = read_32bitLE(0x08,streamFile);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
start_offset = 0x40; start_offset = 0x40;
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); vgmstream->sample_rate = read_32bitLE(0x0C,streamFile);
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = ((read_32bitLE(0x10,streamFile))*mib_blocks)*28/16; 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" */ if (read_32bitBE(0x00,streamFile) != 0x4E505346) /* "NPSF" */
goto fail; goto fail;
loop_flag = (read_32bitLE(0x14,streamFile) != 0xFFFFFFFF); loop_flag = (read_32bitLE(0x14,streamFile) != 0xFFFFFFFF);
channel_count = read_32bitLE(0x0C,streamFile); channel_count = read_32bitLE(0x0C,streamFile);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->channels = read_32bitLE(0x0C,streamFile); vgmstream->channels = read_32bitLE(0x0C,streamFile);
vgmstream->sample_rate = read_32bitLE(0x18,streamFile); vgmstream->sample_rate = read_32bitLE(0x18,streamFile);
vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x08,streamFile), 1); /* single channel data */ vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x08,streamFile), 1); /* single channel data */
if(vgmstream->loop_flag) { if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile); vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile);
vgmstream->loop_end_sample = ps_bytes_to_samples(read_32bitLE(0x08,streamFile), 1); vgmstream->loop_end_sample = ps_bytes_to_samples(read_32bitLE(0x08,streamFile), 1);
} }
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;

View File

@ -186,30 +186,30 @@ VGMSTREAM * init_vgmstream_ps2_rxw(STREAMFILE *streamFile) {
/* check RXWS/FORM Header */ /* check RXWS/FORM Header */
if (!((read_32bitBE(0x00,streamFile) == 0x52585753) && if (!((read_32bitBE(0x00,streamFile) == 0x52585753) &&
(read_32bitBE(0x10,streamFile) == 0x464F524D))) (read_32bitBE(0x10,streamFile) == 0x464F524D)))
goto fail; goto fail;
loop_flag = (read_32bitLE(0x3C,streamFile)!=0xFFFFFFFF); loop_flag = (read_32bitLE(0x3C,streamFile)!=0xFFFFFFFF);
channel_count=2; /* Always stereo files */ channel_count=2; /* Always stereo files */
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x2E,streamFile); vgmstream->sample_rate = read_32bitLE(0x2E,streamFile);
vgmstream->num_samples = (read_32bitLE(0x38,streamFile)*28/16)/2; vgmstream->num_samples = (read_32bitLE(0x38,streamFile)*28/16)/2;
/* Get loop point values */ /* Get loop point values */
if(vgmstream->loop_flag) { if(vgmstream->loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x3C,streamFile)/16*14; vgmstream->loop_start_sample = read_32bitLE(0x3C,streamFile)/16*14;
vgmstream->loop_end_sample = read_32bitLE(0x38,streamFile)/16*14; vgmstream->loop_end_sample = read_32bitLE(0x38,streamFile)/16*14;
} }
vgmstream->interleave_block_size = read_32bitLE(0x1c,streamFile)+0x10; vgmstream->interleave_block_size = read_32bitLE(0x1c,streamFile)+0x10;
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_PS2_RXWS; vgmstream->meta_type = meta_PS2_RXWS;
start_offset = 0x40; start_offset = 0x40;
/* open the file for reading */ /* open the file for reading */
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) 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]; char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
int loop_flag = 0; int loop_flag = 0;
int channel_count; int channel_count;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
@ -18,28 +18,28 @@ VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x544B3553) if (read_32bitBE(0x00,streamFile) != 0x544B3553)
goto fail; goto fail;
loop_flag = (read_32bitLE(0x0C,streamFile)!=0); loop_flag = (read_32bitLE(0x0C,streamFile)!=0);
channel_count = 2; channel_count = 2;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
start_offset = 0x800; start_offset = 0x800;
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = 48000; vgmstream->sample_rate = 48000;
vgmstream->coding_type = coding_PSX_badflags; 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->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10; vgmstream->interleave_block_size = 0x10;
vgmstream->meta_type = meta_PS2_TK5; vgmstream->meta_type = meta_PS2_TK5;
if (vgmstream->loop_flag) if (vgmstream->loop_flag)
{ {
vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28; vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28;
vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28); vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28);
} }
/* open the file for reading */ /* open the file for reading */
{ {
@ -71,7 +71,7 @@ VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE *streamFile) {
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
int loop_flag = 0; int loop_flag = 0;
int channel_count; int channel_count;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
@ -81,28 +81,28 @@ VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x544B3553) if (read_32bitBE(0x00,streamFile) != 0x544B3553)
goto fail; goto fail;
loop_flag = (read_32bitLE(0x0C,streamFile)!=0); loop_flag = (read_32bitLE(0x0C,streamFile)!=0);
channel_count = 2; channel_count = 2;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
start_offset = 0x800; start_offset = 0x800;
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = 44100; vgmstream->sample_rate = 44100;
vgmstream->coding_type = coding_PSX_badflags; 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->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10; vgmstream->interleave_block_size = 0x10;
vgmstream->meta_type = meta_PS2_TK1; vgmstream->meta_type = meta_PS2_TK1;
if (vgmstream->loop_flag) if (vgmstream->loop_flag)
{ {
vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28; vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28;
vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28); vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28);
} }
/* open the file for reading */ /* 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 /* channels are usually at 0x1e, but not in Ukiyo no Roushi which has some kind
* of loop-like values instead (who designs this crap?) */ * of loop-like values instead (who designs this crap?) */
if (read_32bitBE(0x18,streamFile) != 0 || read_32bitBE(0x1c,streamFile) > 0x20) { if (read_32bitBE(0x18,streamFile) == 0
channel_count = 1; && (read_32bitBE(0x1c,streamFile) & 0xFFFF00FF) == 0
} else { && read_8bit(0x1e,streamFile) < 16) {
channel_count = read_8bit(0x1e,streamFile); channel_count = read_8bit(0x1e,streamFile);
if (channel_count == 0) if (channel_count == 0)
channel_count = 1; /* ex. early Vita vag (Lumines) */ channel_count = 1; /* ex. early Vita vag (Lumines) */
} }
else {
channel_count = 1;
}
} }
else { else {
loop_flag = vag_find_loop_offsets(streamFile, 0x30, &loopStart, &loopEnd); 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; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
size_t fileLength; size_t fileLength;
off_t readOffset = 0; off_t readOffset = 0;
off_t start_offset; off_t start_offset;
off_t loop_start_offset = 0; off_t loop_start_offset = 0;
off_t loop_end_offset = 0; off_t loop_end_offset = 0;
uint8_t testBuffer[0x10]; uint8_t testBuffer[0x10];
int loop_flag = 0; int loop_flag = 0;
int channel_count; int channel_count;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
@ -27,71 +27,71 @@ VGMSTREAM * init_vgmstream_ps2_vgs(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x56475300) if (read_32bitBE(0x00,streamFile) != 0x56475300)
goto fail; goto fail;
// get file length // get file length
fileLength = get_streamfile_size(streamFile); fileLength = get_streamfile_size(streamFile);
// Find loop start // Find loop start
do { do {
readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile);
// Loop Start ...
if(testBuffer[0x01] == 0x06)
{
loop_start_offset = readOffset - 0x10;
break;
}
} 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 } while (streamFile->get_offset(streamFile)<((int32_t)fileLength));
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 // start at last line of file and move up
if (loop_start_offset > 0) readOffset = (int32_t)fileLength - 0x10;
{
loop_flag = 1; // Find loop end
do {
// if we have a start loop, use EOF if end loop is not found readOffset -= (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile);
if (loop_end_offset == 0)
{ // Loop End ...
loop_end_offset = (int32_t)fileLength - 0x10; if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77))
} {
} loop_end_offset = readOffset + 0x20;
else break;
{ }
loop_flag = 0; } 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; channel_count = 2;
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
start_offset = 0x30; start_offset = 0x30;
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x10,streamFile); vgmstream->sample_rate = read_32bitBE(0x10,streamFile);
vgmstream->coding_type = coding_PSX; 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) if (loop_flag)
{ {
vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28; vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28;
vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28; vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28;
} }
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x04,streamFile)*0x1000; 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]; char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
int loop_flag = 0; int loop_flag = 0;
int channel_count; int channel_count;
int header_size; int header_size;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
@ -19,27 +19,27 @@ VGMSTREAM * init_vgmstream_ps2_vms(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) != 0x564D5320) if (read_32bitBE(0x00,streamFile) != 0x564D5320)
goto fail; goto fail;
loop_flag = 1; loop_flag = 1;
channel_count = read_8bit(0x08,streamFile); channel_count = read_8bit(0x08,streamFile);
header_size = read_32bitLE(0x1C, streamFile); header_size = read_32bitLE(0x1C, streamFile);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
start_offset = header_size; start_offset = header_size;
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x14,streamFile); vgmstream->sample_rate = read_32bitLE(0x14,streamFile);
vgmstream->coding_type = coding_PSX; 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->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile); vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile);
vgmstream->meta_type = meta_PS2_VMS; vgmstream->meta_type = meta_PS2_VMS;
vgmstream->loop_start_sample = 0; vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (get_streamfile_size(streamFile))/16/ channel_count * 28; vgmstream->loop_end_sample = (get_streamfile_size(streamFile))/16/ channel_count * 28;
/* open the file for reading */ /* open the file for reading */
{ {

View File

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

View File

@ -2,19 +2,19 @@
#include "../util.h" #include "../util.h"
/* IVAG /* 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 * init_vgmstream_ps3_ivag(STREAMFILE *streamFile)
{ {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
off_t start_offset; off_t start_offset;
int loop_flag = 0; int loop_flag = 0;
int channel_count; int channel_count;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); 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" if (read_32bitBE(0x00,streamFile) != 0x49564147) // "IVAG"
goto fail; goto fail;
// channel count // channel count
channel_count = read_32bitBE(0x08, streamFile); channel_count = read_32bitBE(0x08, streamFile);
// header size // header size
start_offset = 0x40 + (0x40 * channel_count); start_offset = 0x40 + (0x40 * channel_count);
// loop flag // loop flag
if ((read_32bitBE(0x14, streamFile) != 0 || if ((read_32bitBE(0x14, streamFile) != 0 ||
(read_32bitBE(0x18, streamFile) != 0))) (read_32bitBE(0x18, streamFile) != 0)))
{ {
loop_flag = 1; loop_flag = 1;
} }
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
vgmstream->channels = channel_count; vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x0C,streamFile); vgmstream->sample_rate = read_32bitBE(0x0C,streamFile);
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitBE(0x10,streamFile); vgmstream->num_samples = read_32bitBE(0x10,streamFile);
if (loop_flag) if (loop_flag)
{ {
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile); vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile);
} }
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x1C,streamFile); 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); file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail; 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].streamfile = file;
vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset + (vgmstream->interleave_block_size * i); vgmstream->ch[i].offset=start_offset + (vgmstream->interleave_block_size * i);
} }
} }
return vgmstream; return vgmstream;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,6 +34,8 @@ typedef struct {
size_t stream_id_offset; size_t stream_id_offset;
int has_short_channels; int has_short_channels;
int has_internal_names; int has_internal_names;
int has_extra_name_flag;
int has_rotating_ids;
/* derived */ /* derived */
size_t main_size; size_t main_size;
@ -73,8 +75,6 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
/* check extension (number represents the platform, see later) */ /* check extension (number represents the platform, see later) */
if ( !check_extensions(streamFile,"sb0,sb1,sb2,sb3,sb4,sb5,sb6,sb7") ) if ( !check_extensions(streamFile,"sb0,sb1,sb2,sb3,sb4,sb5,sb6,sb7") )
goto fail; 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 /* .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.main_size + sb.section1_size + sb.section2_size + sb.extra_size + sb.section3_size;
start_offset += sb.stream_offset; 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 */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(sb.channels,loop_flag); vgmstream = allocate_vgmstream(sb.channels,loop_flag);
@ -131,7 +131,7 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
switch(sb.codec) { switch(sb.codec) {
case UBI_ADPCM: { //todo move to its own decoder case UBI_ADPCM: {
vgmstream->coding_type = coding_UBI_IMA; vgmstream->coding_type = coding_UBI_IMA;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = ubi_ima_bytes_to_samples(sb.stream_size, sb.channels, streamData, start_offset); 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: case RAW_PCM:
vgmstream->coding_type = coding_PCM16LE; vgmstream->coding_type = coding_PCM16LE; /* always LE even on Wii */
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02; vgmstream->interleave_block_size = 0x02;
vgmstream->num_samples = pcm_bytes_to_samples(sb.stream_size, sb.channels, 16); 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; break;
case RAW_PSX: case RAW_PSX:
@ -183,7 +182,8 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = sb.stream_size / sb.channels; 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 if (sb.channels > 1) { VGM_LOG("UBI SB: >1 channel\n"); goto fail; } //todo
break; break;
@ -264,7 +264,7 @@ fail:
static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) { static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(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; int target_stream = streamFile->stream_index;
if (target_stream == 0) target_stream = 1; 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->section1_num = read_32bit(0x04, streamFile); /* group headers? */
sb->section2_num = read_32bit(0x08, streamFile); /* streams headers (internal or external) */ sb->section2_num = read_32bit(0x08, streamFile); /* streams headers (internal or external) */
sb->section3_num = read_32bit(0x0c, streamFile); /* internal streams table */ 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->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 */ 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) if (read_32bit(offset + 0x04, streamFile) != 0x01)
continue; 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) */ /* update streams (total_stream also doubles as current) */
sb->total_streams++; sb->total_streams++;
if (sb->total_streams != target_stream) if (sb->total_streams != target_stream)
continue; 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_id = read_32bit(offset + 0x00, streamFile); /* 16b+16b group+sound id */
sb->header_type = read_32bit(offset + 0x04, streamFile); 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) if (sb->num_samples_offset)
sb->stream_samples = read_32bit(offset + sb->num_samples_offset, streamFile); 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); 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) */ /* external stream name can be found in the header (first versions) or the extra table (later versions) */
if (sb->stream_name_offset) { 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 */ /* not always set and must be derived */
if (sb->external_flag_offset) { if (sb->external_flag_offset) {
sb->is_external = read_32bit(offset + sb->external_flag_offset, streamFile); 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) { } else if (sb->section3_num == 0) {
sb->is_external = 1; sb->is_external = 1;
} else { } else {
@ -361,7 +394,7 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
goto fail; 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); VGM_LOG("UBI SB: unexpected number of internal streams %i\n", sb->section3_num);
goto fail; goto fail;
} }
@ -392,6 +425,10 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
} }
break; break;
case 0x01: /* PCM (Wii, rarely used) */
sb->codec = RAW_PCM;
break;
case 0x03: /* Ubi ADPCM (main external stream codec, has subtypes) */ case 0x03: /* Ubi ADPCM (main external stream codec, has subtypes) */
sb->codec = UBI_ADPCM; sb->codec = UBI_ADPCM;
break; break;
@ -404,7 +441,6 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
sb->codec = FMT_AT3; sb->codec = FMT_AT3;
break; break;
case 0x01: /* PCM? (Wii, rarely used) */
default: default:
VGM_LOG("UBI SB: unknown stream_type %x\n", sb->stream_type); VGM_LOG("UBI SB: unknown stream_type %x\n", sb->stream_type);
goto fail; goto fail;
@ -413,12 +449,11 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile) {
/* uncommon but possible */ /* uncommon but possible */
//VGM_ASSERT(sb->is_external && sb->section3_num != 0, "UBI SS: mixed external and internal streams\n"); //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"); //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) */ /* 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++) { 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; 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->section2_entry_size = 0x78;
sb->external_flag_offset = 0x2c; sb->external_flag_offset = 0x2c;
sb->stream_id_offset = 0x34;//todo test sb->stream_id_offset = 0x34;
sb->num_samples_offset = 0x40; sb->num_samples_offset = 0x40;
sb->sample_rate_offset = 0x54; sb->sample_rate_offset = 0x54;
sb->channels_offset = 0x5c; sb->channels_offset = 0x5c;
sb->stream_type_offset = 0x60; sb->stream_type_offset = 0x60;
sb->extra_name_offset = 0x64; sb->extra_name_offset = 0x64;
sb->has_extra_name_flag = 1;
return 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->section1_entry_size = 0x48;
sb->section2_entry_size = 0x5c; sb->section2_entry_size = 0x5c;
sb->external_flag_offset = 0; /* no apparent flag */ sb->external_flag_offset = 0;
sb->channels_offset = 0x2c; sb->channels_offset = 0x2c;
sb->sample_rate_offset = 0x30; sb->sample_rate_offset = 0x30;
sb->num_samples_offset = 0x3c; sb->num_samples_offset = 0x3c;
sb->extra_name_offset = 0x4c; sb->extra_name_offset = 0x4c;
sb->stream_type_offset = 0x50; sb->stream_type_offset = 0x50;
sb->has_extra_name_flag = 1;
return 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->section1_entry_size = 0x48;
sb->section2_entry_size = 0x58; sb->section2_entry_size = 0x58;
sb->external_flag_offset = 0; /* no apparent flag */ sb->external_flag_offset = 0;
sb->num_samples_offset = 0x28; sb->num_samples_offset = 0x28;
sb->stream_id_offset = 0x34;//todo test sb->stream_id_offset = 0;
sb->sample_rate_offset = 0x3c; sb->sample_rate_offset = 0x3c;
sb->channels_offset = 0x44; sb->channels_offset = 0x44;
sb->stream_type_offset = 0x48; sb->stream_type_offset = 0x48;
sb->extra_name_offset = 0x4c; sb->extra_name_offset = 0x4c;
sb->has_internal_names = 1; sb->has_extra_name_flag = 1;
sb->has_rotating_ids = 1;
return 1; return 1;
} }
@ -677,18 +715,34 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile)
return 1; 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) */ /* Prince of Persia: Rival Swords (2007)(PSP) */
if (sb->version == 0x00180005 && is_sb5) { if (sb->version == 0x00180005 && is_sb5) {
sb->section1_entry_size = 0x48; sb->section1_entry_size = 0x48;
sb->section2_entry_size = 0x54; sb->section2_entry_size = 0x54;
sb->external_flag_offset = 0; /* no apparent flag */ sb->external_flag_offset = 0;
sb->channels_offset = 0x28; sb->channels_offset = 0x28;
sb->sample_rate_offset = 0x2c; sb->sample_rate_offset = 0x2c;
//sb->num_samples_offset = 0x34 or 0x3c /* varies */ //sb->num_samples_offset = 0x34 or 0x3c /* varies */
sb->extra_name_offset = 0x44; sb->extra_name_offset = 0x44;
sb->stream_type_offset = 0x48; sb->stream_type_offset = 0x48;
sb->has_extra_name_flag = 1;
return 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->external_flag_offset = 0x28; /* maybe 0x2c */
sb->channels_offset = 0x3c; sb->channels_offset = 0x3c;
sb->sample_rate_offset = 0x44; sb->sample_rate_offset = 0x40;
sb->num_samples_offset = 0x48; sb->num_samples_offset = 0x48;
sb->extra_name_offset = 0x58; sb->extra_name_offset = 0x58;
sb->stream_type_offset = 0x5c; sb->stream_type_offset = 0x5c;

View File

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

View File

@ -128,8 +128,8 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
} }
/* other Wwise specific: */ /* other Wwise specific: */
//"JUNK": optional padding so that raw data starts in an offset multiple of 0x10 (0-size JUNK exists too) //"JUNK": optional padding for usually aligment (0-size JUNK exists too)
//"akd ": unknown (IMA/PCM; "audiokinetic data"?) //"akd ": seem to store extra info for Wwise editor (wave peaks/loudness/HDR envelope?)
} }
/* format to codec */ /* format to codec */
@ -158,7 +158,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
ww.codec = DSP; 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. * 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 */ * We'll add basic support to avoid complaints of this or that .wem not playing */
if (ww.data_size > ww.file_size) { if (ww.data_size > ww.file_size) {
@ -560,50 +560,50 @@ fail:
0x00 (4): num_samples 0x00 (4): num_samples
0x04 (4): skip samples? 0x04 (4): skip samples?
0x08 (4): ? (small if loop, 0 otherwise) 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) 0x10 (4): ? (small, 0..~0x400)
0x14 (4): approximate data size without seek table? (almost setup+packets) 0x14 (4): approximate data size without seek table? (almost setup+packets)
0x18 (4): setup_offset within data (0 = no seek table) 0x18 (4): setup_offset within data (0 = no seek table)
0x1c (4): audio_offset within data 0x1c (4): audio_offset within data
0x20 (4): biggest packet size (not including header)? 0x20 (2): biggest packet size (not including header)?
0x24 (4): ? (mid, 0~0x5000) 0x22 (2): ? (small, N..~0x100) uLastGranuleExtra?
0x28 (4): ? (mid, 0~0x5000) 0x24 (4): ? (mid, 0~0x5000) dwDecodeAllocSize?
0x2c (4): parent bank/event id? (shared by several .wem a game, but not all need to share it) 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) 0x30 (1): blocksize_1_exp (small)
0x31 (1): blocksize_0_exp (large) 0x31 (1): blocksize_0_exp (large)
0x32 (2): empty 0x32 (2): empty
"vorb" size 0x28 / 0x2a "vorb" size 0x28 / 0x2a
0x00 (4): num_samples 0x00 (4): num_samples
0x04 (4): loop offset after seek table+setup (offset after setup if file doesn't loop) 0x04 (4): data start offset after seek table+setup, or loop start when "smpl" is present
0x08 (4): data size without seek table (setup+packets) 0x08 (4): data end offset after seek table (setup+packets), or loop end when "smpl" is present
0x0c (2): ? (small, 0..~0x400) 0x0c (2): ? (small, 0..~0x400)
0x10 (4): setup_offset within data (0 = no seek table) 0x10 (4): setup_offset within data (0 = no seek table)
0x14 (4): audio_offset within data 0x14 (4): audio_offset within data
0x18 (2): ? (small, 0..~0x400) 0x18 (2): biggest packet size (not including header)?
0x1a (2): ? (small, N..~0x100) 0x1a (2): ? (small, N..~0x100) uLastGranuleExtra?
0x1c (4): ? (mid, 0~0x5000) 0x1c (4): ? (mid, 0~0x5000) dwDecodeAllocSize?
0x20 (4): ? (mid, 0~0x5000) 0x20 (4): ? (mid, 0~0x5000) dwDecodeX64AllocSize?
0x24 (4): parent bank/event id? (shared by several .wem a game, but not all need to share it) 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] 0x28 (1): blocksize_1_exp (small) [removed when size is 0x28]
0x29 (1): blocksize_0_exp (large) [removed when size is 0x28] 0x29 (1): blocksize_0_exp (large) [removed when size is 0x28]
- new format: - new format:
"fmt" size 0x42, extra size 0x30 "fmt" size 0x42, extra size 0x30
0x12 (2): flag? (00,10,18): not related to seek table, codebook type, chunk count, looping, etc 0x12 (2): flag? (00,10,18): not related to seek table, codebook type, chunk count, looping, etc
0x14 (4): channel config 0x14 (4): channel config
0x18 (4): num_samples 0x18 (4): num_samples
0x1c (4): loop offset after seek table+setup (offset after setup if file doesn't loop) 0x1c (4): data start offset after seek table+setup, or loop start when "smpl" is present
0x20 (4): data size without seek table (setup+packets) 0x20 (4): data end offset after seek table (setup+packets), or loop end when "smpl" is present
0x24 (2): ?1 (small, 0..~0x400) 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 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) 0x28 (4): setup offset within data (0 = no seek table)
0x2c (4): audio offset within data 0x2c (4): audio offset within data
0x30 (2): biggest packet size (not including header) 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?) 0x32 (2): (small, 0..~0x100) uLastGranuleExtra?
0x34 (4): bitrate config? (mid, 0~0x5000) 0x34 (4): ? (mid, 0~0x5000) dwDecodeAllocSize?
0x38 (4): bitrate config? (mid, 0~0x5000) (2 byte with max/min?) 0x38 (4): ? (mid, 0~0x5000) dwDecodeX64AllocSize?
0x40 (1): blocksize_1_exp (small) 0x40 (1): blocksize_1_exp (small)
0x41 (1): blocksize_0_exp (large) 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 { typedef struct {
int little_endian; int little_endian;
int version; int version;
@ -124,8 +124,6 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
/* for Techland's XWB with no data */ /* for Techland's XWB with no data */
if (xwb.base_offset == 0) goto fail; 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) */ /* read base entry (WAVEBANKDATA) */
off = xwb.base_offset; 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_start = (uint32_t)read_32bit(off+0x0c, streamFile);
xwb.loop_end = (uint32_t)read_32bit(off+0x10, streamFile);//length 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 { else {
uint32_t entry_info = (uint32_t)read_32bit(off+0x00, streamFile); 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_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_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; case 1: xwb.codec = XBOX_ADPCM; break;
default: goto fail; default: goto fail;
} }
} else if (xwb.version <= XACT1_1_MAX) { }
else if (xwb.version <= XACT1_1_MAX) {
switch(xwb.tag){ switch(xwb.tag){
case 0: xwb.codec = PCM; break; case 0: xwb.codec = PCM; break;
case 1: xwb.codec = XBOX_ADPCM; break; case 1: xwb.codec = XBOX_ADPCM; break;
case 2: xwb.codec = WMA; break; case 2: xwb.codec = WMA; break;
case 3: xwb.codec = OGG; break; /* extension */
default: goto fail; default: goto fail;
} }
} else if (xwb.version <= XACT2_2_MAX) { }
else if (xwb.version <= XACT2_2_MAX) {
switch(xwb.tag) { switch(xwb.tag) {
case 0: xwb.codec = PCM; break; case 0: xwb.codec = PCM; break;
/* Table Tennis (v34): XMA1, Prey (v38): XMA2, v35/36/37: ? */ /* 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; case 2: xwb.codec = MS_ADPCM; break;
default: goto fail; default: goto fail;
} }
} else { }
else {
switch(xwb.tag) { switch(xwb.tag) {
case 0: xwb.codec = PCM; break; case 0: xwb.codec = PCM; break;
case 1: xwb.codec = XMA2; 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); 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 */ /* fix samples */
if (xwb.version <= XACT2_2_MAX && xwb.codec == PCM) { if (xwb.version <= XACT2_2_MAX && xwb.codec == PCM) {
@ -435,7 +452,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
break; break;
} }
case ATRAC3: { /* Techland extension */ case ATRAC3: { /* Techland PS3 extension */
uint8_t buf[200]; uint8_t buf[200];
int bytes; int bytes;
@ -452,6 +469,15 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
break; 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 #endif
default: default:

View File

@ -5,7 +5,6 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "formats.h"
#include "vgmstream.h" #include "vgmstream.h"
#include "meta/meta.h" #include "meta/meta.h"
#include "layout/layout.h" #include "layout/layout.h"
@ -202,7 +201,6 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
init_vgmstream_wii_smp, init_vgmstream_wii_smp,
init_vgmstream_emff_ps2, init_vgmstream_emff_ps2,
init_vgmstream_emff_ngc, init_vgmstream_emff_ngc,
init_vgmstream_ss_stream,
init_vgmstream_thp, init_vgmstream_thp,
init_vgmstream_wii_sts, init_vgmstream_wii_sts,
init_vgmstream_ps2_p2bt, 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 */ /* do format detection, return pointer to a usable VGMSTREAM, or NULL on failure */
VGMSTREAM * init_vgmstream(const char * const filename); VGMSTREAM * init_vgmstream(const char * const filename);
/* init with custom IO via streamfile */
VGMSTREAM * init_vgmstream_from_STREAMFILE(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_from_STREAMFILE(STREAMFILE *streamFile);
/* reset a VGMSTREAM to start of stream */ /* 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. */ * stream. Compares files by absolute paths. */
int get_vgmstream_average_bitrate(VGMSTREAM * vgmstream); 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 */ /* vgmstream "private" API */
/* -------------------------------------------------------------------------*/ /* -------------------------------------------------------------------------*/
@ -1203,4 +1207,9 @@ int vgmstream_do_loop(VGMSTREAM * vgmstream);
* returns 0 on failure */ * returns 0 on failure */
int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t start_offset); 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 #endif

View File

@ -14,8 +14,9 @@ REM #TODO: escape & ! % in file/folder names
setlocal enableDelayedExpansion setlocal enableDelayedExpansion
REM #-------------------------------------------------------------------------
REM #options REM #options
REM #-------------------------------------------------------------------------
REM # -vo <exe> -vn <exe>: path to old/new exe REM # -vo <exe> -vn <exe>: path to old/new exe
set OP_CMD_OLD=test_old.exe set OP_CMD_OLD=test_old.exe
set OP_CMD_NEW=test.exe set OP_CMD_NEW=test.exe
@ -27,6 +28,8 @@ REM # -nd: don't delete compared files
set OP_NODELETE= set OP_NODELETE=
REM # -nc: don't report correct files REM # -nc: don't report correct files
set OP_NOCORRECT= set OP_NOCORRECT=
REM # -p: performance test (decode with new exe and no comparison done)
set OP_PERFORMANCE=
REM # parse options REM # parse options
@ -38,6 +41,7 @@ if "%~1"=="-f" set OP_SEARCH=%2
if "%~1"=="-r" set OP_RECURSIVE=/s if "%~1"=="-r" set OP_RECURSIVE=/s
if "%~1"=="-nd" set OP_NODELETE=true if "%~1"=="-nd" set OP_NODELETE=true
if "%~1"=="-nc" set OP_NOCORRECT=true if "%~1"=="-nc" set OP_NOCORRECT=true
if "%~1"=="-p" set OP_PERFORMANCE=true
shift shift
goto set_options goto set_options
:end_options :end_options
@ -61,7 +65,8 @@ if %OP_SEARCH%=="" (
) )
REM # process start REM # process start
echo VRTS: start @%time% set TIME_START=%time%
echo VRTS: start @%TIME_START%
REM # search for files REM # search for files
set CMD_DIR=dir /a:-d /b %OP_RECURSIVE% %OP_SEARCH% 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 REM # process files
for /f "delims=" %%x in ('%CMD_DIR% ^| %CMD_FIND%') do ( for /f "delims=" %%x in ('%CMD_DIR% ^| %CMD_FIND%') do (
set CMD_FILE=%%x 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) 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 # test a single file
REM # ########################################################################
:process_file outer :process_file outer
REM # ignore files starting with dot (no filename) REM # ignore files starting with dot (no filename)
set CMD_SHORTNAME=%~n1 set CMD_SHORTNAME=%~n1
if "%CMD_SHORTNAME%" == "" goto continue if "%CMD_SHORTNAME%" == "" goto process_file_continue
REM # get file REM # get file
set CMD_FILE=%1 set CMD_FILE=%1
@ -105,7 +131,7 @@ REM # test a single file
REM echo VRTS: nothing created for file %CMD_FILE% REM echo VRTS: nothing created for file %CMD_FILE%
if exist "%TXT_NEW%" del /a:a "%TXT_NEW%" if exist "%TXT_NEW%" del /a:a "%TXT_NEW%"
if exist "%TXT_OLD%" del /a:a "%TXT_OLD%" 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%" if exist "%TXT_NEW%" del /a:a "%TXT_NEW%"
) )
:continue :process_file_continue
exit /B exit /B
REM :process_file end, continue from last call 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 # hack to get colored output in Windows CMD using findstr + temp file
REM # ########################################################################
:echo_color :echo_color
set TEMP_FILE=%2-result set TEMP_FILE=%2-result
set TEMP_FILE=%TEMP_FILE:"=% set TEMP_FILE=%TEMP_FILE:"=%
@ -165,14 +221,10 @@ exit /B
REM :echo_color end, continue from last call REM :echo_color end, continue from last call
:done REM # ########################################################################
echo VRTS: done @%time%
goto exit
:error :error
echo VRTS: error @%time% echo VRTS: error
goto exit goto exit
: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, /* 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). * 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. */ * 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 #ifdef _MSC_VER
#define _CRT_SECURE_NO_DEPRECATE #define _CRT_SECURE_NO_DEPRECATE
@ -19,7 +20,6 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include "../src/formats.h"
#include "../src/vgmstream.h" #include "../src/vgmstream.h"
#include "in2.h" #include "in2.h"
#include "wa_ipc.h" #include "wa_ipc.h"
@ -68,7 +68,7 @@ In_Module input_module;
DWORD WINAPI __stdcall decode(void *arg); DWORD WINAPI __stdcall decode(void *arg);
/* Winamp Play extension list, needed to accept/play and associate extensions in Windows */ /* 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 #define EXT_BUFFER_SIZE 200
char working_extension_list[EXTENSION_LIST_SIZE] = {0}; 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" */ * Each extension must be in this format: "extension\0Description\0" */
static void build_extension_list() { static void build_extension_list() {
const char ** ext_list; const char ** ext_list;
int ext_list_len; size_t ext_list_len;
int i; int i;
working_extension_list[0]='\0'; working_extension_list[0]='\0';
working_extension_list[1]='\0'; working_extension_list[1]='\0';
ext_list = vgmstream_get_formats(); ext_list = vgmstream_get_formats(&ext_list_len);
ext_list_len = vgmstream_get_formats_length();
for (i=0; i < ext_list_len; i++) { for (i=0; i < ext_list_len; i++) {
add_extension(EXTENSION_LIST_SIZE, working_extension_list, ext_list[i]); add_extension(EXTENSION_LIST_SIZE, working_extension_list, ext_list[i]);

View File

@ -11,7 +11,6 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include "../src/formats.h"
#include "../src/vgmstream.h" #include "../src/vgmstream.h"
#include "xmpin.h" #include "xmpin.h"
@ -27,7 +26,7 @@
/* XMPlay extension list, only needed to associate extensions in Windows */ /* 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...) */ /* 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 #define XMPLAY_MAX_PATH 32768
/* XMPlay function library */ /* 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" */ * Extensions must be in this format: "Description\0extension1/.../extensionN" */
static void build_extension_list() { static void build_extension_list() {
const char ** ext_list; const char ** ext_list;
int ext_list_len; size_t ext_list_len;
int i, written; int i, written;
written = sprintf(working_extension_list, "%s%c", "vgmstream files",'\0'); written = sprintf(working_extension_list, "%s%c", "vgmstream files",'\0');
ext_list = vgmstream_get_formats(); ext_list = vgmstream_get_formats(&ext_list_len);
ext_list_len = vgmstream_get_formats_length();
for (i=0; i < ext_list_len; i++) { for (i=0; i < ext_list_len; i++) {
written += add_extension(EXTENSION_LIST_SIZE-written, working_extension_list + written, ext_list[i]); written += add_extension(EXTENSION_LIST_SIZE-written, working_extension_list + written, ext_list[i]);