/// <summary> /// Deliver a new encoded audio packet /// </summary> /// <remarks>It will be placed into a transfer buffer and will be moved into the actual buffer when FlushTransferBuffer is called on the audio playback thread</remarks> /// <param name="packet"></param> /// <param name="now"></param> /// <returns>How delayed this packet is from when it should arrive</returns> public float Push(VoicePacket packet, DateTime now) { Log.Trace("Received frame {0} from network", packet.SequenceNumber); // copy the data out of the frame, as the network thread will re-use the heap allocated things List <RemoteChannel> channelsCopy = null; if (packet.Channels != null) { channelsCopy = _channelListPool.Get(); channelsCopy.Clear(); channelsCopy.AddRange(packet.Channels); } var frameCopy = packet.EncodedAudioFrame.CopyTo(_bytePool.Get()); var packetCopy = new VoicePacket( packet.SenderPlayerId, packet.PlaybackOptions.Priority, packet.PlaybackOptions.AmplitudeMultiplier, packet.PlaybackOptions.IsPositional, frameCopy, packet.SequenceNumber, channelsCopy ); // queue the frame onto the transfer buffer if (!_inputBuffer.TryWrite(packetCopy)) { Log.Warn("Failed to write an encoded audio packet into the input transfer buffer"); } // We've received a packet but not been prepared yet, which means audio playback hasn't started yet - immediately flush the transfer buffer // It's safe to do this because we know playback isn't going, so the audio thread won't be accessing the buffer at the same time as we're flushing if (!_prepared) { FlushTransferBuffer(); } // calculate how late the packet is if (!_firstFrameArrival.HasValue) { _firstFrameArrival = now; _firstFrameSeq = packet.SequenceNumber; return(0); } else { var expectedTime = _firstFrameArrival.Value + TimeSpan.FromTicks(_frameDuration.Ticks * (packet.SequenceNumber - _firstFrameSeq)); var delay = now - expectedTime; return((float)delay.TotalSeconds); } }
/// <summary> /// Push a new encoded audio packet /// </summary> /// <param name="packet"></param> /// <param name="now"></param> /// <returns>How delayed this packet is from when it should arrive</returns> public float Push(VoicePacket packet, DateTime now) { Log.Trace("Received frame {0} from network", packet.SequenceNumber); // copy the data out of the frame, as the network thread will re-use the heap allocated things List <RemoteChannel> channelsCopy = null; if (packet.Channels != null) { channelsCopy = _channelListPool.Get(); channelsCopy.Clear(); channelsCopy.AddRange(packet.Channels); } var frameCopy = packet.EncodedAudioFrame.CopyTo(_bytePool.Get()); var packetCopy = new VoicePacket( packet.SenderPlayerId, packet.PlaybackOptions.Priority, packet.PlaybackOptions.AmplitudeMultiplier, packet.PlaybackOptions.IsPositional, frameCopy, packet.SequenceNumber, channelsCopy ); // queue the frame onto the transfer buffer if (!_inputBuffer.TryWrite(packetCopy)) { Log.Warn("Failed to write an encoded audio packet into the input transfer buffer"); } // calculate how late the packet is if (!_firstFrameArrival.HasValue) { _firstFrameArrival = now; _firstFrameSeq = packet.SequenceNumber; return(0); } else { var expectedTime = _firstFrameArrival.Value + TimeSpan.FromTicks(_frameDuration.Ticks * (packet.SequenceNumber - _firstFrameSeq)); var delay = now - expectedTime; return((float)delay.TotalSeconds); } }
internal static void SendLogMessage(string message, LogLevel level) { #if NCRUNCH Console.WriteLine(message); #else var msg = new LogMessage(message, level); if (_main == null || _main == Thread.CurrentThread) { msg.Log(); } else { LogsFromOtherThreads.TryWrite(msg); } #endif }