Merge branch 'master' of https://github.com/highfidelity/hifi into audio-rolloff

This commit is contained in:
Stephen Birarda 2014-07-03 13:37:06 -07:00
commit c0d0ca5066
20 changed files with 81 additions and 41 deletions

View file

@ -104,6 +104,8 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
// connections to AccountManager for authentication // connections to AccountManager for authentication
connect(&AccountManager::getInstance(), &AccountManager::authRequired, connect(&AccountManager::getInstance(), &AccountManager::authRequired,
this, &AssignmentClient::handleAuthenticationRequest); this, &AssignmentClient::handleAuthenticationRequest);
NetworkAccessManager::getInstance();
} }
void AssignmentClient::sendAssignmentRequest() { void AssignmentClient::sendAssignmentRequest() {

View file

@ -101,8 +101,7 @@ int AudioMixerClientData::parseData(const QByteArray& packet) {
if (!matchingInjectedRingBuffer) { if (!matchingInjectedRingBuffer) {
// we don't have a matching injected audio ring buffer, so add it // we don't have a matching injected audio ring buffer, so add it
matchingInjectedRingBuffer = new InjectedAudioRingBuffer(streamIdentifier, matchingInjectedRingBuffer = new InjectedAudioRingBuffer(streamIdentifier, AudioMixer::getUseDynamicJitterBuffers());
AudioMixer::getUseDynamicJitterBuffers());
_ringBuffers.push_back(matchingInjectedRingBuffer); _ringBuffers.push_back(matchingInjectedRingBuffer);
} }

View file

@ -216,9 +216,13 @@ int OctreeInboundPacketProcessor::sendNackPackets() {
} }
const SharedNodePointer& destinationNode = NodeList::getInstance()->getNodeHash().value(nodeUUID); const SharedNodePointer& destinationNode = NodeList::getInstance()->getNodeHash().value(nodeUUID);
const QSet<unsigned short int>& missingSequenceNumbers = nodeStats.getIncomingEditSequenceNumberStats().getMissingSet();
// retrieve sequence number stats of node, prune its missing set
SequenceNumberStats& sequenceNumberStats = nodeStats.getIncomingEditSequenceNumberStats();
sequenceNumberStats.pruneMissingSet();
// construct nack packet(s) for this node // construct nack packet(s) for this node
const QSet<unsigned short int>& missingSequenceNumbers = sequenceNumberStats.getMissingSet();
int numSequenceNumbersAvailable = missingSequenceNumbers.size(); int numSequenceNumbersAvailable = missingSequenceNumbers.size();
QSet<unsigned short int>::const_iterator missingSequenceNumberIterator = missingSequenceNumbers.constBegin(); QSet<unsigned short int>::const_iterator missingSequenceNumberIterator = missingSequenceNumbers.constBegin();
while (numSequenceNumbersAvailable > 0) { while (numSequenceNumbersAvailable > 0) {

View file

@ -35,6 +35,7 @@ public:
{ return _totalElementsInPacket == 0 ? 0 : _totalLockWaitTime / _totalElementsInPacket; } { return _totalElementsInPacket == 0 ? 0 : _totalLockWaitTime / _totalElementsInPacket; }
const SequenceNumberStats& getIncomingEditSequenceNumberStats() const { return _incomingEditSequenceNumberStats; } const SequenceNumberStats& getIncomingEditSequenceNumberStats() const { return _incomingEditSequenceNumberStats; }
SequenceNumberStats& getIncomingEditSequenceNumberStats() { return _incomingEditSequenceNumberStats; }
void trackInboundPacket(unsigned short int incomingSequence, quint64 transitTime, void trackInboundPacket(unsigned short int incomingSequence, quint64 transitTime,
int editsInPacket, quint64 processTime, quint64 lockWaitTime); int editsInPacket, quint64 processTime, quint64 lockWaitTime);

View file

@ -42,7 +42,7 @@ OctreeQueryNode::OctreeQueryNode() :
_lastRootTimestamp(0), _lastRootTimestamp(0),
_myPacketType(PacketTypeUnknown), _myPacketType(PacketTypeUnknown),
_isShuttingDown(false), _isShuttingDown(false),
_sentPacketHistory(1000) _sentPacketHistory()
{ {
} }

View file

@ -36,9 +36,12 @@ DomainServerSettingsManager::DomainServerSettingsManager() :
// load the existing config file to get the current values // load the existing config file to get the current values
QFile configFile(QCoreApplication::applicationDirPath() + SETTINGS_CONFIG_FILE_RELATIVE_PATH); QFile configFile(QCoreApplication::applicationDirPath() + SETTINGS_CONFIG_FILE_RELATIVE_PATH);
configFile.open(QIODevice::ReadOnly);
_settingsMap = QJsonDocument::fromJson(configFile.readAll()).toVariant().toMap(); if (configFile.exists()) {
configFile.open(QIODevice::ReadOnly);
_settingsMap = QJsonDocument::fromJson(configFile.readAll()).toVariant().toMap();
}
} }
const QString DESCRIPTION_SETTINGS_KEY = "settings"; const QString DESCRIPTION_SETTINGS_KEY = "settings";

View file

@ -2184,11 +2184,11 @@ int Application::sendNackPackets() {
_octreeSceneStatsLock.unlock(); _octreeSceneStatsLock.unlock();
continue; continue;
} }
OctreeSceneStats& stats = _octreeServerSceneStats[nodeUUID];
// make copy of missing sequence numbers from stats // get sequence number stats of node, prune its missing set, and make a copy of the missing set
const QSet<OCTREE_PACKET_SEQUENCE> missingSequenceNumbers = SequenceNumberStats& sequenceNumberStats = _octreeServerSceneStats[nodeUUID].getIncomingOctreeSequenceNumberStats();
stats.getIncomingOctreeSequenceNumberStats().getMissingSet(); sequenceNumberStats.pruneMissingSet();
const QSet<OCTREE_PACKET_SEQUENCE> missingSequenceNumbers = sequenceNumberStats.getMissingSet();
_octreeSceneStatsLock.unlock(); _octreeSceneStatsLock.unlock();

View file

@ -67,7 +67,7 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) :
_proceduralAudioOutput(NULL), _proceduralAudioOutput(NULL),
_proceduralOutputDevice(NULL), _proceduralOutputDevice(NULL),
_inputRingBuffer(0), _inputRingBuffer(0),
_ringBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL), _ringBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO),
_isStereoInput(false), _isStereoInput(false),
_averagedLatency(0.0), _averagedLatency(0.0),
_measuredJitter(0), _measuredJitter(0),
@ -93,7 +93,7 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) :
_processSpatialAudio(false), _processSpatialAudio(false),
_spatialAudioStart(0), _spatialAudioStart(0),
_spatialAudioFinish(0), _spatialAudioFinish(0),
_spatialAudioRingBuffer(NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL, true), // random access mode _spatialAudioRingBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, true), // random access mode
_scopeEnabled(false), _scopeEnabled(false),
_scopeEnabledPause(false), _scopeEnabledPause(false),
_scopeInputOffset(0), _scopeInputOffset(0),

View file

@ -149,13 +149,19 @@ void DatagramProcessor::processDatagrams() {
break; break;
} }
case PacketTypeVoxelEditNack: case PacketTypeVoxelEditNack:
application->_voxelEditSender.processNackPacket(incomingPacket); if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
application->_voxelEditSender.processNackPacket(incomingPacket);
}
break; break;
case PacketTypeParticleEditNack: case PacketTypeParticleEditNack:
application->_particleEditSender.processNackPacket(incomingPacket); if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
application->_particleEditSender.processNackPacket(incomingPacket);
}
break; break;
case PacketTypeModelEditNack: case PacketTypeModelEditNack:
application->_modelEditSender.processNackPacket(incomingPacket); if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableNackPackets)) {
application->_modelEditSender.processNackPacket(incomingPacket);
}
break; break;
default: default:
nodeList->processNodeData(senderSockAddr, incomingPacket); nodeList->processNodeData(senderSockAddr, incomingPacket);

View file

@ -19,10 +19,11 @@
#include "AudioRingBuffer.h" #include "AudioRingBuffer.h"
AudioRingBuffer::AudioRingBuffer(int numFrameSamples, bool randomAccessMode) : AudioRingBuffer::AudioRingBuffer(int numFrameSamples, bool randomAccessMode, int numFramesCapacity) :
NodeData(), NodeData(),
_overflowCount(0), _overflowCount(0),
_sampleCapacity(numFrameSamples * RING_BUFFER_LENGTH_FRAMES), _frameCapacity(numFramesCapacity),
_sampleCapacity(numFrameSamples * numFramesCapacity),
_isFull(false), _isFull(false),
_numFrameSamples(numFrameSamples), _numFrameSamples(numFrameSamples),
_isStarved(true), _isStarved(true),
@ -48,6 +49,8 @@ AudioRingBuffer::~AudioRingBuffer() {
} }
void AudioRingBuffer::reset() { void AudioRingBuffer::reset() {
_overflowCount = 0;
_isFull = false;
_endOfLastWrite = _buffer; _endOfLastWrite = _buffer;
_nextOutput = _buffer; _nextOutput = _buffer;
_isStarved = true; _isStarved = true;
@ -55,13 +58,13 @@ void AudioRingBuffer::reset() {
void AudioRingBuffer::resizeForFrameSize(int numFrameSamples) { void AudioRingBuffer::resizeForFrameSize(int numFrameSamples) {
delete[] _buffer; delete[] _buffer;
_sampleCapacity = numFrameSamples * RING_BUFFER_LENGTH_FRAMES; _sampleCapacity = numFrameSamples * _frameCapacity;
_numFrameSamples = numFrameSamples;
_buffer = new int16_t[_sampleCapacity]; _buffer = new int16_t[_sampleCapacity];
if (_randomAccessMode) { if (_randomAccessMode) {
memset(_buffer, 0, _sampleCapacity * sizeof(int16_t)); memset(_buffer, 0, _sampleCapacity * sizeof(int16_t));
} }
_nextOutput = _buffer; reset();
_endOfLastWrite = _buffer;
} }
int AudioRingBuffer::parseData(const QByteArray& packet) { int AudioRingBuffer::parseData(const QByteArray& packet) {

View file

@ -31,15 +31,15 @@ const int NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL = NETWORK_BUFFER_LENGTH_BYTE
const unsigned int BUFFER_SEND_INTERVAL_USECS = floorf((NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL const unsigned int BUFFER_SEND_INTERVAL_USECS = floorf((NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL
/ (float) SAMPLE_RATE) * 1000 * 1000); / (float) SAMPLE_RATE) * 1000 * 1000);
const short RING_BUFFER_LENGTH_FRAMES = 10;
const int MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max(); const int MAX_SAMPLE_VALUE = std::numeric_limits<int16_t>::max();
const int MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min(); const int MIN_SAMPLE_VALUE = std::numeric_limits<int16_t>::min();
const int DEFAULT_RING_BUFFER_FRAME_CAPACITY = 10;
class AudioRingBuffer : public NodeData { class AudioRingBuffer : public NodeData {
Q_OBJECT Q_OBJECT
public: public:
AudioRingBuffer(int numFrameSamples, bool randomAccessMode = false); AudioRingBuffer(int numFrameSamples, bool randomAccessMode = false, int numFramesCapacity = DEFAULT_RING_BUFFER_FRAME_CAPACITY);
~AudioRingBuffer(); ~AudioRingBuffer();
void reset(); void reset();
@ -84,6 +84,7 @@ protected:
int _overflowCount; /// how many times has the ring buffer has overwritten old data int _overflowCount; /// how many times has the ring buffer has overwritten old data
int _frameCapacity;
int _sampleCapacity; int _sampleCapacity;
bool _isFull; bool _isFull;
int _numFrameSamples; int _numFrameSamples;

View file

@ -20,7 +20,7 @@
#include "InjectedAudioRingBuffer.h" #include "InjectedAudioRingBuffer.h"
InjectedAudioRingBuffer::InjectedAudioRingBuffer(const QUuid& streamIdentifier, bool dynamicJitterBuffer) : InjectedAudioRingBuffer::InjectedAudioRingBuffer(const QUuid& streamIdentifier, bool dynamicJitterBuffer) :
PositionalAudioRingBuffer(PositionalAudioRingBuffer::Injector, /* isStereo=*/ false , dynamicJitterBuffer), PositionalAudioRingBuffer(PositionalAudioRingBuffer::Injector, false, dynamicJitterBuffer),
_streamIdentifier(streamIdentifier), _streamIdentifier(streamIdentifier),
_radius(0.0f), _radius(0.0f),
_attenuationRatio(0) _attenuationRatio(0)

View file

@ -85,10 +85,10 @@ quint64 InterframeTimeGapStats::getWindowMaxGap() {
} }
PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer::Type type, PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer::Type type, bool isStereo, bool dynamicJitterBuffers) :
bool isStereo, bool dynamicJitterBuffers) :
AudioRingBuffer(isStereo ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL), AudioRingBuffer(isStereo ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL,
false, AUDIOMIXER_INBOUND_RING_BUFFER_FRAME_CAPACITY),
_type(type), _type(type),
_position(0.0f, 0.0f, 0.0f), _position(0.0f, 0.0f, 0.0f),
_orientation(0.0f, 0.0f, 0.0f, 0.0f), _orientation(0.0f, 0.0f, 0.0f, 0.0f),
@ -98,7 +98,7 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer::
_isStereo(isStereo), _isStereo(isStereo),
_listenerUnattenuatedZone(NULL), _listenerUnattenuatedZone(NULL),
_desiredJitterBufferFrames(1), _desiredJitterBufferFrames(1),
_currentJitterBufferFrames(0), _currentJitterBufferFrames(-1),
_dynamicJitterBuffers(dynamicJitterBuffers) _dynamicJitterBuffers(dynamicJitterBuffers)
{ {
} }
@ -216,8 +216,8 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
// if the buffer doesn't have a full frame of samples to take for mixing, it is starved // if the buffer doesn't have a full frame of samples to take for mixing, it is starved
_isStarved = true; _isStarved = true;
// set to 0 to indicate the jitter buffer is starved // set to -1 to indicate the jitter buffer is starved
_currentJitterBufferFrames = 0; _currentJitterBufferFrames = -1;
// reset our _shouldOutputStarveDebug to true so the next is printed // reset our _shouldOutputStarveDebug to true so the next is printed
_shouldOutputStarveDebug = true; _shouldOutputStarveDebug = true;
@ -261,7 +261,7 @@ void PositionalAudioRingBuffer::updateDesiredJitterBufferFrames() {
if (_desiredJitterBufferFrames < 1) { if (_desiredJitterBufferFrames < 1) {
_desiredJitterBufferFrames = 1; _desiredJitterBufferFrames = 1;
} }
const int maxDesired = RING_BUFFER_LENGTH_FRAMES - 1; const int maxDesired = _frameCapacity - 1;
if (_desiredJitterBufferFrames > maxDesired) { if (_desiredJitterBufferFrames > maxDesired) {
_desiredJitterBufferFrames = maxDesired; _desiredJitterBufferFrames = maxDesired;
} }

View file

@ -43,6 +43,8 @@ private:
bool _newWindowMaxGapAvailable; bool _newWindowMaxGapAvailable;
}; };
const int AUDIOMIXER_INBOUND_RING_BUFFER_FRAME_CAPACITY = 100;
class PositionalAudioRingBuffer : public AudioRingBuffer { class PositionalAudioRingBuffer : public AudioRingBuffer {
public: public:
enum Type { enum Type {
@ -103,6 +105,11 @@ protected:
int _desiredJitterBufferFrames; int _desiredJitterBufferFrames;
int _currentJitterBufferFrames; int _currentJitterBufferFrames;
bool _dynamicJitterBuffers; bool _dynamicJitterBuffers;
// extra stats
int _starveCount;
int _silentFramesDropped;
}; };
#endif // hifi_PositionalAudioRingBuffer_h #endif // hifi_PositionalAudioRingBuffer_h

View file

@ -15,10 +15,12 @@
#include <qbytearray.h> #include <qbytearray.h>
#include <qvector.h> #include <qvector.h>
#include "SequenceNumberStats.h"
class SentPacketHistory { class SentPacketHistory {
public: public:
SentPacketHistory(int size = 1000); SentPacketHistory(int size = MAX_REASONABLE_SEQUENCE_GAP);
void packetSent(uint16_t sequenceNumber, const QByteArray& packet); void packetSent(uint16_t sequenceNumber, const QByteArray& packet);
const QByteArray* getPacket(uint16_t sequenceNumber) const; const QByteArray* getPacket(uint16_t sequenceNumber) const;

View file

@ -39,7 +39,6 @@ void SequenceNumberStats::reset() {
} }
static const int UINT16_RANGE = std::numeric_limits<uint16_t>::max() + 1; static const int UINT16_RANGE = std::numeric_limits<uint16_t>::max() + 1;
static const int MAX_REASONABLE_SEQUENCE_GAP = 1000; // this must be less than UINT16_RANGE / 2 for rollover handling to work
void SequenceNumberStats::sequenceNumberReceived(quint16 incoming, QUuid senderUUID, const bool wantExtraDebugging) { void SequenceNumberStats::sequenceNumberReceived(quint16 incoming, QUuid senderUUID, const bool wantExtraDebugging) {
@ -95,6 +94,7 @@ void SequenceNumberStats::sequenceNumberReceived(quint16 incoming, QUuid senderU
_numEarly++; _numEarly++;
_numLost += (incomingInt - expectedInt); _numLost += (incomingInt - expectedInt);
_lastReceived = incoming;
// add all sequence numbers that were skipped to the missing sequence numbers list // add all sequence numbers that were skipped to the missing sequence numbers list
for (int missingInt = expectedInt; missingInt < incomingInt; missingInt++) { for (int missingInt = expectedInt; missingInt < incomingInt; missingInt++) {
@ -106,14 +106,14 @@ void SequenceNumberStats::sequenceNumberReceived(quint16 incoming, QUuid senderU
if (_missingSet.size() > MAX_REASONABLE_SEQUENCE_GAP) { if (_missingSet.size() > MAX_REASONABLE_SEQUENCE_GAP) {
pruneMissingSet(wantExtraDebugging); pruneMissingSet(wantExtraDebugging);
} }
_lastReceived = incoming;
} else { // late } else { // late
if (wantExtraDebugging) { if (wantExtraDebugging) {
qDebug() << "this packet is later than expected..."; qDebug() << "this packet is later than expected...";
} }
_numLate++; _numLate++;
// do not update _lastReceived; it shouldn't become smaller
// remove this from missing sequence number if it's in there // remove this from missing sequence number if it's in there
if (_missingSet.remove(incoming)) { if (_missingSet.remove(incoming)) {
if (wantExtraDebugging) { if (wantExtraDebugging) {
@ -127,8 +127,6 @@ void SequenceNumberStats::sequenceNumberReceived(quint16 incoming, QUuid senderU
} }
_numDuplicate++; _numDuplicate++;
} }
// do not update _incomingLastSequence; it shouldn't become smaller
} }
} }
} }

View file

@ -15,13 +15,15 @@
#include "SharedUtil.h" #include "SharedUtil.h"
#include <quuid.h> #include <quuid.h>
const int MAX_REASONABLE_SEQUENCE_GAP = 1000;
class SequenceNumberStats { class SequenceNumberStats {
public: public:
SequenceNumberStats(); SequenceNumberStats();
void reset(); void reset();
void sequenceNumberReceived(quint16 incoming, QUuid senderUUID = QUuid(), const bool wantExtraDebugging = false); void sequenceNumberReceived(quint16 incoming, QUuid senderUUID = QUuid(), const bool wantExtraDebugging = false);
void pruneMissingSet(const bool wantExtraDebugging = false);
quint32 getNumReceived() const { return _numReceived; } quint32 getNumReceived() const { return _numReceived; }
quint32 getNumUnreasonable() const { return _numUnreasonable; } quint32 getNumUnreasonable() const { return _numUnreasonable; }
@ -34,8 +36,6 @@ public:
const QSet<quint16>& getMissingSet() const { return _missingSet; } const QSet<quint16>& getMissingSet() const { return _missingSet; }
private: private:
void pruneMissingSet(const bool wantExtraDebugging);
quint16 _lastReceived; quint16 _lastReceived;
QSet<quint16> _missingSet; QSet<quint16> _missingSet;

View file

@ -168,6 +168,7 @@ public:
float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); } float getIncomingFlightTimeAverage() { return _incomingFlightTimeAverage.getAverage(); }
const SequenceNumberStats& getIncomingOctreeSequenceNumberStats() const { return _incomingOctreeSequenceNumberStats; } const SequenceNumberStats& getIncomingOctreeSequenceNumberStats() const { return _incomingOctreeSequenceNumberStats; }
SequenceNumberStats& getIncomingOctreeSequenceNumberStats() { return _incomingOctreeSequenceNumberStats; }
private: private:

View file

@ -29,7 +29,7 @@ void AudioRingBufferTests::runAllTests() {
int readIndexAt; int readIndexAt;
AudioRingBuffer ringBuffer(10); // makes buffer of 100 int16_t samples AudioRingBuffer ringBuffer(10, false, 10); // makes buffer of 100 int16_t samples
for (int T = 0; T < 300; T++) { for (int T = 0; T < 300; T++) {
writeIndexAt = 0; writeIndexAt = 0;

View file

@ -115,6 +115,11 @@ void SequenceNumberStatsTests::earlyLateTest() {
} }
} }
stats.reset(); stats.reset();
numSent = 0;
numEarly = 0;
numLate = 0;
numLost = 0;
numRecovered = 0;
} }
} }
@ -203,6 +208,11 @@ void SequenceNumberStatsTests::duplicateTest() {
} }
} }
stats.reset(); stats.reset();
numSent = 0;
numDuplicate = 0;
numEarly = 0;
numLate = 0;
numLost = 0;
} }
} }
@ -263,5 +273,8 @@ void SequenceNumberStatsTests::pruneTest() {
} }
} }
stats.reset(); stats.reset();
numSent = 0;
numEarly = 0;
numLost = 0;
} }
} }