From feb99a151c17d7cfbba90b965e8971c939cf7676 Mon Sep 17 00:00:00 2001 From: fastelbja Date: Wed, 14 May 2008 20:44:19 +0000 Subject: [PATCH] added MIB / MIB+MIH / MI4 support git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@118 51a99a44-fe44-0410-b1ba-c3e57ba2b86b --- src/libvgmstream.vcproj | 4 + src/meta/meta.h | 2 + src/meta/ps2_mib.c | 171 ++++++++++++++++++++++++++++++++++++++++ src/vgmstream.c | 9 ++- src/vgmstream.h | 4 +- winamp/in_vgmstream.c | 4 +- 6 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 src/meta/ps2_mib.c diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index 51d4fbb8..06e7fe07 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -254,6 +254,10 @@ RelativePath=".\meta\ps2_int.c" > + + diff --git a/src/meta/meta.h b/src/meta/meta.h index 39abdace..f1fc8de9 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -47,4 +47,6 @@ VGMSTREAM * init_vgmstream_ps2_exst(const char * const filename); VGMSTREAM * init_vgmstream_ps2_svag(const char * const filename); +VGMSTREAM * init_vgmstream_ps2_mib(const char * const filename); + #endif diff --git a/src/meta/ps2_mib.c b/src/meta/ps2_mib.c new file mode 100644 index 00000000..14086506 --- /dev/null +++ b/src/meta/ps2_mib.c @@ -0,0 +1,171 @@ +#include "meta.h" +#include "../util.h" + +/* MIB + + PS2 MIB format is a headerless format. + The interleave value can be found by checking the body of the data. + + The interleave start allways at offset 0 with a int value (which can have + many values : 0x0000, 0x0002, 0x0006 etc...) follow by 12 empty (zero) values. + + The interleave value is the offset where you found the same 16 bytes. + + The n° of channels can be found by checking each time you found this 16 bytes. + + The interleave value can be very "large" (up to 0x20000 found so far) and is allways + a 0x10 multiply value. + + The loop values can be found by checking the 'tags' offset (found @ 0x02 each 0x10 bytes). + 06 = start of the loop point (can be found for each channel) + 03 - end of the loop point (can be found for each channel) + + The .MIH header contains all informations about frequency, numbers of channels, interleave + but has, afaik, no loop values. + + known extensions : MIB (MIH for the header) MIC (concatenation of MIB+MIH) + Nota : the MIC stuff is not supported here as there is + another MIC format which can be found in Koei Games. + + 2008-05-14 - Fastelbja : First version ... +*/ + +VGMSTREAM * init_vgmstream_ps2_mib(const char * const filename) { + + VGMSTREAM * vgmstream = NULL; + STREAMFILE * infile = NULL; + STREAMFILE * infileMIH = NULL; + + uint8_t mibBuffer[0x10]; + uint8_t testBuffer[0x10]; + + size_t readLength; + size_t fileLength; + + off_t loopStart = 0; + off_t loopEnd = 0; + off_t interleave = 0; + off_t readOffset = 0; + + size_t bufOffset; + + char * filenameMIH; + + uint8_t gotMIH=0; + + int i, loop_flag, channel_count=1; + + /* check extension, case insensitive */ + if (strcasecmp("mib",filename_extension(filename)) && + strcasecmp("mi4",filename_extension(filename))) goto fail; + + /* check for .MIH file */ + filenameMIH=(char *)malloc(strlen(filename)); + + if (!filenameMIH) goto fail; + + strcpy(filenameMIH,filename); + strcpy(filenameMIH+strlen(filenameMIH)-3,"MIH"); + + infileMIH = open_streamfile(filenameMIH); + if (infileMIH) gotMIH = 1; + + /* Search for interleave value & loop points */ + /* Get the first 16 values */ + infile=open_streamfile_buffer(filename,0x8000); + + if(!infile) goto fail; + + fileLength = get_streamfile_size(infile); + + readOffset+=read_streamfile(mibBuffer,0,0x10,infile); + + do { + readOffset+=read_streamfile(testBuffer,readOffset,0x10,infile); + + if(!memcmp(testBuffer,mibBuffer,0x10)) { + if(interleave==0) interleave=readOffset-0x10; + + // be sure to point to an interleave value + if((((readOffset-0x10)%interleave)==interleave) || ((readOffset-0x10)==interleave)) { + if (channel_count<6) channel_count++; + } + } + + // Loop Start ... + if(testBuffer[0x01]==0x06) { + if(loopStart==0) loopStart = readOffset-0x10; + } + + // Loop End ... + if(testBuffer[0x01]==0x03) { + if(loopEnd==0) loopEnd = readOffset-0x10; + } + + } while (infile->offsetchannels = read_32bitLE(0x08,infileMIH); + vgmstream->sample_rate = read_32bitLE(0x0C,infileMIH); + vgmstream->interleave_block_size = read_32bitLE(0x10,infileMIH); + vgmstream->num_samples=((read_32bitLE(0x10,infileMIH)* + (read_32bitLE(0x14,infileMIH)-1)*2)+ + ((read_32bitLE(0x04,infileMIH)>>8)*2))/16*28/2; + } else { + vgmstream->channels = channel_count; + vgmstream->interleave_block_size = interleave; + + if(!strcasecmp("mib",filename_extension(filename))) + vgmstream->sample_rate = 44100; + + if(!strcasecmp("mi4",filename_extension(filename))) + vgmstream->sample_rate = 48000; + + vgmstream->num_samples = fileLength/16*14; + } + + if(loopStart!=0) { + vgmstream->loop_start_sample = ((loopStart/(interleave*channel_count))*interleave)/16*14*channel_count; + vgmstream->loop_start_sample += (loopStart%(interleave*channel_count))/16*14*channel_count; + vgmstream->loop_end_sample = ((loopEnd/(interleave*channel_count))*interleave)/16*14*channel_count; + vgmstream->loop_end_sample += (loopEnd%(interleave*channel_count))/16*14*channel_count; + } + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + + vgmstream->meta_type = meta_PS2_MIB; + close_streamfile(infile); infile=NULL; + + if (gotMIH) { + vgmstream->meta_type = meta_PS2_MIB_MIH; + close_streamfile(infileMIH); infileMIH=NULL; + } + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = open_streamfile_buffer(filename,0x8000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=0; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (infile) close_streamfile(infile); + if (infileMIH) close_streamfile(infileMIH); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream.c b/src/vgmstream.c index d9574899..f30227ae 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -15,7 +15,7 @@ * List of functions that will recognize files. These should correspond pretty * directly to the metadata types */ -#define INIT_VGMSTREAM_FCNS 22 +#define INIT_VGMSTREAM_FCNS 23 VGMSTREAM * (*init_vgmstream_fcns[INIT_VGMSTREAM_FCNS])(const char * const) = { init_vgmstream_adx, /* 0 */ init_vgmstream_brstm, /* 1 */ @@ -39,6 +39,7 @@ VGMSTREAM * (*init_vgmstream_fcns[INIT_VGMSTREAM_FCNS])(const char * const) = { init_vgmstream_ngc_dsp_stm, /* 19 */ init_vgmstream_ps2_exst, /* 20 */ init_vgmstream_ps2_svag, /* 21 */ + init_vgmstream_ps2_mib, /* 22 */ }; @@ -606,6 +607,12 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { case meta_PS2_SVAG: snprintf(temp,TEMPSIZE,"Konami SVAG header"); break; + case meta_PS2_MIB: + snprintf(temp,TEMPSIZE,"assumed MIB Interleaved file by .mib extension"); + break; + case meta_PS2_MIB_MIH: + snprintf(temp,TEMPSIZE,"assumed MIB with MIH Info Header file by .mib+.mih extension"); + break; default: snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET"); } diff --git a/src/vgmstream.h b/src/vgmstream.h index a97cd260..255d5323 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -80,7 +80,9 @@ typedef enum { meta_PS2_RAW, /* RAW Interleaved Format */ meta_PS2_EXST, /* Shadow of Colossus EXST */ meta_PS2_SVAG, /* Konami SVAG */ - + meta_PS2_MIB, /* MIB File */ + meta_PS2_MIB_MIH, /* MIB File + MIH Header*/ + meta_PSX_XA, /* CD-XA with RIFF header */ } meta_t; diff --git a/winamp/in_vgmstream.c b/winamp/in_vgmstream.c index 2ed96224..dfde4868 100644 --- a/winamp/in_vgmstream.c +++ b/winamp/in_vgmstream.c @@ -45,7 +45,7 @@ int fade_samples = 0; #define EXTENSION_LIST_SIZE 1024 char working_extension_list[EXTENSION_LIST_SIZE] = {0}; -#define EXTENSION_COUNT 20 +#define EXTENSION_COUNT 22 char * extension_list[EXTENSION_COUNT] = { "adx\0ADX Audio File (*.ADX)\0", "afc\0AFC Audio File (*.AFC)\0", @@ -67,6 +67,8 @@ char * extension_list[EXTENSION_COUNT] = { "int\0PS2 RAW Interleaved PCM (*.INT)\0", "sts\0PS2 EXST Audio File (*.STS)\0", "svag\0PS2 SVAG Audio File (*.SVAG)\0", + "mib\0PS2 MIB Audio File (*.MIB)\0", + "mi4\0PS2 MI4 Audio File (*.MI4)\0", }; /* stubs, we don't do anything fancy yet */