Browse Source

radio: keep drain diagnostics at burst boundaries and test queued PCM

master
evgeny 2 days ago
parent
commit
d149bad5fc
  1. 8
      src/radio/radio_audio.c
  2. 8
      tools/chatgui/tests/test_voice_tx.cpp

8
src/radio/radio_audio.c

@ -640,8 +640,10 @@ void radio_audio_playback_progress(uint64_t group_id, uint64_t position, uint64_
g_output_tracked = 1;
if (g_output_voice_end > g_output_played && position >= g_output_voice_end) {
radio_audio_rx_guard(get_time_tb() + delay_tb + RADIO_VAD_BUSY_TB);
DEBUG_DEBUG(DEBUG_CATEGORY_VAD, "VAD output drained group=%016llx position=%llu delay=%.1fms guard=200ms",
(unsigned long long)group_id, (unsigned long long)position, delay_tb / 10.0);
int sources = 0;
for (int i = 0; i < RADIO_AUDIO_MAX_SOURCES; ++i) sources += g_sources[i].used != 0;
if (!sources) DEBUG_DEBUG(DEBUG_CATEGORY_VAD, "VAD output drained group=%016llx position=%llu delay=%.1fms guard=200ms",
(unsigned long long)group_id, (unsigned long long)position, delay_tb / 10.0);
}
g_output_played = position;
}
@ -924,7 +926,6 @@ static void radio_audio_vad_sample(const int16_t* frame) {
pthread_mutex_lock(&g_mtx);
g_vad_win_len = 0;
uint64_t now = get_time_tb();
if (radio_audio_vad_block(now)) return; /* RX мог начаться, пока Silero работал без общего mutex. */
uint64_t inference_tb = now - started;
uint64_t gap_tb = g_vad_diag.last_window_tb ? now - g_vad_diag.last_window_tb : 0;
g_vad_diag.last_window_tb = now;
@ -937,6 +938,7 @@ static void radio_audio_vad_sample(const int16_t* frame) {
DEBUG_ERROR(DEBUG_CATEGORY_VAD, "VAD inference failed group=%016llx window=%llu rc=%d inference=%.1fms",
(unsigned long long)g_group_id, (unsigned long long)g_vad_diag.total_windows, result, inference_tb / 10.0);
}
if (radio_audio_vad_block(now)) return; /* RX мог начаться, пока Silero работал без общего mutex. */
struct radio_vad_fsm before = g_vad_fsm;
int busy = 0;
int64_t rx_age_ms = g_last_rx_tb ? (int64_t)((now - g_last_rx_tb) / 10) : -1;

8
tools/chatgui/tests/test_voice_tx.cpp

@ -303,8 +303,10 @@ static void test_vad_receive_guard(UTUN_INSTANCE* instance) {
std::array<int16_t, 3072> speech; speech.fill(1200);
uint8_t opus[256]; int len = opus_codec_encode(encoder, speech.data(), 960, opus, sizeof(opus)); REQUIRE(len > 0);
opus_codec_encoder_destroy(encoder);
auto receive = [&](uint64_t source, int fin) {
radio_audio_on_frame(instance, 7, source, 1, fin ? 1 : 0, fin, fin ? nullptr : opus, fin ? 0 : len, nullptr);
auto receive = [&](uint64_t source, int fin, uint16_t first = 0) {
if (fin) radio_audio_on_frame(instance, 7, source, 1, first + 8, 1, nullptr, 0, nullptr);
else for (int i = 0; i < 8; ++i)
radio_audio_on_frame(instance, 7, source, 1, first + i, 0, opus, len, nullptr);
};
auto feed = [&] { REQUIRE(radio_audio_feed_pcm(7, speech.data(), speech.size()) == 0); };
uint64_t pulled = 0;
@ -325,7 +327,7 @@ static void test_vad_receive_guard(UTUN_INSTANCE* instance) {
test_time += 3000; feed(); REQUIRE(!radio_audio_transmitting() && vad_windows == before);
receive(42, 1); drain(); radio_audio_playback_progress(7, pulled, 0);
test_time += 3000; feed(); REQUIRE(!radio_audio_transmitting()); // Второй пир всё ещё говорит.
receive(43, 1); drain();
receive(43, 0, 8); receive(43, 1, 8); drain();
test_time += 10000; feed(); REQUIRE(!radio_audio_transmitting()); // PCM ещё не дошёл до выхода.
radio_audio_playback_progress(7, pulled, 500); // Desktop: последние 50мс ещё в устройстве.
test_time += 2499; feed(); REQUIRE(!radio_audio_transmitting() && vad_windows == before);

Loading…
Cancel
Save