From b18d8e22540504dc400cea0d4dee77d1add49bbb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Sep 2018 10:41:21 -0700 Subject: [PATCH] pull out removal and adding of streams to sep functions --- .../src/audio/AudioMixerSlave.cpp | 135 ++++++++++-------- assignment-client/src/audio/AudioMixerSlave.h | 3 + 2 files changed, 78 insertions(+), 60 deletions(-) diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index 9d2f3728a5..7c0566ee44 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -132,6 +132,77 @@ bool containsNodeID(const V& vector, QUuid nodeID) { }); } +void AudioMixerSlave::addStreams(Node& listener, AudioMixerClientData& listenerData) { + auto& ignoredNodeIDs = listener.getIgnoredNodeIDs(); + auto& ignoringNodeIDs = listenerData.getIgnoringNodeIDs(); + + auto& mixableStreams = listenerData.getMixableStreams(); + + // add data for newly created streams to our vector + if (!listenerData.getHasReceivedFirstMix()) { + // when this listener is new, we need to fill its added streams object with all available streams + std::for_each(_begin, _end, [&](const SharedNodePointer& node) { + AudioMixerClientData* nodeData = static_cast(node->getLinkedData()); + if (nodeData) { + for (auto& stream : nodeData->getAudioStreams()) { + mixableStreams.emplace_back(node->getUUID(), node->getLocalID(), + stream->getStreamIdentifier(), &(*stream)); + + // pre-populate ignored and ignoring flags for this stream + mixableStreams.back().ignoredByListener = containsNodeID(ignoredNodeIDs, node->getUUID()); + mixableStreams.back().ignoringListener = containsNodeID(ignoringNodeIDs, node->getUUID()); + } + } + }); + + // flag this listener as having received their first mix so we know we don't need to enumerate all nodes again + listenerData.setHasReceivedFirstMix(true); + } else { + for (const auto& newStream : _sharedData.addedStreams) { + mixableStreams.emplace_back(newStream.nodeIDStreamID, newStream.positionalStream); + + // pre-populate ignored and ignoring flags for this stream + mixableStreams.back().ignoredByListener = containsNodeID(ignoredNodeIDs, newStream.nodeIDStreamID.nodeID); + mixableStreams.back().ignoringListener = containsNodeID(ignoringNodeIDs, newStream.nodeIDStreamID.nodeID); + } + } +} + +void AudioMixerSlave::removeStreams(AudioMixerClientData::MixableStreamsVector& mixableStreams) { + if (_sharedData.removedNodes.size() > 0) { + // enumerate the available streams + auto it = mixableStreams.begin(); + auto end = mixableStreams.end(); + + while (it != end) { + // check if this node (and therefore all of the node's streams) has been removed + auto& nodeIDStreamID = it->nodeStreamID; + auto matchedRemovedNode = std::find(_sharedData.removedNodes.cbegin(), _sharedData.removedNodes.cend(), + nodeIDStreamID.nodeLocalID); + bool streamRemoved = matchedRemovedNode != _sharedData.removedNodes.cend(); + + // if the node wasn't removed, check if this stream was specifically removed + if (!streamRemoved) { + auto matchedRemovedStream = std::find(_sharedData.removedStreams.cbegin(), _sharedData.removedStreams.cend(), + nodeIDStreamID); + streamRemoved = matchedRemovedStream != _sharedData.removedStreams.cend(); + } + + if (streamRemoved) { + // this stream was removed, so swap it with the last item and decrease the end iterator + --end; + std::swap(*it, *end); + + // process the it element (which is now the element that was the last item before the swap) + continue; + } + } + + // erase any removed streams that were swapped to the end + mixableStreams.erase(end, mixableStreams.end()); + } +} + bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { AvatarAudioStream* listenerAudioStream = static_cast(listener->getLinkedData())->getAvatarAudioStream(); AudioMixerClientData* listenerData = static_cast(listener->getLinkedData()); @@ -143,42 +214,7 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { auto nodeList = DependencyManager::get(); -#ifdef HIFI_AUDIO_MIXER_DEBUG - auto mixStart = p_high_resolution_clock::now(); -#endif - auto& mixableStreams = listenerData->getMixableStreams(); - auto& ignoredNodeIDs = listener->getIgnoredNodeIDs(); - auto& ignoringNodeIDs = listenerData->getIgnoringNodeIDs(); - - // add data for newly created streams to our vector - if (!listenerData->getHasReceivedFirstMix()) { - // when this listener is new, we need to fill its added streams object with all available streams - std::for_each(_begin, _end, [&](const SharedNodePointer& node) { - AudioMixerClientData* nodeData = static_cast(node->getLinkedData()); - if (nodeData) { - for (auto& stream : nodeData->getAudioStreams()) { - mixableStreams.emplace_back(node->getUUID(), node->getLocalID(), - stream->getStreamIdentifier(), &(*stream)); - - // pre-populate ignored and ignoring flags for this stream - mixableStreams.back().ignoredByListener = containsNodeID(ignoredNodeIDs, node->getUUID()); - mixableStreams.back().ignoringListener = containsNodeID(ignoringNodeIDs, node->getUUID()); - } - } - }); - - // flag this listener as having received their first mix so we know we don't need to enumerate all nodes again - listenerData->setHasReceivedFirstMix(true); - } else { - for (const auto& newStream : _sharedData.addedStreams) { - mixableStreams.emplace_back(newStream.nodeIDStreamID, newStream.positionalStream); - - // pre-populate ignored and ignoring flags for this stream - mixableStreams.back().ignoredByListener = containsNodeID(ignoredNodeIDs, newStream.nodeIDStreamID.nodeID); - mixableStreams.back().ignoringListener = containsNodeID(ignoringNodeIDs, newStream.nodeIDStreamID.nodeID); - } - } // grab the unprocessed ignores and unignores from and for this listener const auto& nodesIgnoredByListener = listenerData->getNewIgnoredNodeIDs(); @@ -186,32 +222,14 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { const auto& nodesIgnoringListener = listenerData->getNewIgnoringNodeIDs(); const auto& nodesUnignoringListener = listenerData->getNewUnignoringNodeIDs(); + removeStreams(mixableStreams); + addStreams(*listener, *listenerData); + // enumerate the available streams auto it = mixableStreams.begin(); - auto end = mixableStreams.end(); - while (it != end) { + while (it != mixableStreams.end()) { - // check if this node (and therefore all of the node's streams) has been removed auto& nodeIDStreamID = it->nodeStreamID; - auto matchedRemovedNode = std::find(_sharedData.removedNodes.cbegin(), _sharedData.removedNodes.cend(), - nodeIDStreamID.nodeLocalID); - bool streamRemoved = matchedRemovedNode != _sharedData.removedNodes.cend(); - - // if the node wasn't removed, check if this stream was specifically removed - if (!streamRemoved) { - auto matchedRemovedStream = std::find(_sharedData.removedStreams.cbegin(), _sharedData.removedStreams.cend(), - nodeIDStreamID); - streamRemoved = matchedRemovedStream != _sharedData.removedStreams.cend(); - } - - if (streamRemoved) { - // this stream was removed, so swap it with the last item and decrease the end iterator - --end; - std::swap(*it, *end); - - // process the it element (which is now the element that was the last item before the swap) - continue; - } if (it->nodeStreamID.nodeLocalID == listener->getLocalID()) { // streams from this node should be skipped unless loopback is specifically requested @@ -297,9 +315,6 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { ++it; } - // erase any removed streams that were swapped to the end - mixableStreams.erase(end, mixableStreams.end()); - if (isThrottling) { // since we're throttling, we need to partition the mixable into throttled and unthrottled streams auto numToRetain = std::distance(_begin, _end) * (1 - _throttlingRatio); diff --git a/assignment-client/src/audio/AudioMixerSlave.h b/assignment-client/src/audio/AudioMixerSlave.h index da960cb1fd..a2860f3f75 100644 --- a/assignment-client/src/audio/AudioMixerSlave.h +++ b/assignment-client/src/audio/AudioMixerSlave.h @@ -58,6 +58,9 @@ private: void addStream(AudioMixerClientData::MixableStream& mixableStream, AvatarAudioStream& listeningNodeStream, float masterListenerGain, bool throttle); + void removeStreams(AudioMixerClientData::MixableStreamsVector& mixableStreams); + void addStreams(Node& listener, AudioMixerClientData& listenerData); + // mixing buffers float _mixSamples[AudioConstants::NETWORK_FRAME_SAMPLES_STEREO]; int16_t _bufferSamples[AudioConstants::NETWORK_FRAME_SAMPLES_STEREO];