Beispiel #1
0
    public static void Write(byte[] data, string file)
    {
        Unity_Studio.EndianStream stream = new Unity_Studio.EndianStream(new System.IO.MemoryStream(data), Unity_Studio.EndianType.LittleEndian);

        // Because constructor is broken
        stream.endian = Unity_Studio.EndianType.LittleEndian;

        string magic = stream.ReadASCII(4);

        if (!magic.Equals("FSB5"))
        {
            return;
        }

        uint version           = stream.ReadUInt32();
        uint numSamples        = stream.ReadUInt32();
        uint sampleHeadersSize = stream.ReadUInt32();
        uint nameTableSize     = stream.ReadUInt32();
        uint dataSize          = stream.ReadUInt32();
        uint mode = stream.ReadUInt32();

        string zero  = stream.ReadASCII(8);
        string hash  = stream.ReadASCII(16);
        string dummy = stream.ReadASCII(8);

        long nameOffset = stream.Position + sampleHeadersSize;
        long baseOffset = nameOffset + nameTableSize;

        // Only support Vorbis
        if (mode != (int)FSBAudioFormat.FMOD_SOUND_FORMAT_VORBIS)
        {
            return;
        }

        for (int i = 0; i < numSamples; i++)
        {
            Ogg  ogg          = new Ogg();
            uint offset       = stream.ReadUInt32();
            bool extraHeaders = (offset & 0x01) != 0;
            uint type         = offset & ((1 << 7) - 1);
            offset        = (offset >> 7) * 0x20;
            ogg.channels  = (type >> 5) + 1;
            ogg.frequency = 44100;
            switch ((type >> 1) & ((1 << 4) - 1))
            {
            case 0: ogg.frequency = 4000; break;

            case 1: ogg.frequency = 8000; break;

            case 2: ogg.frequency = 11000; break;

            case 3: ogg.frequency = 12000; break;

            case 4: ogg.frequency = 16000; break;

            case 5: ogg.frequency = 22050; break;

            case 6: ogg.frequency = 24000; break;

            case 7: ogg.frequency = 32000; break;

            case 8: ogg.frequency = 44100; break;

            case 9: ogg.frequency = 48000; break;

            case 10: ogg.frequency = 96000; break;

            default: ogg.frequency = 44100; break;
            }

            uint unknown = stream.ReadUInt32() >> 2;

            while (extraHeaders)
            {
                byte dataByte = stream.ReadByte();
                extraHeaders = (dataByte & 0x01) != 0;
                long extraLen = dataByte >> 1;
                extraLen += stream.ReadByte() << 7;
                extraLen += stream.ReadByte() << 15;
                dataByte  = stream.ReadByte();
                if (dataByte == 0x02)
                {
                    ogg.channels = stream.ReadByte();
                    extraLen    -= 1;
                }
                if (dataByte == 0x04)
                {
                    ogg.frequency = stream.ReadUInt32();
                    extraLen     -= 4;
                }
                if (dataByte == 0x06)
                {
                    ogg.loopStart = stream.ReadUInt32();
                    ogg.loopEnd   = stream.ReadUInt32();
                    extraLen     -= 8;
                }
                if (dataByte == 0x16)
                {
                    ogg.crc32 = stream.ReadUInt32();
                    extraLen -= 4;
                }
                stream.Position += extraLen;
            }

            long nextFilePos = stream.Position;

            long size = stream.ReadUInt32();
            if (size == 0)
            {
                size = dataSize + baseOffset;
            }
            else
            {
                size = ((size >> 7) * 0x20) + baseOffset;
            }
            if (size < 0 || size > data.Length)
            {
                size = data.Length;
            }
            long fileOffset = baseOffset + offset;
            size -= fileOffset;

            if (i == 0)
            {
                WriteFile(stream, file, (int)fileOffset, (int)size, ogg);
            }
            else
            {
                WriteFile(stream, file + i, (int)fileOffset, (int)size, ogg);
            }

            stream.Position = nextFilePos;
        }
        stream.Dispose(true);
    }