HifiExperimentsenable warnings as errors6ff5e171 year agoHistory
224 lines · 8.6 KB · C
RawDownload
////  AudioMixerClientData.h//  assignment-client/src/audio////  Created by Stephen Birarda on 10/18/13.//  Copyright 2013 High Fidelity, Inc.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// #ifndef hifi_AudioMixerClientData_h#define hifi_AudioMixerClientData_h #include <queue> #include <QtCore/QJsonObject>#include <QtCore/QSharedPointer> #include <AABox.h>#include <AudioHRTF.h>#include <AudioLimiter.h>#include <TBBHelpers.h>#include <UUIDHasher.h> #include <plugins/Forward.h>#include <plugins/CodecPlugin.h> #include "PositionalAudioStream.h"#include "AvatarAudioStream.h" class AudioMixerClientData : public NodeData {    Q_OBJECTpublic:    struct AddedStream {        NodeIDStreamID nodeIDStreamID;        PositionalAudioStream* positionalStream;         AddedStream(QUuid nodeID, Node::LocalID localNodeID,                    StreamID streamID, PositionalAudioStream* positionalStream) :            nodeIDStreamID(nodeID, localNodeID, streamID), positionalStream(positionalStream) {};    };     using ConcurrentAddedStreams = tbb::concurrent_vector<AddedStream>;     AudioMixerClientData(const QUuid& nodeID, Node::LocalID nodeLocalID);    ~AudioMixerClientData();     using SharedStreamPointer = std::shared_ptr<PositionalAudioStream>;    using AudioStreamVector = std::vector<SharedStreamPointer>;     void queuePacket(QSharedPointer<ReceivedMessage> packet, SharedNodePointer node);    int processPackets(ConcurrentAddedStreams& addedStreams); // returns the number of available streams this frame     AudioStreamVector& getAudioStreams() { return _audioStreams; }    AvatarAudioStream* getAvatarAudioStream();     void removeAgentAvatarAudioStream();     // packet parsers    int parseData(ReceivedMessage& message) override;    void processStreamPacket(ReceivedMessage& message, ConcurrentAddedStreams& addedStreams);    void negotiateAudioFormat(ReceivedMessage& message, const SharedNodePointer& node);    void parseRequestsDomainListData(ReceivedMessage& message);    void parsePerAvatarGainSet(ReceivedMessage& message, const SharedNodePointer& node);    void parseInjectorGainSet(ReceivedMessage& message, const SharedNodePointer& node);    void parseNodeIgnoreRequest(QSharedPointer<ReceivedMessage> message, const SharedNodePointer& node);    void parseRadiusIgnoreRequest(QSharedPointer<ReceivedMessage> message, const SharedNodePointer& node);    void parseSoloRequest(QSharedPointer<ReceivedMessage> message, const SharedNodePointer& node);    void parseStopInjectorPacket(QSharedPointer<ReceivedMessage> packet);     // attempt to pop a frame from each audio stream, and return the number of streams from this client    int checkBuffersBeforeFrameSend();     QJsonObject getAudioStreamStats();     void sendAudioStreamStatsPackets(const SharedNodePointer& destinationNode);     void incrementOutgoingMixedAudioSequenceNumber() { _outgoingMixedAudioSequenceNumber++; }    quint16 getOutgoingSequenceNumber() const { return _outgoingMixedAudioSequenceNumber; }     // uses randomization to have the AudioMixer send a stats packet to this node around every second    bool shouldSendStats(int frameNumber);     float getPrimaryAvatarGain() const { return _primaryAvatarGain; }    void setPrimaryAvatarGain(float gain) { _primaryAvatarGain = gain; }    float getPrimaryInjectorGain() const { return _primaryInjectorGain; }    void setPrimaryInjectorGain(float gain) { _primaryInjectorGain = gain; }     AudioLimiter audioLimiter;     void setupCodec(CodecPluginPointer codec, const QString& codecName);    void cleanupCodec();    void encode(const QByteArray& decodedBuffer, QByteArray& encodedBuffer) {        if (_encoder) {            _encoder->encode(decodedBuffer, encodedBuffer);        } else {            encodedBuffer = decodedBuffer;        }        // once you have encoded, you need to flush eventually.        _shouldFlushEncoder = true;    }    void encodeFrameOfZeros(QByteArray& encodedZeros);    bool shouldFlushEncoder() { return _shouldFlushEncoder; }     QString getCodecName() { return _selectedCodecName; }     bool shouldMuteClient() { return _shouldMuteClient; }    void setShouldMuteClient(bool shouldMuteClient) { _shouldMuteClient = shouldMuteClient; }    glm::vec3 getPosition() { return getAvatarAudioStream() ? getAvatarAudioStream()->getPosition() : glm::vec3(0); }    bool getRequestsDomainListData() const { return _requestsDomainListData; }    void setRequestsDomainListData(bool requesting) { _requestsDomainListData = requesting; }     void setupCodecForReplicatedAgent(QSharedPointer<ReceivedMessage> message);     struct MixableStream {        float approximateVolume { 0.0f };        NodeIDStreamID nodeStreamID;        std::unique_ptr<AudioHRTF> hrtf;        PositionalAudioStream* positionalStream;        bool ignoredByListener { false };        bool ignoringListener { false };         MixableStream(NodeIDStreamID nodeIDStreamID, PositionalAudioStream* positionalStream) :            nodeStreamID(nodeIDStreamID), hrtf(new AudioHRTF), positionalStream(positionalStream) {};        MixableStream(QUuid nodeID, Node::LocalID localNodeID, StreamID streamID, PositionalAudioStream* positionalStream) :            nodeStreamID(nodeID, localNodeID, streamID), hrtf(new AudioHRTF), positionalStream(positionalStream) {};    };     using MixableStreamsVector = std::vector<MixableStream>;    struct Streams {        MixableStreamsVector active;        MixableStreamsVector inactive;        MixableStreamsVector skipped;    };     Streams& getStreams() { return _streams; }     // thread-safe, called from AudioMixerWorker(s) while processing ignore packets for other nodes    void ignoredByNode(QUuid nodeID);    void unignoredByNode(QUuid nodeID);     // start of methods called non-concurrently from single AudioMixerWorker mixing for the owning node     const Node::IgnoredNodeIDs& getNewIgnoredNodeIDs() const { return _newIgnoredNodeIDs; }    const Node::IgnoredNodeIDs& getNewUnignoredNodeIDs() const { return _newUnignoredNodeIDs; }     using ConcurrentIgnoreNodeIDs = tbb::concurrent_vector<QUuid>;    const ConcurrentIgnoreNodeIDs& getNewIgnoringNodeIDs() const { return _newIgnoringNodeIDs; }    const ConcurrentIgnoreNodeIDs& getNewUnignoringNodeIDs() const { return _newUnignoringNodeIDs; }     void clearStagedIgnoreChanges();     const Node::IgnoredNodeIDs& getIgnoringNodeIDs() const { return _ignoringNodeIDs; }      const std::vector<QUuid>& getSoloedNodes() const { return _soloedNodes; }     bool getHasReceivedFirstMix() const { return _hasReceivedFirstMix; }    void setHasReceivedFirstMix(bool hasReceivedFirstMix) { _hasReceivedFirstMix = hasReceivedFirstMix; }     // end of methods called non-concurrently from single AudioMixerWorker signals:    void injectorStreamFinished(const QUuid& streamID); public slots:    void handleMismatchAudioFormat(SharedNodePointer node, const QString& currentCodec, const QString& recievedCodec);    void sendSelectAudioFormat(SharedNodePointer node, const QString& selectedCodecName); private:    struct PacketQueue : public std::queue<QSharedPointer<ReceivedMessage>> {        QWeakPointer<Node> node;    };    PacketQueue _packetQueue;     AudioStreamVector _audioStreams; // microphone stream from avatar has a null stream ID     void optionallyReplicatePacket(ReceivedMessage& packet, const Node& node);     void setGainForAvatar(QUuid nodeID, float gain);     bool containsValidPosition(ReceivedMessage& message) const;     Streams _streams;     quint16 _outgoingMixedAudioSequenceNumber;     AudioStreamStats _downstreamAudioStreamStats;     int _frameToSendStats { 0 };     float _primaryAvatarGain { 1.0f };   // per-listener mixing gain, applied only to avatars    float _primaryInjectorGain { 1.0f }; // per-listener mixing gain, applied only to injectors     CodecPluginPointer _codec;    QString _selectedCodecName;    Encoder* _encoder{ nullptr }; // for outbound mixed stream    Decoder* _decoder{ nullptr }; // for mic stream     bool _shouldFlushEncoder { false };     bool _shouldMuteClient { false };    bool _requestsDomainListData { false };     std::vector<AddedStream> _newAddedStreams;     Node::IgnoredNodeIDs _newIgnoredNodeIDs;    Node::IgnoredNodeIDs _newUnignoredNodeIDs;     tbb::concurrent_vector<QUuid> _newIgnoringNodeIDs;    tbb::concurrent_vector<QUuid> _newUnignoringNodeIDs;     std::mutex _ignoringNodeIDsMutex;    Node::IgnoredNodeIDs _ignoringNodeIDs;     std::atomic_bool _isIgnoreRadiusEnabled { false };     std::vector<QUuid> _soloedNodes;     bool _hasReceivedFirstMix { false };}; #endif // hifi_AudioMixerClientData_h