Browse Source

Account for complete output callbacks and test adaptive PCM reserve

master
evgeny 4 days ago
parent
commit
3083cc05dc
  1. 3
      tools/chatgui/src/sound_manager.cpp
  2. 4
      tools/chatgui/src/voice_audio_io.cpp
  3. 16
      tools/chatgui/tests/test_voice_audio_io.cpp

3
tools/chatgui/src/sound_manager.cpp

@ -164,7 +164,8 @@ unsigned SoundManager::renderOutput(ma_engine* engine, const std::array<VoiceAud
if (engine && ma_engine_read_pcm_frames(engine, destination, count, nullptr) != MA_SUCCESS) {
++errors; std::fill_n(destination, count * 2, 0.0f);
}
for (auto* voice : voices) if (voice) voice->mix(destination, count, firstTimeUs + (int64_t)offset * 1000000 / 48000, measured);
for (auto* voice : voices) if (voice)
voice->mix(destination, count, firstTimeUs + (int64_t)offset * 1000000 / 48000, measured, frames);
for (unsigned i = 0; i < count * 2; ++i) {
float value = destination[i];
destination[i] = std::isfinite(value) ? std::clamp(value, -1.0f, 1.0f) : 0.0f;

4
tools/chatgui/src/voice_audio_io.cpp

@ -177,6 +177,7 @@ void VoiceAudioIo::playbackLoop() {
unsigned missing = 0;
VoicePlaybackBuffer buffering;
PlaybackProgress lastProgress{};
int64_t lastProgressUs = 0;
call_clock_snapshot clock{};
if (m_kind == Kind::Call && call_audio_get_clock(m_session, voice_time_us(), &clock) != 0)
DEBUG_WARN(DEBUG_CATEGORY_CALL, "voice-io: call clock unavailable session=%llu", (unsigned long long)m_session);
@ -210,6 +211,7 @@ void VoiceAudioIo::playbackLoop() {
queueUs.add(int64_t(progress.queuedFrames) * 1000000 / 48000);
missing += progress.missing;
lastProgress = progress;
lastProgressUs = voice_time_us();
if (!progress.consumed) continue;
int64_t now = voice_time_us(), remaining = progress.endTimeUs - now;
if (m_kind == Kind::Call)
@ -259,7 +261,7 @@ void VoiceAudioIo::playbackLoop() {
int64_t queuedUs = (position - lastProgress.position) * 1000000 / 48000;
std::lock_guard lock(m_latencyMutex);
m_outputLatency = {int(queuedUs / 1000), int((queuedUs + std::max(lastProgress.endTimeUs - now, int64_t(0))) / 1000),
lastProgress.measured, now};
lastProgress.measured, lastProgressUs};
}
}
}

16
tools/chatgui/tests/test_voice_audio_io.cpp

@ -1,6 +1,7 @@
/* Настоящие workers/AEC; граница сервисного PCM заменена наблюдателями без сети/устройства. */
#include "../src/voice_audio_io.h"
#include "../src/voice_capture_clock.h"
#include "../src/voice_playback_buffer.h"
extern "C" {
#include "call/call_audio.h"
#include "radio/radio_audio.h"
@ -74,6 +75,18 @@ static void reset() {
}
int main() {
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN);
// Резерв уменьшается только при стабильной работе; крупный callback и starvation повышают минимум.
VoicePlaybackBuffer buffering;
buffering.sample(1, 512, false);
buffering.sample(10000000, 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);
buffering.reset(); REQUIRE(buffering.blocks == 2);
// Десять минут +/-300ppm дрейфа: связь с физическим временем сохраняется, шага >2мс нет.
for (double drift : {-0.0003, 0.0003}) {
VoiceCaptureClock clock;
@ -106,9 +119,12 @@ int main() {
voice.mix(partial, 240, now_us() + 500000);
await([] { return output_position.load() == 240; });
REQUIRE(output_delay > 4500);
auto latency = voice.outputLatency();
REQUIRE(latency.outputMs >= latency.queueMs + 450);
voice.mix(partial, 720, now_us());
await([] { return output_position.load() == 960; });
voice.stop();
REQUIRE(voice.outputLatency().outputMs == -1);
voice.start(VoiceAudioIo::Kind::Radio, 7); REQUIRE(voice.startCapture(1, false));
voice.capture(pcm.data(), 240, 0); voice.setPtt(true);
voice.capture(pcm.data(), 360, 0); voice.setPtt(false); voice.capture(pcm.data(), 360, 0);

Loading…
Cancel
Save