6
PS2 MIB format is a headerless format.
7
The interleave value can be found by checking the body of the data.
9
The interleave start allways at offset 0 with a int value (which can have
10
many values : 0x0000, 0x0002, 0x0006 etc...) follow by 12 empty (zero) values.
12
The interleave value is the offset where you found the same 16 bytes.
14
The n� of channels can be found by checking each time you found this 16 bytes.
16
The interleave value can be very "large" (up to 0x20000 found so far) and is allways
17
a 0x10 multiply value.
19
The loop values can be found by checking the 'tags' offset (found @ 0x02 each 0x10 bytes).
20
06 = start of the loop point (can be found for each channel)
21
03 - end of the loop point (can be found for each channel)
23
The .MIH header contains all informations about frequency, numbers of channels, interleave
24
but has, afaik, no loop values.
26
known extensions : MIB (MIH for the header) MIC (concatenation of MIB+MIH)
27
Nota : the MIC stuff is not supported here as there is
28
another MIC format which can be found in Koei Games.
30
2008-05-14 - Fastelbja : First version ...
31
2008-05-20 - Fastelbja : Fix loop value when loopEnd==0
34
VGMSTREAM * init_vgmstream_ps2_mib(STREAMFILE *streamFile) {
36
VGMSTREAM * vgmstream = NULL;
37
STREAMFILE * streamFileMIH = NULL;
40
uint8_t mibBuffer[0x10];
41
uint8_t testBuffer[0x10];
50
char filenameMIH[260];
54
int i, channel_count=1;
56
/* check extension, case insensitive */
57
streamFile->get_name(streamFile,filename,sizeof(filename));
58
if (strcasecmp("mib",filename_extension(filename)) &&
59
strcasecmp("mi4",filename_extension(filename))) goto fail;
61
/* check for .MIH file */
62
strcpy(filenameMIH,filename);
63
strcpy(filenameMIH+strlen(filenameMIH)-3,"MIH");
65
streamFileMIH = streamFile->open(streamFile,filenameMIH,STREAMFILE_DEFAULT_BUFFER_SIZE);
66
if (streamFileMIH) gotMIH = 1;
68
/* Search for interleave value & loop points */
69
/* Get the first 16 values */
70
fileLength = get_streamfile_size(streamFile);
72
readOffset+=(off_t)read_streamfile(mibBuffer,0,0x10,streamFile);
75
readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile);
77
if(!memcmp(testBuffer,mibBuffer,0x10)) {
78
if(interleave==0) interleave=readOffset-0x10;
80
// be sure to point to an interleave value
81
if(((readOffset-0x10)==channel_count*interleave)) {
87
if(testBuffer[0x01]==0x06) {
88
if(loopStart==0) loopStart = readOffset-0x10;
92
if(testBuffer[0x01]==0x03) {
93
if(loopEnd==0) loopEnd = readOffset-0x10;
96
} while (streamFile->get_offset(streamFile)<(int32_t)fileLength);
99
channel_count=read_32bitLE(0x08,streamFileMIH);
101
/* build the VGMSTREAM */
102
vgmstream = allocate_vgmstream(channel_count,((loopStart!=0) && (loopEnd!=0)));
103
if (!vgmstream) goto fail;
105
if(interleave==0) interleave=0x10;
107
/* fill in the vital statistics */
109
// Read stuff from the MIH file
110
vgmstream->channels = read_32bitLE(0x08,streamFileMIH);
111
vgmstream->sample_rate = read_32bitLE(0x0C,streamFileMIH);
112
vgmstream->interleave_block_size = read_32bitLE(0x10,streamFileMIH);
113
vgmstream->num_samples=((read_32bitLE(0x10,streamFileMIH)*
114
(read_32bitLE(0x14,streamFileMIH)-1)*2)+
115
((read_32bitLE(0x04,streamFileMIH)>>8)*2))/16*28/2;
117
vgmstream->channels = channel_count;
118
vgmstream->interleave_block_size = interleave;
120
if(!strcasecmp("mib",filename_extension(filename)))
121
vgmstream->sample_rate = 44100;
123
if(!strcasecmp("mi4",filename_extension(filename)))
124
vgmstream->sample_rate = 48000;
126
vgmstream->num_samples = (int32_t)(fileLength/16/channel_count*28);
130
if(vgmstream->channels==1) {
131
vgmstream->loop_start_sample = loopStart/16*18;
132
vgmstream->loop_end_sample = loopEnd/16*28;
134
vgmstream->loop_start_sample = ((loopStart/(interleave*channel_count))*interleave)/16*14*(2/channel_count);
135
vgmstream->loop_start_sample += (loopStart%(interleave*channel_count))/16*14*(2/channel_count);
136
vgmstream->loop_end_sample = ((loopEnd/(interleave*channel_count))*interleave)/16*28*(2/channel_count);
137
vgmstream->loop_end_sample += (loopEnd%(interleave*channel_count))/16*14*(2/channel_count);
141
vgmstream->coding_type = coding_PSX;
142
vgmstream->layout_type = layout_interleave;
144
vgmstream->meta_type = meta_PS2_MIB;
147
vgmstream->meta_type = meta_PS2_MIB_MIH;
148
close_streamfile(streamFileMIH); streamFileMIH=NULL;
151
/* open the file for reading by each channel */
153
for (i=0;i<channel_count;i++) {
154
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000);
156
if (!vgmstream->ch[i].streamfile) goto fail;
158
vgmstream->ch[i].channel_start_offset=
159
vgmstream->ch[i].offset=i*vgmstream->interleave_block_size;
165
/* clean up anything we may have opened */
167
if (streamFileMIH) close_streamfile(streamFileMIH);
168
if (vgmstream) close_vgmstream(vgmstream);