コード例 #1
0
        public static Celt FromStream(Stream stream)
        {
            Celt celt = new Celt();

            using (AwesomeReader ar = new AwesomeReader(stream, false))
            {
                // Checks for "BFAD" magic
                switch (ar.ReadInt32())
                {
                case MAGIC:
                    ar.BigEndian = false;
                    break;

                case MAGIC_R:
                    ar.BigEndian = true;
                    break;

                default:
                    throw new Exception("Invalid magic. Expected \"BFAD\"");
                }

                celt.BigEndian = ar.BigEndian; // Sets endianess

                // Parses header information
                celt.Channels     = ar.ReadUInt16();
                celt.Encrypted    = Convert.ToBoolean(ar.ReadInt16());
                celt.TotalSamples = ar.ReadUInt32();
                celt.Bitrate      = ar.ReadUInt32();

                celt.FrameSize  = ar.ReadUInt16();
                celt.Unknown1   = ar.ReadUInt16();
                celt.SampleRate = ar.ReadUInt16();
                celt.Unknown2   = ar.ReadUInt16();

                celt.ReckoningOffset    = ar.ReadUInt32();
                celt.ReckoningSize      = ar.ReadUInt32();
                celt.PacketStreamOffset = ar.ReadUInt32();
                celt.PacketStreamSize   = ar.ReadUInt32();
                celt.FixOffsets();                                                // Only useful for audio extracted from RAM, harmless

                uint reckonSize = celt.PacketStreamOffset - celt.ReckoningOffset; // Multiple of 4
                uint streamSize = celt.PacketStreamSize;

                if ((reckonSize + streamSize) % 16 != 0)
                {
                    streamSize += 16 - ((reckonSize + streamSize) % 16);
                }

                if (celt.Encrypted)
                {
                    var encryptedBytes = ar.ReadBytes((int)(reckonSize + streamSize));

                    // Decrypt audio data in ECB mode with the 256-bit key
                    using (Aes aes = Aes.Create())
                    {
                        aes.Mode      = CipherMode.ECB;
                        aes.KeySize   = 256;
                        aes.BlockSize = 128;
                        aes.Padding   = PaddingMode.None;
                        using (var decryptor = aes.CreateDecryptor(AesKey, new byte[16]))
                        {
                            decryptor.TransformBlock(encryptedBytes, 0, encryptedBytes.Length, encryptedBytes, 0);
                        }
                    }

                    celt.Reckoning    = new byte[reckonSize];
                    celt.PacketStream = new byte[streamSize];
                    Array.Copy(encryptedBytes, celt.Reckoning, reckonSize);
                    Array.Copy(encryptedBytes, reckonSize, celt.PacketStream, 0, streamSize);
                    celt.Encrypted = false;
                }
                else
                {
                    celt.Reckoning    = ar.ReadBytes((int)reckonSize);
                    celt.PacketStream = ar.ReadBytes((int)streamSize);
                }
            }

            return(celt);
        }
コード例 #2
0
ファイル: Celt.cs プロジェクト: PikminGuts92/BFForever
        public static Celt FromAudio(string path)
        {
            // TODO: Clean all of this up and implement tracking packet offsets
            AudioFileReader afr  = new AudioFileReader(path);
            Celt            celt = new Celt()
            {
                SampleRate = (ushort)afr.WaveFormat.SampleRate
            };

            OpusEncoder encoder = OpusEncoder.Create(celt.SampleRate, NUM_CHANNELS, OpusApplication.OPUS_APPLICATION_AUDIO);

            encoder.Bitrate    = (int)celt.Bitrate;
            encoder.ForceMode  = OpusMode.MODE_CELT_ONLY;
            encoder.SignalType = OpusSignal.OPUS_SIGNAL_MUSIC;

            float[] buffer = new float[celt.FrameSize * NUM_CHANNELS];
            byte[]  packet = new byte[MAX_PACKET_SIZE];

            byte[]     packetSize = new byte[2];
            bool       skipMode   = true;
            List <int> recks      = new List <int>()
            {
                0
            };

            MemoryStream ms = new MemoryStream();

            // Encoding loop
            while (afr.Position < afr.Length)
            {
                int bufferLength = afr.Read(buffer, 0, buffer.Length);
                int packetLength = encoder.Encode(buffer, 0, celt.FrameSize, packet, 0, packet.Length);

                // Tracks reckoning counts
                if (packetLength <= 3) // Checks if packet is empty
                {
                    if (!skipMode)
                    {
                        recks.Add(0);
                        skipMode = !skipMode;
                    }

                    recks[recks.Count - 1] += 1;
                    continue;
                }
                else
                {
                    if (skipMode)
                    {
                        recks.Add(0);
                        skipMode = !skipMode;
                    }

                    recks[recks.Count - 1] += 1;
                }

                // Encodes 15-bit packet size
                packetSize[0] = (byte)(0x80 | (0xFF & (packetLength >> 8)));
                packetSize[1] = (byte)(0xFF & packetLength);

                ms.Write(packetSize, 0, packetSize.Length);
                ms.Write(packet, 0, packetLength);
            }

            int packetCount = recks.Sum();

            int hdEncodeSize;

            byte[] hdBytes;

            // Writes packet offsets
            using (MemoryStream hdStream = new MemoryStream())
            {
                byte[] hdBuff = new byte[2];

                foreach (int count in recks)
                {
                    if (count > 127)
                    {
                        // Encodes as two bytes
                        hdBuff[0] = (byte)(0x80 | (0xFF & (count >> 8)));
                        hdBuff[1] = (byte)(0xFF & count);
                        hdStream.Write(hdBuff, 0, 2);
                    }
                    else
                    {
                        // Encodes as one byte
                        hdBuff[0] = (byte)count;
                        hdStream.Write(hdBuff, 0, 1);
                    }
                }

                hdEncodeSize = (int)hdStream.Length;

                // Adds remaining bytes
                if (hdEncodeSize % 4 != 0)
                {
                    int difference = 4 - (hdEncodeSize % 4);
                    hdStream.Write(new byte[difference], 0, difference);
                }

                hdBytes = hdStream.ToArray();
            }

            celt.TotalSamples = (uint)(packetCount * celt.FrameSize);

            celt.Reckoning       = hdBytes;
            celt.ReckoningOffset = 40;
            celt.ReckoningSize   = (uint)hdEncodeSize;

            celt.PacketStreamOffset = (uint)(40 + hdBytes.Length);
            celt.PacketStreamSize   = (uint)ms.Length;

            // Adds remaining bytes
            if ((ms.Length + hdBytes.Length) % 16 != 0)
            {
                int difference = 16 - ((int)(ms.Length + hdBytes.Length) % 16);
                ms.Write(new byte[difference], 0, difference);
            }

            celt.PacketStream = ms.ToArray();
            return(celt);
        }