From 711e6ca3f5b4dff11154f1db763cb1f766fb294c Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 17:43:55 -0700 Subject: [PATCH 01/59] clean up casts and types to fix warnings in a cleaner way --- libraries/octree/src/OctreeSceneStats.cpp | 4 ++-- libraries/octree/src/OctreeSceneStats.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index 5cf906d82d..a21ab60493 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -919,13 +919,13 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, if (wantExtraDebugging) { qDebug() << "too many _missingSequenceNumbers:" << _missingSequenceNumbers.size(); } - foreach(unsigned int missingItem, _missingSequenceNumbers) { + foreach(uint16_t missingItem, _missingSequenceNumbers) { if (wantExtraDebugging) { qDebug() << "checking item:" << missingItem << "is it in need of pruning?"; qDebug() << "(_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE):" << (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE); } - if (missingItem <= (unsigned int)std::max(0, (int)_incomingLastSequence - (int)MAX_MISSING_SEQUENCE_OLD_AGE)) { + if (missingItem <= std::max(0, _incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE)) { if (wantExtraDebugging) { qDebug() << "pruning really old missing sequence:" << missingItem; } diff --git a/libraries/octree/src/OctreeSceneStats.h b/libraries/octree/src/OctreeSceneStats.h index 2b39b3434c..866c5d0b85 100644 --- a/libraries/octree/src/OctreeSceneStats.h +++ b/libraries/octree/src/OctreeSceneStats.h @@ -269,7 +269,7 @@ private: unsigned int _incomingLate; /// out of order later than expected unsigned int _incomingReallyLate; /// out of order and later than MAX_MISSING_SEQUENCE_OLD_AGE late unsigned int _incomingPossibleDuplicate; /// out of order possibly a duplicate - QSet _missingSequenceNumbers; + QSet _missingSequenceNumbers; SimpleMovingAverage _incomingFlightTimeAverage; // features related items From c958ae8cfbdf4d502ad9e71630dd22783af83586 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 17:47:19 -0700 Subject: [PATCH 02/59] fix LocalVoxelsOverlay types to match --- interface/src/ui/LocalVoxelsOverlay.cpp | 2 +- interface/src/ui/LocalVoxelsOverlay.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/LocalVoxelsOverlay.cpp b/interface/src/ui/LocalVoxelsOverlay.cpp index 9ad1428535..7eaf9ed5c5 100644 --- a/interface/src/ui/LocalVoxelsOverlay.cpp +++ b/interface/src/ui/LocalVoxelsOverlay.cpp @@ -41,7 +41,7 @@ void LocalVoxelsOverlay::update(float deltatime) { } _tree->lockForRead(); - if (_visible && _voxelCount != (int)_tree->getOctreeElementsCount()) { + if (_visible && _voxelCount != _tree->getOctreeElementsCount()) { _voxelCount = _tree->getOctreeElementsCount(); _voxelSystem->forceRedrawEntireTree(); } diff --git a/interface/src/ui/LocalVoxelsOverlay.h b/interface/src/ui/LocalVoxelsOverlay.h index c5582a54eb..2b3ba1f535 100644 --- a/interface/src/ui/LocalVoxelsOverlay.h +++ b/interface/src/ui/LocalVoxelsOverlay.h @@ -43,7 +43,7 @@ private: QString _treeName; StrongVoxelTreePointer _tree; // so that the tree doesn't get freed - int _voxelCount; + unsigned long _voxelCount; StrongVoxelSystemPointer _voxelSystem; }; From 72449fdb6a827ab0d1f094e2f03b3f7626687771 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 14 Mar 2014 17:50:57 -0700 Subject: [PATCH 03/59] initial optimizations to AudioMixer with mmx additions --- assignment-client/src/audio/AudioMixer.cpp | 71 ++++++++++++++++------ interface/interface_en.ts | 16 ++--- libraries/audio/src/AudioRingBuffer.cpp | 3 - libraries/audio/src/AudioRingBuffer.h | 4 ++ 4 files changed, 64 insertions(+), 30 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 812acc8d70..572da1a6c4 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -6,6 +6,7 @@ // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // +#include #include #include #include @@ -157,27 +158,59 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // if the bearing relative angle to source is > 0 then the delayed channel is the right one int delayedChannelOffset = (bearingRelativeAngleToSource > 0.0f) ? 1 : 0; int goodChannelOffset = delayedChannelOffset == 0 ? 1 : 0; + + const int16_t* nextOutputStart = bufferToAdd->getNextOutput(); + const int16_t* delayNextOutputStart = nextOutputStart - numSamplesDelay; + const int16_t* bufferStart = bufferToAdd->getBuffer(); + int ringBufferSampleCapacity = bufferToAdd->getSampleCapacity(); + + if (delayNextOutputStart < bufferStart) { + delayNextOutputStart = bufferStart + ringBufferSampleCapacity - numSamplesDelay; + } - for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 2) { - if ((s / 2) < numSamplesDelay) { - // pull the earlier sample for the delayed channel - int earlierSample = (*bufferToAdd)[(s / 2) - numSamplesDelay] * attenuationCoefficient * weakChannelAmplitudeRatio; - _clientSamples[s + delayedChannelOffset] = glm::clamp(_clientSamples[s + delayedChannelOffset] + earlierSample, - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - } - - // pull the current sample for the good channel - int16_t currentSample = (*bufferToAdd)[s / 2] * attenuationCoefficient; - _clientSamples[s + goodChannelOffset] = glm::clamp(_clientSamples[s + goodChannelOffset] + currentSample, - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - - if ((s / 2) + numSamplesDelay < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { - // place the current sample at the right spot in the delayed channel - int16_t clampedSample = glm::clamp((int) (_clientSamples[s + (numSamplesDelay * 2) + delayedChannelOffset] - + (currentSample * weakChannelAmplitudeRatio)), - MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - _clientSamples[s + (numSamplesDelay * 2) + delayedChannelOffset] = clampedSample; + int16_t correctMixSample[2], correctBufferSample[2], delayMixSample[2], delayBufferSample[2]; + int delayedChannelIndex[2]; + + float attenuationAndWeakChannelRatio = attenuationCoefficient * weakChannelAmplitudeRatio; + + for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 4) { + + // setup the int16_t variables for the two sample sets + correctBufferSample[0] = nextOutputStart[s / 2] * attenuationCoefficient; + correctBufferSample[1] = nextOutputStart[(s / 2) + 1] * attenuationCoefficient; + correctMixSample[0] = _clientSamples[s + goodChannelOffset]; + correctMixSample[1] = _clientSamples[s + goodChannelOffset + 2]; + + for (int i = 0; i < 2; ++i) { + if ((s / 2) + numSamplesDelay + i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { + // for the delayed channel we fill the range (n + numSamplesDelay) to NETWORK_BUFFER_LENGTH_SAMPLES_STEREO first + delayedChannelIndex[i] = s + (numSamplesDelay * 2) + (i * 2) + delayedChannelOffset; + delayBufferSample[i] = correctBufferSample[i] * weakChannelAmplitudeRatio; + } else { + // now that the right most range has been filled, we go back to fill in numSamples delay at the beginning + int samplesBack = (s / 2) - NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL + i; + + delayBufferSample[i] = delayNextOutputStart[numSamplesDelay + samplesBack] * attenuationAndWeakChannelRatio; + delayedChannelIndex[i] = (numSamplesDelay + samplesBack) * 2 + delayedChannelOffset; + } } + + delayMixSample[0] = _clientSamples[delayedChannelIndex[0]]; + delayMixSample[1] = _clientSamples[delayedChannelIndex[1]]; + + __m64 bufferSamples = _mm_set_pi16(correctMixSample[0], correctMixSample[1], delayMixSample[0], delayMixSample[1]); + __m64 addedSamples = _mm_set_pi16(correctBufferSample[0], correctBufferSample[1], + delayBufferSample[0], delayBufferSample[1]); + + // perform the MMX add (with saturation) of two correct and delayed samples + __m64 mmxResult = _mm_adds_pi16(bufferSamples, addedSamples); + int16_t* shortResults = reinterpret_cast(&mmxResult); + + // assign the results from the result of the mmx arithmetic + _clientSamples[s + goodChannelOffset] = shortResults[3]; + _clientSamples[s + goodChannelOffset + 2] = shortResults[2]; + _clientSamples[delayedChannelIndex[0]] = shortResults[1]; + _clientSamples[delayedChannelIndex[1]] = shortResults[0]; } } diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 80433032dc..0be997acba 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -4,22 +4,22 @@ Application - + Export Voxels - + Sparse Voxel Octree Files (*.svo) - + Open Script - + JavaScript Files (*.js) @@ -113,18 +113,18 @@ Menu - + Open .ini config file - - + + Text files (*.ini) - + Save .ini config file diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 9bac210c39..56f6d038c2 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -121,9 +121,6 @@ qint64 AudioRingBuffer::writeData(const char* data, qint64 maxSize) { } int16_t& AudioRingBuffer::operator[](const int index) { - // make sure this is a valid index - assert(index > -_sampleCapacity && index < _sampleCapacity); - return *shiftedPositionAccomodatingWrap(_nextOutput, index); } diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index b6e75a2e86..577c01a63c 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -45,6 +45,10 @@ public: int getSampleCapacity() const { return _sampleCapacity; } int parseData(const QByteArray& packet); + + // assume callers using this will never wrap around the end + const int16_t* getNextOutput() { return _nextOutput; } + const int16_t* getBuffer() { return _buffer; } qint64 readSamples(int16_t* destination, qint64 maxSamples); qint64 writeSamples(const int16_t* source, qint64 maxSamples); From 0e7e337807e61290cc568bd80a0d20f885b184b6 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 18:05:40 -0700 Subject: [PATCH 04/59] fixed uninitialized variable warning --- libraries/shared/src/ShapeCollider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index 7f36d948e8..e83e6842a9 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -313,7 +313,7 @@ bool capsuleCapsule(const CapsuleShape* capsuleA, const CapsuleShape* capsuleB, // Since there are only three comparisons to do we unroll the sort algorithm... // and use a fifth slot as temp during swap. - if (points[4] > points[2]) { + if (points[1] > points[2]) { points[4] = points[1]; points[1] = points[2]; points[2] = points[4]; From 2766860b52fec7f3ebf519f1ed15a7767e48714f Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 18:11:22 -0700 Subject: [PATCH 05/59] fix some windows warnings in fsbinarystream.cpp --- interface/external/faceshift/src/fsbinarystream.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/external/faceshift/src/fsbinarystream.cpp b/interface/external/faceshift/src/fsbinarystream.cpp index 0a2d41e4b3..96434afd9b 100644 --- a/interface/external/faceshift/src/fsbinarystream.cpp +++ b/interface/external/faceshift/src/fsbinarystream.cpp @@ -160,7 +160,7 @@ void fsBinaryStream::received(long int sz, const char *data) { new_end = m_end + sz; } - if (new_end > Size(m_buffer.size())) m_buffer.resize(1.5*new_end); + if (new_end > Size(m_buffer.size())) m_buffer.resize((new_end * 15 / 10)); // HIFI: to get 1.5 without warnings memcpy(&m_buffer[0] + m_end, data, sz); m_end += sz; @@ -172,7 +172,7 @@ static bool decodeInfo(fsTrackingData & _trackingData, const std::string &buffer success &= read_pod(_trackingData.m_timestamp, buffer, start); unsigned char tracking_successfull = 0; success &= read_pod( tracking_successfull, buffer, start ); - _trackingData.m_trackingSuccessful = bool(tracking_successfull); + _trackingData.m_trackingSuccessful = bool(tracking_successfull != 0); // HIFI: get rid of windows warning return success; } From c0ee3fa1f0bd1831cc8945a82d85568884bf5022 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 18:14:54 -0700 Subject: [PATCH 06/59] fix unix warning --- libraries/shared/src/SharedUtil.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 70fac3efe4..e5aded2798 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -631,8 +631,7 @@ void debug::setDeadBeef(void* memoryVoid, int size) { } void debug::checkDeadBeef(void* memoryVoid, int size) { - unsigned char* memoryAt = (unsigned char*)memoryVoid; - assert(memcmp(memoryAt, DEADBEEF, std::min(size, DEADBEEF_SIZE)) != 0); + assert(memcmp((unsigned char*)memoryVoid, DEADBEEF, std::min(size, DEADBEEF_SIZE)) != 0); } // Safe version of glm::eulerAngles; uses the factorization method described in David Eberly's From c6f8d34ded2cc05966192a66eacf3dbfca723b0e Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 18:16:38 -0700 Subject: [PATCH 07/59] fix unix warning --- libraries/shared/src/NodeList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 263e29bc94..0cca9731b0 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -348,7 +348,7 @@ void NodeList::addSetOfNodeTypesToNodeInterestSet(const NodeSet& setOfNodeTypes) const uint32_t RFC_5389_MAGIC_COOKIE = 0x2112A442; const int NUM_BYTES_STUN_HEADER = 20; -const int NUM_STUN_REQUESTS_BEFORE_FALLBACK = 5; +const unsigned int NUM_STUN_REQUESTS_BEFORE_FALLBACK = 5; void NodeList::sendSTUNRequest() { const char STUN_SERVER_HOSTNAME[] = "stun.highfidelity.io"; From 1f775058717857b894df380076ca026d02bf3b37 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Fri, 14 Mar 2014 18:35:34 -0700 Subject: [PATCH 08/59] more unix warnings cleanup --- libraries/octree/src/Octree.cpp | 9 ++++----- libraries/octree/src/OctreePacketData.cpp | 2 +- libraries/octree/src/OctreePacketData.h | 14 +++++++------- libraries/octree/src/OctreeRenderer.cpp | 10 +++++----- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 4c8ed8c9f6..fc867ec698 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -807,13 +807,14 @@ int Octree::encodeTreeBitstream(OctreeElement* node, // write the octal code bool roomForOctalCode = false; // assume the worst - int codeLength; + int codeLength = 1; // assume root if (params.chopLevels) { unsigned char* newCode = chopOctalCode(node->getOctalCode(), params.chopLevels); roomForOctalCode = packetData->startSubTree(newCode); if (newCode) { delete newCode; + codeLength = numberOfThreeBitSectionsInCode(newCode); } else { codeLength = 1; } @@ -1559,14 +1560,13 @@ void Octree::copySubTreeIntoNewTree(OctreeElement* startNode, Octree* destinatio } static OctreePacketData packetData; - int bytesWritten = 0; while (!nodeBag.isEmpty()) { OctreeElement* subTree = nodeBag.extract(); packetData.reset(); // reset the packet between usage // ask our tree to write a bitsteam EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS, chopLevels); - bytesWritten = encodeTreeBitstream(subTree, &packetData, nodeBag, params); + encodeTreeBitstream(subTree, &packetData, nodeBag, params); // ask destination tree to read the bitstream ReadBitstreamToTreeParams args(WANT_COLOR, NO_EXISTS_BITS); destinationTree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args); @@ -1595,7 +1595,6 @@ void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinat nodeBag.insert(sourceTree->_rootNode); static OctreePacketData packetData; - int bytesWritten = 0; while (!nodeBag.isEmpty()) { OctreeElement* subTree = nodeBag.extract(); @@ -1604,7 +1603,7 @@ void Octree::copyFromTreeIntoSubTree(Octree* sourceTree, OctreeElement* destinat // ask our tree to write a bitsteam EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, WANT_COLOR, NO_EXISTS_BITS); - bytesWritten = sourceTree->encodeTreeBitstream(subTree, &packetData, nodeBag, params); + sourceTree->encodeTreeBitstream(subTree, &packetData, nodeBag, params); // ask destination tree to read the bitstream bool wantImportProgress = true; diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index bb613f57c1..5123d0711a 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -23,7 +23,7 @@ OctreePacketData::OctreePacketData(bool enableCompression, int targetSize) { changeSettings(enableCompression, targetSize); // does reset... } -void OctreePacketData::changeSettings(bool enableCompression, int targetSize) { +void OctreePacketData::changeSettings(bool enableCompression, size_t targetSize) { _enableCompression = enableCompression; _targetSize = std::min(MAX_OCTREE_UNCOMRESSED_PACKET_SIZE, targetSize); reset(); diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index a71a3f893c..526cb7c65e 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -30,15 +30,15 @@ typedef uint16_t OCTREE_PACKET_INTERNAL_SECTION_SIZE; const int MAX_OCTREE_PACKET_SIZE = MAX_PACKET_SIZE; // this is overly conservative - sizeof(PacketType) is 8 bytes but a packed PacketType could be as small as one byte -const int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS) +const size_t OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME); -const int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE); +const size_t MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE); -const int MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE; +const size_t MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE; -const int MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40; -const int COMPRESS_PADDING = 15; +const size_t MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40; +const size_t COMPRESS_PADDING = 15; const int REASONABLE_NUMBER_OF_PACKING_ATTEMPTS = 5; const int PACKET_IS_COLOR_BIT = 0; @@ -69,7 +69,7 @@ public: ~OctreePacketData(); /// change compression and target size settings - void changeSettings(bool enableCompression = false, int targetSize = MAX_OCTREE_PACKET_DATA_SIZE); + void changeSettings(bool enableCompression = false, size_t targetSize = MAX_OCTREE_PACKET_DATA_SIZE); /// reset completely, all data is discarded void reset(); @@ -186,7 +186,7 @@ private: /// append a single byte, might fail if byte would cause packet to be too large bool append(unsigned char byte); - int _targetSize; + size_t _targetSize; bool _enableCompression; unsigned char _uncompressed[MAX_OCTREE_UNCOMRESSED_PACKET_SIZE]; diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 8fdc2139af..1066e53845 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -57,9 +57,9 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails); - int packetLength = dataByteArray.size(); + size_t packetLength = dataByteArray.size(); PacketType command = packetTypeForPacket(dataByteArray); - int numBytesPacketHeader = numBytesForPacketHeader(dataByteArray); + size_t numBytesPacketHeader = numBytesForPacketHeader(dataByteArray); QUuid sourceUUID = uuidFromPacketHeader(dataByteArray); PacketType expectedType = getExpectedPacketType(); @@ -86,11 +86,11 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar int flightTime = arrivedAt - sentAt + clockSkew; OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - int dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); + size_t dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); if (extraDebugging) { qDebug("OctreeRenderer::processDatagram() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d", + " color:%s compressed:%s sequence: %u flight:%d usec size:%lu data:%lu", debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), sequence, flightTime, packetLength, dataBytes); } @@ -119,7 +119,7 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar packetData.loadFinalizedContent(dataAt, sectionLength); if (extraDebugging) { qDebug("OctreeRenderer::processDatagram() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d" + " color:%s compressed:%s sequence: %u flight:%d usec size:%lu data:%lu" " subsection:%d sectionLength:%d uncompressed:%d", debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), sequence, flightTime, packetLength, dataBytes, subsection, sectionLength, From 0200ac9da868d624066b13440b9cb84ba550d364 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 14 Mar 2014 22:43:31 -0700 Subject: [PATCH 09/59] more unix warnings fixes --- interface/src/VoxelSystem.cpp | 14 +++++--------- interface/src/VoxelSystem.h | 4 ++-- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index a8bdeb1114..6c4ed12e9e 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -243,7 +243,7 @@ VoxelSystem::~VoxelSystem() { // This is called by the main application thread on both the initialization of the application and when // the preferences dialog box is called/saved -void VoxelSystem::setMaxVoxels(int maxVoxels) { +void VoxelSystem::setMaxVoxels(unsigned long maxVoxels) { if (maxVoxels == _maxVoxels) { return; } @@ -550,7 +550,7 @@ int VoxelSystem::parseData(const QByteArray& packet) { int flightTime = arrivedAt - sentAt; OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - int dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); + size_t dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); int subsection = 1; while (dataBytes > 0) { @@ -576,7 +576,7 @@ int VoxelSystem::parseData(const QByteArray& packet) { packetData.loadFinalizedContent(dataAt, sectionLength); if (Application::getInstance()->getLogger()->extraDebugging()) { qDebug("VoxelSystem::parseData() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d" + " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%lu" " subsection:%d sectionLength:%d uncompressed:%d", debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), sequence, flightTime, packet.size(), dataBytes, subsection, sectionLength, @@ -919,13 +919,11 @@ void VoxelSystem::copyWrittenDataSegmentToReadArrays(glBufferIndex segmentStart, // Depending on if we're using per vertex normals, we will need more or less vertex points per voxel int vertexPointsPerVoxel = GLOBAL_NORMALS_VERTEX_POINTS_PER_VOXEL; - GLintptr segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLfloat); GLsizeiptr segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLfloat); GLfloat* readVerticesAt = _readVerticesArray + (segmentStart * vertexPointsPerVoxel); GLfloat* writeVerticesAt = _writeVerticesArray + (segmentStart * vertexPointsPerVoxel); memcpy(readVerticesAt, writeVerticesAt, segmentSizeBytes); - segmentStartAt = segmentStart * vertexPointsPerVoxel * sizeof(GLubyte); segmentSizeBytes = segmentLength * vertexPointsPerVoxel * sizeof(GLubyte); GLubyte* readColorsAt = _readColorsArray + (segmentStart * vertexPointsPerVoxel); GLubyte* writeColorsAt = _writeColorsArray + (segmentStart * vertexPointsPerVoxel); @@ -1958,10 +1956,8 @@ bool VoxelSystem::showAllSubTreeOperation(OctreeElement* element, void* extraDat // If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not // consider that case. - ViewFrustum::location inLastCulledFrustum; - if (args->culledOnce && args->wantDeltaFrustums) { - inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum); + ViewFrustum::location inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum); // if this node is fully inside our last culled view frustum, then we don't need to recurse further if (inLastCulledFrustum == ViewFrustum::INSIDE) { @@ -2001,7 +1997,7 @@ bool VoxelSystem::hideOutOfViewOperation(OctreeElement* element, void* extraData // If we've culled at least once, then we will use the status of this voxel in the last culled frustum to determine // how to proceed. If we've never culled, then we just consider all these voxels to be UNKNOWN so that we will not // consider that case. - ViewFrustum::location inLastCulledFrustum; + ViewFrustum::location inLastCulledFrustum = ViewFrustum::OUTSIDE; // assume outside, but should get reset to actual value if (args->culledOnce && args->wantDeltaFrustums) { inLastCulledFrustum = voxel->inFrustum(args->lastViewFrustum); diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index 49b47c6f25..bdc55450dd 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -67,7 +67,7 @@ public: ViewFrustum* getLastCulledViewFrustum() { return &_lastCulledViewFrustum; } - void setMaxVoxels(int maxVoxels); + void setMaxVoxels(unsigned long maxVoxels); long int getMaxVoxels() const { return _maxVoxels; } unsigned long getVoxelMemoryUsageRAM() const { return _memoryUsageRAM; } unsigned long getVoxelMemoryUsageVBO() const { return _memoryUsageVBO; } @@ -263,7 +263,7 @@ private: bool _usePrimitiveRenderer; ///< Flag primitive renderer for use PrimitiveRenderer* _renderer; ///< Voxel renderer - static const int _sNumOctantsPerHemiVoxel = 4; + static const unsigned int _sNumOctantsPerHemiVoxel = 4; static int _sCorrectedChildIndex[8]; static unsigned short _sSwizzledOcclusionBits[64]; ///< Swizzle value of bit pairs of the value of index static unsigned char _sOctantIndexToBitMask[8]; ///< Map octant index to partition mask From 61a905961e0116575cf4875eb2297d9a000533bc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 14 Mar 2014 22:48:32 -0700 Subject: [PATCH 10/59] darnit I hate casts.. --- libraries/octree/src/OctreePacketData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 5123d0711a..219d8612fc 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -369,7 +369,7 @@ bool OctreePacketData::compressContent() { QByteArray compressedData = qCompress(uncompressedData, uncompressedSize, MAX_COMPRESSION); - if (compressedData.size() < MAX_OCTREE_PACKET_DATA_SIZE) { + if (compressedData.size() < (int)MAX_OCTREE_PACKET_DATA_SIZE) { _compressedBytes = compressedData.size(); for (int i = 0; i < _compressedBytes; i++) { _compressed[i] = compressedData[i]; From 4a6cc99be672985d983ecba1e3b7c5fda98fe371 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Sat, 15 Mar 2014 21:30:45 -0700 Subject: [PATCH 11/59] slightly different approach to windows warning fix --- interface/external/faceshift/src/fsbinarystream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/external/faceshift/src/fsbinarystream.cpp b/interface/external/faceshift/src/fsbinarystream.cpp index 96434afd9b..85f3ac7e7f 100644 --- a/interface/external/faceshift/src/fsbinarystream.cpp +++ b/interface/external/faceshift/src/fsbinarystream.cpp @@ -160,7 +160,7 @@ void fsBinaryStream::received(long int sz, const char *data) { new_end = m_end + sz; } - if (new_end > Size(m_buffer.size())) m_buffer.resize((new_end * 15 / 10)); // HIFI: to get 1.5 without warnings + if (new_end > Size(m_buffer.size())) m_buffer.resize((int)(1.5f * (float)new_end)); // HIFI: to get 1.5 without warnings memcpy(&m_buffer[0] + m_end, data, sz); m_end += sz; From adb6ffe7c4eb8ea66cc57591bb086acda26bf490 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Mar 2014 22:00:44 -0700 Subject: [PATCH 12/59] more warnings fixes --- animation-server/src/AnimationServer.cpp | 21 +++++++------------ assignment-client/src/audio/AudioMixer.cpp | 1 - .../src/octree/OctreeSendThread.cpp | 4 +--- interface/src/Util.cpp | 10 ++++----- libraries/voxels/src/VoxelTreeElement.cpp | 7 ++++--- 5 files changed, 17 insertions(+), 26 deletions(-) diff --git a/animation-server/src/AnimationServer.cpp b/animation-server/src/AnimationServer.cpp index b165590c30..1f0828ec17 100644 --- a/animation-server/src/AnimationServer.cpp +++ b/animation-server/src/AnimationServer.cpp @@ -40,13 +40,13 @@ bool waitForVoxelServer = true; const int ANIMATION_LISTEN_PORT = 40107; int ANIMATE_FPS = 60; double ANIMATE_FPS_IN_MILLISECONDS = 1000.0/ANIMATE_FPS; // determines FPS from our desired FPS -int ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000.0); // converts from milliseconds to usecs +quint64 ANIMATE_VOXELS_INTERVAL_USECS = (ANIMATE_FPS_IN_MILLISECONDS * 1000); // converts from milliseconds to usecs int PROCESSING_FPS = 60; double PROCESSING_FPS_IN_MILLISECONDS = 1000.0/PROCESSING_FPS; // determines FPS from our desired FPS int FUDGE_USECS = 650; // a little bit of fudge to actually do some processing -int PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000.0) - FUDGE_USECS; // converts from milliseconds to usecs +quint64 PROCESSING_INTERVAL_USECS = (PROCESSING_FPS_IN_MILLISECONDS * 1000) - FUDGE_USECS; // converts from milliseconds to usecs bool wantLocalDomain = false; @@ -611,9 +611,6 @@ void* animateVoxels(void* args) { } lastProcessTime = usecTimestampNow(); - int packetsStarting = 0; - int packetsEnding = 0; - // The while loop will be running at PROCESSING_FPS, but we only want to call these animation functions at // ANIMATE_FPS. So we check out last animate time and only call these if we've elapsed that time. quint64 now = usecTimestampNow(); @@ -627,8 +624,6 @@ void* animateVoxels(void* args) { animateLoopsPerAnimate++; lastAnimateTime = now; - packetsStarting = ::voxelEditPacketSender->packetsToSendCount(); - // some animations //sendVoxelBlinkMessage(); @@ -652,8 +647,6 @@ void* animateVoxels(void* args) { doBuildStreet(); } - packetsEnding = ::voxelEditPacketSender->packetsToSendCount(); - if (animationElapsed > ANIMATE_VOXELS_INTERVAL_USECS) { animationElapsed -= ANIMATE_VOXELS_INTERVAL_USECS; // credit ourselves one animation frame } else { @@ -670,9 +663,9 @@ void* animateVoxels(void* args) { processesPerAnimate++; } // dynamically sleep until we need to fire off the next set of voxels - quint64 usecToSleep = PROCESSING_INTERVAL_USECS - (usecTimestampNow() - lastProcessTime); - if (usecToSleep > PROCESSING_INTERVAL_USECS) { - usecToSleep = PROCESSING_INTERVAL_USECS; + quint64 usecToSleep = ::PROCESSING_INTERVAL_USECS - (usecTimestampNow() - lastProcessTime); + if (usecToSleep > ::PROCESSING_INTERVAL_USECS) { + usecToSleep = ::PROCESSING_INTERVAL_USECS; } if (usecToSleep > 0) { @@ -758,7 +751,7 @@ AnimationServer::AnimationServer(int &argc, char **argv) : } } printf("ANIMATE_FPS=%d\n",ANIMATE_FPS); - printf("ANIMATE_VOXELS_INTERVAL_USECS=%d\n",ANIMATE_VOXELS_INTERVAL_USECS); + printf("ANIMATE_VOXELS_INTERVAL_USECS=%llu\n",ANIMATE_VOXELS_INTERVAL_USECS); const char* processingFPSCommand = getCmdOption(argc, (const char**) argv, "--ProcessingFPS"); const char* processingIntervalCommand = getCmdOption(argc, (const char**) argv, "--ProcessingInterval"); @@ -774,7 +767,7 @@ AnimationServer::AnimationServer(int &argc, char **argv) : } } printf("PROCESSING_FPS=%d\n",PROCESSING_FPS); - printf("PROCESSING_INTERVAL_USECS=%d\n",PROCESSING_INTERVAL_USECS); + printf("PROCESSING_INTERVAL_USECS=%llu\n",PROCESSING_INTERVAL_USECS); nodeList->linkedDataCreateCallback = NULL; // do we need a callback? diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 812acc8d70..4c745ef2eb 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -79,7 +79,6 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf if (bufferToAdd != listeningNodeBuffer) { // if the two buffer pointers do not match then these are different buffers - glm::vec3 listenerPosition = listeningNodeBuffer->getPosition(); glm::vec3 relativePosition = bufferToAdd->getPosition() - listeningNodeBuffer->getPosition(); glm::quat inverseOrientation = glm::inverse(listeningNodeBuffer->getOrientation()); diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index ef69771607..09ebb99298 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -54,15 +54,13 @@ bool OctreeSendThread::process() { nodeData = (OctreeQueryNode*) node->getLinkedData(); - int packetsSent = 0; - // Sometimes the node data has not yet been linked, in which case we can't really do anything if (nodeData) { bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); if (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug()) { printf("nodeData->updateCurrentViewFrustum() changed=%s\n", debug::valueOf(viewFrustumChanged)); } - packetsSent = packetDistributor(node, nodeData, viewFrustumChanged); + packetDistributor(node, nodeData, viewFrustumChanged); } } else { _nodeMissingCount++; diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 45b2c4a616..f54bfb9d00 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -535,7 +535,7 @@ void runTimingTests() { } gettimeofday(&endTime, NULL); elapsedMsecs = diffclock(&startTime, &endTime); - qDebug("rand() stored in array usecs: %f", 1000.0f * elapsedMsecs / (float) numTests); + qDebug("rand() stored in array usecs: %f, first result:%d", 1000.0f * elapsedMsecs / (float) numTests, iResults[0]); // Random number generation using randFloat() gettimeofday(&startTime, NULL); @@ -544,7 +544,7 @@ void runTimingTests() { } gettimeofday(&endTime, NULL); elapsedMsecs = diffclock(&startTime, &endTime); - qDebug("randFloat() stored in array usecs: %f", 1000.0f * elapsedMsecs / (float) numTests); + qDebug("randFloat() stored in array usecs: %f, first result: %f", 1000.0f * elapsedMsecs / (float) numTests, fResults[0]); // PowF function fTest = 1145323.2342f; @@ -567,8 +567,8 @@ void runTimingTests() { } gettimeofday(&endTime, NULL); elapsedMsecs = diffclock(&startTime, &endTime); - qDebug("vector math usecs: %f [%f msecs total for %d tests]", - 1000.0f * elapsedMsecs / (float) numTests, elapsedMsecs, numTests); + qDebug("vector math usecs: %f [%f msecs total for %d tests], last result:%f", + 1000.0f * elapsedMsecs / (float) numTests, elapsedMsecs, numTests, distance); // Vec3 test glm::vec3 vecA(randVector()), vecB(randVector()); @@ -581,7 +581,7 @@ void runTimingTests() { } gettimeofday(&endTime, NULL); elapsedMsecs = diffclock(&startTime, &endTime); - qDebug("vec3 assign and dot() usecs: %f", 1000.0f * elapsedMsecs / (float) numTests); + qDebug("vec3 assign and dot() usecs: %f, last result:%f", 1000.0f * elapsedMsecs / (float) numTests, result); } float loadSetting(QSettings* settings, const char* name, float defaultValue) { diff --git a/libraries/voxels/src/VoxelTreeElement.cpp b/libraries/voxels/src/VoxelTreeElement.cpp index be6bd50e3d..debcfee987 100644 --- a/libraries/voxels/src/VoxelTreeElement.cpp +++ b/libraries/voxels/src/VoxelTreeElement.cpp @@ -178,13 +178,14 @@ void VoxelTreeElement::calculateAverageFromChildren() { bool VoxelTreeElement::collapseChildren() { // scan children, verify that they are ALL present and accounted for bool allChildrenMatch = true; // assume the best (ottimista) - int red,green,blue; + int red = 0; + int green = 0; + int blue = 0; for (int i = 0; i < NUMBER_OF_CHILDREN; i++) { VoxelTreeElement* childAt = getChildAtIndex(i); // if no child, child isn't a leaf, or child doesn't have a color if (!childAt || !childAt->isLeaf() || !childAt->isColored()) { - allChildrenMatch=false; - //qDebug("SADNESS child missing or not colored! i=%d\n",i); + allChildrenMatch = false; break; } else { if (i==0) { From 851764a7053c2501b9b03e4b5ce80043c5ddc7ab Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Mar 2014 22:36:43 -0700 Subject: [PATCH 13/59] more warning fixes --- libraries/avatars/src/AvatarData.cpp | 2 +- libraries/avatars/src/HandData.cpp | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 518b10ddea..21de041343 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -288,7 +288,7 @@ int AvatarData::parseData(const QByteArray& packet) { // joint data int jointCount = *sourceBuffer++; _jointData.resize(jointCount); - unsigned char validity; + unsigned char validity = 0; // although always set below, this fixes a warning of potential uninitialized use int validityBit = 0; for (int i = 0; i < jointCount; i++) { if (validityBit == 0) { diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 46dade6d64..15be4636a7 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -217,11 +217,12 @@ int HandData::decodeRemoteData(const QByteArray& dataByteArray) { palm.setActive(false); } - // One byte for error checking safety. - unsigned char requiredLength = (unsigned char)(sourceBuffer - startPosition); - unsigned char checkLength = *sourceBuffer++; - assert(checkLength == requiredLength); - + // One byte for error checking safety. Last byte contains the expected length (less itself) + // actualLength less expected byte = (sourceBuffer - startPosition) + // expectedLength less expected byte = (*sourceBuffer) + assert((unsigned char)(sourceBuffer - startPosition) == (unsigned char)(*sourceBuffer)); + sourceBuffer++; // skip the trailing byte which is expected length + return sourceBuffer - startPosition; } From 6f85cfdb2f153302948d53dbe4d826a9d118d57f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Mar 2014 23:00:03 -0700 Subject: [PATCH 14/59] more warnings fixes --- assignment-client/src/octree/OctreeQueryNode.h | 6 +++--- assignment-client/src/octree/OctreeSendThread.cpp | 2 +- libraries/octree/src/OctreePacketData.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index 6d4dee300a..29fdea0da2 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -34,13 +34,13 @@ public: void writeToPacket(const unsigned char* buffer, int bytes); // writes to end of packet const unsigned char* getPacket() const { return _octreePacket; } - int getPacketLength() const { return (MAX_PACKET_SIZE - _octreePacketAvailableBytes); } + unsigned int getPacketLength() const { return (MAX_PACKET_SIZE - _octreePacketAvailableBytes); } bool isPacketWaiting() const { return _octreePacketWaiting; } bool packetIsDuplicate() const; bool shouldSuppressDuplicatePacket(); - int getAvailable() const { return _octreePacketAvailableBytes; } + unsigned int getAvailable() const { return _octreePacketAvailableBytes; } int getMaxSearchLevel() const { return _maxSearchLevel; } void resetMaxSearchLevel() { _maxSearchLevel = 1; } void incrementMaxSearchLevel() { _maxSearchLevel++; } @@ -92,7 +92,7 @@ private: bool _viewSent; unsigned char* _octreePacket; unsigned char* _octreePacketAt; - int _octreePacketAvailableBytes; + unsigned int _octreePacketAvailableBytes; bool _octreePacketWaiting; unsigned char* _lastOctreePacket; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 09ebb99298..35e9869910 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -506,7 +506,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue } if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) { - qDebug(">>>>>> calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%d", + qDebug(">>>>>> calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%lu", nodeData->getAvailable(), _packetData.getFinalizedSize(), _packetData.getUncompressedSize(), _packetData.getTargetSize()); } diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 526cb7c65e..245f0668cd 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -168,7 +168,7 @@ public: bool isCompressed() const { return _enableCompression; } /// returns the target uncompressed size - int getTargetSize() const { return _targetSize; } + size_t getTargetSize() const { return _targetSize; } /// displays contents for debugging void debugContent(); From 08d89a4565b2632b1f18c4dec6da99dc1e65a6f0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Mar 2014 23:17:03 -0700 Subject: [PATCH 15/59] arg windows signedness warnings --- assignment-client/src/octree/OctreeQueryNode.cpp | 2 +- assignment-client/src/octree/OctreeQueryNode.h | 2 +- assignment-client/src/octree/OctreeSendThread.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 8cb577d2f9..3d5fbefc1f 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -156,7 +156,7 @@ void OctreeQueryNode::resetOctreePacket(bool lastWasSurpressed) { _octreePacketWaiting = false; } -void OctreeQueryNode::writeToPacket(const unsigned char* buffer, int bytes) { +void OctreeQueryNode::writeToPacket(const unsigned char* buffer, unsigned int bytes) { // compressed packets include lead bytes which contain compressed size, this allows packing of // multiple compressed portions together if (_currentPacketIsCompressed) { diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index 29fdea0da2..2a976c6421 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -31,7 +31,7 @@ public: void resetOctreePacket(bool lastWasSurpressed = false); // resets octree packet to after "V" header - void writeToPacket(const unsigned char* buffer, int bytes); // writes to end of packet + void writeToPacket(const unsigned char* buffer, unsigned int bytes); // writes to end of packet const unsigned char* getPacket() const { return _octreePacket; } unsigned int getPacketLength() const { return (MAX_PACKET_SIZE - _octreePacketAvailableBytes); } diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 35e9869910..0259c31374 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -492,7 +492,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue // if for some reason the finalized size is greater than our available size, then probably the "compressed" // form actually inflated beyond our padding, and in this case we will send the current packet, then // write to out new packet... - int writtenSize = _packetData.getFinalizedSize() + unsigned int writtenSize = _packetData.getFinalizedSize() + (nodeData->getCurrentPacketIsCompressed() ? sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) : 0); From 5709a8893e56cabf5721c0a58aa45ec6668fc869 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Mar 2014 23:19:16 -0700 Subject: [PATCH 16/59] more unix signedness warnings --- assignment-client/src/octree/OctreeQueryNode.h | 2 +- assignment-client/src/octree/OctreeSendThread.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index 2a976c6421..e48b7aaff4 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -96,7 +96,7 @@ private: bool _octreePacketWaiting; unsigned char* _lastOctreePacket; - int _lastOctreePacketLength; + unsigned int _lastOctreePacketLength; int _duplicatePacketCount; quint64 _firstSuppressedPacket; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 0259c31374..0c99e94c04 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -140,7 +140,7 @@ int OctreeSendThread::handlePacketSend(const SharedNodePointer& node, OctreeQuer if (nodeData->stats.isReadyToSend()) { // Send the stats message to the client unsigned char* statsMessage = nodeData->stats.getStatsMessage(); - int statsMessageLength = nodeData->stats.getStatsMessageLength(); + unsigned int statsMessageLength = nodeData->stats.getStatsMessageLength(); // If the size of the stats message and the voxel message will fit in a packet, then piggyback them if (nodeData->getPacketLength() + statsMessageLength < MAX_PACKET_SIZE) { From 7d7e1ff28ac0b47d71e38b46d8b62d59b46a6e0b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sat, 15 Mar 2014 23:37:52 -0700 Subject: [PATCH 17/59] one more crack at this signedness comparisons on unix --- assignment-client/src/octree/OctreeSendThread.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 0c99e94c04..498ddb9e2c 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -140,10 +140,11 @@ int OctreeSendThread::handlePacketSend(const SharedNodePointer& node, OctreeQuer if (nodeData->stats.isReadyToSend()) { // Send the stats message to the client unsigned char* statsMessage = nodeData->stats.getStatsMessage(); - unsigned int statsMessageLength = nodeData->stats.getStatsMessageLength(); + int statsMessageLength = nodeData->stats.getStatsMessageLength(); + int piggyBackSize = nodeData->getPacketLength() + statsMessageLength; // If the size of the stats message and the voxel message will fit in a packet, then piggyback them - if (nodeData->getPacketLength() + statsMessageLength < MAX_PACKET_SIZE) { + if (piggyBackSize < MAX_PACKET_SIZE) { // copy voxel message to back of stats message memcpy(statsMessage + statsMessageLength, nodeData->getPacket(), nodeData->getPacketLength()); From bd6b70ee32c6a88a03b82b4e081416688d9c4f4b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Sun, 16 Mar 2014 11:07:24 -0700 Subject: [PATCH 18/59] use unsigned int vs size_t, since that just seems more correct --- .../src/octree/OctreeSendThread.cpp | 2 +- interface/src/VoxelSystem.cpp | 4 ++-- libraries/octree/src/OctreePacketData.cpp | 2 +- libraries/octree/src/OctreePacketData.h | 16 ++++++++-------- libraries/octree/src/OctreeRenderer.cpp | 10 +++++----- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 498ddb9e2c..85839bc53f 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -507,7 +507,7 @@ int OctreeSendThread::packetDistributor(const SharedNodePointer& node, OctreeQue } if (forceDebugging || (_myServer->wantsDebugSending() && _myServer->wantsVerboseDebug())) { - qDebug(">>>>>> calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%lu", + qDebug(">>>>>> calling writeToPacket() available=%d compressedSize=%d uncompressedSize=%d target=%u", nodeData->getAvailable(), _packetData.getFinalizedSize(), _packetData.getUncompressedSize(), _packetData.getTargetSize()); } diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 6c4ed12e9e..4db5af3c04 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -550,7 +550,7 @@ int VoxelSystem::parseData(const QByteArray& packet) { int flightTime = arrivedAt - sentAt; OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - size_t dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); + unsigned int dataBytes = packet.size() - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); int subsection = 1; while (dataBytes > 0) { @@ -576,7 +576,7 @@ int VoxelSystem::parseData(const QByteArray& packet) { packetData.loadFinalizedContent(dataAt, sectionLength); if (Application::getInstance()->getLogger()->extraDebugging()) { qDebug("VoxelSystem::parseData() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%lu" + " color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%u" " subsection:%d sectionLength:%d uncompressed:%d", debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), sequence, flightTime, packet.size(), dataBytes, subsection, sectionLength, diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 219d8612fc..5bd4fdce49 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -23,7 +23,7 @@ OctreePacketData::OctreePacketData(bool enableCompression, int targetSize) { changeSettings(enableCompression, targetSize); // does reset... } -void OctreePacketData::changeSettings(bool enableCompression, size_t targetSize) { +void OctreePacketData::changeSettings(bool enableCompression, unsigned int targetSize) { _enableCompression = enableCompression; _targetSize = std::min(MAX_OCTREE_UNCOMRESSED_PACKET_SIZE, targetSize); reset(); diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 245f0668cd..5d7a904a4c 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -30,15 +30,15 @@ typedef uint16_t OCTREE_PACKET_INTERNAL_SECTION_SIZE; const int MAX_OCTREE_PACKET_SIZE = MAX_PACKET_SIZE; // this is overly conservative - sizeof(PacketType) is 8 bytes but a packed PacketType could be as small as one byte -const size_t OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS) +const unsigned int OCTREE_PACKET_EXTRA_HEADERS_SIZE = sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME); -const size_t MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE); +const unsigned int MAX_OCTREE_PACKET_DATA_SIZE = MAX_PACKET_SIZE - (MAX_PACKET_HEADER_BYTES + OCTREE_PACKET_EXTRA_HEADERS_SIZE); -const size_t MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE; +const unsigned int MAX_OCTREE_UNCOMRESSED_PACKET_SIZE = MAX_OCTREE_PACKET_DATA_SIZE; -const size_t MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40; -const size_t COMPRESS_PADDING = 15; +const unsigned int MINIMUM_ATTEMPT_MORE_PACKING = sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE) + 40; +const unsigned int COMPRESS_PADDING = 15; const int REASONABLE_NUMBER_OF_PACKING_ATTEMPTS = 5; const int PACKET_IS_COLOR_BIT = 0; @@ -69,7 +69,7 @@ public: ~OctreePacketData(); /// change compression and target size settings - void changeSettings(bool enableCompression = false, size_t targetSize = MAX_OCTREE_PACKET_DATA_SIZE); + void changeSettings(bool enableCompression = false, unsigned int targetSize = MAX_OCTREE_PACKET_DATA_SIZE); /// reset completely, all data is discarded void reset(); @@ -168,7 +168,7 @@ public: bool isCompressed() const { return _enableCompression; } /// returns the target uncompressed size - size_t getTargetSize() const { return _targetSize; } + unsigned int getTargetSize() const { return _targetSize; } /// displays contents for debugging void debugContent(); @@ -186,7 +186,7 @@ private: /// append a single byte, might fail if byte would cause packet to be too large bool append(unsigned char byte); - size_t _targetSize; + unsigned int _targetSize; bool _enableCompression; unsigned char _uncompressed[MAX_OCTREE_UNCOMRESSED_PACKET_SIZE]; diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 1066e53845..5d4543e3aa 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -57,9 +57,9 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails); - size_t packetLength = dataByteArray.size(); + unsigned int packetLength = dataByteArray.size(); PacketType command = packetTypeForPacket(dataByteArray); - size_t numBytesPacketHeader = numBytesForPacketHeader(dataByteArray); + unsigned int numBytesPacketHeader = numBytesForPacketHeader(dataByteArray); QUuid sourceUUID = uuidFromPacketHeader(dataByteArray); PacketType expectedType = getExpectedPacketType(); @@ -86,11 +86,11 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar int flightTime = arrivedAt - sentAt + clockSkew; OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0; - size_t dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); + unsigned int dataBytes = packetLength - (numBytesPacketHeader + OCTREE_PACKET_EXTRA_HEADERS_SIZE); if (extraDebugging) { qDebug("OctreeRenderer::processDatagram() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%lu data:%lu", + " color:%s compressed:%s sequence: %u flight:%d usec size:%u data:%u", debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), sequence, flightTime, packetLength, dataBytes); } @@ -119,7 +119,7 @@ void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const Shar packetData.loadFinalizedContent(dataAt, sectionLength); if (extraDebugging) { qDebug("OctreeRenderer::processDatagram() ... Got Packet Section" - " color:%s compressed:%s sequence: %u flight:%d usec size:%lu data:%lu" + " color:%s compressed:%s sequence: %u flight:%d usec size:%u data:%u" " subsection:%d sectionLength:%d uncompressed:%d", debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed), sequence, flightTime, packetLength, dataBytes, subsection, sectionLength, From f652df939966731edcce1c8bd88fea2c3016e82e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 09:19:05 -0700 Subject: [PATCH 19/59] break on MTU size packets from domain-list, closes #2312 --- domain-server/src/DomainServer.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index a425052970..216d249858 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -423,17 +423,25 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif QDataStream broadcastDataStream(&broadcastPacket, QIODevice::Append); broadcastDataStream << node->getUUID(); + int numBroadcastPacketLeadBytes = broadcastDataStream.device()->pos(); + DomainServerNodeData* nodeData = reinterpret_cast(node->getLinkedData()); NodeList* nodeList = NodeList::getInstance(); + if (nodeInterestList.size() > 0) { // if the node has any interest types, send back those nodes as well foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) { + + // reset our nodeByteArray and nodeDataStream + QByteArray nodeByteArray; + QDataStream nodeDataStream(&nodeByteArray, QIODevice::Append); + if (otherNode->getUUID() != node->getUUID() && nodeInterestList.contains(otherNode->getType())) { // don't send avatar nodes to other avatars, that will come from avatar mixer - broadcastDataStream << *otherNode.data(); + nodeDataStream << *otherNode.data(); // pack the secret that these two nodes will use to communicate with each other QUuid secretUUID = nodeData->getSessionSecretHash().value(otherNode->getUUID()); @@ -450,11 +458,26 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif } - broadcastDataStream << secretUUID; + nodeDataStream << secretUUID; + + if (broadcastPacket.size() + nodeByteArray.size() > MAX_PACKET_SIZE) { + // we need to break here and start a new packet + // so send the current one + + nodeList->writeDatagram(broadcastPacket, node, senderSockAddr); + + // reset the broadcastPacket structure + broadcastPacket.resize(numBroadcastPacketLeadBytes); + broadcastDataStream.device()->seek(numBroadcastPacketLeadBytes); + } + + // append the nodeByteArray to the current state of broadcastDataStream + broadcastPacket.append(nodeByteArray); } } } + // always write the last broadcastPacket nodeList->writeDatagram(broadcastPacket, node, senderSockAddr); } From 05d652227963d56d2dc46978f1f67fb990b4acb4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 10:02:00 -0700 Subject: [PATCH 20/59] more MMX optimizations to AudioMixer for delayed samples --- assignment-client/src/audio/AudioMixer.cpp | 133 +++++++++++++++------ assignment-client/src/audio/AudioMixer.h | 5 +- 2 files changed, 103 insertions(+), 35 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 572da1a6c4..f8e68340cb 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -74,9 +74,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf float attenuationCoefficient = 1.0f; int numSamplesDelay = 0; float weakChannelAmplitudeRatio = 1.0f; - - const int PHASE_DELAY_AT_90 = 20; - + if (bufferToAdd != listeningNodeBuffer) { // if the two buffer pointers do not match then these are different buffers @@ -150,7 +148,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // figure out the number of samples of delay and the ratio of the amplitude // in the weak channel for audio spatialization float sinRatio = fabsf(sinf(bearingRelativeAngleToSource)); - numSamplesDelay = PHASE_DELAY_AT_90 * sinRatio; + numSamplesDelay = SAMPLE_PHASE_DELAY_AT_90 * sinRatio; weakChannelAmplitudeRatio = 1 - (PHASE_AMPLITUDE_RATIO_AT_90 * sinRatio); } } @@ -160,45 +158,28 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int goodChannelOffset = delayedChannelOffset == 0 ? 1 : 0; const int16_t* nextOutputStart = bufferToAdd->getNextOutput(); - const int16_t* delayNextOutputStart = nextOutputStart - numSamplesDelay; + const int16_t* bufferStart = bufferToAdd->getBuffer(); int ringBufferSampleCapacity = bufferToAdd->getSampleCapacity(); - - if (delayNextOutputStart < bufferStart) { - delayNextOutputStart = bufferStart + ringBufferSampleCapacity - numSamplesDelay; - } - int16_t correctMixSample[2], correctBufferSample[2], delayMixSample[2], delayBufferSample[2]; - int delayedChannelIndex[2]; - - float attenuationAndWeakChannelRatio = attenuationCoefficient * weakChannelAmplitudeRatio; + int16_t correctBufferSample[2], delayBufferSample[2]; + int delayedChannelIndex = 0; for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 4) { // setup the int16_t variables for the two sample sets correctBufferSample[0] = nextOutputStart[s / 2] * attenuationCoefficient; correctBufferSample[1] = nextOutputStart[(s / 2) + 1] * attenuationCoefficient; - correctMixSample[0] = _clientSamples[s + goodChannelOffset]; - correctMixSample[1] = _clientSamples[s + goodChannelOffset + 2]; - for (int i = 0; i < 2; ++i) { - if ((s / 2) + numSamplesDelay + i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL) { - // for the delayed channel we fill the range (n + numSamplesDelay) to NETWORK_BUFFER_LENGTH_SAMPLES_STEREO first - delayedChannelIndex[i] = s + (numSamplesDelay * 2) + (i * 2) + delayedChannelOffset; - delayBufferSample[i] = correctBufferSample[i] * weakChannelAmplitudeRatio; - } else { - // now that the right most range has been filled, we go back to fill in numSamples delay at the beginning - int samplesBack = (s / 2) - NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL + i; - - delayBufferSample[i] = delayNextOutputStart[numSamplesDelay + samplesBack] * attenuationAndWeakChannelRatio; - delayedChannelIndex[i] = (numSamplesDelay + samplesBack) * 2 + delayedChannelOffset; - } - } + delayedChannelIndex = s + (numSamplesDelay * 2) + delayedChannelOffset; - delayMixSample[0] = _clientSamples[delayedChannelIndex[0]]; - delayMixSample[1] = _clientSamples[delayedChannelIndex[1]]; + delayBufferSample[0] = correctBufferSample[0] * weakChannelAmplitudeRatio; + delayBufferSample[1] = correctBufferSample[1] * weakChannelAmplitudeRatio; - __m64 bufferSamples = _mm_set_pi16(correctMixSample[0], correctMixSample[1], delayMixSample[0], delayMixSample[1]); + __m64 bufferSamples = _mm_set_pi16(_clientSamples[s + goodChannelOffset], + _clientSamples[s + goodChannelOffset + 2], + _clientSamples[delayedChannelIndex], + _clientSamples[delayedChannelIndex + 2]); __m64 addedSamples = _mm_set_pi16(correctBufferSample[0], correctBufferSample[1], delayBufferSample[0], delayBufferSample[1]); @@ -209,8 +190,92 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // assign the results from the result of the mmx arithmetic _clientSamples[s + goodChannelOffset] = shortResults[3]; _clientSamples[s + goodChannelOffset + 2] = shortResults[2]; - _clientSamples[delayedChannelIndex[0]] = shortResults[1]; - _clientSamples[delayedChannelIndex[1]] = shortResults[0]; + _clientSamples[delayedChannelIndex] = shortResults[1]; + _clientSamples[delayedChannelIndex + 2] = shortResults[0]; + } + + // The following code is pretty gross and redundant, but AFAIK it's the best way to avoid + // too many conditionals in handling the delay samples at the beginning of _clientSamples. + // Basically we try to take the samples in batches of four, and then handle the remainder + // conditionally to get rid of the rest. + + if (numSamplesDelay > 0) { + // if there was a sample delay for this buffer, we need to pull samples prior to the nextOutput + // to stick at the beginning + float attenuationAndWeakChannelRatio = attenuationCoefficient * weakChannelAmplitudeRatio; + const int16_t* delayNextOutputStart = nextOutputStart - numSamplesDelay; + if (delayNextOutputStart < bufferStart) { + delayNextOutputStart = bufferStart + ringBufferSampleCapacity - numSamplesDelay; + } + + int i = 0; + + while (i + 3 < numSamplesDelay) { + // handle the first cases where we can MMX add four samples at once + int parentIndex = i * 2; + __m64 bufferSamples = _mm_setr_pi16(_clientSamples[parentIndex + delayedChannelOffset], + _clientSamples[parentIndex + 2 + delayedChannelOffset], + _clientSamples[parentIndex + 4 + delayedChannelOffset], + _clientSamples[parentIndex + 6 + delayedChannelOffset]); + __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, + delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, + delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio, + delayNextOutputStart[i + 3] * attenuationAndWeakChannelRatio); + __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); + int16_t* shortResults = reinterpret_cast(&mmxResult); + + _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; + _clientSamples[parentIndex + 2 + delayedChannelOffset] = shortResults[2]; + _clientSamples[parentIndex + 4 + delayedChannelOffset] = shortResults[1]; + _clientSamples[parentIndex + 6 + delayedChannelOffset] = shortResults[0]; + + // push the index + i += 4; + } + + int parentIndex = i * 2; + + if (i + 2 < numSamplesDelay) { + // MMX add only three delayed samples + + __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], + _clientSamples[parentIndex + 2 + delayedChannelOffset], + _clientSamples[parentIndex + 4 + delayedChannelOffset], + 0); + __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, + delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, + delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio, + 0); + __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); + int16_t* shortResults = reinterpret_cast(&mmxResult); + + _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; + _clientSamples[parentIndex + 2 + delayedChannelOffset] = shortResults[2]; + _clientSamples[parentIndex + 4 + delayedChannelOffset] = shortResults[1]; + + } else if (i + 1 < numSamplesDelay) { + // MMX add two delayed samples + __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], + _clientSamples[parentIndex + 2 + delayedChannelOffset], 0, 0); + __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, + delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, 0, 0); + + __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); + int16_t* shortResults = reinterpret_cast(&mmxResult); + + _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; + _clientSamples[parentIndex + 2 + delayedChannelOffset] = shortResults[2]; + + } else if (i < numSamplesDelay) { + // MMX add a single delayed sample + __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], 0, 0, 0); + __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, 0, 0, 0); + + __m64 mmxResult = _mm_adds_pi16(bufferSamples, addSamples); + int16_t* shortResults = reinterpret_cast(&mmxResult); + + _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; + } } } @@ -303,7 +368,7 @@ void AudioMixer::run() { && ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) { prepareMixForListeningNode(node.data()); - memcpy(_clientMixBuffer.data() + numBytesPacketHeader, _clientSamples, sizeof(_clientSamples)); + memcpy(_clientMixBuffer.data() + numBytesPacketHeader, _clientSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO); nodeList->writeDatagram(_clientMixBuffer, node); } } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index ae5998100f..8032649c17 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -16,6 +16,8 @@ class PositionalAudioRingBuffer; class AvatarAudioRingBuffer; +const int SAMPLE_PHASE_DELAY_AT_90 = 20; + /// Handles assignments of type AudioMixer - mixing streams of audio and re-distributing to various clients. class AudioMixer : public ThreadedAssignment { Q_OBJECT @@ -38,7 +40,8 @@ private: QByteArray _clientMixBuffer; - int16_t _clientSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO]; + // client samples capacity is larger than what will be sent to optimize mixing + int16_t _clientSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + SAMPLE_PHASE_DELAY_AT_90]; }; #endif /* defined(__hifi__AudioMixer__) */ From 2478c995f201ca67a3bdd4965f48c3f351f6c041 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 10:05:44 -0700 Subject: [PATCH 21/59] clarifications to BUILD to remove confusing instructions, closes #2327 --- BUILD.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/BUILD.md b/BUILD.md index 1bc5145704..e033916e08 100644 --- a/BUILD.md +++ b/BUILD.md @@ -104,9 +104,7 @@ We don't currently have a Windows installer, so before running Interface, you wi CMake will need to know where the headers and libraries for required external dependencies are. If you installed ZLIB using the installer, the FindZLIB cmake module will be able to find it. This isn't the case for the others. -You have the choice of setting a variable specific to each library, or having a folder using a defined structure that contains all of the libs. - -The recommended route is to place all of the dependencies in one place and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure: +The recommended route for CMake to find external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure: root_lib_dir -> glm @@ -128,14 +126,6 @@ The recommended route is to place all of the dependencies in one place and set o For many of the external libraries where precompiled binaries are readily available you should be able to simply copy the extracted folder that you get from the download links provided at the top of the guide. Otherwise you may need to build from source and install the built product to this directory. The `root_lib_dir` in the above example can be wherever you choose on your system - as long as the environment variable HIFI_LIB_DIR is set to it. -Should you want to define a location for each library, these are the associated variables you will want to set: - -`GLM_ROOT_DIR, GLUT_ROOT_DIR, GLEW_ROOT_DIR` - -They can be set in your ENV or by passing them to the cmake command on the command line. (There is an example of this in the CMake section earlier in this guide.) - -Each of those designates the root directory that contains the sub-folders for each library. For example, if the GLEW_ROOT_DIR is `C:\libs\glew`, then we would expect to find an `include` folder and a `lib` folder inside `C:\libs\glew`. - *NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit version of libraries for interface.exe to run. The 32-bit version of the static library is the one linked by our CMake find modules* #### DLLs From a1fe41fc1d4ad9e2203be1f78caa553be0318423 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 10:10:26 -0700 Subject: [PATCH 22/59] repair a conflicted translation file --- interface/interface_en.ts | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index d640db2952..75ada1910c 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -14,20 +14,12 @@ -<<<<<<< HEAD - -======= ->>>>>>> 5182ab190432324cdb0d0221c15fe57fe1e602c6 Open Script -<<<<<<< HEAD - -======= ->>>>>>> 5182ab190432324cdb0d0221c15fe57fe1e602c6 JavaScript Files (*.js) @@ -121,31 +113,18 @@ Menu -<<<<<<< HEAD - -======= ->>>>>>> 5182ab190432324cdb0d0221c15fe57fe1e602c6 Open .ini config file -<<<<<<< HEAD - - -======= ->>>>>>> 5182ab190432324cdb0d0221c15fe57fe1e602c6 Text files (*.ini) -<<<<<<< HEAD - -======= ->>>>>>> 5182ab190432324cdb0d0221c15fe57fe1e602c6 Save .ini config file From cc1d309c15e87dd8cfc0fdc18979befe514aeb1f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 10:13:29 -0700 Subject: [PATCH 23/59] some really trivial magic number replacements --- assignment-client/src/audio/AudioMixer.cpp | 37 ++++++++++++---------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index f8e68340cb..24f2c90020 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -165,6 +165,8 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int16_t correctBufferSample[2], delayBufferSample[2]; int delayedChannelIndex = 0; + const int SINGLE_STEREO_OFFSET = 2; + for (int s = 0; s < NETWORK_BUFFER_LENGTH_SAMPLES_STEREO; s += 4) { // setup the int16_t variables for the two sample sets @@ -177,9 +179,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf delayBufferSample[1] = correctBufferSample[1] * weakChannelAmplitudeRatio; __m64 bufferSamples = _mm_set_pi16(_clientSamples[s + goodChannelOffset], - _clientSamples[s + goodChannelOffset + 2], + _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET], _clientSamples[delayedChannelIndex], - _clientSamples[delayedChannelIndex + 2]); + _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET]); __m64 addedSamples = _mm_set_pi16(correctBufferSample[0], correctBufferSample[1], delayBufferSample[0], delayBufferSample[1]); @@ -189,9 +191,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // assign the results from the result of the mmx arithmetic _clientSamples[s + goodChannelOffset] = shortResults[3]; - _clientSamples[s + goodChannelOffset + 2] = shortResults[2]; + _clientSamples[s + goodChannelOffset + SINGLE_STEREO_OFFSET] = shortResults[2]; _clientSamples[delayedChannelIndex] = shortResults[1]; - _clientSamples[delayedChannelIndex + 2] = shortResults[0]; + _clientSamples[delayedChannelIndex + SINGLE_STEREO_OFFSET] = shortResults[0]; } // The following code is pretty gross and redundant, but AFAIK it's the best way to avoid @@ -199,6 +201,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // Basically we try to take the samples in batches of four, and then handle the remainder // conditionally to get rid of the rest. + const int DOUBLE_STEREO_OFFSET = 4; + const int TRIPLE_STEREO_OFFSET = 6; + if (numSamplesDelay > 0) { // if there was a sample delay for this buffer, we need to pull samples prior to the nextOutput // to stick at the beginning @@ -214,9 +219,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // handle the first cases where we can MMX add four samples at once int parentIndex = i * 2; __m64 bufferSamples = _mm_setr_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + 2 + delayedChannelOffset], - _clientSamples[parentIndex + 4 + delayedChannelOffset], - _clientSamples[parentIndex + 6 + delayedChannelOffset]); + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], + _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset], + _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset]); __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, delayNextOutputStart[i + 2] * attenuationAndWeakChannelRatio, @@ -225,9 +230,9 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int16_t* shortResults = reinterpret_cast(&mmxResult); _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; - _clientSamples[parentIndex + 2 + delayedChannelOffset] = shortResults[2]; - _clientSamples[parentIndex + 4 + delayedChannelOffset] = shortResults[1]; - _clientSamples[parentIndex + 6 + delayedChannelOffset] = shortResults[0]; + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; + _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[1]; + _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[0]; // push the index i += 4; @@ -239,8 +244,8 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf // MMX add only three delayed samples __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + 2 + delayedChannelOffset], - _clientSamples[parentIndex + 4 + delayedChannelOffset], + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], + _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset], 0); __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, @@ -250,13 +255,13 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int16_t* shortResults = reinterpret_cast(&mmxResult); _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; - _clientSamples[parentIndex + 2 + delayedChannelOffset] = shortResults[2]; - _clientSamples[parentIndex + 4 + delayedChannelOffset] = shortResults[1]; + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; + _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[1]; } else if (i + 1 < numSamplesDelay) { // MMX add two delayed samples __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], - _clientSamples[parentIndex + 2 + delayedChannelOffset], 0, 0); + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], 0, 0); __m64 addSamples = _mm_set_pi16(delayNextOutputStart[i] * attenuationAndWeakChannelRatio, delayNextOutputStart[i + 1] * attenuationAndWeakChannelRatio, 0, 0); @@ -264,7 +269,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf int16_t* shortResults = reinterpret_cast(&mmxResult); _clientSamples[parentIndex + delayedChannelOffset] = shortResults[3]; - _clientSamples[parentIndex + 2 + delayedChannelOffset] = shortResults[2]; + _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset] = shortResults[2]; } else if (i < numSamplesDelay) { // MMX add a single delayed sample From 68ba2201df10c63269fc137e1486787826bd0481 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 17 Mar 2014 10:22:02 -0700 Subject: [PATCH 24/59] cleanup of Avatar:: and MyAvatar::render() MyAvatar now calls Avatar::render() which does most of the work. Also, made ::renderBody() a proper virtual function --- interface/src/avatar/Avatar.cpp | 69 ++++++++++++++------------ interface/src/avatar/Avatar.h | 4 +- interface/src/avatar/AvatarManager.cpp | 18 +++---- interface/src/avatar/AvatarManager.h | 2 +- interface/src/avatar/MyAvatar.cpp | 62 ++--------------------- interface/src/avatar/MyAvatar.h | 4 +- 6 files changed, 55 insertions(+), 104 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index bcf24a7bfb..cb6e3d67ee 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -189,55 +189,60 @@ static TextRenderer* textRenderer(TextRendererType type) { return displayNameRenderer; } -void Avatar::render(bool forShadowMap) { +void Avatar::render(const glm::vec3& cameraPosition, bool forShadowMap) { // simple frustum check float boundingRadius = getBillboardSize(); - if (Application::getInstance()->getViewFrustum()->sphereInFrustum(_position, boundingRadius) == ViewFrustum::OUTSIDE) { + if (Application::getInstance()->getViewFrustum()->sphereInFrustum(cameraPosition, boundingRadius) == ViewFrustum::OUTSIDE) { return; } - glm::vec3 toTarget = _position - Application::getInstance()->getAvatar()->getPosition(); - float lengthToTarget = glm::length(toTarget); + glm::vec3 toTarget = cameraPosition - Application::getInstance()->getAvatar()->getPosition(); + float distanceToTarget = glm::length(toTarget); { - // glow when moving in the distance - + // glow when moving far away const float GLOW_DISTANCE = 20.0f; - Glower glower(_moving && lengthToTarget > GLOW_DISTANCE && !forShadowMap ? 1.0f : 0.0f); + Glower glower(_moving && distanceToTarget > GLOW_DISTANCE && !forShadowMap ? 1.0f : 0.0f); // render body + if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { + renderBody(forShadowMap); + } if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) { _skeletonModel.renderCollisionProxies(0.7f); } if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionProxies)) { getHead()->getFaceModel().renderCollisionProxies(0.7f); } - if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { - renderBody(); - } - // render voice intensity sphere for avatars that are farther away - const float MAX_SPHERE_ANGLE = 10.f * RADIANS_PER_DEGREE; - const float MIN_SPHERE_ANGLE = 1.f * RADIANS_PER_DEGREE; - const float MIN_SPHERE_SIZE = 0.01f; - const float SPHERE_LOUDNESS_SCALING = 0.0005f; - const float SPHERE_COLOR[] = { 0.5f, 0.8f, 0.8f }; - float height = getSkeletonHeight(); - glm::vec3 delta = height * (getHead()->getCameraOrientation() * IDENTITY_UP) / 2.f; - float angle = abs(angleBetween(toTarget + delta, toTarget - delta)); - float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING; - - if (!forShadowMap && (sphereRadius > MIN_SPHERE_SIZE) && (angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) { - glColor4f(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.f - angle / MAX_SPHERE_ANGLE); - glPushMatrix(); - glTranslatef(_position.x, _position.y, _position.z); - glScalef(height, height, height); - glutSolidSphere(sphereRadius, 15, 15); - glPopMatrix(); + // quick check before falling into the code below: + // (a 10 degree breadth of an almost 2 meter avatar kicks in at about 12m) + const float MIN_VOICE_SPHERE_DISTANCE = 12.f; + if (distanceToTarget > MIN_VOICE_SPHERE_DISTANCE) { + // render voice intensity sphere for avatars that are farther away + const float MAX_SPHERE_ANGLE = 10.f * RADIANS_PER_DEGREE; + const float MIN_SPHERE_ANGLE = 1.f * RADIANS_PER_DEGREE; + const float MIN_SPHERE_SIZE = 0.01f; + const float SPHERE_LOUDNESS_SCALING = 0.0005f; + const float SPHERE_COLOR[] = { 0.5f, 0.8f, 0.8f }; + float height = getSkeletonHeight(); + glm::vec3 delta = height * (getHead()->getCameraOrientation() * IDENTITY_UP) / 2.f; + float angle = abs(angleBetween(toTarget + delta, toTarget - delta)); + float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING; + + if (!forShadowMap && (sphereRadius > MIN_SPHERE_SIZE) && (angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) { + glColor4f(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.f - angle / MAX_SPHERE_ANGLE); + glPushMatrix(); + glTranslatef(_position.x, _position.y, _position.z); + glScalef(height, height, height); + glutSolidSphere(sphereRadius, 15, 15); + glPopMatrix(); + } } } + const float DISPLAYNAME_DISTANCE = 10.0f; - setShowDisplayName(!forShadowMap && lengthToTarget < DISPLAYNAME_DISTANCE); + setShowDisplayName(!forShadowMap && distanceToTarget < DISPLAYNAME_DISTANCE); if (forShadowMap) { return; } @@ -257,7 +262,6 @@ void Avatar::render(bool forShadowMap) { glm::vec3 chatAxis = glm::axis(chatRotation); glRotatef(glm::degrees(glm::angle(chatRotation)), chatAxis.x, chatAxis.y, chatAxis.z); - glColor3f(0.f, 0.8f, 0.f); glRotatef(180.f, 0.f, 1.f, 0.f); glRotatef(180.f, 0.f, 0.f, 1.f); @@ -302,9 +306,12 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { return glm::angleAxis(angle * proportion, axis); } -void Avatar::renderBody() { +void Avatar::renderBody(bool forShadowMap) { if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { // render the billboard until both models are loaded + if (forShadowMap) { + return; + } renderBillboard(); return; } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 2bd7fc89e8..542320805e 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -74,7 +74,7 @@ public: void init(); void simulate(float deltaTime); - void render(bool forShadowMap = false); + virtual void render(const glm::vec3& cameraPosition, bool forShadowMap); //setters void setDisplayingLookatVectors(bool displayingLookatVectors) { getHead()->setRenderLookatVectors(displayingLookatVectors); } @@ -181,6 +181,7 @@ protected: float getPelvisToHeadLength() const; void renderDisplayName(); + virtual void renderBody(bool forShadowMap); private: @@ -189,7 +190,6 @@ private: bool _shouldRenderBillboard; bool _modelsDirty; - void renderBody(); void renderBillboard(); float getBillboardSize() const; diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 88ce2b4399..cd7d360743 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -77,7 +77,7 @@ void AvatarManager::renderAvatars(bool forShadowMapOrMirror, bool selfAvatarOnly "Application::renderAvatars()"); bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::LookAtVectors); - + glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition(); if (!selfAvatarOnly) { foreach (const AvatarSharedPointer& avatarPointer, _avatarHash) { @@ -85,17 +85,13 @@ void AvatarManager::renderAvatars(bool forShadowMapOrMirror, bool selfAvatarOnly if (!avatar->isInitialized()) { continue; } - if (avatar == static_cast(_myAvatar.data())) { - _myAvatar->render(forShadowMapOrMirror); - } else { - avatar->render(forShadowMapOrMirror); - } + avatar->render(cameraPosition, forShadowMapOrMirror); avatar->setDisplayingLookatVectors(renderLookAtVectors); } - renderAvatarFades(forShadowMapOrMirror); + renderAvatarFades(cameraPosition, forShadowMapOrMirror); } else { // just render myAvatar - _myAvatar->render(forShadowMapOrMirror); + _myAvatar->render(cameraPosition, forShadowMapOrMirror); _myAvatar->setDisplayingLookatVectors(renderLookAtVectors); } } @@ -118,13 +114,15 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { } } -void AvatarManager::renderAvatarFades(bool forShadowMap) { +void AvatarManager::renderAvatarFades(const glm::vec3& cameraPosition, bool forShadowMap) { // render avatar fades Glower glower(forShadowMap ? 0.0f : 1.0f); foreach(const AvatarSharedPointer& fadingAvatar, _avatarFades) { Avatar* avatar = static_cast(fadingAvatar.data()); - avatar->render(forShadowMap); + if (avatar != static_cast(_myAvatar.data())) { + avatar->render(cameraPosition, forShadowMap); + } } } diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index c690dfa966..455153b92a 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -45,7 +45,7 @@ private: void processKillAvatar(const QByteArray& datagram); void simulateAvatarFades(float deltaTime); - void renderAvatarFades(bool forShadowMap); + void renderAvatarFades(const glm::vec3& cameraPosition, bool forShadowMap); // virtual override AvatarHash::iterator erase(const AvatarHash::iterator& iterator); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e4aaa07a4b..c56865afc6 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -453,68 +453,14 @@ void MyAvatar::renderDebugBodyPoints() { } -void MyAvatar::render(bool forShadowMapOrMirror) { + +// virtual +void MyAvatar::render(const glm::vec3& cameraPosition, bool forShadowMapOrMirror) { // don't render if we've been asked to disable local rendering if (!_shouldRender) { return; // exit early } - - if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) { - renderBody(forShadowMapOrMirror); - } - // render body - if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) { - _skeletonModel.renderCollisionProxies(0.8f); - } - if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeadCollisionProxies)) { - getHead()->getFaceModel().renderCollisionProxies(0.8f); - } - setShowDisplayName(!forShadowMapOrMirror); - if (forShadowMapOrMirror) { - return; - } - renderDisplayName(); - - if (!_chatMessage.empty()) { - int width = 0; - int lastWidth = 0; - for (string::iterator it = _chatMessage.begin(); it != _chatMessage.end(); it++) { - width += (lastWidth = textRenderer()->computeWidth(*it)); - } - glPushMatrix(); - - glm::vec3 chatPosition = getHead()->getEyePosition() + getBodyUpDirection() * CHAT_MESSAGE_HEIGHT * _scale; - glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z); - glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation(); - glm::vec3 chatAxis = glm::axis(chatRotation); - glRotatef(glm::degrees(glm::angle(chatRotation)), chatAxis.x, chatAxis.y, chatAxis.z); - - glColor3f(0.f, 0.8f, 0.f); - glRotatef(180.f, 0.f, 1.f, 0.f); - glRotatef(180.f, 0.f, 0.f, 1.f); - glScalef(_scale * CHAT_MESSAGE_SCALE, _scale * CHAT_MESSAGE_SCALE, 1.0f); - - glDisable(GL_LIGHTING); - glDepthMask(false); - if (_keyState == NO_KEY_DOWN) { - textRenderer()->draw(-width / 2.0f, 0, _chatMessage.c_str()); - - } else { - // rather than using substr and allocating a new string, just replace the last - // character with a null, then restore it - int lastIndex = _chatMessage.size() - 1; - char lastChar = _chatMessage[lastIndex]; - _chatMessage[lastIndex] = '\0'; - textRenderer()->draw(-width / 2.0f, 0, _chatMessage.c_str()); - _chatMessage[lastIndex] = lastChar; - glColor3f(0.f, 1.f, 0.f); - textRenderer()->draw(width / 2.0f - lastWidth, 0, _chatMessage.c_str() + lastIndex); - } - glEnable(GL_LIGHTING); - glDepthMask(true); - - glPopMatrix(); - } + Avatar::render(cameraPosition, forShadowMapOrMirror); } void MyAvatar::renderHeadMouse() const { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index dfc114d952..3544fb1a61 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -35,7 +35,8 @@ public: void simulate(float deltaTime); void updateFromGyros(float deltaTime); - void render(bool forShadowMapOrMirror = false); + void render(const glm::vec3& cameraPosition, bool forShadowMapOrMirror = false); + void renderBody(bool forceRenderHead); void renderDebugBodyPoints(); void renderHeadMouse() const; @@ -120,7 +121,6 @@ private: bool _billboardValid; // private methods - void renderBody(bool forceRenderHead); void updateThrust(float deltaTime); void updateHandMovementAndTouching(float deltaTime); void updateCollisionWithAvatars(float deltaTime); From 288272f051437b03f4ae9c6910601e7474f48e11 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 11:26:35 -0700 Subject: [PATCH 25/59] fix a reversed MMX add --- assignment-client/src/audio/AudioMixer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 660da1dc52..1637f88859 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -217,7 +217,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf while (i + 3 < numSamplesDelay) { // handle the first cases where we can MMX add four samples at once int parentIndex = i * 2; - __m64 bufferSamples = _mm_setr_pi16(_clientSamples[parentIndex + delayedChannelOffset], + __m64 bufferSamples = _mm_set_pi16(_clientSamples[parentIndex + delayedChannelOffset], _clientSamples[parentIndex + SINGLE_STEREO_OFFSET + delayedChannelOffset], _clientSamples[parentIndex + DOUBLE_STEREO_OFFSET + delayedChannelOffset], _clientSamples[parentIndex + TRIPLE_STEREO_OFFSET + delayedChannelOffset]); From ed3cf36045575a2ba4f1ae8af943943e06977567 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 17 Mar 2014 14:10:42 -0700 Subject: [PATCH 26/59] cleanup: AvatarData doesn't derive from NodeData Cleaner Interface since the AvatarData is already not the NodeList. Reduces overhead/confusing code when parsing packets from AvatarMixer. --- assignment-client/src/avatars/AvatarMixer.cpp | 22 ++++++++++++------- .../src/avatars/AvatarMixerClientData.cpp | 7 ++++++ .../src/avatars/AvatarMixerClientData.h | 8 ++++++- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/AvatarManager.cpp | 12 +--------- libraries/avatars/src/AvatarData.cpp | 12 +++++----- libraries/avatars/src/AvatarData.h | 11 ++++++---- 8 files changed, 44 insertions(+), 34 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index e305972679..47f7084f64 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -62,7 +62,8 @@ void broadcastAvatarData() { mixedAvatarByteArray.resize(numPacketHeaderBytes); AvatarMixerClientData* myData = reinterpret_cast(node->getLinkedData()); - glm::vec3 myPosition = myData->getPosition(); + AvatarData& avatar = myData->getAvatar(); + glm::vec3 myPosition = avatar.getPosition(); // this is an AGENT we have received head data from // send back a packet with other active node data to this node @@ -70,7 +71,8 @@ void broadcastAvatarData() { if (otherNode->getLinkedData() && otherNode->getUUID() != node->getUUID()) { AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); - glm::vec3 otherPosition = otherNodeData->getPosition(); + AvatarData& otherAvatar = otherNodeData->getAvatar(); + glm::vec3 otherPosition = otherAvatar.getPosition(); float distanceToAvatar = glm::length(myPosition - otherPosition); // The full rate distance is the distance at which EVERY update will be sent for this avatar // at a distance of twice the full rate distance, there will be a 50% chance of sending this avatar's update @@ -79,7 +81,7 @@ void broadcastAvatarData() { if ((distanceToAvatar == 0.f) || (randFloat() < FULL_RATE_DISTANCE / distanceToAvatar)) { QByteArray avatarByteArray; avatarByteArray.append(otherNode->getUUID().toRfc4122()); - avatarByteArray.append(otherNodeData->toByteArray()); + avatarByteArray.append(otherAvatar.toByteArray()); if (avatarByteArray.size() + mixedAvatarByteArray.size() > MAX_PACKET_SIZE) { nodeList->writeDatagram(mixedAvatarByteArray, node); @@ -110,7 +112,8 @@ void broadcastIdentityPacket() { if (node->getLinkedData() && node->getType() == NodeType::Agent) { AvatarMixerClientData* nodeData = reinterpret_cast(node->getLinkedData()); - QByteArray individualData = nodeData->identityByteArray(); + AvatarData& avatar = nodeData->getAvatar(); + QByteArray individualData = avatar.identityByteArray(); individualData.replace(0, NUM_BYTES_RFC4122_UUID, node->getUUID().toRfc4122()); if (avatarIdentityPacket.size() + individualData.size() > MAX_PACKET_SIZE) { @@ -135,9 +138,10 @@ void broadcastIdentityPacket() { void broadcastBillboardPacket(const SharedNodePointer& sendingNode) { AvatarMixerClientData* nodeData = static_cast(sendingNode->getLinkedData()); + AvatarData& avatar = nodeData->getAvatar(); QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard); packet.append(sendingNode->getUUID().toRfc4122()); - packet.append(nodeData->getBillboard()); + packet.append(avatar.getBillboard()); NodeList* nodeList = NodeList::getInstance(); foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { @@ -190,12 +194,13 @@ void AvatarMixer::readPendingDatagrams() { if (avatarNode && avatarNode->getLinkedData()) { AvatarMixerClientData* nodeData = reinterpret_cast(avatarNode->getLinkedData()); - if (nodeData->hasIdentityChangedAfterParsing(receivedPacket) + AvatarData& avatar = nodeData->getAvatar(); + if (avatar.hasIdentityChangedAfterParsing(receivedPacket) && !nodeData->hasSentIdentityBetweenKeyFrames()) { // this avatar changed their identity in some way and we haven't sent a packet in this keyframe QByteArray identityPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarIdentity); - QByteArray individualByteArray = nodeData->identityByteArray(); + QByteArray individualByteArray = avatar.identityByteArray(); individualByteArray.replace(0, NUM_BYTES_RFC4122_UUID, avatarNode->getUUID().toRfc4122()); identityPacket.append(individualByteArray); @@ -213,7 +218,8 @@ void AvatarMixer::readPendingDatagrams() { if (avatarNode && avatarNode->getLinkedData()) { AvatarMixerClientData* nodeData = static_cast(avatarNode->getLinkedData()); - if (nodeData->hasBillboardChangedAfterParsing(receivedPacket) + AvatarData& avatar = nodeData->getAvatar(); + if (avatar.hasBillboardChangedAfterParsing(receivedPacket) && !nodeData->hasSentBillboardBetweenKeyFrames()) { // this avatar changed their billboard and we haven't sent a packet in this keyframe broadcastBillboardPacket(avatarNode); diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index 388d6f6488..a29b6efdb4 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -9,8 +9,15 @@ #include "AvatarMixerClientData.h" AvatarMixerClientData::AvatarMixerClientData() : + NodeData(), _hasSentIdentityBetweenKeyFrames(false), _hasSentBillboardBetweenKeyFrames(false) { } + +int AvatarMixerClientData::parseData(const QByteArray& packet) { + // increment to push past the packet header + int offset = numBytesForPacketHeader(packet); + return _avatar.parseDataAtOffset(packet, offset); +} diff --git a/assignment-client/src/avatars/AvatarMixerClientData.h b/assignment-client/src/avatars/AvatarMixerClientData.h index 7240288306..854e8172d3 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.h +++ b/assignment-client/src/avatars/AvatarMixerClientData.h @@ -12,11 +12,14 @@ #include #include +#include -class AvatarMixerClientData : public AvatarData { +class AvatarMixerClientData : public NodeData { Q_OBJECT public: AvatarMixerClientData(); + + int parseData(const QByteArray& packet); bool hasSentIdentityBetweenKeyFrames() const { return _hasSentIdentityBetweenKeyFrames; } void setHasSentIdentityBetweenKeyFrames(bool hasSentIdentityBetweenKeyFrames) @@ -25,11 +28,14 @@ public: bool hasSentBillboardBetweenKeyFrames() const { return _hasSentBillboardBetweenKeyFrames; } void setHasSentBillboardBetweenKeyFrames(bool hasSentBillboardBetweenKeyFrames) { _hasSentBillboardBetweenKeyFrames = hasSentBillboardBetweenKeyFrames; } + + AvatarData& getAvatar() { return _avatar; } private: bool _hasSentIdentityBetweenKeyFrames; bool _hasSentBillboardBetweenKeyFrames; + AvatarData _avatar; }; #endif /* defined(__hifi__AvatarMixerClientData__) */ diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index cb6e3d67ee..75a8386ea9 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -633,11 +633,11 @@ void Avatar::setBillboard(const QByteArray& billboard) { _billboardTexture.reset(); } -int Avatar::parseData(const QByteArray& packet) { +int Avatar::parseDataAtOffset(const QByteArray& packet, int offset) { // change in position implies movement glm::vec3 oldPosition = _position; - int bytesRead = AvatarData::parseData(packet); + int bytesRead = AvatarData::parseDataAtOffset(packet, offset); const float MOVE_DISTANCE_THRESHOLD = 0.001f; _moving = glm::distance(oldPosition, _position) > MOVE_DISTANCE_THRESHOLD; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 542320805e..30073c54d4 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -133,7 +133,7 @@ public: void setShowDisplayName(bool showDisplayName); - int parseData(const QByteArray& packet); + int parseDataAtOffset(const QByteArray& packet, int offset); static void renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, float radius1, float radius2); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index cd7d360743..49479e903e 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -148,10 +148,6 @@ void AvatarManager::processAvatarMixerDatagram(const QByteArray& datagram, const void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QWeakPointer &mixerWeakPointer) { int bytesRead = numBytesForPacketHeader(datagram); - QByteArray dummyAvatarByteArray = byteArrayWithPopulatedHeader(PacketTypeAvatarData); - int numDummyHeaderBytes = dummyAvatarByteArray.size(); - int numDummyHeaderBytesWithoutUUID = numDummyHeaderBytes - NUM_BYTES_RFC4122_UUID; - // enumerate over all of the avatars in this packet // only add them if mixerWeakPointer points to something (meaning that mixer is still around) while (bytesRead < datagram.size() && mixerWeakPointer.data()) { @@ -171,16 +167,10 @@ void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QW qDebug() << "Adding avatar with UUID" << nodeUUID << "to AvatarManager hash."; } - // copy the rest of the packet to the avatarData holder so we can read the next Avatar from there - dummyAvatarByteArray.resize(numDummyHeaderBytesWithoutUUID); - - // make this Avatar's UUID the UUID in the packet and tack the remaining data onto the end - dummyAvatarByteArray.append(datagram.mid(bytesRead)); // have the matching (or new) avatar parse the data from the packet - bytesRead += matchingAvatar->parseData(dummyAvatarByteArray) - numDummyHeaderBytesWithoutUUID; + bytesRead += matchingAvatar->parseDataAtOffset(datagram, bytesRead); } - } void AvatarManager::processAvatarIdentityPacket(const QByteArray &packet) { diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 21de041343..5650d7a800 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -29,7 +29,6 @@ using namespace std; QNetworkAccessManager* AvatarData::networkAccessManager = NULL; AvatarData::AvatarData() : - NodeData(), _handPosition(0,0,0), _bodyYaw(-90.f), _bodyPitch(0.0f), @@ -184,8 +183,8 @@ QByteArray AvatarData::toByteArray() { return avatarDataByteArray.left(destinationBuffer - startPosition); } -// called on the other nodes - assigns it to my views of the others -int AvatarData::parseData(const QByteArray& packet) { +// read data in packet starting at byte offset and return number of bytes parsed +int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { // lazily allocate memory for HeadData in case we're not an Avatar instance if (!_headData) { @@ -197,9 +196,8 @@ int AvatarData::parseData(const QByteArray& packet) { _handData = new HandData(this); } - // increment to push past the packet header const unsigned char* startPosition = reinterpret_cast(packet.data()); - const unsigned char* sourceBuffer = startPosition + numBytesForPacketHeader(packet); + const unsigned char* sourceBuffer = startPosition + offset; // Body world position memcpy(&_position, sourceBuffer, sizeof(float) * 3); @@ -288,13 +286,13 @@ int AvatarData::parseData(const QByteArray& packet) { // joint data int jointCount = *sourceBuffer++; _jointData.resize(jointCount); - unsigned char validity = 0; // although always set below, this fixes a warning of potential uninitialized use + unsigned char validity = 0; int validityBit = 0; for (int i = 0; i < jointCount; i++) { if (validityBit == 0) { validity = *sourceBuffer++; } - _jointData[i].valid = validity & (1 << validityBit); + _jointData[i].valid = (bool)(validity & (1 << validityBit)); validityBit = (validityBit + 1) % BITS_IN_BYTE; } for (int i = 0; i < jointCount; i++) { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 067fadd8b1..c7a93daef5 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -40,7 +40,6 @@ typedef unsigned long long quint64; #include #include -#include #include "HeadData.h" #include "HandData.h" @@ -74,7 +73,7 @@ class QNetworkAccessManager; class JointData; -class AvatarData : public NodeData { +class AvatarData : public QObject { Q_OBJECT Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition) @@ -97,7 +96,7 @@ class AvatarData : public NodeData { Q_PROPERTY(QString billboardURL READ getBillboardURL WRITE setBillboardFromURL) public: AvatarData(); - ~AvatarData(); + virtual ~AvatarData(); const glm::vec3& getPosition() const { return _position; } void setPosition(const glm::vec3 position) { _position = position; } @@ -106,7 +105,11 @@ public: void setHandPosition(const glm::vec3& handPosition); QByteArray toByteArray(); - int parseData(const QByteArray& packet); + + /// \param packet byte array of data + /// \param offset number of bytes into packet where data starts + /// \return number of bytes parsed + virtual int parseDataAtOffset(const QByteArray& packet, int offset); // Body Rotation (degrees) float getBodyYaw() const { return _bodyYaw; } From bc9deb5db7075e069426f22ef3caeb14cbd6cab7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 14:29:53 -0700 Subject: [PATCH 27/59] handle trivial case of not mixing silent audio streams --- assignment-client/src/audio/AudioMixer.cpp | 15 ++++++++------- .../src/audio/AudioMixerClientData.cpp | 11 +++++++++++ .../src/audio/AudioMixerClientData.h | 4 ++++ libraries/audio/src/AudioRingBuffer.cpp | 14 ++++++++++++++ libraries/audio/src/AudioRingBuffer.h | 2 ++ 5 files changed, 39 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 1637f88859..be4da8870d 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -301,7 +301,8 @@ void AudioMixer::prepareMixForListeningNode(Node* node) { if ((*otherNode != *node || otherNodeBuffer->shouldLoopbackForNode()) - && otherNodeBuffer->willBeAddedToMix()) { + && otherNodeBuffer->willBeAddedToMix() + && otherNodeClientData->getNextOutputLoudness() != 0) { addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer); } } @@ -355,12 +356,6 @@ void AudioMixer::run() { while (!_isFinished) { - QCoreApplication::processEvents(); - - if (_isFinished) { - break; - } - foreach (const SharedNodePointer& node, nodeList->getNodeHash()) { if (node->getLinkedData()) { ((AudioMixerClientData*) node->getLinkedData())->checkBuffersBeforeFrameSend(JITTER_BUFFER_SAMPLES); @@ -383,6 +378,12 @@ void AudioMixer::run() { ((AudioMixerClientData*) node->getLinkedData())->pushBuffersAfterFrameSend(); } } + + QCoreApplication::processEvents(); + + if (_isFinished) { + break; + } int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow(); diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index a41889e77c..8907796094 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -13,6 +13,13 @@ #include "AudioMixerClientData.h" +AudioMixerClientData::AudioMixerClientData() : + _ringBuffers(), + _nextOutputLoudness(0) +{ + +} + AudioMixerClientData::~AudioMixerClientData() { for (unsigned int i = 0; i < _ringBuffers.size(); i++) { // delete this attached PositionalAudioRingBuffer @@ -80,6 +87,10 @@ void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSam // this is a ring buffer that is ready to go // set its flag so we know to push its buffer when all is said and done _ringBuffers[i]->setWillBeAddedToMix(true); + + // calculate the average loudness for the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL + // that would be mixed in + _nextOutputLoudness = _ringBuffers[i]->averageLoudnessForBoundarySamples(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); } } } diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index 8031dfec3e..bb10098e23 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -18,16 +18,20 @@ class AudioMixerClientData : public NodeData { public: + AudioMixerClientData(); ~AudioMixerClientData(); const std::vector getRingBuffers() const { return _ringBuffers; } AvatarAudioRingBuffer* getAvatarAudioRingBuffer() const; + float getNextOutputLoudness() const { return _nextOutputLoudness; } + int parseData(const QByteArray& packet); void checkBuffersBeforeFrameSend(int jitterBufferLengthSamples); void pushBuffersAfterFrameSend(); private: std::vector _ringBuffers; + float _nextOutputLoudness; }; #endif /* defined(__hifi__AudioMixerClientData__) */ diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 56f6d038c2..aed601ec39 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -55,6 +55,20 @@ int AudioRingBuffer::parseData(const QByteArray& packet) { return writeData(packet.data() + numBytesPacketHeader, packet.size() - numBytesPacketHeader); } +float AudioRingBuffer::averageLoudnessForBoundarySamples(int numSamples) { + // ForBoundarySamples means that we expect the number of samples not to roll of the end of the ring buffer + float averageLoudness = 0; + + for (int i = 0; i < numSamples; ++i) { + averageLoudness += _nextOutput[i]; + } + + averageLoudness /= numSamples; + averageLoudness /= MAX_SAMPLE_VALUE; + + return averageLoudness; +} + qint64 AudioRingBuffer::readSamples(int16_t* destination, qint64 maxSamples) { return readData((char*) destination, maxSamples * sizeof(int16_t)); } diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index 577c01a63c..c4d3f87814 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -49,6 +49,8 @@ public: // assume callers using this will never wrap around the end const int16_t* getNextOutput() { return _nextOutput; } const int16_t* getBuffer() { return _buffer; } + + float averageLoudnessForBoundarySamples(int numSamples); qint64 readSamples(int16_t* destination, qint64 maxSamples); qint64 writeSamples(const int16_t* source, qint64 maxSamples); From 1428d2d1de772a611baa7d182f48be5a0f014fcc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 14:35:04 -0700 Subject: [PATCH 28/59] take an absolute value for correct loudness --- libraries/audio/src/AudioRingBuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index aed601ec39..d07a334d81 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -60,7 +60,7 @@ float AudioRingBuffer::averageLoudnessForBoundarySamples(int numSamples) { float averageLoudness = 0; for (int i = 0; i < numSamples; ++i) { - averageLoudness += _nextOutput[i]; + averageLoudness += fabsf(_nextOutput[i]); } averageLoudness /= numSamples; From c7e12824a8e03c6c06ee0fe41a18a6d0c7ebb36a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 14:35:26 -0700 Subject: [PATCH 29/59] clarify check for audio loudness in AudioMixer --- assignment-client/src/audio/AudioMixer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index be4da8870d..aeabd1548b 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -302,7 +302,7 @@ void AudioMixer::prepareMixForListeningNode(Node* node) { if ((*otherNode != *node || otherNodeBuffer->shouldLoopbackForNode()) && otherNodeBuffer->willBeAddedToMix() - && otherNodeClientData->getNextOutputLoudness() != 0) { + && otherNodeClientData->getNextOutputLoudness() > 0) { addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer); } } From 9f24bd9c4718b359b173c396622da0aab78376d7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 15:12:02 -0700 Subject: [PATCH 30/59] have the AudioMixer handle silent audio, send silence from Interface when gate closed --- interface/src/Audio.cpp | 48 +++++++++++++++---- libraries/audio/src/AudioRingBuffer.cpp | 13 +++++ libraries/audio/src/AudioRingBuffer.h | 2 + .../audio/src/PositionalAudioRingBuffer.cpp | 15 +++++- libraries/shared/src/PacketHeaders.h | 2 +- 5 files changed, 67 insertions(+), 13 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index cf51a479ab..dcb955597e 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -436,9 +436,8 @@ void Audio::handleAudioInput() { } } if (!_noiseGateOpen) { - for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) { - monoAudioSamples[i] = 0; - } + memset(monoAudioSamples, 0, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + _lastInputLoudness = 0; } } @@ -482,9 +481,26 @@ void Audio::handleAudioInput() { // we need the amount of bytes in the buffer + 1 for type // + 12 for 3 floats for position + float for bearing + 1 attenuation byte - - PacketType packetType = Menu::getInstance()->isOptionChecked(MenuOption::EchoServerAudio) - ? PacketTypeMicrophoneAudioWithEcho : PacketTypeMicrophoneAudioNoEcho; + + int numAudioBytes = 0; + + PacketType packetType; + if (_lastInputLoudness == 0) { + packetType = PacketTypeSilentAudioListener; + + // we need to indicate how many silent samples this is to the audio mixer + monoAudioSamples[0] = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; + numAudioBytes = sizeof(int16_t); + + } else { + numAudioBytes = NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL; + + if (Menu::getInstance()->isOptionChecked(MenuOption::EchoServerAudio)) { + packetType = PacketTypeMicrophoneAudioWithEcho; + } else { + packetType = PacketTypeMicrophoneAudioNoEcho; + } + } char* currentPacketPtr = monoAudioDataPacket + populatePacketHeader(monoAudioDataPacket, packetType); @@ -495,10 +511,8 @@ void Audio::handleAudioInput() { // memcpy our orientation memcpy(currentPacketPtr, &headOrientation, sizeof(headOrientation)); currentPacketPtr += sizeof(headOrientation); - - nodeList->writeDatagram(monoAudioDataPacket, - NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes, - audioMixer); + + nodeList->writeDatagram(monoAudioDataPacket, numAudioBytes + leadingBytes, audioMixer); Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO) .updateValue(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes); @@ -638,7 +652,14 @@ void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { int16_t collisionSample = (int16_t) sample; + _lastInputLoudness = 0; + monoInput[i] = glm::clamp(monoInput[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); + + _lastInputLoudness += fabsf(monoInput[i]); + _lastInputLoudness /= numSamples; + _lastInputLoudness /= MAX_SAMPLE_VALUE; + _localProceduralSamples[i] = glm::clamp(_localProceduralSamples[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); @@ -662,7 +683,14 @@ void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { int16_t collisionSample = (int16_t) sample; + _lastInputLoudness = 0; + monoInput[i] = glm::clamp(monoInput[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); + + _lastInputLoudness += fabsf(monoInput[i]); + _lastInputLoudness /= numSamples; + _lastInputLoudness /= MAX_SAMPLE_VALUE; + _localProceduralSamples[i] = glm::clamp(_localProceduralSamples[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index d07a334d81..ba21c6c9b9 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -156,6 +156,19 @@ unsigned int AudioRingBuffer::samplesAvailable() const { } } +void AudioRingBuffer::addSilentFrame(int numSilentSamples) { + // setup the silent frame + int numSilentBytes = numSilentSamples * sizeof(int16_t); + char* silentFrame = new char[numSilentBytes]; + memset(silentFrame, 0, numSilentBytes); + + // write it + writeData(silentFrame, numSilentBytes); + + // delete the temporary silent frame + delete[] silentFrame; +} + bool AudioRingBuffer::isNotStarvedOrHasMinimumSamples(unsigned int numRequiredSamples) const { if (!_isStarved) { return true; diff --git a/libraries/audio/src/AudioRingBuffer.h b/libraries/audio/src/AudioRingBuffer.h index c4d3f87814..0beb45ca18 100644 --- a/libraries/audio/src/AudioRingBuffer.h +++ b/libraries/audio/src/AudioRingBuffer.h @@ -70,6 +70,8 @@ public: void setIsStarved(bool isStarved) { _isStarved = isStarved; } bool hasStarted() const { return _hasStarted; } + + void addSilentFrame(int numSilentSamples); protected: // disallow copying of AudioRingBuffer objects AudioRingBuffer(const AudioRingBuffer&); diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index 27b62a8a56..0ac53231a1 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -44,8 +44,19 @@ int PositionalAudioRingBuffer::parseData(const QByteArray& packet) { packetStream.skipRawData(numBytesForPacketHeader(packet)); packetStream.skipRawData(parsePositionalData(packet.mid(packetStream.device()->pos()))); - packetStream.skipRawData(writeData(packet.data() + packetStream.device()->pos(), - packet.size() - packetStream.device()->pos())); + + if (packetTypeForPacket(packet) == PacketTypeSilentAudioListener) { + // this source had no audio to send us, but this counts as a packet + // write silence equivalent to the number of silent samples they just sent us + int16_t numSilentSamples; + packetStream >> numSilentSamples; + addSilentFrame(numSilentSamples); + } else { + // there is audio data to read + packetStream.skipRawData(writeData(packet.data() + packetStream.device()->pos(), + packet.size() - packetStream.device()->pos())); + } + return packetStream.device()->pos(); } diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 0122e36a61..6f87ac8e3f 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -32,7 +32,7 @@ enum PacketType { PacketTypeMicrophoneAudioNoEcho, PacketTypeMicrophoneAudioWithEcho, PacketTypeBulkAvatarData, - PacketTypeTransmitterData, // usable + PacketTypeSilentAudioListener, PacketTypeEnvironmentData, PacketTypeDomainListRequest, PacketTypeRequestAssignment, From 61594b9a1ebb9e723b3203c5c6344412cc6ac78e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 16:27:49 -0700 Subject: [PATCH 31/59] fixes to silent audio frame sending --- assignment-client/src/audio/AudioMixer.cpp | 3 ++- assignment-client/src/audio/AudioMixerClientData.cpp | 3 ++- interface/src/Audio.cpp | 8 ++++---- libraries/audio/src/PositionalAudioRingBuffer.cpp | 5 +++-- libraries/shared/src/PacketHeaders.h | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index aeabd1548b..54f9d962b0 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -322,7 +322,8 @@ void AudioMixer::readPendingDatagrams() { PacketType mixerPacketType = packetTypeForPacket(receivedPacket); if (mixerPacketType == PacketTypeMicrophoneAudioNoEcho || mixerPacketType == PacketTypeMicrophoneAudioWithEcho - || mixerPacketType == PacketTypeInjectAudio) { + || mixerPacketType == PacketTypeInjectAudio + || mixerPacketType == PacketTypeSilentAudioFrame) { nodeList->findNodeAndUpdateWithDataFromPacket(receivedPacket); } else { diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 8907796094..b2da0a0aaa 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -41,7 +41,8 @@ AvatarAudioRingBuffer* AudioMixerClientData::getAvatarAudioRingBuffer() const { int AudioMixerClientData::parseData(const QByteArray& packet) { PacketType packetType = packetTypeForPacket(packet); if (packetType == PacketTypeMicrophoneAudioWithEcho - || packetType == PacketTypeMicrophoneAudioNoEcho) { + || packetType == PacketTypeMicrophoneAudioNoEcho + || packetType == PacketTypeSilentAudioFrame) { // grab the AvatarAudioRingBuffer from the vector (or create it if it doesn't exist) AvatarAudioRingBuffer* avatarRingBuffer = getAvatarAudioRingBuffer(); diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index dcb955597e..b684cec46e 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -436,7 +436,7 @@ void Audio::handleAudioInput() { } } if (!_noiseGateOpen) { - memset(monoAudioSamples, 0, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + memset(monoAudioSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); _lastInputLoudness = 0; } } @@ -450,7 +450,7 @@ void Audio::handleAudioInput() { // our input loudness is 0, since we're muted _lastInputLoudness = 0; } - + // add procedural effects to the appropriate input samples addProceduralSounds(monoAudioSamples, NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); @@ -486,7 +486,7 @@ void Audio::handleAudioInput() { PacketType packetType; if (_lastInputLoudness == 0) { - packetType = PacketTypeSilentAudioListener; + packetType = PacketTypeSilentAudioFrame; // we need to indicate how many silent samples this is to the audio mixer monoAudioSamples[0] = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; @@ -515,7 +515,7 @@ void Audio::handleAudioInput() { nodeList->writeDatagram(monoAudioDataPacket, numAudioBytes + leadingBytes, audioMixer); Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::AUDIO) - .updateValue(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL + leadingBytes); + .updateValue(numAudioBytes + leadingBytes); } delete[] inputAudioSamples; } diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index 0ac53231a1..11e1a7c2ae 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -45,11 +45,12 @@ int PositionalAudioRingBuffer::parseData(const QByteArray& packet) { packetStream.skipRawData(parsePositionalData(packet.mid(packetStream.device()->pos()))); - if (packetTypeForPacket(packet) == PacketTypeSilentAudioListener) { + if (packetTypeForPacket(packet) == PacketTypeSilentAudioFrame) { // this source had no audio to send us, but this counts as a packet // write silence equivalent to the number of silent samples they just sent us int16_t numSilentSamples; - packetStream >> numSilentSamples; + packetStream.readRawData(reinterpret_cast(&numSilentSamples), sizeof(int16_t)); + addSilentFrame(numSilentSamples); } else { // there is audio data to read diff --git a/libraries/shared/src/PacketHeaders.h b/libraries/shared/src/PacketHeaders.h index 6f87ac8e3f..c6ce6bdd6b 100644 --- a/libraries/shared/src/PacketHeaders.h +++ b/libraries/shared/src/PacketHeaders.h @@ -32,7 +32,7 @@ enum PacketType { PacketTypeMicrophoneAudioNoEcho, PacketTypeMicrophoneAudioWithEcho, PacketTypeBulkAvatarData, - PacketTypeSilentAudioListener, + PacketTypeSilentAudioFrame, PacketTypeEnvironmentData, PacketTypeDomainListRequest, PacketTypeRequestAssignment, From d652cec7667466886961c9961c8ee16bfbce5a7e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 16:30:58 -0700 Subject: [PATCH 32/59] some potential fixes to QByteArray crash --- assignment-client/src/audio/AudioMixer.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 54f9d962b0..d4b5c91488 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -287,7 +287,7 @@ void AudioMixer::prepareMixForListeningNode(Node* node) { AvatarAudioRingBuffer* nodeRingBuffer = ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer(); // zero out the client mix for this node - memset(_clientSamples, 0, sizeof(_clientSamples)); + memset(_clientSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_STEREO); // loop through all other nodes that have sufficient audio to mix foreach (const SharedNodePointer& otherNode, NodeList::getInstance()->getNodeHash()) { @@ -367,8 +367,9 @@ void AudioMixer::run() { if (node->getType() == NodeType::Agent && node->getActiveSocket() && node->getLinkedData() && ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) { prepareMixForListeningNode(node.data()); - - memcpy(_clientMixBuffer.data() + numBytesPacketHeader, _clientSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO); + + _clientMixBuffer.replace(numBytesPacketHeader, NETWORK_BUFFER_LENGTH_BYTES_STEREO, + reinterpret_cast(_clientSamples)); nodeList->writeDatagram(_clientMixBuffer, node); } } From 7e0da71527602d216c676dc72bb3b4ddf1bdc75e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 16:38:39 -0700 Subject: [PATCH 33/59] have agent optionally send silent stream flag --- libraries/script-engine/src/ScriptEngine.cpp | 27 +++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 9a672317ae..cc61633e60 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -267,15 +267,36 @@ void ScriptEngine::run() { if (_avatarAudioBuffer && _numAvatarAudioBufferSamples > 0) { // if have an avatar audio stream then send it out to our audio-mixer - QByteArray audioPacket = byteArrayWithPopulatedHeader(PacketTypeMicrophoneAudioNoEcho); + + bool silentFrame = true; + + // check if the all of the _numAvatarAudioBufferSamples to be sent are silence + for (int i = 0; i < _numAvatarAudioBufferSamples; ++i) { + if (_avatarAudioBuffer[i] != 0) { + silentFrame = false; + break; + } + } + + QByteArray audioPacket = byteArrayWithPopulatedHeader(silentFrame + ? PacketTypeSilentAudioFrame + : PacketTypeMicrophoneAudioNoEcho); QDataStream packetStream(&audioPacket, QIODevice::Append); // use the orientation and position of this avatar for the source of this audio packetStream.writeRawData(reinterpret_cast(&_avatarData->getPosition()), sizeof(glm::vec3)); glm::quat headOrientation = _avatarData->getHeadOrientation(); packetStream.writeRawData(reinterpret_cast(&headOrientation), sizeof(glm::quat)); - packetStream.writeRawData(reinterpret_cast(_avatarAudioBuffer), - _numAvatarAudioBufferSamples * sizeof(int16_t)); + + if (silentFrame) { + // write the number of silent samples so the audio-mixer can uphold timing + int16_t numSilentSamples = _numAvatarAudioBufferSamples; + packetStream.writeRawData(reinterpret_cast(&numSilentSamples), sizeof(int16_t)); + } else { + // write the raw audio data + packetStream.writeRawData(reinterpret_cast(_avatarAudioBuffer), + _numAvatarAudioBufferSamples * sizeof(int16_t)); + } nodeList->broadcastToNodes(audioPacket, NodeSet() << NodeType::AudioMixer); } From 447f23a1c947ab41558f3892e0e1a1c8546db327 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 16:56:29 -0700 Subject: [PATCH 34/59] repair _clientSamples copying into _clientMix --- assignment-client/src/audio/AudioMixer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index d4b5c91488..e097fd22a1 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -368,8 +368,7 @@ void AudioMixer::run() { && ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) { prepareMixForListeningNode(node.data()); - _clientMixBuffer.replace(numBytesPacketHeader, NETWORK_BUFFER_LENGTH_BYTES_STEREO, - reinterpret_cast(_clientSamples)); + memcpy(_clientMixBuffer.data() + numBytesPacketHeader, _clientSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO); nodeList->writeDatagram(_clientMixBuffer, node); } } From 07a71d87963953d8a758ac239082c2662e37c14a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 17:22:16 -0700 Subject: [PATCH 35/59] use char instead of QByteArray for mix samples in AudioMixer --- assignment-client/src/audio/AudioMixer.cpp | 7 +++---- assignment-client/src/audio/AudioMixer.h | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 1637f88859..34f53a65b4 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -62,8 +62,7 @@ void attachNewBufferToNode(Node *newNode) { } AudioMixer::AudioMixer(const QByteArray& packet) : - ThreadedAssignment(packet), - _clientMixBuffer(NETWORK_BUFFER_LENGTH_BYTES_STEREO + numBytesForPacketHeaderGivenPacketType(PacketTypeMixedAudio), 0) + ThreadedAssignment(packet) { connect(NodeList::getInstance(), &NodeList::uuidChanged, this, &AudioMixer::receivedSessionUUID); } @@ -372,8 +371,8 @@ void AudioMixer::run() { && ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) { prepareMixForListeningNode(node.data()); - memcpy(_clientMixBuffer.data() + numBytesPacketHeader, _clientSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO); - nodeList->writeDatagram(_clientMixBuffer, node); + memcpy(_clientMixBuffer + numBytesPacketHeader, _clientSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO); + nodeList->writeDatagram(_clientMixBuffer, NETWORK_BUFFER_LENGTH_BYTES_STEREO + numBytesPacketHeader, node); } } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 8032649c17..0db205d845 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -38,10 +38,9 @@ private: /// prepares and sends a mix to one Node void prepareMixForListeningNode(Node* node); - QByteArray _clientMixBuffer; - // client samples capacity is larger than what will be sent to optimize mixing int16_t _clientSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + SAMPLE_PHASE_DELAY_AT_90]; + char _clientMixBuffer[NETWORK_BUFFER_LENGTH_BYTES_STEREO + MAX_PACKET_HEADER_BYTES]; }; #endif /* defined(__hifi__AudioMixer__) */ From 7ba595338ea9460d41c11e56f91fd2e34971cfab Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 17:39:08 -0700 Subject: [PATCH 36/59] guard around update to last heard for a NULL matching node --- libraries/shared/src/NodeList.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 0cca9731b0..0354bd8bf9 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -267,7 +267,9 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr // the node decided not to do anything with this packet // if it comes from a known source we should keep that node alive SharedNodePointer matchingNode = sendingNodeForPacket(packet); - matchingNode->setLastHeardMicrostamp(usecTimestampNow()); + if (matchingNode) { + matchingNode->setLastHeardMicrostamp(usecTimestampNow()); + } break; } From f3910f8c1af675d4b7fc6dc6efdb381b87cb3b9a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 17:54:27 -0700 Subject: [PATCH 37/59] scope clientMixBuffer only to AudioMixer run --- assignment-client/src/audio/AudioMixer.cpp | 16 +++++++--------- assignment-client/src/audio/AudioMixer.h | 3 --- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 90a901f5c9..c5c112d0f0 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -64,7 +64,7 @@ void attachNewBufferToNode(Node *newNode) { AudioMixer::AudioMixer(const QByteArray& packet) : ThreadedAssignment(packet) { - connect(NodeList::getInstance(), &NodeList::uuidChanged, this, &AudioMixer::receivedSessionUUID); + } void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd, @@ -332,10 +332,6 @@ void AudioMixer::readPendingDatagrams() { } } -void AudioMixer::receivedSessionUUID(const QUuid& sessionUUID) { - populatePacketHeader(_clientMixBuffer, PacketTypeMixedAudio); -} - void AudioMixer::run() { commonInit(AUDIO_MIXER_LOGGING_TARGET_NAME, NodeType::AudioMixer); @@ -350,8 +346,8 @@ void AudioMixer::run() { timeval startTime; gettimeofday(&startTime, NULL); - - int numBytesPacketHeader = numBytesForPacketHeaderGivenPacketType(PacketTypeMixedAudio); + + char clientMixBuffer[NETWORK_BUFFER_LENGTH_BYTES_STEREO + MAX_PACKET_HEADER_BYTES]; while (!_isFinished) { @@ -365,9 +361,11 @@ void AudioMixer::run() { if (node->getType() == NodeType::Agent && node->getActiveSocket() && node->getLinkedData() && ((AudioMixerClientData*) node->getLinkedData())->getAvatarAudioRingBuffer()) { prepareMixForListeningNode(node.data()); + + int numBytesPacketHeader = populatePacketHeader(clientMixBuffer, PacketTypeMixedAudio); - memcpy(_clientMixBuffer + numBytesPacketHeader, _clientSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO); - nodeList->writeDatagram(_clientMixBuffer, NETWORK_BUFFER_LENGTH_BYTES_STEREO + numBytesPacketHeader, node); + memcpy(clientMixBuffer + numBytesPacketHeader, _clientSamples, NETWORK_BUFFER_LENGTH_BYTES_STEREO); + nodeList->writeDatagram(clientMixBuffer, NETWORK_BUFFER_LENGTH_BYTES_STEREO + numBytesPacketHeader, node); } } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 0db205d845..5a68b0023f 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -28,8 +28,6 @@ public slots: void run(); void readPendingDatagrams(); -private slots: - void receivedSessionUUID(const QUuid& sessionUUID); private: /// adds one buffer to the mix for a listening node void addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuffer* bufferToAdd, @@ -40,7 +38,6 @@ private: // client samples capacity is larger than what will be sent to optimize mixing int16_t _clientSamples[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + SAMPLE_PHASE_DELAY_AT_90]; - char _clientMixBuffer[NETWORK_BUFFER_LENGTH_BYTES_STEREO + MAX_PACKET_HEADER_BYTES]; }; #endif /* defined(__hifi__AudioMixer__) */ From 1fc9ac18151876edd3bc38a1a058e9453caf8ad3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 17 Mar 2014 17:55:47 -0700 Subject: [PATCH 38/59] make the client mix buffer only as large as it needs to be --- assignment-client/src/audio/AudioMixer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index c5c112d0f0..a2c56405ec 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -347,7 +347,8 @@ void AudioMixer::run() { gettimeofday(&startTime, NULL); - char clientMixBuffer[NETWORK_BUFFER_LENGTH_BYTES_STEREO + MAX_PACKET_HEADER_BYTES]; + char* clientMixBuffer = new char[NETWORK_BUFFER_LENGTH_BYTES_STEREO + + numBytesForPacketHeaderGivenPacketType(PacketTypeMixedAudio)]; while (!_isFinished) { @@ -391,4 +392,6 @@ void AudioMixer::run() { } } + + delete[] clientMixBuffer; } From 75ab970c0d938f2157b4ae4735dc1ae7dd69b7c7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 17 Mar 2014 18:23:09 -0700 Subject: [PATCH 39/59] fix bug: bad offset into avatar data during decode --- interface/src/avatar/AvatarManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 49479e903e..29b23e1f5b 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -152,6 +152,7 @@ void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QW // only add them if mixerWeakPointer points to something (meaning that mixer is still around) while (bytesRead < datagram.size() && mixerWeakPointer.data()) { QUuid nodeUUID = QUuid::fromRfc4122(datagram.mid(bytesRead, NUM_BYTES_RFC4122_UUID)); + bytesRead += NUM_BYTES_RFC4122_UUID; AvatarSharedPointer matchingAvatar = _avatarHash.value(nodeUUID); @@ -167,7 +168,6 @@ void AvatarManager::processAvatarDataPacket(const QByteArray &datagram, const QW qDebug() << "Adding avatar with UUID" << nodeUUID << "to AvatarManager hash."; } - // have the matching (or new) avatar parse the data from the packet bytesRead += matchingAvatar->parseDataAtOffset(datagram, bytesRead); } From 3296447af67e59801e958c3eedabf033aac22e31 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 17 Mar 2014 18:23:55 -0700 Subject: [PATCH 40/59] remove dupe hand data from avatar updates partial progress toward issue #2256 --- libraries/avatars/src/AvatarData.cpp | 10 --- libraries/avatars/src/HandData.cpp | 117 --------------------------- libraries/avatars/src/HandData.h | 6 -- 3 files changed, 133 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 5650d7a800..b1615ffb9d 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -93,7 +93,6 @@ QByteArray AvatarData::toByteArray() { destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedPitch()); destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedRoll()); - // Head lean X,Z (head lateral and fwd/back motion relative to torso) memcpy(destinationBuffer, &_headData->_leanSideways, sizeof(_headData->_leanSideways)); destinationBuffer += sizeof(_headData->_leanSideways); @@ -177,9 +176,6 @@ QByteArray AvatarData::toByteArray() { } } - // hand data - destinationBuffer += HandData::encodeData(_handData, destinationBuffer); - return avatarDataByteArray.left(destinationBuffer - startPosition); } @@ -302,12 +298,6 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { } } - // hand data - if (sourceBuffer - startPosition < packet.size()) { - // check passed, bytes match - sourceBuffer += _handData->decodeRemoteData(packet.mid(sourceBuffer - startPosition)); - } - return sourceBuffer - startPosition; } diff --git a/libraries/avatars/src/HandData.cpp b/libraries/avatars/src/HandData.cpp index 15be4636a7..c84ed77dae 100644 --- a/libraries/avatars/src/HandData.cpp +++ b/libraries/avatars/src/HandData.cpp @@ -109,123 +109,6 @@ _owningHandData(owningHandData) setTrailLength(standardTrailLength); } -// static -int HandData::encodeData(HandData* hand, unsigned char* destinationBuffer) { - if (hand) { - return hand->encodeRemoteData(destinationBuffer); - } - // else encode empty data: - // One byte for zero hands - // One byte for error checking. - *destinationBuffer = 0; - *(destinationBuffer + 1) = 1; - return 2; -} - -int HandData::encodeRemoteData(unsigned char* destinationBuffer) { - const unsigned char* startPosition = destinationBuffer; - - unsigned int numPalms = 0; - for (unsigned int handIndex = 0; handIndex < getNumPalms(); ++handIndex) { - PalmData& palm = getPalms()[handIndex]; - if (palm.isActive()) { - numPalms++; - } - } - *destinationBuffer++ = numPalms; - - for (unsigned int handIndex = 0; handIndex < getNumPalms(); ++handIndex) { - PalmData& palm = getPalms()[handIndex]; - if (palm.isActive()) { - destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, palm.getRawPosition(), fingerVectorRadix); - destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, palm.getRawNormal(), fingerVectorRadix); - - unsigned int numFingers = 0; - for (unsigned int fingerIndex = 0; fingerIndex < palm.getNumFingers(); ++fingerIndex) { - FingerData& finger = palm.getFingers()[fingerIndex]; - if (finger.isActive()) { - numFingers++; - } - } - *destinationBuffer++ = numFingers; - - for (unsigned int fingerIndex = 0; fingerIndex < palm.getNumFingers(); ++fingerIndex) { - FingerData& finger = palm.getFingers()[fingerIndex]; - if (finger.isActive()) { - destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, finger.getTipRawPosition(), fingerVectorRadix); - destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, finger.getRootRawPosition(), fingerVectorRadix); - } - } - } - } - // One byte for error checking safety. - size_t checkLength = destinationBuffer - startPosition; - *destinationBuffer++ = (unsigned char)checkLength; - - // just a double-check, while tracing a crash. -// decodeRemoteData(destinationBuffer - (destinationBuffer - startPosition)); - - return destinationBuffer - startPosition; -} - -int HandData::decodeRemoteData(const QByteArray& dataByteArray) { - const unsigned char* startPosition; - const unsigned char* sourceBuffer = startPosition = reinterpret_cast(dataByteArray.data()); - unsigned int numPalms = *sourceBuffer++; - - for (unsigned int handIndex = 0; handIndex < numPalms; ++handIndex) { - if (handIndex >= (unsigned int)getNumPalms()) - addNewPalm(); - PalmData& palm = getPalms()[handIndex]; - - glm::vec3 handPosition; - glm::vec3 handNormal; - sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, handPosition, fingerVectorRadix); - sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, handNormal, fingerVectorRadix); - unsigned int numFingers = *sourceBuffer++; - - palm.setRawPosition(handPosition); - palm.setRawNormal(handNormal); - palm.setActive(true); - - // For received data, set the sixense controller ID to match the order initialized and sent - 0 Left, 1 Right - palm.setSixenseID(handIndex); - - for (unsigned int fingerIndex = 0; fingerIndex < numFingers; ++fingerIndex) { - if (fingerIndex < (unsigned int)palm.getNumFingers()) { - FingerData& finger = palm.getFingers()[fingerIndex]; - - glm::vec3 tipPosition; - glm::vec3 rootPosition; - sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, tipPosition, fingerVectorRadix); - sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, rootPosition, fingerVectorRadix); - - finger.setRawTipPosition(tipPosition); - finger.setRawRootPosition(rootPosition); - finger.setActive(true); - } - } - // Turn off any fingers which weren't used. - for (unsigned int fingerIndex = numFingers; fingerIndex < palm.getNumFingers(); ++fingerIndex) { - FingerData& finger = palm.getFingers()[fingerIndex]; - finger.setActive(false); - } - } - // Turn off any hands which weren't used. - for (unsigned int handIndex = numPalms; handIndex < getNumPalms(); ++handIndex) { - PalmData& palm = getPalms()[handIndex]; - palm.setActive(false); - } - - // One byte for error checking safety. Last byte contains the expected length (less itself) - // actualLength less expected byte = (sourceBuffer - startPosition) - // expectedLength less expected byte = (*sourceBuffer) - assert((unsigned char)(sourceBuffer - startPosition) == (unsigned char)(*sourceBuffer)); - sourceBuffer++; // skip the trailing byte which is expected length - - return sourceBuffer - startPosition; -} - void HandData::setFingerTrailLength(unsigned int length) { for (size_t i = 0; i < getNumPalms(); ++i) { PalmData& palm = getPalms()[i]; diff --git a/libraries/avatars/src/HandData.h b/libraries/avatars/src/HandData.h index f649faf080..fffc596247 100755 --- a/libraries/avatars/src/HandData.h +++ b/libraries/avatars/src/HandData.h @@ -63,12 +63,6 @@ public: void setFingerTrailLength(unsigned int length); void updateFingerTrails(); - static int encodeData(HandData* hand, unsigned char* destinationBuffer); - - // Use these for sending and receiving hand data - int encodeRemoteData(unsigned char* destinationBuffer); - int decodeRemoteData(const QByteArray& dataByteArray); - /// Checks for penetration between the described sphere and the hand. /// \param penetratorCenter the center of the penetration test sphere /// \param penetratorRadius the radius of the penetration test sphere From d80f110961277728a6022c5c569b23963d61b0c8 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Mar 2014 09:12:23 -0700 Subject: [PATCH 41/59] Prevent audio average from becoming less than zero (thus causing sqrt to return nan, thus making our fake blendshape coefficient nan, thus making the jaw disappear). Closes #2334. --- interface/src/avatar/Head.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index a9b85ffce2..44001a2015 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -90,8 +90,7 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { _saccade += (_saccadeTarget - _saccade) * 0.50f; const float AUDIO_AVERAGING_SECS = 0.05f; - _averageLoudness = (1.f - deltaTime / AUDIO_AVERAGING_SECS) * _averageLoudness + - (deltaTime / AUDIO_AVERAGING_SECS) * _audioLoudness; + _averageLoudness = glm::mix(_averageLoudness, _audioLoudness, glm::min(deltaTime / AUDIO_AVERAGING_SECS, 1.0f)); // Detect transition from talking to not; force blink after that and a delay bool forceBlink = false; From 272cb879f8b9b24d65d4eb7c4ac9b9fff0c31d9f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Mar 2014 09:38:49 -0700 Subject: [PATCH 42/59] change wording of comment --- assignment-client/src/avatars/AvatarMixerClientData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assignment-client/src/avatars/AvatarMixerClientData.cpp b/assignment-client/src/avatars/AvatarMixerClientData.cpp index a29b6efdb4..90088173a9 100644 --- a/assignment-client/src/avatars/AvatarMixerClientData.cpp +++ b/assignment-client/src/avatars/AvatarMixerClientData.cpp @@ -17,7 +17,7 @@ AvatarMixerClientData::AvatarMixerClientData() : } int AvatarMixerClientData::parseData(const QByteArray& packet) { - // increment to push past the packet header + // compute the offset to the data payload int offset = numBytesForPacketHeader(packet); return _avatar.parseDataAtOffset(packet, offset); } From b69c33927943cac68b8ffc42eaefb3a5b60b1afb Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Mar 2014 09:39:05 -0700 Subject: [PATCH 43/59] don't send redundant head rot and hand pos info --- libraries/avatars/src/AvatarData.cpp | 38 ---------------------------- 1 file changed, 38 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index b1615ffb9d..8ed0ce51ec 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -88,22 +88,6 @@ QByteArray AvatarData::toByteArray() { // Body scale destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _targetScale); - // Head rotation (NOTE: This needs to become a quaternion to save two bytes) - destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedYaw()); - destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedPitch()); - destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedRoll()); - - // Head lean X,Z (head lateral and fwd/back motion relative to torso) - memcpy(destinationBuffer, &_headData->_leanSideways, sizeof(_headData->_leanSideways)); - destinationBuffer += sizeof(_headData->_leanSideways); - memcpy(destinationBuffer, &_headData->_leanForward, sizeof(_headData->_leanForward)); - destinationBuffer += sizeof(_headData->_leanForward); - - // Hand Position - is relative to body position - glm::vec3 handPositionRelative = _handPosition - _position; - memcpy(destinationBuffer, &handPositionRelative, sizeof(float) * 3); - destinationBuffer += sizeof(float) * 3; - // Lookat Position memcpy(destinationBuffer, &_headData->_lookAtPosition, sizeof(_headData->_lookAtPosition)); destinationBuffer += sizeof(_headData->_lookAtPosition); @@ -207,28 +191,6 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { // Body scale sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer, _targetScale); - // Head rotation (NOTE: This needs to become a quaternion to save two bytes) - float headYaw, headPitch, headRoll; - sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &headYaw); - sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &headPitch); - sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &headRoll); - - _headData->setYaw(headYaw); - _headData->setPitch(headPitch); - _headData->setRoll(headRoll); - - // Head position relative to pelvis - memcpy(&_headData->_leanSideways, sourceBuffer, sizeof(_headData->_leanSideways)); - sourceBuffer += sizeof(float); - memcpy(&_headData->_leanForward, sourceBuffer, sizeof(_headData->_leanForward)); - sourceBuffer += sizeof(_headData->_leanForward); - - // Hand Position - is relative to body position - glm::vec3 handPositionRelative; - memcpy(&handPositionRelative, sourceBuffer, sizeof(float) * 3); - _handPosition = _position + handPositionRelative; - sourceBuffer += sizeof(float) * 3; - // Lookat Position memcpy(&_headData->_lookAtPosition, sourceBuffer, sizeof(_headData->_lookAtPosition)); sourceBuffer += sizeof(_headData->_lookAtPosition); From 6aa1f286bbda109476b6a48f8823633948e538ec Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 18 Mar 2014 10:13:23 -0700 Subject: [PATCH 44/59] Alpha is the new default. --- libraries/shared/src/DomainInfo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/DomainInfo.h b/libraries/shared/src/DomainInfo.h index 35564e7cd8..da65525f9d 100644 --- a/libraries/shared/src/DomainInfo.h +++ b/libraries/shared/src/DomainInfo.h @@ -16,7 +16,7 @@ #include "HifiSockAddr.h" -const QString DEFAULT_DOMAIN_HOSTNAME = "root.highfidelity.io"; +const QString DEFAULT_DOMAIN_HOSTNAME = "alpha.highfidelity.io"; const unsigned short DEFAULT_DOMAIN_SERVER_PORT = 40102; class DomainInfo : public QObject { From 9079c3ecd83c6a52af1302068df9609e2bdc759b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Mar 2014 10:41:14 -0700 Subject: [PATCH 45/59] explicit casts to remove warnings --- interface/src/MetavoxelSystem.cpp | 5 +++-- interface/src/avatar/Hand.cpp | 4 ++-- interface/src/avatar/SkeletonModel.cpp | 2 +- libraries/metavoxels/src/MetavoxelData.cpp | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 54cc3b4cdb..23e50176eb 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -185,10 +185,11 @@ int MetavoxelSystem::SimulateVisitor::visit(MetavoxelInfo& info) { } QRgb color = info.inputValues.at(0).getInlineValue(); QRgb normal = info.inputValues.at(1).getInlineValue(); - int alpha = qAlpha(color); + quint8 alpha = qAlpha(color); if (alpha > 0) { Point point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size), - { qRed(color), qGreen(color), qBlue(color), alpha }, { qRed(normal), qGreen(normal), qBlue(normal) } }; + { quint8(qRed(color)), quint8(qGreen(color)), quint8(qBlue(color)), alpha }, + { quint8(qRed(normal)), quint8(qGreen(normal)), quint8(qBlue(normal)) } }; _points.append(point); } return STOP_RECURSION; diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index b4866c9478..43a1787d13 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -206,8 +206,8 @@ void Hand::collideAgainstOurself() { } // ignoring everything below the parent of the parent of the last free joint int skipIndex = skeletonModel.getParentJointIndex(skeletonModel.getParentJointIndex( - skeletonModel.getLastFreeJointIndex(((int)i == leftPalmIndex) ? skeletonModel.getLeftHandJointIndex() : - ((int)i == rightPalmIndex) ? skeletonModel.getRightHandJointIndex() : -1))); + skeletonModel.getLastFreeJointIndex((int(i) == leftPalmIndex) ? skeletonModel.getLeftHandJointIndex() : + (int(i) == rightPalmIndex) ? skeletonModel.getRightHandJointIndex() : -1))); handCollisions.clear(); if (_owningAvatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, handCollisions, skipIndex)) { diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 1ffa3d838e..7173cb0b84 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -140,7 +140,7 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin direction += fingerVector / length; } fingerVector = glm::inverse(palmRotation) * fingerVector * -sign; - IndexValue indexValue = { i, atan2f(fingerVector.z, fingerVector.x) }; + IndexValue indexValue = { int(i), atan2f(fingerVector.z, fingerVector.x) }; fingerIndices.append(indexValue); } qSort(fingerIndices.begin(), fingerIndices.end()); diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 08cd62f30d..397e10d45f 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -1096,7 +1096,7 @@ QScriptValue ScriptedMetavoxelGuide::visit(QScriptContext* context, QScriptEngin QScriptValue minimum = infoValue.property(guide->_minimumHandle); MetavoxelInfo info = { glm::vec3(minimum.property(0).toNumber(), minimum.property(1).toNumber(), minimum.property(2).toNumber()), - infoValue.property(guide->_sizeHandle).toNumber(), guide->_visitation->info.inputValues, + float(infoValue.property(guide->_sizeHandle).toNumber()), guide->_visitation->info.inputValues, guide->_visitation->info.outputValues, infoValue.property(guide->_isLeafHandle).toBool() }; // extract and convert the values provided by the script From 7ed982a07333cdfcb3721a9845e789c227b4d80b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 18 Mar 2014 11:12:36 -0700 Subject: [PATCH 46/59] cleanup writing of silent frame to ring buffer --- libraries/audio/src/AudioRingBuffer.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index ba21c6c9b9..9cef64e216 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -157,16 +157,18 @@ unsigned int AudioRingBuffer::samplesAvailable() const { } void AudioRingBuffer::addSilentFrame(int numSilentSamples) { - // setup the silent frame - int numSilentBytes = numSilentSamples * sizeof(int16_t); - char* silentFrame = new char[numSilentBytes]; - memset(silentFrame, 0, numSilentBytes); - - // write it - writeData(silentFrame, numSilentBytes); - - // delete the temporary silent frame - delete[] silentFrame; + // memset zeroes into the buffer, accomodate a wrap around the end + // push the _endOfLastWrite to the correct spot + if (_endOfLastWrite + numSilentSamples <= _buffer + _sampleCapacity) { + memset(_endOfLastWrite, 0, numSilentSamples * sizeof(int16_t)); + _endOfLastWrite += numSilentSamples; + } else { + int numSamplesToEnd = (_buffer + _sampleCapacity) - _endOfLastWrite; + memset(_endOfLastWrite, 0, numSilentSamples * sizeof(int16_t)); + memset(_buffer, 0, (numSilentSamples - numSamplesToEnd) * sizeof(int16_t)); + + _endOfLastWrite = _buffer + (numSilentSamples - numSamplesToEnd); + } } bool AudioRingBuffer::isNotStarvedOrHasMinimumSamples(unsigned int numRequiredSamples) const { From c8d3cd2a1b8e3c8ed03fe02924900ed0194fafb2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 18 Mar 2014 11:55:11 -0700 Subject: [PATCH 47/59] fix go to orientation to not put the user sideways --- interface/src/avatar/MyAvatar.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e4aaa07a4b..5c94a7db9d 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1158,6 +1158,8 @@ void MyAvatar::updateLocationInDataServer() { QString positionString(createByteArray(_position)); QString orientationString(createByteArray(glm::degrees(safeEulerAngles(getOrientation())))); + qDebug() << orientationString; + // construct the json to put the user's location QString locationPutJson = QString() + "{\"address\":{\"position\":\"" + positionString + "\", \"orientation\":\"" + orientationString + "\"}}"; @@ -1188,11 +1190,13 @@ void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { NodeList::getInstance()->getDomainInfo().setHostname(domainHostnameString); + qDebug() << orientationItems[0] << orientationItems[1] << orientationItems[2]; + // orient the user to face the target glm::quat newOrientation = glm::quat(glm::vec3(orientationItems[0].toFloat(), orientationItems[1].toFloat(), orientationItems[2].toFloat())) - * glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); + * glm::angleAxis(180.0f, glm::vec3(0.0f, 1.0f, 0.0f)); setOrientation(newOrientation); // move the user a couple units away From 1d944ac829d647f1cf6e189f6204568b49411a25 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 18 Mar 2014 12:02:12 -0700 Subject: [PATCH 48/59] reset orientation to identity with spacebar, fix orientation storing --- interface/src/avatar/MyAvatar.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 5c94a7db9d..92039fb04a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -85,6 +85,7 @@ void MyAvatar::reset() { setVelocity(glm::vec3(0,0,0)); setThrust(glm::vec3(0,0,0)); + setOrientation(glm::quat(glm::vec3(0,0,0))); } void MyAvatar::setMoveTarget(const glm::vec3 moveTarget) { @@ -1156,7 +1157,7 @@ void MyAvatar::updateLocationInDataServer() { if (accountManager.isLoggedIn()) { QString positionString(createByteArray(_position)); - QString orientationString(createByteArray(glm::degrees(safeEulerAngles(getOrientation())))); + QString orientationString(createByteArray(safeEulerAngles(getOrientation()))); qDebug() << orientationString; @@ -1196,7 +1197,7 @@ void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { glm::quat newOrientation = glm::quat(glm::vec3(orientationItems[0].toFloat(), orientationItems[1].toFloat(), orientationItems[2].toFloat())) - * glm::angleAxis(180.0f, glm::vec3(0.0f, 1.0f, 0.0f)); + * glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); setOrientation(newOrientation); // move the user a couple units away From 05e2bb80228477bf317aebd051fa494addd02622 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 18 Mar 2014 12:04:03 -0700 Subject: [PATCH 49/59] keep storing degrees in data-web but convert on receipt --- interface/src/avatar/MyAvatar.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 92039fb04a..4d0403aa77 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1157,7 +1157,7 @@ void MyAvatar::updateLocationInDataServer() { if (accountManager.isLoggedIn()) { QString positionString(createByteArray(_position)); - QString orientationString(createByteArray(safeEulerAngles(getOrientation()))); + QString orientationString(createByteArray(glm::degrees(safeEulerAngles(getOrientation())))); qDebug() << orientationString; @@ -1194,9 +1194,9 @@ void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { qDebug() << orientationItems[0] << orientationItems[1] << orientationItems[2]; // orient the user to face the target - glm::quat newOrientation = glm::quat(glm::vec3(orientationItems[0].toFloat(), - orientationItems[1].toFloat(), - orientationItems[2].toFloat())) + glm::quat newOrientation = glm::quat(glm::radians(glm::vec3(orientationItems[0].toFloat(), + orientationItems[1].toFloat(), + orientationItems[2].toFloat()))) * glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); setOrientation(newOrientation); From c7c51c75048a56380312987cae96c6517cc7ba8d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 18 Mar 2014 12:05:32 -0700 Subject: [PATCH 50/59] remove orientation string debug --- interface/src/avatar/MyAvatar.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 4d0403aa77..be27ab6ef2 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1159,8 +1159,6 @@ void MyAvatar::updateLocationInDataServer() { QString positionString(createByteArray(_position)); QString orientationString(createByteArray(glm::degrees(safeEulerAngles(getOrientation())))); - qDebug() << orientationString; - // construct the json to put the user's location QString locationPutJson = QString() + "{\"address\":{\"position\":\"" + positionString + "\", \"orientation\":\"" + orientationString + "\"}}"; From db25ae886538199a6071876ac3736cd90c08b163 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 18 Mar 2014 12:27:45 -0700 Subject: [PATCH 51/59] remove extra debug --- interface/src/avatar/MyAvatar.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index be27ab6ef2..18305e1641 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1189,8 +1189,6 @@ void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { NodeList::getInstance()->getDomainInfo().setHostname(domainHostnameString); - qDebug() << orientationItems[0] << orientationItems[1] << orientationItems[2]; - // orient the user to face the target glm::quat newOrientation = glm::quat(glm::radians(glm::vec3(orientationItems[0].toFloat(), orientationItems[1].toFloat(), From a2fea49f582f69f18e803a132dc63267e43c1818 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Mar 2014 12:36:48 -0700 Subject: [PATCH 52/59] bump version of PacketTypeAvatarData from 1 to 2 --- libraries/shared/src/PacketHeaders.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/PacketHeaders.cpp b/libraries/shared/src/PacketHeaders.cpp index eccfa4fefa..307453d8bf 100644 --- a/libraries/shared/src/PacketHeaders.cpp +++ b/libraries/shared/src/PacketHeaders.cpp @@ -45,7 +45,7 @@ int packArithmeticallyCodedValue(int value, char* destination) { PacketVersion versionForPacketType(PacketType type) { switch (type) { case PacketTypeAvatarData: - return 1; + return 2; case PacketTypeParticleData: return 1; case PacketTypeDomainList: From e7acd0bad3f5f8f9ac68540bb7a16caee7d9cef5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 18 Mar 2014 12:58:29 -0700 Subject: [PATCH 53/59] don't use QDataStream in parseData since we don't really need it --- libraries/audio/src/PositionalAudioRingBuffer.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index 11e1a7c2ae..775786027d 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -38,28 +38,27 @@ PositionalAudioRingBuffer::~PositionalAudioRingBuffer() { } int PositionalAudioRingBuffer::parseData(const QByteArray& packet) { - QDataStream packetStream(packet); // skip the packet header (includes the source UUID) - packetStream.skipRawData(numBytesForPacketHeader(packet)); + int readBytes = numBytesForPacketHeader(packet); - packetStream.skipRawData(parsePositionalData(packet.mid(packetStream.device()->pos()))); + readBytes += parsePositionalData(packet.mid(readBytes)); if (packetTypeForPacket(packet) == PacketTypeSilentAudioFrame) { // this source had no audio to send us, but this counts as a packet // write silence equivalent to the number of silent samples they just sent us int16_t numSilentSamples; - packetStream.readRawData(reinterpret_cast(&numSilentSamples), sizeof(int16_t)); + memcpy(&numSilentSamples, packet.data(), sizeof(int16_t)); + readBytes += sizeof(int16_t); + addSilentFrame(numSilentSamples); } else { // there is audio data to read - packetStream.skipRawData(writeData(packet.data() + packetStream.device()->pos(), - packet.size() - packetStream.device()->pos())); + readBytes += writeData(packet.data() + readBytes, packet.size() - readBytes); } - - return packetStream.device()->pos(); + return readBytes; } int PositionalAudioRingBuffer::parsePositionalData(const QByteArray& positionalByteArray) { From 9fbb4f14282a01c2d5ebccea839599a3fee29a9e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 18 Mar 2014 13:04:28 -0700 Subject: [PATCH 54/59] spacing fix and silent sample read fix --- libraries/audio/src/PositionalAudioRingBuffer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/audio/src/PositionalAudioRingBuffer.cpp b/libraries/audio/src/PositionalAudioRingBuffer.cpp index 775786027d..66a27647d6 100644 --- a/libraries/audio/src/PositionalAudioRingBuffer.cpp +++ b/libraries/audio/src/PositionalAudioRingBuffer.cpp @@ -48,9 +48,9 @@ int PositionalAudioRingBuffer::parseData(const QByteArray& packet) { // this source had no audio to send us, but this counts as a packet // write silence equivalent to the number of silent samples they just sent us int16_t numSilentSamples; - memcpy(&numSilentSamples, packet.data(), sizeof(int16_t)); - readBytes += sizeof(int16_t); + memcpy(&numSilentSamples, packet.data() + readBytes, sizeof(int16_t)); + readBytes += sizeof(int16_t); addSilentFrame(numSilentSamples); } else { From f80a077637664a1e97131cb7b1dfcd19c55fb715 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 18 Mar 2014 13:33:29 -0700 Subject: [PATCH 55/59] fix memory overrun from silent sample writing --- libraries/audio/src/AudioRingBuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/audio/src/AudioRingBuffer.cpp b/libraries/audio/src/AudioRingBuffer.cpp index 9cef64e216..0e92ab4eb5 100644 --- a/libraries/audio/src/AudioRingBuffer.cpp +++ b/libraries/audio/src/AudioRingBuffer.cpp @@ -164,7 +164,7 @@ void AudioRingBuffer::addSilentFrame(int numSilentSamples) { _endOfLastWrite += numSilentSamples; } else { int numSamplesToEnd = (_buffer + _sampleCapacity) - _endOfLastWrite; - memset(_endOfLastWrite, 0, numSilentSamples * sizeof(int16_t)); + memset(_endOfLastWrite, 0, numSamplesToEnd * sizeof(int16_t)); memset(_buffer, 0, (numSilentSamples - numSamplesToEnd) * sizeof(int16_t)); _endOfLastWrite = _buffer + (numSilentSamples - numSamplesToEnd); From 07497ea4f7e8a8faa51e06506f866698af47c893 Mon Sep 17 00:00:00 2001 From: Ryan Date: Tue, 18 Mar 2014 15:35:25 -0700 Subject: [PATCH 56/59] removing fly to voxel option --- interface/src/Menu.cpp | 2 +- interface/src/Menu.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ca059a53da..c23b312d3a 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -165,7 +165,7 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::Gravity, Qt::SHIFT | Qt::Key_G, false); - addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::ClickToFly); + addAvatarCollisionSubMenu(editMenu); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index df622be6ac..f99ebe0685 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -272,7 +272,6 @@ namespace MenuOption { const QString OffAxisProjection = "Off-Axis Projection"; const QString OldVoxelCullingMode = "Old Voxel Culling Mode"; const QString TurnWithHead = "Turn using Head"; - const QString ClickToFly = "Fly to voxel on click"; const QString LoadScript = "Open and Run Script..."; const QString Oscilloscope = "Audio Oscilloscope"; const QString Pair = "Pair"; From 281f2c6614763bfef02588ccb507112ed16887de Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 18 Mar 2014 17:04:27 -0700 Subject: [PATCH 57/59] return false in packetVersionAndHashMatch on version mismatch --- libraries/shared/src/NodeList.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 0354bd8bf9..1e7a8cfaf0 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -91,6 +91,8 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) { qDebug() << "Packet version mismatch on" << packetTypeForPacket(packet) << "- Sender" << uuidFromPacketHeader(packet) << "sent" << qPrintable(QString::number(packet[numPacketTypeBytes])) << "but" << qPrintable(QString::number(versionForPacketType(mismatchType))) << "expected."; + + return false; } const QSet NON_VERIFIED_PACKETS = QSet() From f86b793c96e06a5c6f3b9cec10a3f5e68913ac82 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 18 Mar 2014 17:14:57 -0700 Subject: [PATCH 58/59] only output version mismatch once per sender per packet --- libraries/shared/src/NodeList.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 1e7a8cfaf0..6d699322de 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -88,9 +88,16 @@ bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) { PacketType mismatchType = packetTypeForPacket(packet); int numPacketTypeBytes = numBytesArithmeticCodingFromBuffer(packet.data()); - qDebug() << "Packet version mismatch on" << packetTypeForPacket(packet) << "- Sender" + static QMultiMap versionDebugSuppressMap; + + QUuid senderUUID = uuidFromPacketHeader(packet); + if (!versionDebugSuppressMap.contains(senderUUID, checkType)) { + qDebug() << "Packet version mismatch on" << packetTypeForPacket(packet) << "- Sender" << uuidFromPacketHeader(packet) << "sent" << qPrintable(QString::number(packet[numPacketTypeBytes])) << "but" << qPrintable(QString::number(versionForPacketType(mismatchType))) << "expected."; + + versionDebugSuppressMap.insert(senderUUID, checkType); + } return false; } From 6340024daa906a4ecd8e3b0f760cec162332d4db Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 18 Mar 2014 17:42:58 -0700 Subject: [PATCH 59/59] fix bad startPosition in datagram unpack The startPosition was wrong (too far back) and the bytesRead return value was too big and the unpacking of the second chunk of the datagram would start in the middle of the chunk. --- libraries/avatars/src/AvatarData.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 8ed0ce51ec..e5e0e4b3d7 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -176,8 +176,8 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { _handData = new HandData(this); } - const unsigned char* startPosition = reinterpret_cast(packet.data()); - const unsigned char* sourceBuffer = startPosition + offset; + const unsigned char* startPosition = reinterpret_cast(packet.data()) + offset; + const unsigned char* sourceBuffer = startPosition; // Body world position memcpy(&_position, sourceBuffer, sizeof(float) * 3);