Browse Source

Back off PCM reserve probes after starvation and exclude output pauses

master
evgeny 5 days ago
parent
commit
b3ed8b06e7
  1. 10
      tools/chatgui/src/voice_playback_buffer.h
  2. 13
      tools/chatgui/tests/test_voice_audio_io.cpp

10
tools/chatgui/src/voice_playback_buffer.h

@ -9,21 +9,23 @@ class VoicePlaybackBuffer {
public:
unsigned blocks = 2;
unsigned callbackFrames = 960;
void reset() { blocks = 2; callbackFrames = 960; stableSince = 0; lastGrowth = 0; }
void reset() { blocks = 2; callbackFrames = 960; stableSince = 0; lastGrowth = 0; lastSample = 0; probeUs = 10000000; }
void sample(int64_t nowUs, unsigned frames, bool missing) {
callbackFrames = frames;
unsigned minimum = std::clamp((frames + 959) / 960, 1u, 4u);
if (!stableSince) stableSince = nowUs;
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 >= 10000000) {
} else if (blocks > minimum && nowUs - stableSince >= probeUs) {
--blocks; stableSince = nowUs;
}
}
private:
int64_t stableSince = 0, lastGrowth = 0;
int64_t stableSince = 0, lastGrowth = 0, lastSample = 0, probeUs = 10000000;
};

13
tools/chatgui/tests/test_voice_audio_io.cpp

@ -78,15 +78,20 @@ int main() {
// Резерв уменьшается только при стабильной работе; крупный callback и starvation повышают минимум.
VoicePlaybackBuffer buffering;
buffering.sample(1, 512, false);
buffering.sample(10000000, 512, false); REQUIRE(buffering.blocks == 2);
for (int64_t t = 1000000; t <= 10000000; t += 1000000) buffering.sample(t, 512, false);
REQUIRE(buffering.blocks == 2);
buffering.sample(10000001, 512, false); REQUIRE(buffering.blocks == 1);
buffering.sample(10020001, 512, true); REQUIRE(buffering.blocks == 2);
buffering.sample(10020002, 512, true); REQUIRE(buffering.blocks == 2);
buffering.sample(10520001, 512, true); REQUIRE(buffering.blocks == 3);
buffering.sample(20520001, 2048, false); REQUIRE(buffering.blocks == 3);
buffering.sample(30520001, 512, false); REQUIRE(buffering.blocks == 2);
buffering.sample(40520001, 512, false); REQUIRE(buffering.blocks == 1);
for (int64_t t = 11520001; t <= 50520001; t += 1000000) buffering.sample(t, 2048, false);
REQUIRE(buffering.blocks == 3);
buffering.sample(50520002, 512, false); REQUIRE(buffering.blocks == 2);
for (int64_t t = 51520002; t <= 90520002; t += 1000000) buffering.sample(t, 512, false);
REQUIRE(buffering.blocks == 1);
buffering.reset(); REQUIRE(buffering.blocks == 2);
buffering.sample(1, 512, false);
buffering.sample(20000001, 512, false); REQUIRE(buffering.blocks == 2); // Пауза не означает стабильный вывод.
// Десять минут +/-300ppm дрейфа: связь с физическим временем сохраняется, шага >2мс нет.
for (double drift : {-0.0003, 0.0003}) {
VoiceCaptureClock clock;

Loading…
Cancel
Save