void AudioMixerClientData::processStreamPacket(ReceivedMessage& message, ConcurrentAddedStreams &addedStreams) { if (!containsValidPosition(message)) { qDebug() << "Refusing to process audio stream from" << message.getSourceID() << "with invalid position"; return; } SharedStreamPointer matchingStream; auto packetType = message.getType(); bool newStream = false; if (packetType == PacketType::MicrophoneAudioWithEcho || packetType == PacketType::MicrophoneAudioNoEcho || packetType == PacketType::SilentAudioFrame) { auto micStreamIt = std::find_if(_audioStreams.begin(), _audioStreams.end(), [](const SharedStreamPointer& stream){ return stream->getStreamIdentifier().isNull(); }); if (micStreamIt == _audioStreams.end()) { // we don't have a mic stream yet, so add it // hop past the sequence number that leads the packet message.seek(sizeof(StreamSequenceNumber)); // pull the codec string from the packet auto codecString = message.readString(); // determine if the stream is stereo or not bool isStereo; if (packetType == PacketType::SilentAudioFrame || packetType == PacketType::ReplicatedSilentAudioFrame) { SilentSamplesBytes numSilentSamples; message.readPrimitive(&numSilentSamples); isStereo = numSilentSamples == AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; } else { ChannelFlag channelFlag; message.readPrimitive(&channelFlag); isStereo = channelFlag == 1; } auto avatarAudioStream = new AvatarAudioStream(isStereo, AudioMixer::getStaticJitterFrames()); avatarAudioStream->setupCodec(_codec, _selectedCodecName, isStereo ? AudioConstants::STEREO : AudioConstants::MONO); if (_isIgnoreRadiusEnabled) { avatarAudioStream->enableIgnoreBox(); } else { avatarAudioStream->disableIgnoreBox(); } qCDebug(audio) << "creating new AvatarAudioStream... codec:" << _selectedCodecName << "isStereo:" << isStereo; connect(avatarAudioStream, &InboundAudioStream::mismatchedAudioCodec, this, &AudioMixerClientData::handleMismatchAudioFormat); matchingStream = SharedStreamPointer(avatarAudioStream); _audioStreams.push_back(matchingStream); newStream = true; } else { matchingStream = *micStreamIt; } } else if (packetType == PacketType::InjectAudio) { // this is injected audio // skip the sequence number and codec string and grab the stream identifier for this injected audio message.seek(sizeof(StreamSequenceNumber)); message.readString(); QUuid streamIdentifier = QUuid::fromRfc4122(message.readWithoutCopy(NUM_BYTES_RFC4122_UUID)); auto streamIt = std::find_if(_audioStreams.begin(), _audioStreams.end(), [&streamIdentifier](const SharedStreamPointer& stream) { return stream->getStreamIdentifier() == streamIdentifier; }); if (streamIt == _audioStreams.end()) { bool isStereo; message.readPrimitive(&isStereo); // we don't have this injected stream yet, so add it auto injectorStream = new InjectedAudioStream(streamIdentifier, isStereo, AudioMixer::getStaticJitterFrames()); #if INJECTORS_SUPPORT_CODECS injectorStream->setupCodec(_codec, _selectedCodecName, isStereo ? AudioConstants::STEREO : AudioConstants::MONO); qCDebug(audio) << "creating new injectorStream... codec:" << _selectedCodecName << "isStereo:" << isStereo; #endif matchingStream = SharedStreamPointer(injectorStream); _audioStreams.push_back(matchingStream); newStream = true; } else { matchingStream = *streamIt; } } // seek to the beginning of the packet so that the next reader is in the right spot message.seek(0); // check the overflow count before we parse data auto overflowBefore = matchingStream->getOverflowCount(); matchingStream->parseData(message); if (matchingStream->getOverflowCount() > overflowBefore) { qCDebug(audio) << "Just overflowed on stream" << matchingStream->getStreamIdentifier() << "from" << message.getSourceID(); } if (newStream) { // whenever a stream is added, push it to the concurrent vector of streams added this frame addedStreams.push_back(AddedStream(getNodeID(), getNodeLocalID(), matchingStream->getStreamIdentifier(), matchingStream.get())); } }