diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index d486ff6f50..99dcaa7eff 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -124,6 +124,11 @@ Audio::Audio(QObject* parent) : _audioOutputMsecsUnplayedStats(1, FRAMES_AVAILABLE_STATS_WINDOW_SECONDS), _lastSentAudioPacket(0), _outputBufferSizeFrames(DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES), + _outputStarveDetectionStartTimeMsec(0), + _outputStarveDetectionCount(0), + _outputStarveDetectionEnabled(true), + _outputStarveDetectionPeriodMsec(DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD), + _outputStarveDetectionThreshold(DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_THRESHOLD), _packetSentTimeGaps(1, APPROXIMATELY_30_SECONDS_OF_AUDIO_PACKETS), _audioOutputIODevice(_receivedAudioStream, this) { @@ -1830,8 +1835,24 @@ void Audio::outputNotify() { if (recentUnfulfilled > 0) { qDebug() << "WARNING --- WE HAD at least:" << recentUnfulfilled << "recently unfulfilled readData() calls"; - // TODO: Ryan Huffman -- add code here to increase the AUDIO_OUTPUT_BUFFER_SIZE_FRAMES... this code only - // runs in cases where the audio device requested data samples, and ran dry because we couldn't fulfill the request + if (_outputStarveDetectionEnabled) { + quint64 now = QDateTime::currentMSecsSinceEpoch(); + quint64 dt = now - _outputStarveDetectionStartTimeMsec; + if (dt > _outputStarveDetectionPeriodMsec) { + _outputStarveDetectionStartTimeMsec = now; + _outputStarveDetectionCount = 0; + } else { + _outputStarveDetectionCount += recentUnfulfilled; + if (_outputStarveDetectionCount > _outputStarveDetectionThreshold) { + int newOutputBufferSizeFrames = _outputBufferSizeFrames + 1; + qDebug() << "Starve detection threshold met, increasing buffer size to " << newOutputBufferSizeFrames; + setOutputBufferSize(newOutputBufferSizeFrames); + + _outputStarveDetectionStartTimeMsec = now; + _outputStarveDetectionCount = 0; + } + } + } } } diff --git a/interface/src/Audio.h b/interface/src/Audio.h index ff22d2d03f..8cb46c6328 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -63,7 +63,10 @@ static const int MAX_16_BIT_AUDIO_SAMPLE = 32767; static const int DEFAULT_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 3; static const int MIN_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 1; -static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 50; +static const int MAX_AUDIO_OUTPUT_BUFFER_SIZE_FRAMES = 20; +static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED = true; +static const int DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_THRESHOLD = 3; +static const quint64 DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD = 10 * 1000; // 10 Seconds class QAudioInput; class QAudioOutput; @@ -134,6 +137,15 @@ public: int getOutputBufferSize() { return _outputBufferSizeFrames; } + bool getOutputStarveDetectionEnabled() { return _outputStarveDetectionEnabled; } + void setOutputStarveDetectionEnabled(bool enabled) { _outputStarveDetectionEnabled = enabled; } + + int getOutputStarveDetectionPeriod() { return _outputStarveDetectionPeriodMsec; } + void setOutputStarveDetectionPeriod(int msecs) { _outputStarveDetectionPeriodMsec = msecs; } + + int getOutputStarveDetectionThreshold() { return _outputStarveDetectionThreshold; } + void setOutputStarveDetectionThreshold(int threshold) { _outputStarveDetectionThreshold = threshold; } + public slots: void start(); void stop(); @@ -161,6 +173,7 @@ public slots: void addLastFrameRepeatedWithFadeToScope(int samplesPerChannel); void addStereoSamplesToScope(const QByteArray& samples); void processReceivedSamples(const QByteArray& inputBuffer, QByteArray& outputBuffer); + void setOutputBufferSize(int numFrames); virtual bool outputLocalInjector(bool isStereo, qreal volume, AudioInjector* injector); @@ -219,6 +232,12 @@ private: QString _outputAudioDeviceName; int _outputBufferSizeFrames; + bool _outputStarveDetectionEnabled; + quint64 _outputStarveDetectionStartTimeMsec; + int _outputStarveDetectionCount; + int _outputStarveDetectionPeriodMsec; + int _outputStarveDetectionThreshold; // Maximum number of starves per _outputStarveDetectionPeriod before increasing buffer size + StDev _stdev; QElapsedTimer _timeSinceLastReceived;