mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 15:00:11 +01:00
added MIB / MIB+MIH / MI4 support
git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@118 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
parent
f935a034e0
commit
feb99a151c
@ -254,6 +254,10 @@
|
|||||||
RelativePath=".\meta\ps2_int.c"
|
RelativePath=".\meta\ps2_int.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\meta\ps2_mib.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\meta\ps2_npsf.c"
|
RelativePath=".\meta\ps2_npsf.c"
|
||||||
>
|
>
|
||||||
|
@ -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_svag(const char * const filename);
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_ps2_mib(const char * const filename);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
171
src/meta/ps2_mib.c
Normal file
171
src/meta/ps2_mib.c
Normal file
@ -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->offset<fileLength);
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channel_count,(loopStart!=0));
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
/* fill in the vital statistics */
|
||||||
|
if(gotMIH) {
|
||||||
|
// Read stuff from the MIH file
|
||||||
|
vgmstream->channels = 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;i<channel_count;i++) {
|
||||||
|
vgmstream->ch[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;
|
||||||
|
}
|
@ -15,7 +15,7 @@
|
|||||||
* List of functions that will recognize files. These should correspond pretty
|
* List of functions that will recognize files. These should correspond pretty
|
||||||
* directly to the metadata types
|
* 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) = {
|
VGMSTREAM * (*init_vgmstream_fcns[INIT_VGMSTREAM_FCNS])(const char * const) = {
|
||||||
init_vgmstream_adx, /* 0 */
|
init_vgmstream_adx, /* 0 */
|
||||||
init_vgmstream_brstm, /* 1 */
|
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_ngc_dsp_stm, /* 19 */
|
||||||
init_vgmstream_ps2_exst, /* 20 */
|
init_vgmstream_ps2_exst, /* 20 */
|
||||||
init_vgmstream_ps2_svag, /* 21 */
|
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:
|
case meta_PS2_SVAG:
|
||||||
snprintf(temp,TEMPSIZE,"Konami SVAG header");
|
snprintf(temp,TEMPSIZE,"Konami SVAG header");
|
||||||
break;
|
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:
|
default:
|
||||||
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");
|
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,9 @@ typedef enum {
|
|||||||
meta_PS2_RAW, /* RAW Interleaved Format */
|
meta_PS2_RAW, /* RAW Interleaved Format */
|
||||||
meta_PS2_EXST, /* Shadow of Colossus EXST */
|
meta_PS2_EXST, /* Shadow of Colossus EXST */
|
||||||
meta_PS2_SVAG, /* Konami SVAG */
|
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_PSX_XA, /* CD-XA with RIFF header */
|
||||||
|
|
||||||
} meta_t;
|
} meta_t;
|
||||||
|
@ -45,7 +45,7 @@ int fade_samples = 0;
|
|||||||
|
|
||||||
#define EXTENSION_LIST_SIZE 1024
|
#define EXTENSION_LIST_SIZE 1024
|
||||||
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
|
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
|
||||||
#define EXTENSION_COUNT 20
|
#define EXTENSION_COUNT 22
|
||||||
char * extension_list[EXTENSION_COUNT] = {
|
char * extension_list[EXTENSION_COUNT] = {
|
||||||
"adx\0ADX Audio File (*.ADX)\0",
|
"adx\0ADX Audio File (*.ADX)\0",
|
||||||
"afc\0AFC Audio File (*.AFC)\0",
|
"afc\0AFC Audio File (*.AFC)\0",
|
||||||
@ -67,6 +67,8 @@ char * extension_list[EXTENSION_COUNT] = {
|
|||||||
"int\0PS2 RAW Interleaved PCM (*.INT)\0",
|
"int\0PS2 RAW Interleaved PCM (*.INT)\0",
|
||||||
"sts\0PS2 EXST Audio File (*.STS)\0",
|
"sts\0PS2 EXST Audio File (*.STS)\0",
|
||||||
"svag\0PS2 SVAG Audio File (*.SVAG)\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 */
|
/* stubs, we don't do anything fancy yet */
|
||||||
|
Loading…
Reference in New Issue
Block a user