[psp][lumines]vag解码程序

vag是dvd音频格式,lumines中使用的略有不同,不分512块的左右声道,而是左右各一个文件。单个声道内连续存放数据块。
修改后可以解为wav.

#include <stdio.h>
#include 
<string.h>
#include 
<stdlib.h>

struct VAGState
{
    VAGState() 
{ Reset(); }
    
    
void Reset() { s[0= s[1= 0; }
    
    
double s[2];
}
;

void DecodeVAGBlock(const unsigned char in[16], short out[28], VAGState* state);

const double filter[5][2=
{
    
0.00.0 },
    
60.0 / 64.00.0 },
    
115.0 / 64.0-52.0 / 64.0 },
    
98.0 / 64.0-55.0 / 64.0 },
    
122.0 / 64.0-60.0 / 64.0 }
}
;

const unsigned char wavhdr[44=
{
    
'R','I','F','F',
        
0,0,0,0,  // length of file - 8
        'W','A','V','E',
        
        
'f','m','t',' ',
        
0x10,0,0,0,
        
1,0,2,0,
        
0,0,0,0,  // sample rate
        0,0xF4,1,0,
        
4,0,0x10,0,
        
        
'd','a','t','a',
        
0,0,0,0,  // length of file - 0x2C
}
;

int main(int argc, char *argv[])
{
    
int rate = 32000;
    
    argc
--;
    argv
++;
    
    
while (argc && (argv[0][0== '-'))
    
{
        
char parm = argv[0][1];
        
        
if (parm == 'r')
        
{
            
if (argv[0][2])
            
{
                rate 
= atoi(argv[0+ 2);
            }

            
else
            
{
                argc
--;
                argv
++;
                rate 
= atoi(argv[0]);
            }

            
            printf(
"Sample rate : %d\n", rate);
        }

        
        argc
--;
        argv
++;
    }

    
    
char src[256];
    
char dst[256];
    
    
if (argc == 1)
    
{
        sprintf(src, 
"%s", argv[0]);
        sprintf(dst, 
"%s.WAV", argv[0]);
    }

    
else if (argc == 2)
    
{
        strcpy(src, argv[
0]);
        strcpy(dst, argv[
1]);
    }

    
else
    
{
        printf(
"Usage: Decode [-r | []\n");
        
return -1;
    }

    
    FILE
* vag = fopen(src, "rb");
    
if (!vag)
    
{
        printf(
"Can't open source file %s\n", src);
        
return -1;
    }

    
    
// find number of blocks
    fseek(vag, 0, SEEK_END);
    
int length = (ftell(vag) - 0x40/ 16;
    fseek(vag, 
0x0c, SEEK_SET);
    unsigned 
char buf[8];
    fread(buf, 
2sizeof(unsigned long), vag);
    length 
= ((unsigned int)buf[0]<<24+ ((unsigned int)buf[1]<<16+ ((unsigned int)buf[2]<<8+ (unsigned int)buf[3];
    length 
-= 0x20;
    rate 
= ((unsigned int)buf[4]<<24+ ((unsigned int)buf[5]<<16+ ((unsigned int)buf[6]<<8+ (unsigned int)buf[7];
    rate
/=2;
    fseek(vag, 
0x20, SEEK_SET);
    fread(dst, 
0x201, vag);
    fseek(vag, 
0x40, SEEK_SET);
    
const int size = 1;

    
//length /= size*2;
    
    FILE
* wav = fopen(dst, "wb");
    
if (!wav)
    
{
        printf(
"Can't open destination file %s\n", dst);
        
return -1;
    }

    
    printf(
"Length : %d blocks\n", length);
    
    unsigned 
char hdr[44];
    
int*  ihdr = (int*)hdr;
    memcpy(hdr, wavhdr, 
44);
    ihdr[
1= length * 28 * size * 2 + 0x24;
    ihdr[
10= length * 28 * size * 2;
    ihdr[
6= rate;
    
    fwrite(hdr, 
144, wav);
    
    VAGState st[
2];
    unsigned 
char bl[size * 16];
    
short out[size * 28 * 2];
    
    
extern int vag_depack(unsigned char *entree, unsigned char *sortie );
    
    
for (int blk = 0; blk < length; blk+=16)
    
{
        
short obuf[28];
        fread(bl, 
161, vag);
        
int flags = (bl[1>> 4 ) & 0x0f;
        
if (flags == 7)
            
break;
        
if (flags ==3)
            
break;
        
if (flags ==4)
            
break;
        
if (flags ==6)
            
break;
        DecodeVAGBlock(bl, obuf, 
&st[0]);
        fwrite(obuf, 
228, wav);
    }

    fclose(wav);
    fclose(vag);
    
    
return 0;
}


int highnibble(int a) return (a >> 4& 15; }
int lownibble(int a) return a & 15; }

short quantize(double sample)
{
    
int a = int(sample + 0.5);
    
    
if (a < -32768return -32768
    
if (a > 32767return 32767;
    
    
return short(a);
}


void DecodeVAGBlock(const unsigned char in[16], short out[28], VAGState* state)
{
    
double s[2];
    
    s[
0= state->s[0];
    s[
1= state->s[1];
    
    
int predictor = highnibble(in[0]);
    
int shift = lownibble(in[0]);
    
int flags = in[1];
    
    
if (predictor > 4)
    
{
        
// this should never happen in a valid VAG block
        printf("Predictor %d!\n", predictor);
        predictor 
= 0;
    }

    
int ii;
    
for (ii = 0; ii < 14; ii++)
    
{
        
int byte = in[ii + 2];
        
        
out[ii * 2= short(lownibble(byte<< 12>> shift;
        
out[ii * 2 + 1= short(highnibble(byte<< 12>> shift;
    }

    
    
for (ii = 0; ii < 28; ii++)
    
{
        
double filt = out[ii] + s[0* filter[predictor][0+ s[1* filter[predictor][1];
        s[
1= s[0];
        s[
0= filt;
        
        
out[ii] = quantize(filt);
    }

    
    state
->s[0= s[0];
    state
->s[1= s[1];
}

原文地址:https://www.cnblogs.com/kaikai/p/189997.html