mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 21:26:25 +02:00
use a vector for audio streams
This commit is contained in:
parent
aed79b3b17
commit
09cfe4dbc1
3 changed files with 38 additions and 40 deletions
|
@ -213,9 +213,12 @@ void AudioMixerClientData::parseRadiusIgnoreRequest(QSharedPointer<ReceivedMessa
|
||||||
AvatarAudioStream* AudioMixerClientData::getAvatarAudioStream() {
|
AvatarAudioStream* AudioMixerClientData::getAvatarAudioStream() {
|
||||||
QReadLocker readLocker { &_streamsLock };
|
QReadLocker readLocker { &_streamsLock };
|
||||||
|
|
||||||
auto it = _audioStreams.find(QUuid());
|
auto it = std::find_if(_audioStreams.begin(), _audioStreams.end(), [](const SharedStreamPointer& stream){
|
||||||
|
return stream->getStreamIdentifier().isNull();
|
||||||
|
});
|
||||||
|
|
||||||
if (it != _audioStreams.end()) {
|
if (it != _audioStreams.end()) {
|
||||||
return dynamic_cast<AvatarAudioStream*>(it->second.get());
|
return dynamic_cast<AvatarAudioStream*>(it->get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// no mic stream found - return NULL
|
// no mic stream found - return NULL
|
||||||
|
@ -238,11 +241,14 @@ void AudioMixerClientData::removeHRTFForStream(const QUuid& nodeID, const QUuid&
|
||||||
|
|
||||||
void AudioMixerClientData::removeAgentAvatarAudioStream() {
|
void AudioMixerClientData::removeAgentAvatarAudioStream() {
|
||||||
QWriteLocker writeLocker { &_streamsLock };
|
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()) {
|
if (it != _audioStreams.end()) {
|
||||||
_audioStreams.erase(it);
|
_audioStreams.erase(it);
|
||||||
}
|
}
|
||||||
writeLocker.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudioMixerClientData::parseData(ReceivedMessage& message) {
|
int AudioMixerClientData::parseData(ReceivedMessage& message) {
|
||||||
|
@ -271,7 +277,9 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) {
|
||||||
|
|
||||||
QWriteLocker writeLocker { &_streamsLock };
|
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()) {
|
if (micStreamIt == _audioStreams.end()) {
|
||||||
// we don't have a mic stream yet, so add it
|
// we don't have a mic stream yet, so add it
|
||||||
|
|
||||||
|
@ -301,16 +309,12 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) {
|
||||||
connect(avatarAudioStream, &InboundAudioStream::mismatchedAudioCodec,
|
connect(avatarAudioStream, &InboundAudioStream::mismatchedAudioCodec,
|
||||||
this, &AudioMixerClientData::handleMismatchAudioFormat);
|
this, &AudioMixerClientData::handleMismatchAudioFormat);
|
||||||
|
|
||||||
auto emplaced = _audioStreams.emplace(
|
matchingStream = SharedStreamPointer(avatarAudioStream);
|
||||||
QUuid(),
|
_audioStreams.push_back(matchingStream);
|
||||||
std::unique_ptr<PositionalAudioStream> { avatarAudioStream }
|
} else {
|
||||||
);
|
matchingStream = *micStreamIt;
|
||||||
|
|
||||||
micStreamIt = emplaced.first;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
matchingStream = micStreamIt->second;
|
|
||||||
|
|
||||||
writeLocker.unlock();
|
writeLocker.unlock();
|
||||||
|
|
||||||
isMicStream = true;
|
isMicStream = true;
|
||||||
|
@ -327,7 +331,9 @@ int AudioMixerClientData::parseData(ReceivedMessage& message) {
|
||||||
|
|
||||||
QWriteLocker writeLock { &_streamsLock };
|
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()) {
|
if (streamIt == _audioStreams.end()) {
|
||||||
// we don't have this injected stream yet, so add it
|
// 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;
|
qCDebug(audio) << "creating new injectorStream... codec:" << _selectedCodecName << "isStereo:" << isStereo;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto emplaced = _audioStreams.emplace(
|
matchingStream = SharedStreamPointer(injectorStream);
|
||||||
streamIdentifier,
|
_audioStreams.push_back(matchingStream);
|
||||||
std::unique_ptr<InjectedAudioStream> { injectorStream }
|
} else {
|
||||||
);
|
matchingStream = *streamIt;
|
||||||
|
|
||||||
streamIt = emplaced.first;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
matchingStream = streamIt->second;
|
|
||||||
|
|
||||||
writeLock.unlock();
|
writeLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +375,7 @@ int AudioMixerClientData::checkBuffersBeforeFrameSend() {
|
||||||
|
|
||||||
auto it = _audioStreams.begin();
|
auto it = _audioStreams.begin();
|
||||||
while (it != _audioStreams.end()) {
|
while (it != _audioStreams.end()) {
|
||||||
SharedStreamPointer stream = it->second;
|
SharedStreamPointer stream = *it;
|
||||||
|
|
||||||
if (stream->popFrames(1, true) > 0) {
|
if (stream->popFrames(1, true) > 0) {
|
||||||
stream->updateLastPopOutputLoudnessAndTrailingLoudness();
|
stream->updateLastPopOutputLoudnessAndTrailingLoudness();
|
||||||
|
@ -388,7 +390,7 @@ int AudioMixerClientData::checkBuffersBeforeFrameSend() {
|
||||||
// this is an inactive injector, pull it from our streams
|
// 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
|
// 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
|
// erase the stream to drop our ref to the shared pointer and remove it
|
||||||
it = _audioStreams.erase(it);
|
it = _audioStreams.erase(it);
|
||||||
|
@ -441,7 +443,7 @@ void AudioMixerClientData::sendAudioStreamStatsPackets(const SharedNodePointer&
|
||||||
|
|
||||||
// pack the calculated number of stream stats
|
// pack the calculated number of stream stats
|
||||||
for (int i = 0; i < numStreamStatsToPack; i++) {
|
for (int i = 0; i < numStreamStatsToPack; i++) {
|
||||||
PositionalAudioStream* stream = it->second.get();
|
PositionalAudioStream* stream = it->get();
|
||||||
|
|
||||||
stream->perSecondCallbackForUpdatingStats();
|
stream->perSecondCallbackForUpdatingStats();
|
||||||
|
|
||||||
|
@ -513,12 +515,12 @@ QJsonObject AudioMixerClientData::getAudioStreamStats() {
|
||||||
QJsonArray injectorArray;
|
QJsonArray injectorArray;
|
||||||
auto streamsCopy = getAudioStreams();
|
auto streamsCopy = getAudioStreams();
|
||||||
for (auto& injectorPair : streamsCopy) {
|
for (auto& injectorPair : streamsCopy) {
|
||||||
if (injectorPair.second->getType() == PositionalAudioStream::Injector) {
|
if (injectorPair->getType() == PositionalAudioStream::Injector) {
|
||||||
QJsonObject upstreamStats;
|
QJsonObject upstreamStats;
|
||||||
|
|
||||||
AudioStreamStats streamStats = injectorPair.second->getAudioStreamStats();
|
AudioStreamStats streamStats = injectorPair->getAudioStreamStats();
|
||||||
upstreamStats["inj.desired"] = streamStats._desiredJitterBufferFrames;
|
upstreamStats["inj.desired"] = streamStats._desiredJitterBufferFrames;
|
||||||
upstreamStats["desired_calc"] = injectorPair.second->getCalculatedJitterBufferFrames();
|
upstreamStats["desired_calc"] = injectorPair->getCalculatedJitterBufferFrames();
|
||||||
upstreamStats["available_avg_10s"] = streamStats._framesAvailableAverage;
|
upstreamStats["available_avg_10s"] = streamStats._framesAvailableAverage;
|
||||||
upstreamStats["available"] = (double) streamStats._framesAvailable;
|
upstreamStats["available"] = (double) streamStats._framesAvailable;
|
||||||
upstreamStats["unplayed"] = (double) streamStats._unplayedMs;
|
upstreamStats["unplayed"] = (double) streamStats._unplayedMs;
|
||||||
|
|
|
@ -34,13 +34,12 @@ public:
|
||||||
~AudioMixerClientData();
|
~AudioMixerClientData();
|
||||||
|
|
||||||
using SharedStreamPointer = std::shared_ptr<PositionalAudioStream>;
|
using SharedStreamPointer = std::shared_ptr<PositionalAudioStream>;
|
||||||
using AudioStreamMap = std::unordered_map<QUuid, SharedStreamPointer>;
|
using AudioStreamVector = std::vector<SharedStreamPointer>;
|
||||||
|
|
||||||
void queuePacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer node);
|
void queuePacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer node);
|
||||||
void processPackets();
|
void processPackets();
|
||||||
|
|
||||||
// locks the mutex to make a copy
|
AudioStreamVector& getAudioStreams() { return _audioStreams; }
|
||||||
AudioStreamMap getAudioStreams() { QReadLocker readLock { &_streamsLock }; return _audioStreams; }
|
|
||||||
AvatarAudioStream* getAvatarAudioStream();
|
AvatarAudioStream* getAvatarAudioStream();
|
||||||
|
|
||||||
// returns whether self (this data's node) should ignore node, memoized by frame
|
// returns whether self (this data's node) should ignore node, memoized by frame
|
||||||
|
@ -127,7 +126,7 @@ private:
|
||||||
PacketQueue _packetQueue;
|
PacketQueue _packetQueue;
|
||||||
|
|
||||||
QReadWriteLock _streamsLock;
|
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);
|
void optionallyReplicatePacket(ReceivedMessage& packet, const Node& node);
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "InjectedAudioStream.h"
|
#include "InjectedAudioStream.h"
|
||||||
#include "AudioHelpers.h"
|
#include "AudioHelpers.h"
|
||||||
|
|
||||||
using AudioStreamMap = AudioMixerClientData::AudioStreamMap;
|
using AudioStreamVector = AudioMixerClientData::AudioStreamVector;
|
||||||
|
|
||||||
// packet helpers
|
// packet helpers
|
||||||
std::unique_ptr<NLPacket> createAudioPacket(PacketType type, int size, quint16 sequence, QString codec);
|
std::unique_ptr<NLPacket> 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 forAllStreams = [&](const SharedNodePointer& node, AudioMixerClientData* nodeData, MixFunctor mixFunctor) {
|
||||||
auto nodeID = node->getUUID();
|
auto nodeID = node->getUUID();
|
||||||
for (auto& streamPair : nodeData->getAudioStreams()) {
|
for (auto& streamPair : nodeData->getAudioStreams()) {
|
||||||
auto nodeStream = streamPair.second;
|
(this->*mixFunctor)(*listenerData, nodeID, *listenerAudioStream, *streamPair);
|
||||||
(this->*mixFunctor)(*listenerData, nodeID, *listenerAudioStream, *nodeStream);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -164,9 +163,8 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) {
|
||||||
if (*node == *listener) {
|
if (*node == *listener) {
|
||||||
// only mix the echo, if requested
|
// only mix the echo, if requested
|
||||||
for (auto& streamPair : nodeData->getAudioStreams()) {
|
for (auto& streamPair : nodeData->getAudioStreams()) {
|
||||||
auto nodeStream = streamPair.second;
|
if (streamPair->shouldLoopbackForNode()) {
|
||||||
if (nodeStream->shouldLoopbackForNode()) {
|
mixStream(*listenerData, node->getUUID(), *listenerAudioStream, *streamPair);
|
||||||
mixStream(*listenerData, node->getUUID(), *listenerAudioStream, *nodeStream);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!listenerData->shouldIgnore(listener, node, _frame)) {
|
} else if (!listenerData->shouldIgnore(listener, node, _frame)) {
|
||||||
|
@ -177,8 +175,7 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) {
|
||||||
|
|
||||||
// compute the node's max relative volume
|
// compute the node's max relative volume
|
||||||
float nodeVolume = 0.0f;
|
float nodeVolume = 0.0f;
|
||||||
for (auto& streamPair : nodeData->getAudioStreams()) {
|
for (auto& nodeStream : nodeData->getAudioStreams()) {
|
||||||
auto nodeStream = streamPair.second;
|
|
||||||
|
|
||||||
// approximate the gain
|
// approximate the gain
|
||||||
glm::vec3 relativePosition = nodeStream->getPosition() - listenerAudioStream->getPosition();
|
glm::vec3 relativePosition = nodeStream->getPosition() - listenerAudioStream->getPosition();
|
||||||
|
|
Loading…
Reference in a new issue