public static byte[] ToPacket(PolycomPTTPacket packet)
        {
            List <byte> alertPacket = new List <byte>();

            // Op Code
            //alertPacket.Add(15);
            switch (packet.OpCode)
            {
            case OpCode.Alert:
                alertPacket.Add(15);
                break;

            case OpCode.Transmit:
                alertPacket.Add(16);
                break;

            case OpCode.EndOfTransmit:
                alertPacket.Add(255);
                break;
            }

            // Channel Number
            alertPacket.Add((byte)packet.ChannelNumber);

            //MAC
            string hsn = packet.HostSerialNumber;

            string[] hex = hsn.Split('-');
            //int value = Convert.ToInt32(hex[0], 16);

            alertPacket.Add((byte)Convert.ToInt32(hex[0], 16)); //F2
            alertPacket.Add((byte)Convert.ToInt32(hex[1], 16)); // 11
            alertPacket.Add((byte)Convert.ToInt32(hex[2], 16)); //15
            alertPacket.Add((byte)Convert.ToInt32(hex[3], 16)); //11

            // caller id length
            alertPacket.Add(13);

            char[] caller = packet.CallerID.ToCharArray();
            for (int i = 0; i < 13; i++)
            {
                if (i < caller.Length)
                {
                    alertPacket.Add((byte)caller[i]);
                }
                else
                {
                    alertPacket.Add(0);
                }
            }

            if (packet.OpCode == OpCode.Transmit)
            {
                //NO!
                //alertPacket.Add(9); // 09

                // codec
                if (packet.Codec == Codec.G711U)
                {
                    alertPacket.Add(0x00);
                }
                else if (packet.Codec == Codec.G722)
                {
                    alertPacket.Add(0x09);
                }
                else if (packet.Codec == Codec.G726QI)
                {
                    alertPacket.Add(0xFF);
                }

                // flags
                int flagsValue = Convert.ToInt32(packet.Flags, 16);
                alertPacket.Add((byte)flagsValue);

                // RTP info
                byte[] sampleBytes = BitConverter.GetBytes(packet.SampleCount);
                Array.Reverse(sampleBytes);

                //if (tt == TimestampType.Try1)
                {
                    alertPacket.AddRange(sampleBytes);
                }
                //else if (tt == TimestampType.Try2)
                {
                    //alertPacket.Add(sampleBytes[1]);
                    //alertPacket.Add(sampleBytes[2]);
                    //alertPacket.Add(sampleBytes[3]);
                    //alertPacket.Add(0);
                }

                //redundant audio
                if (packet.PreviousAudioData != null)
                {
                    alertPacket.AddRange(packet.PreviousAudioData);
                }

                //audio
                if (packet.AudioData != null)
                {
                    alertPacket.AddRange(packet.AudioData);
                }
            }

            return(alertPacket.ToArray());
        }
        internal void Send(int channelNumber, string callerId, Dictionary <uint, byte[]> audioData, Codec codec)
        {
            string mac = GetMacAddress();

            string hostSerialNumber = string.Format("{0}{1}-{2}{3}-{4}{5}-{6}{7}", mac[4], mac[5], mac[6], mac[7], mac[8], mac[9], mac[10], mac[11]);

            {
                PolycomPTTPacket alertPacket = new PolycomPTTPacket();
                alertPacket.OpCode           = OpCode.Alert;
                alertPacket.ChannelNumber    = channelNumber;
                alertPacket.CallerID         = callerId;
                alertPacket.HostSerialNumber = hostSerialNumber;

                for (int i = 0; i < 31; i++)
                {
                    //Console.WriteLine("Alert");
                    byte[] packetData = alertPacket.ToPacket();

                    if (i > 0)
                    {
                        WaitFor(_sleepBetweenAlertPackets);
                    }

                    SendPacket(packetData);
                }
            }

            byte[] previousAudioData = null;

            foreach (var audioDataItem in audioData)
            {
                PolycomPTTPacket audioPacket = new PolycomPTTPacket();
                audioPacket.OpCode           = OpCode.Transmit;
                audioPacket.ChannelNumber    = channelNumber;
                audioPacket.CallerID         = callerId;
                audioPacket.HostSerialNumber = hostSerialNumber;

                audioPacket.Codec       = codec;
                audioPacket.Flags       = "00";
                audioPacket.SampleCount = audioDataItem.Key;

                audioPacket.AudioData         = (byte[])audioDataItem.Value.Clone();
                audioPacket.PreviousAudioData = previousAudioData;

                //Console.WriteLine("Transmit");
                byte[] packetData = audioPacket.ToPacket();

                WaitFor(_sleepBetweenPackets);

                SendPacket(packetData);
                previousAudioData = (byte[])audioPacket.AudioData.Clone();
            }

            WaitFor(_sleepBeforeEndPackets);

            {
                PolycomPTTPacket endPacket = new PolycomPTTPacket();
                endPacket.OpCode           = OpCode.EndOfTransmit;
                endPacket.ChannelNumber    = channelNumber;
                endPacket.CallerID         = callerId;
                endPacket.HostSerialNumber = hostSerialNumber;

                for (int i = 0; i < 12; i++)
                {
                    //Console.WriteLine("EndOfTransmit");
                    byte[] packetData = endPacket.ToPacket();

                    if (i > 0)
                    {
                        WaitFor(_sleepBetweenEndPackets);
                    }

                    SendPacket(packetData);
                }
            }
        }
        public static PolycomPTTPacket Parse(byte[] data)
        {
            PolycomPTTPacket packet = new PolycomPTTPacket();

            int offset = 42;

            byte opCodeByte = data[offset + 0];

            if (opCodeByte == 0x0F)
            {
                packet.OpCode = OpCode.Alert;
            }
            else if (opCodeByte == 0x10)
            {
                packet.OpCode = OpCode.Transmit;
            }
            else if (opCodeByte == 0xFF)
            {
                packet.OpCode = OpCode.EndOfTransmit;
            }

            byte channel = data[offset + 1];

            packet.ChannelNumber = channel;

            byte[] serial = new byte[4];
            serial[0] = data[offset + 2];
            serial[1] = data[offset + 3];
            serial[2] = data[offset + 4];
            serial[3] = data[offset + 5];
            packet.HostSerialNumber = ByteArrayToString(serial);

            int    callerIdLength = data[offset + 6];
            int    currentOffset  = 0;
            string callerId       = "";

            for (int i = 0; i < callerIdLength; i++)
            {
                currentOffset = offset + 7 + i;
                byte cid = data[currentOffset];

                if (cid == 0)
                {
                    continue;
                }
                callerId += System.Text.Encoding.ASCII.GetString(new[] { cid });
            }
            packet.CallerID = callerId;

            if (packet.OpCode == OpCode.Transmit)
            {
                currentOffset += 1;

                //byte nullChar = data[currentOffset];

                //if (nullChar != 9)
                //{
                //    Console.WriteLine("wtf!");
                //}
                //currentOffset += 1;

                byte codec = data[currentOffset];
                if (codec == 0x00)
                {
                    packet.Codec = Codec.G711U;
                }
                else if (codec == 0x09)
                {
                    packet.Codec = Codec.G722;
                }
                else if (codec == 0xFF)
                {
                    packet.Codec = Codec.G726QI;
                }
                currentOffset += 1;


                byte flags = data[currentOffset];
                currentOffset += 1;
                packet.Flags   = ByteArrayToString(new byte[] { flags });

                byte[] sampleCount = new byte[4];
                sampleCount[0] = data[currentOffset];
                currentOffset += 1;
                sampleCount[1] = data[currentOffset];
                currentOffset += 1;
                sampleCount[2] = data[currentOffset];
                currentOffset += 1;
                sampleCount[3] = data[currentOffset];
                currentOffset += 1;



                packet.SampleCountString = ByteArrayToString(sampleCount);
                uint left = Convert.ToUInt32(packet.SampleCountString.Replace("-", ""), 16);
                //int right = BitConverter.ToUInt16(sampleCountRight, 0);
                //float f = float.Parse(left + "." + right);
                packet.SampleCount = left;



                List <byte> bytes = new List <byte>();
                for (int i = currentOffset; i < data.Length; i++)
                {
                    bytes.Add(data[i]);
                }
                byte[] allAudioData = bytes.ToArray();

                if (allAudioData.Length > 160)
                {
                    List <byte> first = new List <byte>();
                    for (int i = 0; i < 160; i++)
                    {
                        first.Add(allAudioData[i]);
                    }
                    string      firstString = ByteArrayToString(first.ToArray());
                    List <byte> last        = new List <byte>();
                    for (int i = 160; i < allAudioData.Length; i++)
                    {
                        last.Add(allAudioData[i]);
                    }
                    string lastString = ByteArrayToString(last.ToArray());

                    string allString = ByteArrayToString(allAudioData);
                    packet.AudioData = last.ToArray();
                }
                else
                {
                    string allString = ByteArrayToString(allAudioData);
                    packet.AudioData = (byte[])allAudioData.Clone();
                }



                packet.AudioDataString = ByteArrayToString(packet.AudioData);
            }

            return(packet);
        }