#pragma once #include #include /* Только управляющий поток. Исходный запрос не меняется без повторных backend XRUN. * Рост периода на 5мс, запрос полной ёмкости до 100мс; прогрев 1с, между изменениями 5с. * Нужны два опроса с ошибками за 5с: пачка уведомлений одного сбоя не увеличивает буфер. * Состояние живёт до смены устройства/сессии; begin() сохраняет подобранный размер при reopen. */ struct AudioBufferTuning { enum Result { Unchanged, Increase, Limit }; unsigned requestedMs = 0, baseMs = 0, actualMs = 0, periods = 1; int64_t settleUntil = 0, changeAfter = 0, firstFaultAt = -1; unsigned faultPolls = 0; void begin(int64_t now, unsigned actualPeriodMs, unsigned periodCount) { actualMs = actualPeriodMs; periods = std::max(1u, periodCount); settleUntil = now + 1000; firstFaultAt = -1; faultPolls = 0; } Result observe(int64_t now, unsigned glitches) { if (!glitches || now < settleUntil) return Unchanged; if (firstFaultAt < 0 || now - firstFaultAt > 5000) { firstFaultAt = now; faultPolls = 0; } faultPolls = std::min(faultPolls + 1, 2u); if (faultPolls < 2 || now < changeAfter) return Unchanged; firstFaultAt = -1; faultPolls = 0; changeAfter = now + 5000; unsigned current = std::max({actualMs, requestedMs, baseMs}), maximum = 100 / periods; if (!current || current >= maximum) return Limit; requestedMs = std::min(current + 5, maximum); return Increase; } };