Skip to content

Commit d61f812

Browse files
committed
SoundDeviceNetwork: Be more relaxed in case of one delayed callback. This allows to catch up without immediately replacing the delayed frames with silence. The worker has a longer latency and enough buffer to compensate that.
1 parent a2bd38e commit d61f812

1 file changed

Lines changed: 49 additions & 50 deletions

File tree

src/soundio/sounddevicenetwork.cpp

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -300,69 +300,68 @@ void SoundDeviceNetwork::workerWriteProcess(NetworkOutputStreamWorkerPtr pWorker
300300
int writeExpected = writeExpectedFrames * m_numOutputChannels;
301301

302302
if (writeExpected <= 0) {
303-
// Overflow
304-
// kLogger.debug() << "workerWriteProcess: buffer full"
303+
// Overflow: We more than one buffer ahead. That happens if the engine tries to catch up
304+
// already earlier misses already filled with silence
305+
// kLogger.debug() << "workerWriteProcess: ahead of time"
305306
// << "outChunkSize" << outChunkSize
306307
// << "readAvailable" << readAvailable
307308
// << "writeExpected" << writeExpected
308309
// << "streamTime" << pWorker->getStreamTimeFrames();
309310
// catch up by skipping chunk
310311
m_pSoundManager->underflowHappened(25);
312+
return;
311313
}
312-
int copyCount = qMin(readAvailable, writeExpected);
313314

314-
if (copyCount > 0) {
315-
if (writeExpected - copyCount > outChunkSize) {
316-
// Underflow
317-
// kLogger.debug() << "workerWriteProcess: buffer empty."
318-
// << "Catch up with silence:" << writeExpected - copyCount
319-
// << "streamTime" << pWorker->getStreamTimeFrames();;
320-
// catch up by filling buffer until we are synced
321-
workerWriteSilence(pWorker, (writeExpected - copyCount) / m_numOutputChannels);
322-
m_pSoundManager->underflowHappened(24);
323-
} else if (writeExpected - copyCount > outChunkSize / 2) {
324-
// try to keep PAs buffer filled up to 0.5 chunks
325-
if (pWorker->outputDrift()) {
326-
// duplicate one frame
327-
// kLogger.debug() << "workerWriteProcess() duplicate one frame"
328-
// << (float)writeExpected / outChunkSize
329-
// << (float)readAvailable / outChunkSize;
330-
workerWrite(pWorker, dataPtr1, 1);
331-
} else {
332-
pWorker->setOutputDrift(true);
333-
}
334-
} else if (writeExpected < outChunkSize / 2) {
335-
// We will overshoot by more than a half of the new frames
336-
if (pWorker->outputDrift()) {
337-
// kLogger.debug() << "SoundDeviceNetwork::workerWriteProcess() "
338-
// "skip one frame"
339-
// << (float)writeAvailable / outChunkSize
340-
// << (float)readAvailable / outChunkSize;
341-
if (size1 >= m_numOutputChannels) {
342-
dataPtr1 += m_numOutputChannels;
343-
size1 -= m_numOutputChannels;
344-
}
345-
} else {
346-
pWorker->setOutputDrift(true);
315+
if (writeExpected - readAvailable > outChunkSize) {
316+
// Underflow: We are late by more than one buffer outChunkSize
317+
318+
// kLogger.debug() << "workerWriteProcess: buffer empty."
319+
// << "Catch up with silence:" << writeExpected - copyCount
320+
// << "streamTime" << pWorker->getStreamTimeFrames();;
321+
// catch up by filling buffer until we are synced
322+
workerWriteSilence(pWorker, (writeExpected - readAvailable) / m_numOutputChannels);
323+
m_pSoundManager->underflowHappened(24);
324+
} else if (writeExpected - readAvailable > outChunkSize / 2) {
325+
// try to keep PAs buffer filled up to 0.5 chunks
326+
if (pWorker->outputDrift()) {
327+
// duplicate one frame
328+
// kLogger.debug() << "workerWriteProcess() duplicate one frame"
329+
// << (float)writeExpected / outChunkSize
330+
// << (float)readAvailable / outChunkSize;
331+
workerWrite(pWorker, dataPtr1, 1);
332+
} else {
333+
pWorker->setOutputDrift(true);
334+
}
335+
} else if (writeExpected < outChunkSize / 2) {
336+
// We will overshoot by more than a half of the new frames
337+
if (pWorker->outputDrift()) {
338+
// kLogger.debug() << "SoundDeviceNetwork::workerWriteProcess() "
339+
// "skip one frame"
340+
// << (float)writeAvailable / outChunkSize
341+
// << (float)readAvailable / outChunkSize;
342+
if (size1 >= m_numOutputChannels) {
343+
dataPtr1 += m_numOutputChannels;
344+
size1 -= m_numOutputChannels;
347345
}
348346
} else {
349-
pWorker->setOutputDrift(false);
347+
pWorker->setOutputDrift(true);
350348
}
349+
} else {
350+
pWorker->setOutputDrift(false);
351+
}
351352

352-
workerWrite(pWorker, dataPtr1, size1 / m_numOutputChannels);
353-
if (size2 > 0) {
354-
workerWrite(pWorker, dataPtr2, size2 / m_numOutputChannels);
355-
}
353+
workerWrite(pWorker, dataPtr1, size1 / m_numOutputChannels);
354+
if (size2 > 0) {
355+
workerWrite(pWorker, dataPtr2, size2 / m_numOutputChannels);
356+
}
356357

357-
QSharedPointer<FIFO<CSAMPLE>> pFifo = pWorker->getOutputFifo();
358-
if (pFifo) {
359-
// interval = copyCount
360-
// Check for desired kNetworkLatencyFrames + 1/2 interval to
361-
// avoid big jitter due to interferences with sync code
362-
if (pFifo->readAvailable() + copyCount / 2 >=
363-
(m_numOutputChannels * kNetworkLatencyFrames)) {
364-
pWorker->outputAvailable();
365-
}
358+
QSharedPointer<FIFO<CSAMPLE>> pFifo = pWorker->getOutputFifo();
359+
if (pFifo) {
360+
// Check for desired kNetworkLatencyFrames + 1/2 interval to
361+
// avoid big jitter due to interferences with sync code
362+
if (pFifo->readAvailable() + outChunkSize / 2 >=
363+
(m_numOutputChannels * kNetworkLatencyFrames)) {
364+
pWorker->outputAvailable();
366365
}
367366
}
368367
}

0 commit comments

Comments
 (0)