From 09cfe4dbc1d65cc5234cd912ca47bedeac874ec4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 3 Aug 2018 12:11:41 -0700 Subject: [PATCH] use a vector for audio streams --- .../src/audio/AudioMixerClientData.cpp | 58 ++++++++++--------- .../src/audio/AudioMixerClientData.h | 7 +-- .../src/audio/AudioMixerSlave.cpp | 13 ++--- 3 files changed, 38 insertions(+), 40 deletions(-) diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index bbaf04c6a5..a8398abcd3 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -213,9 +213,12 @@ void AudioMixerClientData::parseRadiusIgnoreRequest(QSharedPointergetStreamIdentifier().isNull(); + }); + if (it != _audioStreams.end()) { - return dynamic_cast(it->second.get()); + return dynamic_cast(it->get()); } // no mic stream found - return NULL @@ -238,11 +241,14 @@ void AudioMixerClientData::removeHRTFForStream(const QUuid& nodeID, const QUuid& void AudioMixerClientData::removeAgentAvatarAudioStream() { QWriteLocker writeLocker { &_streamsLock }; - auto it = _audioStreams.find(QUuid()); + + auto it = std::remove_if(_audioStreams.begin(), _audioStreams.end(), [](const SharedStreamPointer& stream){ + return stream->getStreamIdentifier().isNull(); + }); + if (it != _audioStreams.end()) { _audioStreams.erase(it); } - writeLocker.unlock(); } int AudioMixerClientData::parseData(ReceivedMessage& message) { @@ -271,7 +277,9 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) { QWriteLocker writeLocker { &_streamsLock }; - auto micStreamIt = _audioStreams.find(QUuid()); + 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 @@ -301,16 +309,12 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) { connect(avatarAudioStream, &InboundAudioStream::mismatchedAudioCodec, this, &AudioMixerClientData::handleMismatchAudioFormat); - auto emplaced = _audioStreams.emplace( - QUuid(), - std::unique_ptr { avatarAudioStream } - ); - - micStreamIt = emplaced.first; + matchingStream = SharedStreamPointer(avatarAudioStream); + _audioStreams.push_back(matchingStream); + } else { + matchingStream = *micStreamIt; } - matchingStream = micStreamIt->second; - writeLocker.unlock(); isMicStream = true; @@ -327,7 +331,9 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) { QWriteLocker writeLock { &_streamsLock }; - auto streamIt = _audioStreams.find(streamIdentifier); + auto streamIt = std::find_if(_audioStreams.begin(), _audioStreams.end(), [&streamIdentifier](const SharedStreamPointer& stream) { + return stream->getStreamIdentifier() == streamIdentifier; + }); if (streamIt == _audioStreams.end()) { // we don't have this injected stream yet, so add it @@ -338,16 +344,12 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) { qCDebug(audio) << "creating new injectorStream... codec:" << _selectedCodecName << "isStereo:" << isStereo; #endif - auto emplaced = _audioStreams.emplace( - streamIdentifier, - std::unique_ptr { injectorStream } - ); - - streamIt = emplaced.first; + matchingStream = SharedStreamPointer(injectorStream); + _audioStreams.push_back(matchingStream); + } else { + matchingStream = *streamIt; } - matchingStream = streamIt->second; - writeLock.unlock(); } @@ -373,7 +375,7 @@ int AudioMixerClientData::checkBuffersBeforeFrameSend() { auto it = _audioStreams.begin(); while (it != _audioStreams.end()) { - SharedStreamPointer stream = it->second; + SharedStreamPointer stream = *it; if (stream->popFrames(1, true) > 0) { stream->updateLastPopOutputLoudnessAndTrailingLoudness(); @@ -388,7 +390,7 @@ int AudioMixerClientData::checkBuffersBeforeFrameSend() { // this is an inactive injector, pull it from our streams // first emit that it is finished so that the HRTF objects for this source can be cleaned up - emit injectorStreamFinished(it->second->getStreamIdentifier()); + emit injectorStreamFinished(stream->getStreamIdentifier()); // erase the stream to drop our ref to the shared pointer and remove it it = _audioStreams.erase(it); @@ -441,7 +443,7 @@ void AudioMixerClientData::sendAudioStreamStatsPackets(const SharedNodePointer& // pack the calculated number of stream stats for (int i = 0; i < numStreamStatsToPack; i++) { - PositionalAudioStream* stream = it->second.get(); + PositionalAudioStream* stream = it->get(); stream->perSecondCallbackForUpdatingStats(); @@ -513,12 +515,12 @@ QJsonObject AudioMixerClientData::getAudioStreamStats() { QJsonArray injectorArray; auto streamsCopy = getAudioStreams(); for (auto& injectorPair : streamsCopy) { - if (injectorPair.second->getType() == PositionalAudioStream::Injector) { + if (injectorPair->getType() == PositionalAudioStream::Injector) { QJsonObject upstreamStats; - AudioStreamStats streamStats = injectorPair.second->getAudioStreamStats(); + AudioStreamStats streamStats = injectorPair->getAudioStreamStats(); upstreamStats["inj.desired"] = streamStats._desiredJitterBufferFrames; - upstreamStats["desired_calc"] = injectorPair.second->getCalculatedJitterBufferFrames(); + upstreamStats["desired_calc"] = injectorPair->getCalculatedJitterBufferFrames(); upstreamStats["available_avg_10s"] = streamStats._framesAvailableAverage; upstreamStats["available"] = (double) streamStats._framesAvailable; upstreamStats["unplayed"] = (double) streamStats._unplayedMs; diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index 7d77169eaf..201ccfe867 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -34,13 +34,12 @@ public: ~AudioMixerClientData(); using SharedStreamPointer = std::shared_ptr; - using AudioStreamMap = std::unordered_map; + using AudioStreamVector = std::vector; void queuePacket(QSharedPointer packet, SharedNodePointer node); void processPackets(); - // locks the mutex to make a copy - AudioStreamMap getAudioStreams() { QReadLocker readLock { &_streamsLock }; return _audioStreams; } + AudioStreamVector& getAudioStreams() { return _audioStreams; } AvatarAudioStream* getAvatarAudioStream(); // returns whether self (this data's node) should ignore node, memoized by frame @@ -127,7 +126,7 @@ private: PacketQueue _packetQueue; QReadWriteLock _streamsLock; - AudioStreamMap _audioStreams; // microphone stream from avatar is stored under key of null UUID + AudioStreamVector _audioStreams; // microphone stream from avatar is stored under key of null UUID void optionallyReplicatePacket(ReceivedMessage& packet, const Node& node); diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index b447048ac9..4b97049758 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -36,7 +36,7 @@ #include "InjectedAudioStream.h" #include "AudioHelpers.h" -using AudioStreamMap = AudioMixerClientData::AudioStreamMap; +using AudioStreamVector = AudioMixerClientData::AudioStreamVector; // packet helpers std::unique_ptr createAudioPacket(PacketType type, int size, quint16 sequence, QString codec); @@ -146,8 +146,7 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { auto forAllStreams = [&](const SharedNodePointer& node, AudioMixerClientData* nodeData, MixFunctor mixFunctor) { auto nodeID = node->getUUID(); for (auto& streamPair : nodeData->getAudioStreams()) { - auto nodeStream = streamPair.second; - (this->*mixFunctor)(*listenerData, nodeID, *listenerAudioStream, *nodeStream); + (this->*mixFunctor)(*listenerData, nodeID, *listenerAudioStream, *streamPair); } }; @@ -164,9 +163,8 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { if (*node == *listener) { // only mix the echo, if requested for (auto& streamPair : nodeData->getAudioStreams()) { - auto nodeStream = streamPair.second; - if (nodeStream->shouldLoopbackForNode()) { - mixStream(*listenerData, node->getUUID(), *listenerAudioStream, *nodeStream); + if (streamPair->shouldLoopbackForNode()) { + mixStream(*listenerData, node->getUUID(), *listenerAudioStream, *streamPair); } } } else if (!listenerData->shouldIgnore(listener, node, _frame)) { @@ -177,8 +175,7 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) { // compute the node's max relative volume float nodeVolume = 0.0f; - for (auto& streamPair : nodeData->getAudioStreams()) { - auto nodeStream = streamPair.second; + for (auto& nodeStream : nodeData->getAudioStreams()) { // approximate the gain glm::vec3 relativePosition = nodeStream->getPosition() - listenerAudioStream->getPosition();