12 #ifndef hifi_AudioMixerClientData_h
13 #define hifi_AudioMixerClientData_h
17 #include <QtCore/QJsonObject>
18 #include <QtCore/QSharedPointer>
21 #include <AudioHRTF.h>
22 #include <AudioLimiter.h>
23 #include <TBBHelpers.h>
24 #include <UUIDHasher.h>
26 #include <plugins/Forward.h>
27 #include <plugins/CodecPlugin.h>
29 #include "PositionalAudioStream.h"
30 #include "AvatarAudioStream.h"
32 class AudioMixerClientData :
public NodeData {
36 NodeIDStreamID nodeIDStreamID;
37 PositionalAudioStream* positionalStream;
39 AddedStream(QUuid nodeID, Node::LocalID localNodeID,
40 StreamID streamID, PositionalAudioStream* positionalStream) :
41 nodeIDStreamID(nodeID, localNodeID, streamID), positionalStream(positionalStream) {};
44 using ConcurrentAddedStreams = tbb::concurrent_vector<AddedStream>;
46 AudioMixerClientData(
const QUuid& nodeID, Node::LocalID nodeLocalID);
47 ~AudioMixerClientData();
49 using SharedStreamPointer = std::shared_ptr<PositionalAudioStream>;
50 using AudioStreamVector = std::vector<SharedStreamPointer>;
52 void queuePacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer node);
53 int processPackets(ConcurrentAddedStreams& addedStreams);
55 AudioStreamVector& getAudioStreams() {
return _audioStreams; }
56 AvatarAudioStream* getAvatarAudioStream();
58 void removeAgentAvatarAudioStream();
61 int parseData(ReceivedMessage& message)
override;
62 void processStreamPacket(ReceivedMessage& message, ConcurrentAddedStreams& addedStreams);
63 void negotiateAudioFormat(ReceivedMessage& message,
const SharedNodePointer& node);
64 void parseRequestsDomainListData(ReceivedMessage& message);
65 void parsePerAvatarGainSet(ReceivedMessage& message,
const SharedNodePointer& node);
66 void parseInjectorGainSet(ReceivedMessage& message,
const SharedNodePointer& node);
67 void parseNodeIgnoreRequest(QSharedPointer<ReceivedMessage> message,
const SharedNodePointer& node);
68 void parseRadiusIgnoreRequest(QSharedPointer<ReceivedMessage> message,
const SharedNodePointer& node);
69 void parseSoloRequest(QSharedPointer<ReceivedMessage> message,
const SharedNodePointer& node);
70 void parseStopInjectorPacket(QSharedPointer<ReceivedMessage> packet);
73 int checkBuffersBeforeFrameSend();
75 QJsonObject getAudioStreamStats();
77 void sendAudioStreamStatsPackets(
const SharedNodePointer& destinationNode);
79 void incrementOutgoingMixedAudioSequenceNumber() { _outgoingMixedAudioSequenceNumber++; }
80 quint16 getOutgoingSequenceNumber()
const {
return _outgoingMixedAudioSequenceNumber; }
83 bool shouldSendStats(
int frameNumber);
85 float getPrimaryAvatarGain()
const {
return _primaryAvatarGain; }
86 void setPrimaryAvatarGain(
float gain) { _primaryAvatarGain = gain; }
87 float getPrimaryInjectorGain()
const {
return _primaryInjectorGain; }
88 void setPrimaryInjectorGain(
float gain) { _primaryInjectorGain = gain; }
90 AudioLimiter audioLimiter;
92 void setupCodec(CodecPluginPointer codec,
const QString& codecName);
94 void encode(
const QByteArray& decodedBuffer, QByteArray& encodedBuffer) {
96 _encoder->encode(decodedBuffer, encodedBuffer);
98 encodedBuffer = decodedBuffer;
101 _shouldFlushEncoder =
true;
103 void encodeFrameOfZeros(QByteArray& encodedZeros);
104 bool shouldFlushEncoder() {
return _shouldFlushEncoder; }
106 QString getCodecName() {
return _selectedCodecName; }
108 bool shouldMuteClient() {
return _shouldMuteClient; }
109 void setShouldMuteClient(
bool shouldMuteClient) { _shouldMuteClient = shouldMuteClient; }
110 glm::vec3 getPosition() {
return getAvatarAudioStream() ? getAvatarAudioStream()->getPosition() : glm::vec3(0); }
111 bool getRequestsDomainListData()
const {
return _requestsDomainListData; }
112 void setRequestsDomainListData(
bool requesting) { _requestsDomainListData = requesting; }
114 void setupCodecForReplicatedAgent(QSharedPointer<ReceivedMessage> message);
116 struct MixableStream {
117 float approximateVolume { 0.0f };
118 NodeIDStreamID nodeStreamID;
119 std::unique_ptr<AudioHRTF> hrtf;
120 PositionalAudioStream* positionalStream;
121 bool ignoredByListener {
false };
122 bool ignoringListener {
false };
124 MixableStream(NodeIDStreamID nodeIDStreamID, PositionalAudioStream* positionalStream) :
125 nodeStreamID(nodeIDStreamID), hrtf(new AudioHRTF), positionalStream(positionalStream) {};
126 MixableStream(QUuid nodeID, Node::LocalID localNodeID, StreamID streamID, PositionalAudioStream* positionalStream) :
127 nodeStreamID(nodeID, localNodeID, streamID), hrtf(new AudioHRTF), positionalStream(positionalStream) {};
130 using MixableStreamsVector = std::vector<MixableStream>;
132 MixableStreamsVector active;
133 MixableStreamsVector inactive;
134 MixableStreamsVector skipped;
137 Streams& getStreams() {
return _streams; }
140 void ignoredByNode(QUuid nodeID);
141 void unignoredByNode(QUuid nodeID);
145 const Node::IgnoredNodeIDs& getNewIgnoredNodeIDs()
const {
return _newIgnoredNodeIDs; }
146 const Node::IgnoredNodeIDs& getNewUnignoredNodeIDs()
const {
return _newUnignoredNodeIDs; }
148 using ConcurrentIgnoreNodeIDs = tbb::concurrent_vector<QUuid>;
149 const ConcurrentIgnoreNodeIDs& getNewIgnoringNodeIDs()
const {
return _newIgnoringNodeIDs; }
150 const ConcurrentIgnoreNodeIDs& getNewUnignoringNodeIDs()
const {
return _newUnignoringNodeIDs; }
152 void clearStagedIgnoreChanges();
154 const Node::IgnoredNodeIDs& getIgnoringNodeIDs()
const {
return _ignoringNodeIDs; }
157 const std::vector<QUuid>& getSoloedNodes()
const {
return _soloedNodes; }
159 bool getHasReceivedFirstMix()
const {
return _hasReceivedFirstMix; }
160 void setHasReceivedFirstMix(
bool hasReceivedFirstMix) { _hasReceivedFirstMix = hasReceivedFirstMix; }
165 void injectorStreamFinished(
const QUuid& streamID);
168 void handleMismatchAudioFormat(SharedNodePointer node,
const QString& currentCodec,
const QString& recievedCodec);
169 void sendSelectAudioFormat(SharedNodePointer node,
const QString& selectedCodecName);
172 struct PacketQueue :
public std::queue<QSharedPointer<ReceivedMessage>> {
173 QWeakPointer<Node> node;
175 PacketQueue _packetQueue;
177 AudioStreamVector _audioStreams;
179 void optionallyReplicatePacket(ReceivedMessage& packet,
const Node& node);
181 void setGainForAvatar(QUuid nodeID,
float gain);
183 bool containsValidPosition(ReceivedMessage& message)
const;
187 quint16 _outgoingMixedAudioSequenceNumber;
189 AudioStreamStats _downstreamAudioStreamStats;
191 int _frameToSendStats { 0 };
193 float _primaryAvatarGain { 1.0f };
194 float _primaryInjectorGain { 1.0f };
196 CodecPluginPointer _codec;
197 QString _selectedCodecName;
198 Encoder* _encoder{
nullptr };
199 Decoder* _decoder{
nullptr };
201 bool _shouldFlushEncoder {
false };
203 bool _shouldMuteClient {
false };
204 bool _requestsDomainListData {
false };
206 std::vector<AddedStream> _newAddedStreams;
208 Node::IgnoredNodeIDs _newIgnoredNodeIDs;
209 Node::IgnoredNodeIDs _newUnignoredNodeIDs;
211 tbb::concurrent_vector<QUuid> _newIgnoringNodeIDs;
212 tbb::concurrent_vector<QUuid> _newUnignoringNodeIDs;
214 std::mutex _ignoringNodeIDsMutex;
215 Node::IgnoredNodeIDs _ignoringNodeIDs;
217 std::atomic_bool _isIgnoreRadiusEnabled {
false };
219 std::vector<QUuid> _soloedNodes;
221 bool _hasReceivedFirstMix {
false };