From 0fd32b36ad2b364f074ad71a23a8fd18dc84116d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 15 Apr 2016 11:04:35 -0700 Subject: [PATCH 1/6] use a steadier clock for AudioMixer block timing --- assignment-client/src/audio/AudioMixer.cpp | 27 ++++++++++++---------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index cc6c4930ff..7f8b44e8b2 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef _WIN32 #include @@ -577,15 +578,14 @@ void AudioMixer::domainSettingsRequestComplete() { void AudioMixer::broadcastMixes() { auto nodeList = DependencyManager::get(); - int64_t nextFrame = 0; - QElapsedTimer timer; - timer.start(); - - int64_t usecToSleep = AudioConstants::NETWORK_FRAME_USECS; + auto nextFrameTimestamp = p_high_resolution_clock::now(); + auto timeToSleep = std::chrono::microseconds(0); const int TRAILING_AVERAGE_FRAMES = 100; int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES; + int currentFrame { 1 }; + while (!_isFinished) { const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f; const float BACK_OFF_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.20f; @@ -595,12 +595,12 @@ void AudioMixer::broadcastMixes() { const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES; const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO; - if (usecToSleep < 0) { - usecToSleep = 0; + if (timeToSleep.count() < 0) { + timeToSleep = std::chrono::microseconds(0); } _trailingSleepRatio = (PREVIOUS_FRAMES_RATIO * _trailingSleepRatio) - + (usecToSleep * CURRENT_FRAME_RATIO / (float) AudioConstants::NETWORK_FRAME_USECS); + + (timeToSleep.count() * CURRENT_FRAME_RATIO / (float) AudioConstants::NETWORK_FRAME_USECS); float lastCutoffRatio = _performanceThrottlingRatio; bool hasRatioChanged = false; @@ -718,11 +718,14 @@ void AudioMixer::broadcastMixes() { break; } - usecToSleep = (++nextFrame * AudioConstants::NETWORK_FRAME_USECS) - (timer.nsecsElapsed() / 1000); + // push the next frame timestamp to when we should send the next + nextFrameTimestamp += std::chrono::microseconds(AudioConstants::NETWORK_FRAME_USECS); - if (usecToSleep > 0) { - usleep(usecToSleep); - } + // sleep as long as we need until next frame, if we can + auto now = p_high_resolution_clock::now(); + timeToSleep = std::chrono::duration_cast(nextFrameTimestamp - now); + + std::this_thread::sleep_for(timeToSleep); } } From 925c1ce26bc9b733926ff801685f9a1db73c9bf6 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 15 Apr 2016 11:04:56 -0700 Subject: [PATCH 2/6] don't send all stats to audio-mixer clients at same time --- assignment-client/src/audio/AudioMixer.cpp | 4 +--- assignment-client/src/audio/AudioMixerClientData.cpp | 9 +++++++++ assignment-client/src/audio/AudioMixerClientData.h | 5 +++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 7f8b44e8b2..2921bca14d 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -694,10 +694,8 @@ void AudioMixer::broadcastMixes() { nodeList->sendPacket(std::move(mixPacket), *node); nodeData->incrementOutgoingMixedAudioSequenceNumber(); - static const int FRAMES_PER_SECOND = int(ceilf(1.0f / AudioConstants::NETWORK_FRAME_SECS)); - // send an audio stream stats packet to the client approximately every second - if (nextFrame % FRAMES_PER_SECOND == 0) { + if (nodeData->shouldSendStats(currentFrame++)) { nodeData->sendAudioStreamStatsPackets(node); } diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 38cb8a174f..c0311f7cc4 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include @@ -26,7 +28,14 @@ AudioMixerClientData::AudioMixerClientData(const QUuid& nodeID) : _outgoingMixedAudioSequenceNumber(0), _downstreamAudioStreamStats() { + // of the ~94 blocks in a second of audio sent from the AudioMixer, pick a random one to send out a stats packet on + // this ensures we send out stats to this client around every second + // but do not send all of the stats packets out at the same time + std::random_device randomDevice; + std::mt19937 numberGenerator { randomDevice() }; + std::uniform_int_distribution<> distribution { 1, (int) ceil(1.0f / AudioConstants::NETWORK_FRAME_SECS) }; + _frameToSendStats = distribution(numberGenerator); } AvatarAudioStream* AudioMixerClientData::getAvatarAudioStream() { diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index 3627a247c0..b95023674b 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -58,6 +58,9 @@ public: 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) { return frameNumber % _frameToSendStats == 0; } + signals: void injectorStreamFinished(const QUuid& streamIdentifier); @@ -72,6 +75,8 @@ private: quint16 _outgoingMixedAudioSequenceNumber; AudioStreamStats _downstreamAudioStreamStats; + + int _frameToSendStats { 0 }; }; #endif // hifi_AudioMixerClientData_h From 38481aac5352ac6f911e953ce3fb63420db298c9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 15 Apr 2016 11:34:28 -0700 Subject: [PATCH 3/6] use HRC clock timings in avatar mixer --- assignment-client/src/avatars/AvatarMixer.cpp | 26 +++++++++---------- assignment-client/src/avatars/AvatarMixer.h | 16 +++++++----- .../src/avatars/AvatarMixerClientData.h | 15 ++++++----- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 759a4956f2..70fc1554f5 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -36,14 +36,7 @@ const unsigned int AVATAR_DATA_SEND_INTERVAL_MSECS = (1.0f / (float) AVATAR_MIXE AvatarMixer::AvatarMixer(ReceivedMessage& message) : ThreadedAssignment(message), - _broadcastThread(), - _lastFrameTimestamp(QDateTime::currentMSecsSinceEpoch()), - _trailingSleepRatio(1.0f), - _performanceThrottlingRatio(0.0f), - _sumListeners(0), - _numStatFrames(0), - _sumBillboardPackets(0), - _sumIdentityPackets(0) + _broadcastThread() { // make sure we hear about node kills so we can tell the other nodes connect(DependencyManager::get().data(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled); @@ -72,7 +65,12 @@ const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 187.0f; // 1) use the view frustum to cull those avatars that are out of view. Since avatar data doesn't need to be present // if the avatar is not in view or in the keyhole. void AvatarMixer::broadcastAvatarData() { - int idleTime = QDateTime::currentMSecsSinceEpoch() - _lastFrameTimestamp; + int idleTime = AVATAR_DATA_SEND_INTERVAL_MSECS; + + if (_lastFrameTimestamp.time_since_epoch().count() > 0) { + auto idleDuration = p_high_resolution_clock::now() - _lastFrameTimestamp; + idleTime = std::chrono::duration_cast(idleDuration).count(); + } ++_numStatFrames; @@ -250,7 +248,7 @@ void AvatarMixer::broadcastAvatarData() { // we will also force a send of billboard or identity packet // if either has changed in the last frame - if (otherNodeData->getBillboardChangeTimestamp() > 0 + if (otherNodeData->getBillboardChangeTimestamp().time_since_epoch().count() > 0 && (forceSend || otherNodeData->getBillboardChangeTimestamp() > _lastFrameTimestamp || distribution(generator) < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { @@ -267,7 +265,7 @@ void AvatarMixer::broadcastAvatarData() { ++_sumBillboardPackets; } - if (otherNodeData->getIdentityChangeTimestamp() > 0 + if (otherNodeData->getIdentityChangeTimestamp().time_since_epoch().count() > 0 && (forceSend || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp || distribution(generator) < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { @@ -385,7 +383,7 @@ void AvatarMixer::broadcastAvatarData() { otherAvatar.doneEncoding(false); }); - _lastFrameTimestamp = QDateTime::currentMSecsSinceEpoch(); + _lastFrameTimestamp = p_high_resolution_clock::now(); } void AvatarMixer::nodeKilled(SharedNodePointer killedNode) { @@ -438,7 +436,7 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer mes // parse the identity packet and update the change timestamp if appropriate if (avatar.hasIdentityChangedAfterParsing(message->getMessage())) { QMutexLocker nodeDataLocker(&nodeData->getMutex()); - nodeData->setIdentityChangeTimestamp(QDateTime::currentMSecsSinceEpoch()); + nodeData->flagIdentityChange(); } } } @@ -452,7 +450,7 @@ void AvatarMixer::handleAvatarBillboardPacket(QSharedPointer me // parse the billboard packet and update the change timestamp if appropriate if (avatar.hasBillboardChangedAfterParsing(message->getMessage())) { QMutexLocker nodeDataLocker(&nodeData->getMutex()); - nodeData->setBillboardChangeTimestamp(QDateTime::currentMSecsSinceEpoch()); + nodeData->flagBillboardChange(); } } diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index 00c53e916b..6fc00960c2 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -15,6 +15,8 @@ #ifndef hifi_AvatarMixer_h #define hifi_AvatarMixer_h +#include + #include /// Handles assignments of type AvatarMixer - distribution of avatar data to various clients @@ -44,15 +46,15 @@ private: QThread _broadcastThread; - quint64 _lastFrameTimestamp; + p_high_resolution_clock::time_point _lastFrameTimestamp; - float _trailingSleepRatio; - float _performanceThrottlingRatio; + float _trailingSleepRatio { 1.0f }; + float _performanceThrottlingRatio { 0.0f }; - int _sumListeners; - int _numStatFrames; - int _sumBillboardPackets; - int _sumIdentityPackets; + int _sumListeners { 0 }; + int _numStatFrames { 0 }; + int _sumBillboardPackets { 0 }; + int _sumIdentityPackets { 0 }; float _maxKbpsPerNode = 0.0f; diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index a310d0f16a..adeac51fcf 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,8 @@ const QString INBOUND_AVATAR_DATA_STATS_KEY = "inbound_av_data_kbps"; class AvatarMixerClientData : public NodeData { Q_OBJECT public: + using HRCTime = p_high_resolution_clock::time_point; + int parseData(ReceivedMessage& message) override; AvatarData& getAvatar() { return *_avatar; } @@ -45,11 +48,11 @@ public: uint16_t getLastReceivedSequenceNumber() const { return _lastReceivedSequenceNumber; } - quint64 getBillboardChangeTimestamp() const { return _billboardChangeTimestamp; } - void setBillboardChangeTimestamp(quint64 billboardChangeTimestamp) { _billboardChangeTimestamp = billboardChangeTimestamp; } + HRCTime getBillboardChangeTimestamp() const { return _billboardChangeTimestamp; } + void flagBillboardChange() { _billboardChangeTimestamp = p_high_resolution_clock::now(); } - quint64 getIdentityChangeTimestamp() const { return _identityChangeTimestamp; } - void setIdentityChangeTimestamp(quint64 identityChangeTimestamp) { _identityChangeTimestamp = identityChangeTimestamp; } + HRCTime getIdentityChangeTimestamp() const { return _identityChangeTimestamp; } + void flagIdentityChange() { _identityChangeTimestamp = p_high_resolution_clock::now(); } void setFullRateDistance(float fullRateDistance) { _fullRateDistance = fullRateDistance; } float getFullRateDistance() const { return _fullRateDistance; } @@ -86,8 +89,8 @@ private: std::unordered_map _lastBroadcastSequenceNumbers; std::unordered_set _hasReceivedFirstPacketsFrom; - quint64 _billboardChangeTimestamp = 0; - quint64 _identityChangeTimestamp = 0; + p_high_resolution_clock::time_point _billboardChangeTimestamp; + p_high_resolution_clock::time_point _identityChangeTimestamp; float _fullRateDistance = FLT_MAX; float _maxAvatarDistance = FLT_MAX; From 33b46bd8e3a40c2cae29d57129b031d96a264e0f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 18 Apr 2016 16:02:23 -0700 Subject: [PATCH 4/6] remove the billboard packet handling from AM --- assignment-client/src/avatars/AvatarMixer.cpp | 42 ++----------------- assignment-client/src/avatars/AvatarMixer.h | 2 - .../src/avatars/AvatarMixerClientData.h | 4 -- 3 files changed, 3 insertions(+), 45 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 70fc1554f5..a109934d10 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -44,7 +44,6 @@ AvatarMixer::AvatarMixer(ReceivedMessage& message) : auto& packetReceiver = DependencyManager::get()->getPacketReceiver(); packetReceiver.registerListener(PacketType::AvatarData, this, "handleAvatarDataPacket"); packetReceiver.registerListener(PacketType::AvatarIdentity, this, "handleAvatarIdentityPacket"); - packetReceiver.registerListener(PacketType::AvatarBillboard, this, "handleAvatarBillboardPacket"); packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket"); } @@ -59,7 +58,7 @@ AvatarMixer::~AvatarMixer() { // An 80% chance of sending a identity packet within a 5 second interval. // assuming 60 htz update rate. -const float BILLBOARD_AND_IDENTITY_SEND_PROBABILITY = 1.0f / 187.0f; +const float IDENTITY_SEND_PROBABILITY = 1.0f / 187.0f; // NOTE: some additional optimizations to consider. // 1) use the view frustum to cull those avatars that are out of view. Since avatar data doesn't need to be present @@ -243,32 +242,13 @@ void AvatarMixer::broadcastAvatarData() { return; } - // make sure we send out identity and billboard packets to and from new arrivals. + // make sure we send out identity packets to and from new arrivals. bool forceSend = !otherNodeData->checkAndSetHasReceivedFirstPacketsFrom(node->getUUID()); - // we will also force a send of billboard or identity packet - // if either has changed in the last frame - if (otherNodeData->getBillboardChangeTimestamp().time_since_epoch().count() > 0 - && (forceSend - || otherNodeData->getBillboardChangeTimestamp() > _lastFrameTimestamp - || distribution(generator) < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { - - QByteArray rfcUUID = otherNode->getUUID().toRfc4122(); - QByteArray billboard = otherNodeData->getAvatar().getBillboard(); - - auto billboardPacket = NLPacket::create(PacketType::AvatarBillboard, rfcUUID.size() + billboard.size()); - billboardPacket->write(rfcUUID); - billboardPacket->write(billboard); - - nodeList->sendPacket(std::move(billboardPacket), *node); - - ++_sumBillboardPackets; - } - if (otherNodeData->getIdentityChangeTimestamp().time_since_epoch().count() > 0 && (forceSend || otherNodeData->getIdentityChangeTimestamp() > _lastFrameTimestamp - || distribution(generator) < BILLBOARD_AND_IDENTITY_SEND_PROBABILITY)) { + || distribution(generator) < IDENTITY_SEND_PROBABILITY)) { QByteArray individualData = otherNodeData->getAvatar().identityByteArray(); @@ -442,20 +422,6 @@ void AvatarMixer::handleAvatarIdentityPacket(QSharedPointer mes } } -void AvatarMixer::handleAvatarBillboardPacket(QSharedPointer message, SharedNodePointer senderNode) { - AvatarMixerClientData* nodeData = dynamic_cast(senderNode->getLinkedData()); - if (nodeData) { - AvatarData& avatar = nodeData->getAvatar(); - - // parse the billboard packet and update the change timestamp if appropriate - if (avatar.hasBillboardChangedAfterParsing(message->getMessage())) { - QMutexLocker nodeDataLocker(&nodeData->getMutex()); - nodeData->flagBillboardChange(); - } - - } -} - void AvatarMixer::handleKillAvatarPacket(QSharedPointer message) { DependencyManager::get()->processKillNode(*message); } @@ -464,7 +430,6 @@ void AvatarMixer::sendStatsPacket() { QJsonObject statsObject; statsObject["average_listeners_last_second"] = (float) _sumListeners / (float) _numStatFrames; - statsObject["average_billboard_packets_per_frame"] = (float) _sumBillboardPackets / (float) _numStatFrames; statsObject["average_identity_packets_per_frame"] = (float) _sumIdentityPackets / (float) _numStatFrames; statsObject["trailing_sleep_percentage"] = _trailingSleepRatio * 100; @@ -505,7 +470,6 @@ void AvatarMixer::sendStatsPacket() { ThreadedAssignment::addPacketStatsAndSendStatsPacket(statsObject); _sumListeners = 0; - _sumBillboardPackets = 0; _sumIdentityPackets = 0; _numStatFrames = 0; } diff --git a/assignment-client/src/avatars/AvatarMixer.h b/assignment-client/src/avatars/AvatarMixer.h index 6fc00960c2..c7761a2cba 100644 --- a/assignment-client/src/avatars/AvatarMixer.h +++ b/assignment-client/src/avatars/AvatarMixer.h @@ -36,7 +36,6 @@ public slots: private slots: void handleAvatarDataPacket(QSharedPointer message, SharedNodePointer senderNode); void handleAvatarIdentityPacket(QSharedPointer message, SharedNodePointer senderNode); - void handleAvatarBillboardPacket(QSharedPointer message, SharedNodePointer senderNode); void handleKillAvatarPacket(QSharedPointer message); void domainSettingsRequestComplete(); @@ -53,7 +52,6 @@ private: int _sumListeners { 0 }; int _numStatFrames { 0 }; - int _sumBillboardPackets { 0 }; int _sumIdentityPackets { 0 }; float _maxKbpsPerNode = 0.0f; diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index adeac51fcf..43cc416dbb 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -48,9 +48,6 @@ public: uint16_t getLastReceivedSequenceNumber() const { return _lastReceivedSequenceNumber; } - HRCTime getBillboardChangeTimestamp() const { return _billboardChangeTimestamp; } - void flagBillboardChange() { _billboardChangeTimestamp = p_high_resolution_clock::now(); } - HRCTime getIdentityChangeTimestamp() const { return _identityChangeTimestamp; } void flagIdentityChange() { _identityChangeTimestamp = p_high_resolution_clock::now(); } @@ -89,7 +86,6 @@ private: std::unordered_map _lastBroadcastSequenceNumbers; std::unordered_set _hasReceivedFirstPacketsFrom; - p_high_resolution_clock::time_point _billboardChangeTimestamp; p_high_resolution_clock::time_point _identityChangeTimestamp; float _fullRateDistance = FLT_MAX; From 1d256be7ee5e04825d24f6a80bbb5bbd8cedf8af Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 18 Apr 2016 16:04:20 -0700 Subject: [PATCH 5/6] fix random stats sending for AudioMixer clients --- assignment-client/src/audio/AudioMixerClientData.cpp | 4 ++++ assignment-client/src/audio/AudioMixerClientData.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index c0311f7cc4..537ef793e1 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -189,6 +189,10 @@ void AudioMixerClientData::checkBuffersBeforeFrameSend() { } } +bool AudioMixerClientData::shouldSendStats(int frameNumber) { + return (frameNumber % (int) ceil(1.0f / AudioConstants::NETWORK_FRAME_SECS)) == _frameToSendStats; +} + void AudioMixerClientData::sendAudioStreamStatsPackets(const SharedNodePointer& destinationNode) { auto nodeList = DependencyManager::get(); diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index b95023674b..ff4143cf08 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -59,7 +59,7 @@ public: 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) { return frameNumber % _frameToSendStats == 0; } + bool shouldSendStats(int frameNumber); signals: void injectorStreamFinished(const QUuid& streamIdentifier); From 93cf5a103518531561c49d64608241672f1b7283 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 18 Apr 2016 16:53:02 -0700 Subject: [PATCH 6/6] fixes for CR comments --- assignment-client/src/audio/AudioMixer.cpp | 6 +++++- assignment-client/src/audio/AudioMixerClientData.cpp | 2 +- assignment-client/src/avatars/AvatarMixerClientData.h | 2 +- libraries/audio/src/AudioConstants.h | 1 + 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 2921bca14d..0f51bd00b1 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -585,6 +585,7 @@ void AudioMixer::broadcastMixes() { int framesSinceCutoffEvent = TRAILING_AVERAGE_FRAMES; int currentFrame { 1 }; + int numFramesPerSecond { (int) ceil(AudioConstants::NETWORK_FRAMES_PER_SEC) }; while (!_isFinished) { const float STRUGGLE_TRIGGER_SLEEP_PERCENTAGE_THRESHOLD = 0.10f; @@ -695,7 +696,10 @@ void AudioMixer::broadcastMixes() { nodeData->incrementOutgoingMixedAudioSequenceNumber(); // send an audio stream stats packet to the client approximately every second - if (nodeData->shouldSendStats(currentFrame++)) { + ++currentFrame; + currentFrame %= numFramesPerSecond; + + if (nodeData->shouldSendStats(currentFrame)) { nodeData->sendAudioStreamStatsPackets(node); } diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 537ef793e1..93a51b1df2 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -190,7 +190,7 @@ void AudioMixerClientData::checkBuffersBeforeFrameSend() { } bool AudioMixerClientData::shouldSendStats(int frameNumber) { - return (frameNumber % (int) ceil(1.0f / AudioConstants::NETWORK_FRAME_SECS)) == _frameToSendStats; + return frameNumber == _frameToSendStats; } void AudioMixerClientData::sendAudioStreamStatsPackets(const SharedNodePointer& destinationNode) { diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 43cc416dbb..4a816291f4 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -86,7 +86,7 @@ private: std::unordered_map _lastBroadcastSequenceNumbers; std::unordered_set _hasReceivedFirstPacketsFrom; - p_high_resolution_clock::time_point _identityChangeTimestamp; + HRCTime _identityChangeTimestamp; float _fullRateDistance = FLT_MAX; float _maxAvatarDistance = FLT_MAX; diff --git a/libraries/audio/src/AudioConstants.h b/libraries/audio/src/AudioConstants.h index 67a3f8c6ff..38fead87f1 100644 --- a/libraries/audio/src/AudioConstants.h +++ b/libraries/audio/src/AudioConstants.h @@ -29,6 +29,7 @@ namespace AudioConstants { const int NETWORK_FRAME_SAMPLES_PER_CHANNEL = NETWORK_FRAME_BYTES_PER_CHANNEL / sizeof(AudioSample); const float NETWORK_FRAME_SECS = (AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL / float(AudioConstants::SAMPLE_RATE)); const float NETWORK_FRAME_MSECS = NETWORK_FRAME_SECS * 1000.0f; + const float NETWORK_FRAMES_PER_SEC = 1.0f / NETWORK_FRAME_SECS; // be careful with overflows when using this constant const int NETWORK_FRAME_USECS = static_cast(NETWORK_FRAME_MSECS * 1000.0f);