Author Topic: VAG File Format  (Read 4678 times)

Offline SilicaAndPina

  • Hot Pockets
  • End User
  • *****
  • Posts: 38
  • Its probably a wiccan thing..
    • View Profile
VAG File Format
« on: August 25, 2019, 10:19:04 AM »
PSVita has a new version of the VAG file format that was found on the PSP..

Header:

0x0: "VAGp" - Magic Identifier
0xC: Int32(Big Endain) - Waveform Data Size
0x10: Int32(Big Endain) - Sample Rate
0x1E: Int8 - Channels (0x0 = 1 mono, 0x2 = stereo)
0x20: String - Track Name
0x40: ADPCM Audio

Audio Data:
The audio data in VAG files is ADPCM compressed, though not in any standard way
samples are encoded in 0x10 blocks,
the structure of said blocks is as follows:

0x1: Decoding Coefficent
0x2: Loop Data
0x3: ADPCM Encoded Data

if the loop data byte is set to 0x7 then the sample is skipped.

The ADPCM Compression uses the following Coefficent Table:
Quote
    {
        private static int[,] HEVAGCoeffTable = new int[,]
        {
            {      0,     0,     0,     0 },
            {   7680,     0,     0,     0 },
            {  14720, -6656,     0,     0 },
            {  12544, -7040,     0,     0 },
            {  15616, -7680,     0,     0 },
            {  14731, -7059,     0,     0 },
            {  14507, -7366,     0,     0 },
            {  13920, -7522,     0,     0 },
            {  13133, -7680,     0,     0 },
            {  12028, -7680,     0,     0 },
            {  10764, -7680,     0,     0 },
            {   9359, -7680,     0,     0 },
            {   7832, -7680,     0,     0 },
            {   6201, -7680,     0,     0 },
            {   4488, -7680,     0,     0 },
            {   2717, -7680,     0,     0 },
            {    910, -7680,     0,     0 },
            {   -910, -7680,     0,     0 },
            {  -2717, -7680,     0,     0 },
            {  -4488, -7680,     0,     0 },
            {  -6201, -7680,     0,     0 },
            {  -7832, -7680,     0,     0 },
            {  -9359, -7680,     0,     0 },
            { -10764, -7680,     0,     0 },
            { -12028, -7680,     0,     0 },
            { -13133, -7680,     0,     0 },
            { -13920, -7522,     0,     0 },
            { -14507, -7366,     0,     0 },
            { -14731, -7059,     0,     0 },
            {   5376, -9216,  3328, -3072 },
            {  -6400, -7168, -3328, -2304 },
            { -10496, -7424, -3584, -1024 },
            {   -167, -2722,  -494,  -541 },
            {  -7430, -2221, -2298,   424 },
            {  -8001, -3166, -2814,   289 },
            {   6018, -4750,  2649, -1298 },
            {   3798, -6946,  3875, -1216 },
            {  -8237, -2596, -2071,   227 },
            {   9199,  1982, -1382, -2316 },
            {  13021, -3044, -3792,  1267 },
            {  13112, -4487, -2250,  1665 },
            {  -1668, -3744, -6456,   840 },
            {   7819, -4328,  2111,  -506 },
            {   9571, -1336,  -757,   487 },
            {  10032, -2562,   300,   199 },
            {  -4745, -4122, -5486, -1493 },
            {  -5896,  2378, -4787, -6947 },
            {  -1193, -9117, -1237, -3114 },
            {   2783, -7108, -1575, -1447 },
            {  -7334, -2062, -2212,   446 },
            {   6127, -2577,  -315,   -18 },
            {   9457, -1858,   102,   258 },
            {   7876, -4483,  2126,  -538 },
            {  -7172, -1795, -2069,   482 },
            {  -7358, -2102, -2233,   440 },
            {  -9170, -3509, -2674,  -391 },
            {  -2638, -2647, -1929, -1637 },
            {   1873,  9183,  1860, -5746 },
            {   9214,  1859, -1124, -2427 },
            {  13204, -3012, -4139,  1370 },
            {  12437, -4792,  -256,   622 },
            {  -2653, -1144, -3182, -6878 },
            {   9331, -1048,  -828,   507 },
            {   1642,  -620,  -946, -4229 },
            {   4246, -7585,  -533, -2259 },
            {  -8988, -3891, -2807,    44 },
            {  -2562, -2735, -1730, -1899 },
            {   3182,  -483,  -714, -1421 },
            {   7937, -3844,  2821, -1019 },
            {  10069, -2609,   314,   195 },
            {   8400, -3297,  1551,  -155 },
            {  -8529, -2775, -2432,  -336 },
            {   9477, -1882,   108,   256 },
            {     75, -2241,  -298, -6937 },
            {  -9143, -4160, -2963,     5 },
            {  -7270, -1958, -2156,   460 },
            {  -2740,  3745,  5936, -1089 },
            {   8993,  1948,  -683, -2704 },
            {  13101, -2835, -3854,  1055 },
            {   9543, -1961,   130,   250 },
            {   5272, -4270,  3124, -3157 },
            {  -7696, -3383, -2907,  -456 },
            {   7309,  2523,   434, -2461 },
            {  10275, -2867,   391,   172 },
            {  10940, -3721,   665,    97 },
            {     24,  -310, -1262,   320 },
            {  -8122, -2411, -2311,  -271 },
            {  -8511, -3067, -2337,   163 },
            {    326, -3846,   419,  -933 },
            {   8895,  2194,  -541, -2880 },
            {  12073, -1876, -2017,  -601 },
            {   8729, -3423,  1674,  -169 },
            {  12950, -3847, -3007,  1946 },
            {  10038, -2570,   302,   198 },
            {   9385, -2757,  1008,    41 },
            {  -4720, -5006, -2852, -1161 },
            {   7869, -4326,  2135,  -501 },
            {   2450, -8597,  1299, -2780 },
            {  10192, -2763,   360,   181 },
            {  11313, -4213,   833,    53 },
            {  10154, -2716,   345,   185 },
            {   9638, -1417,  -737,   482 },
            {   3854, -4554,  2843, -3397 },
            {   6699, -5659,  2249, -1074 },
            {  11082, -3908,   728,    80 },
            {  -1026, -9810,  -805, -3462 },
            {  10396, -3746,  1367,   -96 },
            {  10287,   988, -1915, -1437 },
            {   7953,  3878,  -764, -3263 },
            {  12689, -3375, -3354,  2079 },
            {   6641,  3166,   231, -2089 },
            {  -2348, -7354, -1944, -4122 },
            {   9290, -4039,  1885,  -246 },
            {   4633, -6403,  1748, -1619 },
            {  11247, -4125,   802,    61 },
            {   9807, -2284,   219,   222 },
            {   9736, -1536,  -706,   473 },
            {   8440, -3436,  1562,  -176 },
            {   9307, -1021,  -835,   509 },
            {   1698, -9025,   688, -3037 },
            {  10214, -2791,   368,   179 },
            {   8390,  3248,  -758, -2989 },
            {   7201,  3316,    46, -2614 },
            {    -88, -7809,  -538, -4571 },
            {   6193, -5189,  2760, -1245 },
            {  12325, -1290, -3284,   253 },
            {  13064, -4075, -2824,  1877 },
            {   5333,  2999,   775, -1132 },
        };

the ADPCM samples can then be decoded into PCM using the following code (C#)
Quote
public static byte[] DecodePCM()
        {
            int Hist = 0;
            int Hist2 = 0;
            int Hist3 = 0;
            int Hist4 = 0;

            int FileSize = GetWaveformDataSize() - 0x40;

            BinaryReader VagReader = new BinaryReader(VagStream);

            MemoryStream PCMStream = new MemoryStream();
            BinaryWriter PCMWriter = new BinaryWriter(PCMStream);
           
            VagStream.Seek(0x40, SeekOrigin.Begin);
 
            while (VagStream.Position < FileSize)
            {       
                byte DecodingCoefficent = VagReader.ReadByte();
                int ShiftBy = DecodingCoefficent & 0xf;
                int PredictNr = DecodingCoefficent >> 0x4;
                byte LoopData = VagReader.ReadByte();
                PredictNr |= LoopData & 0xF0;
                int LoopFlag = LoopData & 0xf;
                if (LoopFlag == 0x7)
                {
                    VagStream.Seek(14, SeekOrigin.Current);
                    Hist = 0;
                    Hist2 = 0;
                    Hist3 = 0;
                    Hist4 = 0;
                }
                else
                {

                    for (int i = 0; i < 14; i++)
                    {
                        byte ADPCMData = VagReader.ReadByte();
                        int SampleFlags = ADPCMData & 0xF;
                        int Coefficent;
                        short Sample;
                       
                        for(int ii = 0; ii <= 1; ii++)
                        {
                            if (SampleFlags > 7)
                            {
                                SampleFlags -= 16;
                            }

                            if (PredictNr < 128)
                            {
                                Coefficent = Hist * HEVAGCoeffTable[PredictNr, 0] + Hist2 * HEVAGCoeffTable[PredictNr, 1] + Hist3 * HEVAGCoeffTable[PredictNr, 2] + Hist4 * HEVAGCoeffTable[PredictNr, 3];
                            }
                            else
                            {
                                Coefficent = 0;
                            }

                            Sample = (short)(Coefficent / 32 + (SampleFlags << 20 - ShiftBy) + 128 >> 8 ) ;

                            PCMWriter.Write(Sample);


                            Hist4 = Hist3;
                            Hist3 = Hist2;
                            Hist2 = Hist;
                            Hist = Sample;

                            SampleFlags = ADPCMData >> 4;
                        }
                    }
                }
            }
           
       }


full "vag.cs" for reference: https://bitbucket.org/SilicaAndPina/cxml-decompiler/src/master/AppInfoCli/VAG.cs
« Last Edit: August 25, 2019, 10:24:01 AM by SilicaAndPina »