Files
utun2/tools/chatgui/src/voice_playback_buffer.h
T

35 lines
1.8 KiB
C++

#pragma once
#include <algorithm>
#include <cstdint>
/* Резерв готового PCM desktop: bufferMs = 20..80, кратно 20 (проверяет VoiceAudioIo::start).
* Размер callback и настроенный запас задают нижнюю границу; недостача добавляет
* один блок, 10 секунд стабильного вывода убирают один. Частично сыгранный блок — сверх резерва.
* Только RX worker; время монотонное. Четыре PCM-слота доступны в AudioEventQueue<Playback, 12>. */
class VoicePlaybackBuffer {
public:
explicit VoicePlaybackBuffer(unsigned bufferMs = 20) : minimumBlocks(bufferMs / 20) { reset(); }
unsigned blocks = 1;
unsigned callbackFrames = 960;
void reset() { blocks = minimumBlocks; callbackFrames = 960; stableSince = 0; lastGrowth = 0; lastSample = 0; probeUs = 10000000; }
void sample(int64_t nowUs, unsigned frames, bool missing) {
callbackFrames = frames;
unsigned minimum = std::max(minimumBlocks, std::clamp((frames + 959) / 960, 1u, 4u));
if (!stableSince || nowUs - lastSample > 1000000) stableSince = nowUs;
lastSample = nowUs;
if (minimum > blocks) { blocks = minimum; stableSince = nowUs; }
if (missing) {
stableSince = nowUs;
if (!lastGrowth || nowUs - lastGrowth >= 500000) {
blocks = std::min(blocks + 1, 4u); lastGrowth = nowUs;
probeUs = std::min(probeUs * 2, int64_t(300000000));
}
} else if (blocks > minimum && nowUs - stableSince >= probeUs) {
--blocks; stableSince = nowUs;
}
}
private:
unsigned minimumBlocks;
int64_t stableSince = 0, lastGrowth = 0, lastSample = 0, probeUs = 10000000;
};