From 75485c388ee22ba8fafdc887f3398be201b21d95 Mon Sep 17 00:00:00 2001 From: bnnm Date: Tue, 20 Dec 2016 23:29:36 +0100 Subject: [PATCH] Moved VAG loop finder to function; comments, code preps --- src/meta/ps2_vag.c | 155 +++++++++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 67 deletions(-) diff --git a/src/meta/ps2_vag.c b/src/meta/ps2_vag.c index 5b433121..bda67750 100644 --- a/src/meta/ps2_vag.c +++ b/src/meta/ps2_vag.c @@ -1,101 +1,66 @@ #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 : +static int vag_find_loop_points(STREAMFILE *streamFile, off_t * loop_start, off_t * loop_end); - i : interleaved format +/* PS2 VAG format, found in many Sony games 2008-05-17 - Fastelbja : First version ... */ - VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; char filename[PATH_LIMIT]; - - // 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=1; + int channel_count=0; int i; + int loop_samples_found = 0; /* check extension, case insensitive */ streamFile->get_name(streamFile,filename,sizeof(filename)); if (strcasecmp("vag",filename_extension(filename))) goto fail; /* check VAG Header */ - if (((read_32bitBE(0x00,streamFile) & 0xFFFFFF00) != 0x56414700) && + if (((read_32bitBE(0x00,streamFile) & 0xFFFFFF00) != 0x56414700) && /* "VAG\0" */ ((read_32bitLE(0x00,streamFile) & 0xFFFFFF00) != 0x56414700)) goto fail; - /* Check for correct channel count */ + /* Check for correct channel count and loop flag */ vagID=read_8bit(0x03,streamFile); switch(vagID) { - case '1': + case '1': /* "VAG1" (1 channel) */ channel_count=1; break; - case '2': + case '2': /* "VAG2" (2 channels) */ channel_count=2; break; - case 'i': + case 'i': /* "VAGi" (interleaved) */ channel_count=2; break; - case 'V': - if(read_32bitBE(0x20,streamFile)==0x53746572) // vag Stereo + case 'V': /* pGAV (little endian header) */ + if(read_32bitBE(0x20,streamFile)==0x53746572) /* "Ster" */ channel_count=2; - case 'p': + else + channel_count=1; + break; + case 'p': /* "VAGp" (extended) */ if((read_32bitBE(0x04,streamFile)<=0x00000004) && (read_32bitBE(0x0c,streamFile)<(get_streamfile_size(streamFile)/2))) { loop_flag=(read_32bitBE(0x14,streamFile)!=0); channel_count=2; - } else { - /* Search for loop in VAG */ - fileLength = get_streamfile_size(streamFile); - - do { - readOffset+=0x10; - - // Loop Start ... - if(read_8bit(readOffset+0x01,streamFile)==0x06) { - if(loopStart==0) loopStart = readOffset; - } - - // Loop End ... - if(read_8bit(readOffset+0x01,streamFile)==0x03) { - if(loopEnd==0) loopEnd = readOffset; - } - - // Loop from end to beginning ... - if((read_8bit(readOffset+0x01,streamFile)==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,streamFile); - if((readbuf[0]!=0) && (readbuf[0]!=0x0c)) { - if(memcmp(readbuf,eofVAG,0x10) && (memcmp(readbuf,eofVAG2,0x10))) { - loopStart = 0x40; - loopEnd = readOffset; - } - } - } - - } while (streamFile->get_offset(streamFile)<(off_t)fileLength); - loop_flag = (loopEnd!=0); + } + else { + loop_flag = vag_find_loop_points(streamFile, &loopStart, &loopEnd); /* offset 0x30 */ + channel_count = 1; } break; default: @@ -108,8 +73,9 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { /* fill in the vital statistics */ vgmstream->channels = channel_count; + vgmstream->coding_type = coding_PSX; - switch(vagID) { + switch(vagID) { case '1': // VAG1 vgmstream->layout_type=layout_none; vgmstream->sample_rate = read_32bitBE(0x10,streamFile); @@ -137,7 +103,7 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { break; case 'p': // VAGp vgmstream->sample_rate = read_32bitBE(0x10,streamFile); - interleave=0x10; // used for loop calc + interleave=0x10; if((read_32bitBE(0x04,streamFile)==0x00000004) && (read_32bitBE(0x0c,streamFile)<(get_streamfile_size(streamFile)/2))) { vgmstream->channels=2; @@ -146,6 +112,7 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { if(loop_flag) { vgmstream->loop_start_sample=read_32bitBE(0x14,streamFile); vgmstream->loop_end_sample =read_32bitBE(0x18,streamFile); + loop_samples_found = 1; } start_offset=0x80; @@ -158,8 +125,8 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { interleave=0x1000; start_offset=0; } - - } else { + } + else { vgmstream->layout_type=layout_none; vgmstream->num_samples = read_32bitBE(0x0C,streamFile)/16*28; vgmstream->meta_type=meta_PS2_VAGp; @@ -186,20 +153,16 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { vgmstream->interleave_block_size=interleave; /* Don't add the header size to loop calc points */ - if(vgmstream->meta_type!=meta_PS2_VAGs) { + if(loop_flag && !loop_samples_found) { 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; - } + 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; /* open the file for reading by each channel */ { @@ -225,3 +188,61 @@ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; } + + +/** + * Finds loop points in VAG data using flag markers and updates loop_start and loop_end with the offsets. + * + * returns 0 if not found + */ +static int vag_find_loop_points(STREAMFILE *streamFile, off_t * loop_start, off_t * loop_end) { + off_t loopStart = 0; + off_t loopEnd = 0; + + /* 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]; + + /* Search for loop in VAG */ + size_t fileLength = get_streamfile_size(streamFile); + + + off_t readOffset = 0x20; + do { + readOffset+=0x10; + + // Loop Start ... + if(read_8bit(readOffset+0x01,streamFile)==0x06) { + if(loopStart==0) loopStart = readOffset; + } + + // Loop End ... + if(read_8bit(readOffset+0x01,streamFile)==0x03) { + if(loopEnd==0) loopEnd = readOffset; + } + + // Loop from end to beginning ... + if((read_8bit(readOffset+0x01,streamFile)==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,streamFile); + if((readbuf[0]!=0) && (readbuf[0]!=0x0c)) { + if(memcmp(readbuf,eofVAG,0x10) && (memcmp(readbuf,eofVAG2,0x10))) { + loopStart = 0x40; + loopEnd = readOffset; + } + } + } + + } while (streamFile->get_offset(streamFile)<(off_t)fileLength); + + + if (loopEnd) { + *loop_start = loopStart; + *loop_end = loopEnd; + return 1; + } + + return 0; +}