Пример #1
0
        public void parseSTREAMMetadata(string[] STREAMMetadata)
        {
            STREAM_ID    = convertStringtoInt(getSpecificFileInfoProperties("STREAM ID: ", STREAMMetadata));
            audioEntries = convertStringtoInt(getSpecificFileInfoProperties("Number of audio files: ", STREAMMetadata));

            for (int i = 0; i < audioEntries; i++)
            {
                STREAMFileInfo streamFileInfo = new STREAMFileInfo();
                string         from           = "#Sound: " + (i + 1).ToString();
                string         end            = "#Sound: " + (i + 2).ToString();
                // Getting individual Info for each files
                string[] STREAMSoundInfo = getSpecificFileInfoPropertiesRegion(STREAMMetadata, from, end);

                uint   codec        = convertStringtoUInt(getSpecificFileInfoProperties("Codec: ", STREAMSoundInfo));
                uint   loop_start   = convertStringtoUInt(getSpecificFileInfoProperties("Loop Start: ", STREAMSoundInfo));
                uint   loop_length  = convertStringtoUInt(getSpecificFileInfoProperties("Loop Length: ", STREAMSoundInfo));
                uint   loop_flag    = convertStringtoUInt(getSpecificFileInfoProperties("Loop Flag: ", STREAMSoundInfo));
                float  loop_float   = convertStringtoFloat(getSpecificFileInfoProperties("Loop Float: ", STREAMSoundInfo));
                float  loop_float_2 = convertStringtoFloat(getSpecificFileInfoProperties("Loop Float 2: ", STREAMSoundInfo));
                uint   var_0x50     = convertStringtoUInt(getSpecificFileInfoProperties("var_0x50: ", STREAMSoundInfo));
                uint   var_0x54     = convertStringtoUInt(getSpecificFileInfoProperties("var_0x54: ", STREAMSoundInfo));
                uint   var_0x60     = convertStringtoUInt(getSpecificFileInfoProperties("var_0x60: ", STREAMSoundInfo));
                float  var_0x6C     = convertStringtoFloat(getSpecificFileInfoProperties("var_0x6C: ", STREAMSoundInfo));
                uint   var_0x70     = convertStringtoUInt(getSpecificFileInfoProperties("var_0x70: ", STREAMSoundInfo));
                uint   var_0x9C     = convertStringtoUInt(getSpecificFileInfoProperties("var_0x9C: ", STREAMSoundInfo));
                uint   var_0xAC     = convertStringtoUInt(getSpecificFileInfoProperties("var_0xAC: ", STREAMSoundInfo));
                string file_Name    = getSpecificFileInfoProperties("fileName: ", STREAMSoundInfo);

                streamFileInfo.codec        = codec;
                streamFileInfo.loop_start   = loop_start;
                streamFileInfo.loop_length  = loop_length;
                streamFileInfo.loop_flag    = loop_flag;
                streamFileInfo.loop_float   = loop_float;
                streamFileInfo.loop_float_2 = loop_float_2;
                streamFileInfo.var_0x50     = var_0x50;
                streamFileInfo.var_0x54     = var_0x54;
                streamFileInfo.var_0x60     = var_0x60;
                streamFileInfo.var_0x6C     = var_0x6C;
                streamFileInfo.var_0x70     = var_0x70;
                streamFileInfo.var_0x9C     = var_0x9C;
                streamFileInfo.var_0xAC     = var_0xAC;
                streamFileInfo.file_Name    = file_Name;

                streamFileInfoList.Add(streamFileInfo);
            }
        }
Пример #2
0
        public MemoryStream repackAudioFiles()
        {
            MemoryStream STREAM       = new MemoryStream();
            MemoryStream STREAMHeader = new MemoryStream();
            MemoryStream STREAMData   = new MemoryStream();

            MemoryStream STREAMGeneralInfo = new MemoryStream();
            MemoryStream STREAMAudioInfo   = new MemoryStream();

            List <uint> STREAMInfoPointers = new List <uint>();
            // Calculate the first pointer.
            // Stream general info header is 0x20 in length, and each info file occupies 4 byte pointer, alongside padding.

            uint first_Pointer = (uint)addPaddingSizeCalculation(0x20 + (soundFiles.Count * 0x4));

            STREAMInfoPointers.Add(first_Pointer);

            for (int i = 0; i < soundFiles.Count; i++)
            {
                STREAMFileInfo fileInfo = streamFileInfoList[i];
                // check the info's codec, we target the repack conversion to this.
                uint codec = fileInfo.codec;
                supportedAudioCodec targetCodec = determineInfoCodec(codec);

                FileInfo     file = soundFiles[i];
                FileStream   fs   = file.OpenRead();
                MemoryStream ms   = new MemoryStream();
                fs.CopyTo(ms);

                ms.Seek(0, SeekOrigin.Begin);
                fileName = Path.GetFileName(file.FullName);

                supportedAudioCodec currentCodec = supportedAudioCodec.NONE;

                MemoryStream baseFormatStream = new MemoryStream();
                // Converting the input file to pcm if the file is not the same as the targetCodec
                uint magic = readUIntBigEndian(ms);
                switch (magic)
                {
                case 0x52494646:     // RIFF (pcm, at3)
                    // Need to call this to set the correct currentCodec (differentiate between pcm and at3)
                    currentCodec = determineRIFFCodec(ms);
                    convertToBaseFormat(file, currentCodec, targetCodec).CopyTo(baseFormatStream);
                    break;

                case 0x424E5346:     // BNSF (is14)
                    currentCodec = supportedAudioCodec.BNSF;
                    convertToBaseFormat(file, currentCodec, targetCodec).CopyTo(baseFormatStream);
                    break;

                case 0x56414770:     // VAGp (vag)
                    currentCodec = supportedAudioCodec.VAG;
                    convertToBaseFormat(file, currentCodec, targetCodec).CopyTo(baseFormatStream);
                    break;

                default:
                    break;
                }

                // format ms to be appended on STREAM header.
                MemoryStream sub_header_MS;
                // the actual stream audio data to be appended.
                MemoryStream stream_data_MS;

                baseFormatStream.Seek(0, SeekOrigin.Begin);
                uint baseFmtMagic = readUIntBigEndian(baseFormatStream);

                switch (targetCodec)
                {
                case supportedAudioCodec.AT3:
                    if (baseFmtMagic == 0x52494646 && determineRIFFCodec(baseFormatStream) == supportedAudioCodec.PCM)
                    {
                        baseFormatStream = new MemoryStream(convertWAVtoAT3(file.FullName));
                    }
                    parseAT3(baseFormatStream, out sub_header_MS, out stream_data_MS);
                    break;

                case supportedAudioCodec.BNSF:
                    if (baseFmtMagic == 0x52494646)
                    {
                        // the only way to know sample size (duration) of the audio file is to calculate through the unencoded RIFF file.
                        uint sample_size = determinePCMSampleSize(baseFormatStream);
                        baseFormatStream = new MemoryStream(convertPCMtoBNSF(file.FullName, 48000, 14000, sample_size));
                    }
                    parseBNSF(baseFormatStream, out sub_header_MS, out stream_data_MS);
                    break;

                case supportedAudioCodec.VAG:
                    if (baseFmtMagic == 0x52494646)
                    {
                        baseFormatStream = new MemoryStream(convertPCMtoVAG(file.FullName));
                    }
                    parseVAG(baseFormatStream, out sub_header_MS, out stream_data_MS);
                    break;

                default:
                    throw new Exception("Codec not yet supported for file: " + fileName);
                }

                // Start writing STREAM Header
                MemoryStream audio_Info = new MemoryStream();

                // write codec magic
                switch (targetCodec)
                {
                case supportedAudioCodec.AT3:
                    appendUIntMemoryStream(audio_Info, 0x61743300, true);
                    break;

                case supportedAudioCodec.BNSF:
                    appendUIntMemoryStream(audio_Info, 0x69733134, true);
                    break;

                case supportedAudioCodec.VAG:
                    appendUIntMemoryStream(audio_Info, 0x76616700, true);
                    break;

                default:
                    throw new Exception("Codec not yet supported for file: " + fileName);
                }

                // general infos
                appendIntMemoryStream(audio_Info, STREAM_ID, true);       // STREAM_ID
                appendUIntMemoryStream(audio_Info, (uint)i, true);        // file index
                appendUIntMemoryStream(audio_Info, fileInfo.codec, true); // codec enum
                appendUIntMemoryStream(audio_Info, 0, true);              // unk_0x10, always 0

                // size and offsets
                appendUIntMemoryStream(audio_Info, (uint)stream_data_MS.Length, true); // size of stream data
                appendUIntMemoryStream(audio_Info, (uint)STREAMData.Length, true);     // relative offset of the stream data from the top
                appendUIntMemoryStream(audio_Info, (uint)sub_header_MS.Length, true);  // subheader size

                // Loop stuff
                appendUIntMemoryStream(audio_Info, fileInfo.loop_start, true);
                appendUIntMemoryStream(audio_Info, fileInfo.loop_length, true);
                appendUIntMemoryStream(audio_Info, fileInfo.loop_flag, true);
                appendUIntMemoryStream(audio_Info, 0, true); // always 0

                // unknown section
                appendUIntMemoryStream(audio_Info, 0xFFFFFFFF, true);             // unk_0x30, always 0xFFFFFFFF
                appendFloatMemoryStream(audio_Info, fileInfo.loop_float, true);   // loop_float, if there's no loop this is populated.
                appendFloatMemoryStream(audio_Info, fileInfo.loop_float_2, true); // -99 float (0xC2C60000) without loop
                appendUIntMemoryStream(audio_Info, 0, true);                      // unk_0x3C, always 0

                appendUIntMemoryStream(audio_Info, 0, true);                      // unk_0x40, always 0
                appendUIntMemoryStream(audio_Info, 0, true);                      // unk_0x44, always 0
                appendFloatMemoryStream(audio_Info, 1, true);                     // unk_0x48, always 1 float (0x3F800000)
                appendUIntMemoryStream(audio_Info, 0, true);                      // unk_0x4C, always 0

                appendFloatMemoryStream(audio_Info, fileInfo.var_0x50, true);     // at3 / is14 = 1(Float), vag / wav = 0
                appendUIntMemoryStream(audio_Info, fileInfo.var_0x54, true);      // at3/is14 = 0xA, vag = 0x4, wav = 0
                appendFloatMemoryStream(audio_Info, 1, true);                     // unk_0x58, always 1 float (0x3F800000)
                appendFloatMemoryStream(audio_Info, 1, true);                     // unk_0x5C, always 1 float (0x3F800000)

                appendUIntMemoryStream(audio_Info, fileInfo.var_0x60, true);      // different for each header, not sure what.
                appendUIntMemoryStream(audio_Info, 0, true);                      // unk_0x64, always 0
                appendUIntMemoryStream(audio_Info, 0, true);                      // unk_0x68, always 0
                appendFloatMemoryStream(audio_Info, fileInfo.var_0x6C, true);     // vag = 0, others = -100

                appendUIntMemoryStream(audio_Info, fileInfo.var_0x70, true);      // different for each header, not sure what.
                appendUIntMemoryStream(audio_Info, 0x64, true);                   // unk_0x74, always 0x64
                appendUIntMemoryStream(audio_Info, 0, true);                      // unk_0x78, always 0
                appendUIntMemoryStream(audio_Info, 1, true);                      // unk_0x7C, always 1

                appendUIntMemoryStream(audio_Info, 0, true);                      // unk_0x80, always 0
                appendUIntMemoryStream(audio_Info, 0, true);                      // unk_0x84, always 0
                appendUIntMemoryStream(audio_Info, 0, true);                      // unk_0x88, always 0
                appendFloatMemoryStream(audio_Info, 1, true);                     // unk_0x8C, always 1

                appendUIntMemoryStream(audio_Info, 0x14, true);                   // unk_0x90, always 0x14
                appendUIntMemoryStream(audio_Info, 0, true);                      // unk_0x94, always 0
                appendUIntMemoryStream(audio_Info, 0, true);                      // unk_0x98, always 0
                appendUIntMemoryStream(audio_Info, fileInfo.var_0x9C, true);

                appendUIntMemoryStream(audio_Info, 0, true);                 // unk_0xA0, always 0
                appendUIntMemoryStream(audio_Info, 0, true);                 // unk_0xA4, always 0
                appendFloatMemoryStream(audio_Info, 1, true);                // unk_0xA8, always 1
                appendUIntMemoryStream(audio_Info, fileInfo.var_0xAC, true); // vag = 1, others = 0

                appendUIntMemoryStream(audio_Info, 0, true);                 // unk_0xB0, always 0
                appendUIntMemoryStream(audio_Info, 0, true);                 // unk_0xB4, always 0
                appendUIntMemoryStream(audio_Info, 0, true);                 // unk_0xB8, always 0

                sub_header_MS.Seek(0, SeekOrigin.Begin);
                sub_header_MS.CopyTo(audio_Info);
                addPaddingStream(audio_Info);

                uint nextPointer = STREAMInfoPointers.Last() + (uint)audio_Info.Length;
                STREAMInfoPointers.Add(nextPointer);

                MemoryStream stream_data_MS_appended = new MemoryStream();
                stream_data_MS.Seek(0, SeekOrigin.Begin);
                stream_data_MS.CopyTo(stream_data_MS_appended);
                addPaddingStream(stream_data_MS_appended);

                audio_Info.Seek(0, SeekOrigin.Begin);
                stream_data_MS_appended.Seek(0, SeekOrigin.Begin);
                audio_Info.CopyTo(STREAMAudioInfo);
                stream_data_MS_appended.CopyTo(STREAMData);
            }

            addPaddingStream(STREAMData);

            // Formula to know how many zero to append at the end of STREAM Header.
            // STREAM Header is stored in 2kb size sections. Hence, the size of the STREAM header must be divisible by 2048.
            // Hence, we get the last pointer to the audio Info, use modulo to find the remains, subtract the pointer with it to get the lower 2048 factor
            // After that we add the number with 2048
            uint lastPointer      = STREAMInfoPointers.Last();
            uint STREAMHeaderSize = (lastPointer - (lastPointer % 2048)) + 2048;
            uint appendSize       = STREAMHeaderSize - lastPointer;

            appendUIntMemoryStream(STREAMGeneralInfo, 0x00020100, true); // STREAM Version, also functions as magic
            appendUIntMemoryStream(STREAMGeneralInfo, 0, true);          // Should be 0 for all cases
            appendIntMemoryStream(STREAMGeneralInfo, STREAM_ID, true);
            appendUIntMemoryStream(STREAMGeneralInfo, (uint)soundFiles.Count, true);
            appendUIntMemoryStream(STREAMGeneralInfo, STREAMHeaderSize, true);
            appendUIntMemoryStream(STREAMGeneralInfo, (uint)STREAMData.Length, true);
            appendUIntMemoryStream(STREAMGeneralInfo, 0x20, true);                       // The size of general Info, should be 0x20 for all cases.
            appendUIntMemoryStream(STREAMGeneralInfo, STREAMInfoPointers.First(), true); // The starting point of the audio Info, or the first pointer

            for (int k = 0; k < STREAMInfoPointers.Count; k++)
            {
                uint pointer = STREAMInfoPointers[k];
                if (k != STREAMInfoPointers.Count - 1)
                {
                    appendUIntMemoryStream(STREAMGeneralInfo, pointer, true);
                }
            }

            addPaddingStream(STREAMGeneralInfo);

            STREAMGeneralInfo.Seek(0, SeekOrigin.Begin);
            STREAMAudioInfo.Seek(0, SeekOrigin.Begin);
            STREAMGeneralInfo.CopyTo(STREAMHeader);
            STREAMAudioInfo.CopyTo(STREAMHeader);
            appendZeroMemoryStream(STREAMHeader, (int)appendSize);

            STREAMHeader.Seek(0, SeekOrigin.Begin);
            STREAMData.Seek(0, SeekOrigin.Begin);
            STREAMHeader.CopyTo(STREAM);
            STREAMData.CopyTo(STREAM);
            return(STREAM);
        }