mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-02-17 19:19:16 +01:00
VAG support added (VAGi, VAGp, pGAV, Dual File, Stereo VAG)
git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@157 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
parent
19e067fd8c
commit
1c0d345e61
@ -30,7 +30,7 @@ void decode_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
|
||||
|
||||
sample=0;
|
||||
|
||||
if(flag!=0x07) {
|
||||
if(flag<0x07) {
|
||||
|
||||
short sample_byte = (short)read_8bit(stream->offset+(framesin*16)+2+i/2,stream->streamfile);
|
||||
|
||||
|
@ -274,6 +274,10 @@
|
||||
RelativePath=".\meta\ps2_svag.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\ps2_vag.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\psx_cdxa.c"
|
||||
>
|
||||
|
@ -57,4 +57,6 @@ VGMSTREAM * init_vgmstream_ps2_mic(const char * const filename);
|
||||
|
||||
VGMSTREAM * init_vgmstream_raw(const char * const filename);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_vag(const char * const filename);
|
||||
|
||||
#endif
|
||||
|
175
src/meta/ps2_vag.c
Normal file
175
src/meta/ps2_vag.c
Normal file
@ -0,0 +1,175 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* VAG
|
||||
|
||||
PS2 SVAG format is an interleaved format found in many SONY Games
|
||||
The header start with a "VAG" id and is follow by :
|
||||
|
||||
i : interleaved format
|
||||
|
||||
2008-05-17 - Fastelbja : First version ...
|
||||
*/
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps2_vag(const char * const filename) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
STREAMFILE * infile = NULL;
|
||||
|
||||
// used for loop points ...
|
||||
uint8_t eofVAG[16]={0x00,0x07,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77};
|
||||
uint8_t eofVAG2[16]={0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
||||
uint8_t readbuf[16];
|
||||
|
||||
off_t readOffset = 0x20;
|
||||
|
||||
off_t loopStart = 0;
|
||||
off_t loopEnd = 0;
|
||||
|
||||
uint8_t vagID;
|
||||
off_t start_offset;
|
||||
size_t fileLength;
|
||||
|
||||
size_t interleave;
|
||||
|
||||
int loop_flag=0;
|
||||
int channel_count;
|
||||
int i;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
if (strcasecmp("vag",filename_extension(filename))) goto fail;
|
||||
|
||||
/* try to open the file for header reading */
|
||||
infile = open_streamfile_buffer(filename,0x8000);
|
||||
if (!infile) goto fail;
|
||||
|
||||
/* check VAG Header */
|
||||
if (((read_32bitBE(0x00,infile) & 0xFFFFFF00) != 0x56414700) &&
|
||||
((read_32bitLE(0x00,infile) & 0xFFFFFF00) != 0x56414700))
|
||||
goto fail;
|
||||
|
||||
/* Check for correct channel count */
|
||||
vagID=read_8bit(0x03,infile);
|
||||
|
||||
switch(vagID) {
|
||||
case 'i':
|
||||
channel_count=2;
|
||||
break;
|
||||
case 'V':
|
||||
if(read_32bitBE(0x20,infile)==0x53746572) // vag Stereo
|
||||
channel_count=2;
|
||||
break;
|
||||
case 'p':
|
||||
channel_count=1;
|
||||
|
||||
/* Search for loop in VAG */
|
||||
fileLength = get_streamfile_size(infile);
|
||||
|
||||
do {
|
||||
readOffset+=0x10;
|
||||
|
||||
// Loop Start ...
|
||||
if(read_8bit(readOffset+0x01,infile)==0x06) {
|
||||
if(loopStart==0) loopStart = readOffset;
|
||||
}
|
||||
|
||||
// Loop End ...
|
||||
if(read_8bit(readOffset+0x01,infile)==0x03) {
|
||||
if(loopEnd==0) loopEnd = readOffset;
|
||||
}
|
||||
|
||||
// Loop from end to beginning ...
|
||||
if((read_8bit(readOffset+0x01,infile)==0x01)) {
|
||||
// Check if we have the eof tag after the loop point ...
|
||||
// if so we don't loop, if not present, we loop from end to start ...
|
||||
read_streamfile(readbuf,readOffset+0x10,0x10,infile);
|
||||
if((readbuf[0]!=0) && (readbuf[0]!=0x0c)) {
|
||||
if(memcmp(readbuf,eofVAG,0x10) && (memcmp(readbuf,eofVAG2,0x10))) {
|
||||
loopStart = 0x40;
|
||||
loopEnd = readOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while (infile->offset<(off_t)fileLength);
|
||||
loop_flag = (loopEnd!=0);
|
||||
break;
|
||||
}
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->channels = channel_count;
|
||||
|
||||
switch(vagID) {
|
||||
case 'i': // VAGi
|
||||
vgmstream->layout_type=layout_interleave;
|
||||
vgmstream->sample_rate = read_32bitBE(0x10,infile);
|
||||
vgmstream->num_samples = read_32bitBE(0x0C,infile)/16*28;
|
||||
interleave = read_32bitLE(0x08,infile);
|
||||
vgmstream->meta_type=meta_PS2_VAGi;
|
||||
start_offset=0x800;
|
||||
break;
|
||||
case 'p': // VAGp
|
||||
vgmstream->layout_type=layout_none;
|
||||
vgmstream->sample_rate = read_32bitBE(0x10,infile);
|
||||
vgmstream->num_samples = read_32bitBE(0x0C,infile)/16*28;
|
||||
vgmstream->meta_type=meta_PS2_VAGp;
|
||||
interleave=0x10; // used for loop calc
|
||||
start_offset=0x30;
|
||||
break;
|
||||
case 'V': // pGAV
|
||||
vgmstream->layout_type=layout_interleave;
|
||||
interleave=0x2000;
|
||||
|
||||
// Jak X hack ...
|
||||
if(read_32bitLE(0x1000,infile)==0x56414770)
|
||||
interleave=0x1000;
|
||||
|
||||
vgmstream->sample_rate = read_32bitLE(0x10,infile);
|
||||
vgmstream->num_samples = read_32bitLE(0x0C,infile)/16*14;
|
||||
vgmstream->meta_type=meta_PS2_pGAV;
|
||||
start_offset=0;
|
||||
break;
|
||||
}
|
||||
|
||||
vgmstream->interleave_block_size=interleave;
|
||||
|
||||
/* Don't add the header size to loop calc points */
|
||||
loopStart-=start_offset;
|
||||
loopEnd-=start_offset;
|
||||
|
||||
if(loop_flag!=0) {
|
||||
vgmstream->loop_start_sample = (int32_t)((loopStart/(interleave*channel_count))*interleave)/16*28;
|
||||
vgmstream->loop_start_sample += (int32_t)(loopStart%(interleave*channel_count))/16*28;
|
||||
vgmstream->loop_end_sample = (int32_t)((loopEnd/(interleave*channel_count))*interleave)/16*28;
|
||||
vgmstream->loop_end_sample += (int32_t)(loopEnd%(interleave*channel_count))/16*28;
|
||||
}
|
||||
|
||||
/* Compression Scheme */
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
|
||||
close_streamfile(infile); infile=NULL;
|
||||
|
||||
/* open the file for reading by each channel */
|
||||
{
|
||||
for (i=0;i<channel_count;i++) {
|
||||
vgmstream->ch[i].streamfile = open_streamfile_buffer(filename,vgmstream->interleave_block_size);
|
||||
|
||||
if (!vgmstream->ch[i].streamfile) goto fail;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset=
|
||||
vgmstream->ch[i].offset=
|
||||
(off_t)(start_offset+vgmstream->interleave_block_size*i);
|
||||
}
|
||||
}
|
||||
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (infile) close_streamfile(infile);
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
* List of functions that will recognize files. These should correspond pretty
|
||||
* directly to the metadata types
|
||||
*/
|
||||
#define INIT_VGMSTREAM_FCNS 27
|
||||
#define INIT_VGMSTREAM_FCNS 28
|
||||
VGMSTREAM * (*init_vgmstream_fcns[INIT_VGMSTREAM_FCNS])(const char * const) = {
|
||||
init_vgmstream_adx, /* 0 */
|
||||
init_vgmstream_brstm, /* 1 */
|
||||
@ -44,6 +44,7 @@ VGMSTREAM * (*init_vgmstream_fcns[INIT_VGMSTREAM_FCNS])(const char * const) = {
|
||||
init_vgmstream_ps2_mic, /* 24 */
|
||||
init_vgmstream_ngc_dsp_std_int, /* 25 */
|
||||
init_vgmstream_raw, /* 26 */
|
||||
init_vgmstream_ps2_vag, /* 27 */
|
||||
};
|
||||
|
||||
|
||||
@ -72,7 +73,7 @@ VGMSTREAM * init_vgmstream_internal(const char * const filename, int do_dfs) {
|
||||
}
|
||||
|
||||
/* dual file stereo */
|
||||
if (do_dfs && vgmstream->meta_type == meta_DSP_STD && vgmstream->channels == 1) {
|
||||
if (do_dfs && ((vgmstream->meta_type == meta_DSP_STD) || (vgmstream->meta_type == meta_PS2_VAGp)) && vgmstream->channels == 1) {
|
||||
try_dual_file_stereo(vgmstream, filename);
|
||||
}
|
||||
|
||||
@ -637,6 +638,15 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
||||
break;
|
||||
case meta_RAW:
|
||||
snprintf(temp,TEMPSIZE,"assumed RAW PCM file by .raw extension");
|
||||
break;
|
||||
case meta_PS2_VAGi:
|
||||
snprintf(temp,TEMPSIZE,"Sony VAG Interleaved header (VAGi)");
|
||||
break;
|
||||
case meta_PS2_VAGp:
|
||||
snprintf(temp,TEMPSIZE,"Sony VAG Mono header (VAGp)");
|
||||
break;
|
||||
case meta_PS2_pGAV:
|
||||
snprintf(temp,TEMPSIZE,"Sony VAG Stereo Little Endian header (pGAV)");
|
||||
break;
|
||||
default:
|
||||
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");
|
||||
|
@ -88,6 +88,9 @@ typedef enum {
|
||||
meta_PS2_MIB, /* MIB File */
|
||||
meta_PS2_MIB_MIH, /* MIB File + MIH Header*/
|
||||
meta_PS2_MIC, /* KOEI MIC File */
|
||||
meta_PS2_VAGi, /* VAGi Interleaved File */
|
||||
meta_PS2_VAGp, /* VAGp Mono File */
|
||||
meta_PS2_pGAV, /* VAGp with Little Endian Header */
|
||||
|
||||
meta_PSX_XA, /* CD-XA with RIFF header */
|
||||
|
||||
|
@ -71,7 +71,7 @@ int fade_samples = 0;
|
||||
|
||||
#define EXTENSION_LIST_SIZE 1024
|
||||
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
|
||||
#define EXTENSION_COUNT 27
|
||||
#define EXTENSION_COUNT 28
|
||||
char * extension_list[EXTENSION_COUNT] = {
|
||||
"adx\0ADX Audio File (*.ADX)\0",
|
||||
"afc\0AFC Audio File (*.AFC)\0",
|
||||
@ -100,6 +100,7 @@ char * extension_list[EXTENSION_COUNT] = {
|
||||
"gcm\0GCM Audio File (*.GCM)\0",
|
||||
"mss\0MSS Audio File (*.MSS)\0",
|
||||
"raw\0RAW Audio File (*.RAW)\0",
|
||||
"vag\0VAG Audio File (*.VAG)\0",
|
||||
};
|
||||
|
||||
void about(HWND hwndParent) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user