diff --git a/src/radio/radio_audio.c b/src/radio/radio_audio.c index bcd2f63e..0c5e4643 100644 --- a/src/radio/radio_audio.c +++ b/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; diff --git a/tools/chatgui/tests/test_voice_tx.cpp b/tools/chatgui/tests/test_voice_tx.cpp index 6e9bd2a3..557ca0db 100644 --- a/tools/chatgui/tests/test_voice_tx.cpp +++ b/tools/chatgui/tests/test_voice_tx.cpp @@ -303,8 +303,10 @@ static void test_vad_receive_guard(UTUN_INSTANCE* instance) { std::array 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);