public int RaopBufferQueue(RaopBuffer raop_buffer, byte[] data, ushort datalen, Session session) { int encryptedlen; RaopBufferEntry entry; /* Check packet data length is valid */ if (datalen < 12 || datalen > RAOP_PACKET_LENGTH) { return(-1); } var seqnum = (ushort)((data[2] << 8) | data[3]); if (datalen == 16 && data[12] == 0x0 && data[13] == 0x68 && data[14] == 0x34 && data[15] == 0x0) { return(0); } // Ignore, old if (!raop_buffer.IsEmpty && seqnum < raop_buffer.FirstSeqNum && seqnum != 0) { return(0); } /* Check that there is always space in the buffer, otherwise flush */ if (raop_buffer.FirstSeqNum + RAOP_BUFFER_LENGTH < seqnum || seqnum == 0) { RaopBufferFlush(raop_buffer, seqnum); } entry = raop_buffer.Entries[seqnum % RAOP_BUFFER_LENGTH]; if (entry.Available && entry.SeqNum == seqnum) { /* Packet resent, we can safely ignore */ return(0); } entry.Flags = data[0]; entry.Type = data[1]; entry.SeqNum = seqnum; entry.TimeStamp = (uint)((data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]); entry.SSrc = (uint)((data[8] << 24) | (data[9] << 16) | (data[10] << 8) | data[11]); entry.Available = true; int payloadsize = datalen - 12; var raw = new byte[payloadsize]; encryptedlen = payloadsize / 16 * 16; if (encryptedlen > 0) { _aesCbcDecrypt.ProcessBytes(data, 12, encryptedlen, data, 12); Array.Copy(data, 12, raw, 0, encryptedlen); } Array.Copy(data, 12 + encryptedlen, raw, encryptedlen, payloadsize - encryptedlen); #if DUMP /* RAW -> DUMP */ var fPath = Path.Combine(_dConfig.Path, "frames/"); File.WriteAllBytes($"{fPath}raw_{seqnum}", raw); #endif /* RAW -> PCM */ var length = _decoder.GetOutputStreamLength(); var output = new byte[length]; var res = _decoder.DecodeFrame(raw, ref output, length); if (res != 0) { output = new byte[length]; Console.WriteLine($"Decoding error. Decoder: {_decoder.Type} Code: {res}"); } #if DUMP var pPath = Path.Combine(_dConfig.Path, "pcm/"); Console.WriteLine($"RES: {res}"); Console.WriteLine($"PCM: {output.Length}"); Console.WriteLine($"LNG: {length}"); File.WriteAllBytes($"{pPath}raw_{seqnum}", output); #endif Array.Copy(output, 0, entry.AudioBuffer, 0, output.Length); entry.AudioBufferLen = output.Length; /* Update the raop_buffer seqnums */ if (raop_buffer.IsEmpty) { raop_buffer.FirstSeqNum = seqnum; raop_buffer.LastSeqNum = seqnum; raop_buffer.IsEmpty = false; } if (raop_buffer.LastSeqNum < seqnum) { raop_buffer.LastSeqNum = seqnum; } // Update entries raop_buffer.Entries[seqnum % RAOP_BUFFER_LENGTH] = entry; return(1); }