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); }