This commit is contained in:
Andrzej Kapolka 2014-03-26 12:27:34 -07:00
commit a9097658ad
17 changed files with 219 additions and 71 deletions

View file

@ -26,7 +26,8 @@
Agent::Agent(const QByteArray& packet) : Agent::Agent(const QByteArray& packet) :
ThreadedAssignment(packet), ThreadedAssignment(packet),
_voxelEditSender(), _voxelEditSender(),
_particleEditSender() _particleEditSender(),
_receivedAudioBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO)
{ {
// be the parent of the script engine so it gets moved when we do // be the parent of the script engine so it gets moved when we do
_scriptEngine.setParent(this); _scriptEngine.setParent(this);
@ -113,6 +114,16 @@ void Agent::readPendingDatagrams() {
_voxelViewer.processDatagram(mutablePacket, sourceNode); _voxelViewer.processDatagram(mutablePacket, sourceNode);
} }
} else if (datagramPacketType == PacketTypeMixedAudio) {
// parse the data and grab the average loudness
_receivedAudioBuffer.parseData(receivedPacket);
// pretend like we have read the samples from this buffer so it does not fill
static int16_t garbageAudioBuffer[NETWORK_BUFFER_LENGTH_SAMPLES_STEREO];
_receivedAudioBuffer.readSamples(garbageAudioBuffer, NETWORK_BUFFER_LENGTH_SAMPLES_STEREO);
// let this continue through to the NodeList so it updates last heard timestamp
// for the sending audio mixer
} else { } else {
NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket); NodeList::getInstance()->processNodeData(senderSockAddr, receivedPacket);
} }

View file

@ -15,6 +15,7 @@
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QUrl> #include <QtCore/QUrl>
#include <MixedAudioRingBuffer.h>
#include <ParticleEditPacketSender.h> #include <ParticleEditPacketSender.h>
#include <ParticleTree.h> #include <ParticleTree.h>
#include <ParticleTreeHeadlessViewer.h> #include <ParticleTreeHeadlessViewer.h>
@ -30,6 +31,7 @@ class Agent : public ThreadedAssignment {
Q_PROPERTY(bool isAvatar READ isAvatar WRITE setIsAvatar) Q_PROPERTY(bool isAvatar READ isAvatar WRITE setIsAvatar)
Q_PROPERTY(bool isPlayingAvatarSound READ isPlayingAvatarSound) Q_PROPERTY(bool isPlayingAvatarSound READ isPlayingAvatarSound)
Q_PROPERTY(bool isListeningToAudioStream READ isListeningToAudioStream WRITE setIsListeningToAudioStream) Q_PROPERTY(bool isListeningToAudioStream READ isListeningToAudioStream WRITE setIsListeningToAudioStream)
Q_PROPERTY(float lastReceivedAudioLoudness READ getLastReceivedAudioLoudness)
public: public:
Agent(const QByteArray& packet); Agent(const QByteArray& packet);
@ -41,6 +43,8 @@ public:
bool isListeningToAudioStream() const { return _scriptEngine.isListeningToAudioStream(); } bool isListeningToAudioStream() const { return _scriptEngine.isListeningToAudioStream(); }
void setIsListeningToAudioStream(bool isListeningToAudioStream) void setIsListeningToAudioStream(bool isListeningToAudioStream)
{ _scriptEngine.setIsListeningToAudioStream(isListeningToAudioStream); } { _scriptEngine.setIsListeningToAudioStream(isListeningToAudioStream); }
float getLastReceivedAudioLoudness() const { return _receivedAudioBuffer.getLastReadFrameAverageLoudness(); }
virtual void aboutToFinish(); virtual void aboutToFinish();
@ -56,6 +60,8 @@ private:
ParticleTreeHeadlessViewer _particleViewer; ParticleTreeHeadlessViewer _particleViewer;
VoxelTreeHeadlessViewer _voxelViewer; VoxelTreeHeadlessViewer _voxelViewer;
MixedAudioRingBuffer _receivedAudioBuffer;
}; };
#endif /* defined(__hifi__Agent__) */ #endif /* defined(__hifi__Agent__) */

View file

@ -93,7 +93,7 @@ void AudioMixer::addBufferToMixForListeningNodeWithBuffer(PositionalAudioRingBuf
distanceBetween = EPSILON; distanceBetween = EPSILON;
} }
if (bufferToAdd->getAverageLoudness() / distanceBetween <= _minAudibilityThreshold) { if (bufferToAdd->getNextOutputTrailingLoudness() / distanceBetween <= _minAudibilityThreshold) {
// according to mixer performance we have decided this does not get to be mixed in // according to mixer performance we have decided this does not get to be mixed in
// bail out // bail out
return; return;
@ -324,7 +324,7 @@ void AudioMixer::prepareMixForListeningNode(Node* node) {
if ((*otherNode != *node if ((*otherNode != *node
|| otherNodeBuffer->shouldLoopbackForNode()) || otherNodeBuffer->shouldLoopbackForNode())
&& otherNodeBuffer->willBeAddedToMix() && otherNodeBuffer->willBeAddedToMix()
&& otherNodeBuffer->getAverageLoudness() > 0) { && otherNodeBuffer->getNextOutputTrailingLoudness() > 0) {
addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer); addBufferToMixForListeningNodeWithBuffer(otherNodeBuffer, nodeRingBuffer);
} }
} }

View file

@ -92,7 +92,7 @@ void AudioMixerClientData::checkBuffersBeforeFrameSend(int jitterBufferLengthSam
// calculate the average loudness for the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL // calculate the average loudness for the next NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL
// that would be mixed in // that would be mixed in
_ringBuffers[i]->updateAverageLoudnessForBoundarySamples(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); _ringBuffers[i]->updateNextOutputTrailingLoudness();
} }
} }
} }

View file

@ -32,6 +32,7 @@ const unsigned int AVATAR_DATA_SEND_INTERVAL_MSECS = (1.0f / 60.0f) * 1000;
AvatarMixer::AvatarMixer(const QByteArray& packet) : AvatarMixer::AvatarMixer(const QByteArray& packet) :
ThreadedAssignment(packet), ThreadedAssignment(packet),
_broadcastThread(),
_lastFrameTimestamp(QDateTime::currentMSecsSinceEpoch()), _lastFrameTimestamp(QDateTime::currentMSecsSinceEpoch()),
_trailingSleepRatio(1.0f), _trailingSleepRatio(1.0f),
_performanceThrottlingRatio(0.0f), _performanceThrottlingRatio(0.0f),
@ -44,6 +45,11 @@ AvatarMixer::AvatarMixer(const QByteArray& packet) :
connect(NodeList::getInstance(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled); connect(NodeList::getInstance(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled);
} }
AvatarMixer::~AvatarMixer() {
_broadcastThread.quit();
_broadcastThread.wait();
}
void attachAvatarDataToNode(Node* newNode) { void attachAvatarDataToNode(Node* newNode) {
if (!newNode->getLinkedData()) { if (!newNode->getLinkedData()) {
newNode->setLinkedData(new AvatarMixerClientData()); newNode->setLinkedData(new AvatarMixerClientData());
@ -309,18 +315,15 @@ void AvatarMixer::run() {
nodeList->linkedDataCreateCallback = attachAvatarDataToNode; nodeList->linkedDataCreateCallback = attachAvatarDataToNode;
// create a thead for broadcast of avatar data
QThread* broadcastThread = new QThread(this);
// setup the timer that will be fired on the broadcast thread // setup the timer that will be fired on the broadcast thread
QTimer* broadcastTimer = new QTimer(); QTimer* broadcastTimer = new QTimer();
broadcastTimer->setInterval(AVATAR_DATA_SEND_INTERVAL_MSECS); broadcastTimer->setInterval(AVATAR_DATA_SEND_INTERVAL_MSECS);
broadcastTimer->moveToThread(broadcastThread); broadcastTimer->moveToThread(&_broadcastThread);
// connect appropriate signals and slots // connect appropriate signals and slots
connect(broadcastTimer, &QTimer::timeout, this, &AvatarMixer::broadcastAvatarData, Qt::DirectConnection); connect(broadcastTimer, &QTimer::timeout, this, &AvatarMixer::broadcastAvatarData, Qt::DirectConnection);
connect(broadcastThread, SIGNAL(started()), broadcastTimer, SLOT(start())); connect(&_broadcastThread, SIGNAL(started()), broadcastTimer, SLOT(start()));
// start the broadcastThread // start the broadcastThread
broadcastThread->start(); _broadcastThread.start();
} }

View file

@ -15,7 +15,7 @@
class AvatarMixer : public ThreadedAssignment { class AvatarMixer : public ThreadedAssignment {
public: public:
AvatarMixer(const QByteArray& packet); AvatarMixer(const QByteArray& packet);
~AvatarMixer();
public slots: public slots:
/// runs the avatar mixer /// runs the avatar mixer
void run(); void run();
@ -30,6 +30,8 @@ public slots:
private: private:
void broadcastAvatarData(); void broadcastAvatarData();
QThread _broadcastThread;
quint64 _lastFrameTimestamp; quint64 _lastFrameTimestamp;
float _trailingSleepRatio; float _trailingSleepRatio;

View file

@ -1,5 +1,9 @@
<!--#include file="header.html"--> <!--#include file="header.html"-->
<div id="nodes-lead" class="table-lead"><h3>Nodes</h3><div class="lead-line"></div></div> <div id="nodes-lead" class="table-lead"><h3>Nodes</h3><div class="lead-line"></div></div>
<div style="clear:both;"></div>
<button type="button" class="btn btn-danger" id="kill-all-btn">
<span class="glyphicon glyphicon-fire"></span> Kill all Nodes
</button>
<table id="nodes-table" class="table table-striped"> <table id="nodes-table" class="table table-striped">
<thead> <thead>
<tr> <tr>

View file

@ -49,4 +49,18 @@ $(document).ready(function(){
} }
}); });
}); });
$(document.body).on('click', '#kill-all-btn', function() {
var confirmed_kill = confirm("Are you sure?");
if (confirmed_kill == true) {
$.ajax({
url: "/nodes/",
type: 'DELETE',
success: function(result) {
console.log("Successful request to delete all nodes.");
}
});
}
});
}); });

View file

@ -657,6 +657,8 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
const QString URI_ASSIGNMENT = "/assignment"; const QString URI_ASSIGNMENT = "/assignment";
const QString URI_NODES = "/nodes"; const QString URI_NODES = "/nodes";
const QString UUID_REGEX_STRING = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
if (connection->requestOperation() == QNetworkAccessManager::GetOperation) { if (connection->requestOperation() == QNetworkAccessManager::GetOperation) {
if (url.path() == "/assignments.json") { if (url.path() == "/assignments.json") {
// user is asking for json list of assignments // user is asking for json list of assignments
@ -726,9 +728,8 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
return true; return true;
} else { } else {
const QString NODE_REGEX_STRING = const QString NODE_JSON_REGEX_STRING = QString("\\%1\\/(%2).json\\/?$").arg(URI_NODES).arg(UUID_REGEX_STRING);
QString("\\%1\\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}).json\\/?$").arg(URI_NODES); QRegExp nodeShowRegex(NODE_JSON_REGEX_STRING);
QRegExp nodeShowRegex(NODE_REGEX_STRING);
if (nodeShowRegex.indexIn(url.path()) != -1) { if (nodeShowRegex.indexIn(url.path()) != -1) {
QUuid matchingUUID = QUuid(nodeShowRegex.cap(1)); QUuid matchingUUID = QUuid(nodeShowRegex.cap(1));
@ -801,29 +802,35 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
return true; return true;
} }
} else if (connection->requestOperation() == QNetworkAccessManager::DeleteOperation) { } else if (connection->requestOperation() == QNetworkAccessManager::DeleteOperation) {
if (url.path().startsWith(URI_NODES)) { const QString ALL_NODE_DELETE_REGEX_STRING = QString("\\%1\\/?$").arg(URI_NODES);
// this is a request to DELETE a node by UUID const QString NODE_DELETE_REGEX_STRING = QString("\\%1\\/(%2)\\/$").arg(URI_NODES).arg(UUID_REGEX_STRING);
QRegExp allNodesDeleteRegex(ALL_NODE_DELETE_REGEX_STRING);
QRegExp nodeDeleteRegex(NODE_DELETE_REGEX_STRING);
if (nodeDeleteRegex.indexIn(url.path()) != -1) {
// this is a request to DELETE one node by UUID
// pull the UUID from the url // pull the captured string, if it exists
QUuid deleteUUID = QUuid(url.path().mid(URI_NODES.size() + sizeof('/'))); QUuid deleteUUID = QUuid(nodeDeleteRegex.cap(1));
if (!deleteUUID.isNull()) { SharedNodePointer nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID);
SharedNodePointer nodeToKill = NodeList::getInstance()->nodeWithUUID(deleteUUID);
if (nodeToKill) {
// start with a 200 response
connection->respond(HTTPConnection::StatusCode200);
if (nodeToKill) { // we have a valid UUID and node - kill the node that has this assignment
// start with a 200 response QMetaObject::invokeMethod(NodeList::getInstance(), "killNodeWithUUID", Q_ARG(const QUuid&, deleteUUID));
connection->respond(HTTPConnection::StatusCode200);
// successfully processed request
// we have a valid UUID and node - kill the node that has this assignment return true;
QMetaObject::invokeMethod(NodeList::getInstance(), "killNodeWithUUID", Q_ARG(const QUuid&, deleteUUID));
// successfully processed request
return true;
}
} }
// bad request, couldn't pull a node ID return true;
connection->respond(HTTPConnection::StatusCode400); } else if (allNodesDeleteRegex.indexIn(url.path()) != -1) {
qDebug() << "Received request to kill all nodes.";
NodeList::getInstance()->eraseAllNodes();
return true; return true;
} }

View file

@ -18,9 +18,9 @@
AudioRingBuffer::AudioRingBuffer(int numFrameSamples) : AudioRingBuffer::AudioRingBuffer(int numFrameSamples) :
NodeData(), NodeData(),
_sampleCapacity(numFrameSamples * RING_BUFFER_LENGTH_FRAMES), _sampleCapacity(numFrameSamples * RING_BUFFER_LENGTH_FRAMES),
_numFrameSamples(numFrameSamples),
_isStarved(true), _isStarved(true),
_hasStarted(false), _hasStarted(false)
_averageLoudness(0)
{ {
if (numFrameSamples) { if (numFrameSamples) {
_buffer = new int16_t[_sampleCapacity]; _buffer = new int16_t[_sampleCapacity];
@ -56,33 +56,6 @@ int AudioRingBuffer::parseData(const QByteArray& packet) {
return writeData(packet.data() + numBytesPacketHeader, packet.size() - numBytesPacketHeader); return writeData(packet.data() + numBytesPacketHeader, packet.size() - numBytesPacketHeader);
} }
void AudioRingBuffer::updateAverageLoudnessForBoundarySamples(int numSamples) {
// ForBoundarySamples means that we expect the number of samples not to roll of the end of the ring buffer
float nextLoudness = 0;
for (int i = 0; i < numSamples; ++i) {
nextLoudness += fabsf(_nextOutput[i]);
}
nextLoudness /= numSamples;
nextLoudness /= MAX_SAMPLE_VALUE;
const int TRAILING_AVERAGE_FRAMES = 100;
const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES;
const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO;
const float LOUDNESS_EPSILON = 0.01f;
if (nextLoudness >= _averageLoudness) {
_averageLoudness = nextLoudness;
} else {
_averageLoudness = (_averageLoudness * PREVIOUS_FRAMES_RATIO) + (CURRENT_FRAME_RATIO * nextLoudness);
if (_averageLoudness < LOUDNESS_EPSILON) {
_averageLoudness = 0;
}
}
}
qint64 AudioRingBuffer::readSamples(int16_t* destination, qint64 maxSamples) { qint64 AudioRingBuffer::readSamples(int16_t* destination, qint64 maxSamples) {
return readData((char*) destination, maxSamples * sizeof(int16_t)); return readData((char*) destination, maxSamples * sizeof(int16_t));
} }
@ -112,7 +85,7 @@ qint64 AudioRingBuffer::readData(char *data, qint64 maxSize) {
return numReadSamples * sizeof(int16_t); return numReadSamples * sizeof(int16_t);
} }
qint64 AudioRingBuffer::writeSamples(const int16_t* source, qint64 maxSamples) { qint64 AudioRingBuffer::writeSamples(const int16_t* source, qint64 maxSamples) {
return writeData((const char*) source, maxSamples * sizeof(int16_t)); return writeData((const char*) source, maxSamples * sizeof(int16_t));
} }

View file

@ -49,9 +49,6 @@ public:
// assume callers using this will never wrap around the end // assume callers using this will never wrap around the end
const int16_t* getNextOutput() { return _nextOutput; } const int16_t* getNextOutput() { return _nextOutput; }
const int16_t* getBuffer() { return _buffer; } const int16_t* getBuffer() { return _buffer; }
void updateAverageLoudnessForBoundarySamples(int numSamples);
float getAverageLoudness() const { return _averageLoudness; }
qint64 readSamples(int16_t* destination, qint64 maxSamples); qint64 readSamples(int16_t* destination, qint64 maxSamples);
qint64 writeSamples(const int16_t* source, qint64 maxSamples); qint64 writeSamples(const int16_t* source, qint64 maxSamples);
@ -81,13 +78,12 @@ protected:
int16_t* shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const; int16_t* shiftedPositionAccomodatingWrap(int16_t* position, int numSamplesShift) const;
int _sampleCapacity; int _sampleCapacity;
int _numFrameSamples;
int16_t* _nextOutput; int16_t* _nextOutput;
int16_t* _endOfLastWrite; int16_t* _endOfLastWrite;
int16_t* _buffer; int16_t* _buffer;
bool _isStarved; bool _isStarved;
bool _hasStarted; bool _hasStarted;
float _averageLoudness;
}; };
#endif /* defined(__interface__AudioRingBuffer__) */ #endif /* defined(__interface__AudioRingBuffer__) */

View file

@ -0,0 +1,49 @@
//
// MixedAudioRingBuffer.cpp
// hifi
//
// Created by Stephen Birarda on 2014-03-26.
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
//
#include "MixedAudioRingBuffer.h"
MixedAudioRingBuffer::MixedAudioRingBuffer(int numFrameSamples) :
AudioRingBuffer(numFrameSamples),
_lastReadFrameAverageLoudness(0.0f)
{
}
qint64 MixedAudioRingBuffer::readSamples(int16_t* destination, qint64 maxSamples) {
// calculate the average loudness for the frame about to go out
// read from _nextOutput either _numFrameSamples or to the end of the buffer
int samplesFromNextOutput = _buffer + _sampleCapacity - _nextOutput;
if (samplesFromNextOutput > _numFrameSamples) {
samplesFromNextOutput = _numFrameSamples;
}
float averageLoudness = 0.0f;
for (int s = 0; s < samplesFromNextOutput; s++) {
averageLoudness += fabsf(_nextOutput[s]);
}
// read samples from the beginning of the buffer, if any
int samplesFromBeginning = _numFrameSamples - samplesFromNextOutput;
if (samplesFromBeginning > 0) {
for (int b = 0; b < samplesFromBeginning; b++) {
averageLoudness += fabsf(_buffer[b]);
}
}
// divide by the number of samples and the MAX_SAMPLE_VALUE to get a float from 0 - 1
averageLoudness /= (float) _numFrameSamples;
averageLoudness /= (float) MAX_SAMPLE_VALUE;
_lastReadFrameAverageLoudness = averageLoudness;
return AudioRingBuffer::readSamples(destination, maxSamples);
}

View file

@ -0,0 +1,26 @@
//
// MixedAudioRingBuffer.h
// hifi
//
// Created by Stephen Birarda on 2014-03-26.
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
//
#ifndef __hifi__MixedAudioRingBuffer__
#define __hifi__MixedAudioRingBuffer__
#include "AudioRingBuffer.h"
class MixedAudioRingBuffer : public AudioRingBuffer {
Q_OBJECT
public:
MixedAudioRingBuffer(int numFrameSamples);
float getLastReadFrameAverageLoudness() const { return _lastReadFrameAverageLoudness; }
qint64 readSamples(int16_t* destination, qint64 maxSamples);
private:
float _lastReadFrameAverageLoudness;
};
#endif /* defined(__hifi__MixedAudioRingBuffer__) */

View file

@ -72,6 +72,33 @@ int PositionalAudioRingBuffer::parsePositionalData(const QByteArray& positionalB
return packetStream.device()->pos(); return packetStream.device()->pos();
} }
void PositionalAudioRingBuffer::updateNextOutputTrailingLoudness() {
// ForBoundarySamples means that we expect the number of samples not to roll of the end of the ring buffer
float nextLoudness = 0;
for (int i = 0; i < _numFrameSamples; ++i) {
nextLoudness += fabsf(_nextOutput[i]);
}
nextLoudness /= _numFrameSamples;
nextLoudness /= MAX_SAMPLE_VALUE;
const int TRAILING_AVERAGE_FRAMES = 100;
const float CURRENT_FRAME_RATIO = 1.0f / TRAILING_AVERAGE_FRAMES;
const float PREVIOUS_FRAMES_RATIO = 1.0f - CURRENT_FRAME_RATIO;
const float LOUDNESS_EPSILON = 0.01f;
if (nextLoudness >= _nextOutputTrailingLoudness) {
_nextOutputTrailingLoudness = nextLoudness;
} else {
_nextOutputTrailingLoudness = (_nextOutputTrailingLoudness * PREVIOUS_FRAMES_RATIO) + (CURRENT_FRAME_RATIO * nextLoudness);
if (_nextOutputTrailingLoudness < LOUDNESS_EPSILON) {
_nextOutputTrailingLoudness = 0;
}
}
}
bool PositionalAudioRingBuffer::shouldBeAddedToMix(int numJitterBufferSamples) { bool PositionalAudioRingBuffer::shouldBeAddedToMix(int numJitterBufferSamples) {
if (!isNotStarvedOrHasMinimumSamples(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL + numJitterBufferSamples)) { if (!isNotStarvedOrHasMinimumSamples(NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL + numJitterBufferSamples)) {
if (_shouldOutputStarveDebug) { if (_shouldOutputStarveDebug) {

View file

@ -28,6 +28,9 @@ public:
int parsePositionalData(const QByteArray& positionalByteArray); int parsePositionalData(const QByteArray& positionalByteArray);
int parseListenModeData(const QByteArray& listenModeByteArray); int parseListenModeData(const QByteArray& listenModeByteArray);
void updateNextOutputTrailingLoudness();
float getNextOutputTrailingLoudness() const { return _nextOutputTrailingLoudness; }
bool shouldBeAddedToMix(int numJitterBufferSamples); bool shouldBeAddedToMix(int numJitterBufferSamples);
bool willBeAddedToMix() const { return _willBeAddedToMix; } bool willBeAddedToMix() const { return _willBeAddedToMix; }
@ -50,6 +53,8 @@ protected:
bool _willBeAddedToMix; bool _willBeAddedToMix;
bool _shouldLoopbackForNode; bool _shouldLoopbackForNode;
bool _shouldOutputStarveDebug; bool _shouldOutputStarveDebug;
float _nextOutputTrailingLoudness;
}; };
#endif /* defined(__hifi__PositionalAudioRingBuffer__) */ #endif /* defined(__hifi__PositionalAudioRingBuffer__) */

View file

@ -83,9 +83,33 @@ NodeList::NodeList(char newOwnerType, unsigned short int newSocketListenPort) :
// clear our NodeList when logout is requested // clear our NodeList when logout is requested
connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset); connect(&AccountManager::getInstance(), &AccountManager::logoutComplete , this, &NodeList::reset);
const int LARGER_SNDBUF_SIZE = 1048576;
changeSendSocketBufferSize(LARGER_SNDBUF_SIZE);
_packetStatTimer.start(); _packetStatTimer.start();
} }
void NodeList::changeSendSocketBufferSize(int numSendBytes) {
// change the socket send buffer size to be 1MB
int oldBufferSize = 0;
#ifdef Q_OS_WIN
int sizeOfInt = sizeof(oldBufferSize);
#else
unsigned int sizeOfInt = sizeof(oldBufferSize);
#endif
getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char*>(&oldBufferSize), &sizeOfInt);
setsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, reinterpret_cast<const char*>(&numSendBytes),
sizeof(numSendBytes));
int newBufferSize = 0;
getsockopt(_nodeSocket.socketDescriptor(), SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char*>(&newBufferSize), &sizeOfInt);
qDebug() << "Changed socket send buffer size from" << oldBufferSize << "to" << newBufferSize << "bytes";
}
bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) { bool NodeList::packetVersionAndHashMatch(const QByteArray& packet) {
PacketType checkType = packetTypeForPacket(packet); PacketType checkType = packetTypeForPacket(packet);
if (packet[1] != versionForPacketType(checkType) if (packet[1] != versionForPacketType(checkType)
@ -359,7 +383,7 @@ NodeHash NodeList::getNodeHash() {
return NodeHash(_nodeHash); return NodeHash(_nodeHash);
} }
void NodeList::clear() { void NodeList::eraseAllNodes() {
qDebug() << "Clearing the NodeList. Deleting all nodes in list."; qDebug() << "Clearing the NodeList. Deleting all nodes in list.";
QMutexLocker locker(&_nodeHashMutex); QMutexLocker locker(&_nodeHashMutex);
@ -373,7 +397,7 @@ void NodeList::clear() {
} }
void NodeList::reset() { void NodeList::reset() {
clear(); eraseAllNodes();
_numNoReplyDomainCheckIns = 0; _numNoReplyDomainCheckIns = 0;
// refresh the owner UUID to the NULL UUID // refresh the owner UUID to the NULL UUID

View file

@ -128,6 +128,7 @@ public:
void saveData(QSettings* settings); void saveData(QSettings* settings);
public slots: public slots:
void reset(); void reset();
void eraseAllNodes();
void sendDomainServerCheckIn(); void sendDomainServerCheckIn();
void pingInactiveNodes(); void pingInactiveNodes();
@ -154,13 +155,13 @@ private:
const QUuid& connectionSecret); const QUuid& connectionSecret);
NodeHash::iterator killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill); NodeHash::iterator killNodeAtHashIterator(NodeHash::iterator& nodeItemToKill);
void clear();
void processDomainServerAuthRequest(const QByteArray& packet); void processDomainServerAuthRequest(const QByteArray& packet);
void requestAuthForDomainServer(); void requestAuthForDomainServer();
void activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode); void activateSocketFromNodeCommunication(const QByteArray& packet, const SharedNodePointer& sendingNode);
void timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode); void timePingReply(const QByteArray& packet, const SharedNodePointer& sendingNode);
void changeSendSocketBufferSize(int numSendBytes);
NodeHash _nodeHash; NodeHash _nodeHash;
QMutex _nodeHashMutex; QMutex _nodeHashMutex;