/// <summary> /// Read all the channel data from the packet and accumulate data about the channels we are listening to /// </summary> /// <param name="reader">Packetreader to read data from</param> /// <param name="numChannels">The number of channels in the packet reader</param> /// <param name="allClosing">Indicates if all channels are closing (i.e. we should stop speech after this packet)</param> /// <param name="forceReset">Indicates if a reset of the playback system should be forced (i.e. stop and immediately start speaking)</param> /// <param name="channelsMetadata">Aggregate metadata about all playing channels</param> /// <param name="channelsOut"></param> private void ReadChannels(ref PacketReader reader, ushort numChannels, out bool allClosing, out bool forceReset, out ChannelsMetadata channelsMetadata, [NotNull] ICollection <RemoteChannel> channelsOut) { //Accumulate aggregate information about all the channels channelsMetadata = new ChannelsMetadata(true, 0, ChannelPriority.None); allClosing = true; forceReset = true; //Just in case someone else left a mess, clear the list before using it channelsOut.Clear(); _tmpCompositeIdBuffer.Clear(); for (var i = 0; i < numChannels; i++) { //Parse a channel of information from the header ChannelBitField channel; ushort channelRecipient; reader.ReadVoicePacketChannel(out channel, out channelRecipient); //Skip onwards if we don't care about this channel var c = IsChannelToLocalPlayer(channel, channelRecipient); if (!c.HasValue) { continue; } //Add an entry for this channel to the list channelsOut.Add(c.Value); //Form a unique ID for this channel so we can keep track of it across packets var compositeId = (int)channel.Type | (channelRecipient << 8); _tmpCompositeIdBuffer.Add(compositeId); //Accumulate aggregate metadata over all channels channelsMetadata = channelsMetadata.CombineWith(new ChannelsMetadata(channel.IsPositional, channel.AmplitudeMultiplier, channel.Priority)); allClosing &= channel.IsClosing; //It's possible that a channel was closed and then re-opened between the sending of two packets. If so then we want to consider the channel... //...as closed then re-opened (i.e. reset the channel). However we only need to perform a reset if this applies to *all* the channels this... //...receiver is listening to. forceReset &= HasChannelSessionChanged(compositeId, channel.SessionId); } //Only perform a reset if we were already open (a reset makes no sense if we're not open). forceReset &= Open; //Remove all channels from this peer which we no longer care about RemoveChannelsExcept(_tmpCompositeIdBuffer); _tmpCompositeIdBuffer.Clear(); }
public ChannelsMetadata CombineWith(ChannelsMetadata other) { return(new ChannelsMetadata( // Positional playback if *all* channels are positional IsPositional & other.IsPositional, // Amplitude is max amplitude of channels Math.Max(AmplitudeMultiplier, other.AmplitudeMultiplier), // Priority is max priority of channels (ChannelPriority)Math.Max((int)Priority, (int)other.Priority) )); }