|
1 | 1 | #include "soundio/sounddevicenetwork.h" |
2 | 2 |
|
3 | 3 | #include <QtDebug> |
| 4 | +#include <atomic> |
4 | 5 |
|
5 | 6 | #include "control/controlobject.h" |
6 | 7 | #include "engine/sidechain/enginenetworkstream.h" |
@@ -29,6 +30,19 @@ constexpr int kNetworkLatencyFrames = 8192; // 185 ms @ 44100 Hz |
29 | 30 | const mixxx::Logger kLogger("SoundDeviceNetwork"); |
30 | 31 |
|
31 | 32 | const QString kAppGroup = QStringLiteral("[App]"); |
| 33 | + |
| 34 | +bool updateIfGreater(std::atomic_int* pAtomic, int newValue) { |
| 35 | + int current = pAtomic->load(std::memory_order_relaxed); |
| 36 | + while (newValue > current && |
| 37 | + pAtomic->compare_exchange_weak( |
| 38 | + current, // non const reference, updated each call |
| 39 | + newValue)) { |
| 40 | + // pAtomic has now newValue |
| 41 | + return true; |
| 42 | + } |
| 43 | + return false; |
| 44 | +} |
| 45 | + |
32 | 46 | } // namespace |
33 | 47 |
|
34 | 48 | SoundDeviceNetwork::SoundDeviceNetwork( |
@@ -327,7 +341,10 @@ void SoundDeviceNetwork::workerWriteProcess(NetworkOutputStreamWorkerPtr pWorker |
327 | 341 | workerWriteSilence(pWorker, silenceFrames); |
328 | 342 | // Inform the engine cycle about the extra frames written to avoid |
329 | 343 | // underflows in other code paths. |
330 | | - m_targetTime += static_cast<qint64>(silenceFrames / m_sampleRate.toDouble() * 1000000); |
| 344 | + // Note, this is called for each pWorker (broadcats connection) all |
| 345 | + // running at the same network clock. The value is used for shifting |
| 346 | + // the m_targetTime and then reset to 0. |
| 347 | + updateIfGreater(&m_extraFramesWritten, silenceFrames); |
331 | 348 | m_pSoundManager->underflowHappened(24); |
332 | 349 | } else if (writeExpected - readAvailable > outChunkSize / 2) { |
333 | 350 | // try to keep PAs buffer filled up to 0.5 chunks |
@@ -522,7 +539,8 @@ void SoundDeviceNetwork::callbackProcessClkRef() { |
522 | 539 | void SoundDeviceNetwork::updateCallbackEntryToDacTime(SINT framesPerBuffer) { |
523 | 540 | m_clkRefTimer.start(); |
524 | 541 | qint64 currentTime = m_pNetworkStream->getInputStreamTimeUs(); |
525 | | - // This deadline for the next buffer in microseconds since the Unix epoch |
| 542 | + // Calculate the deadline for the next buffer in microseconds since the Unix epoch |
| 543 | + framesPerBuffer += m_extraFramesWritten.exchange(0, std::memory_order_relaxed); |
526 | 544 | m_targetTime += static_cast<qint64>(framesPerBuffer / m_sampleRate.toDouble() * 1000000); |
527 | 545 | double callbackEntrytoDacSecs = (m_targetTime - currentTime) / 1000000.0; |
528 | 546 | callbackEntrytoDacSecs = math_max(callbackEntrytoDacSecs, 0.0001); |
|
0 commit comments