Skip to content

Commit 3fd5d0e

Browse files
committed
Harden post-capture startup path with Win sync guard and RX warm-up
1 parent b7abc32 commit 3fd5d0e

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

src/gui/app.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,11 +1155,19 @@ void App::stopSimulator() {
11551155

11561156
if (sim_thread_.joinable()) sim_thread_.join();
11571157

1158+
// Keep synchronous decode mode on Windows for startup/runtime stability.
1159+
#ifdef _WIN32
1160+
modem_.setSynchronousMode(true);
1161+
if (virtual_modem_) {
1162+
virtual_modem_->setSynchronousMode(true);
1163+
}
1164+
#else
11581165
// Restore async decode mode for real audio operation
11591166
modem_.setSynchronousMode(false);
11601167
if (virtual_modem_) {
11611168
virtual_modem_->setSynchronousMode(false);
11621169
}
1170+
#endif
11631171

11641172
// Clear buffers
11651173
{
@@ -1509,6 +1517,14 @@ void App::render() {
15091517
ultra::gui::startupTrace("App", "render-set-output-gain-exit");
15101518
}
15111519

1520+
#ifdef _WIN32
1521+
// Keep decode in synchronous mode on fragile Win10 systems.
1522+
if (!simulation_enabled_ && !modem_.isSynchronousMode()) {
1523+
guiLog("Win startup guard: forcing modem synchronous RX mode");
1524+
modem_.setSynchronousMode(true);
1525+
}
1526+
#endif
1527+
15121528
// Process captured RX audio in the main thread.
15131529
// Avoids feeding modem state directly from SDL callback threads.
15141530
pollRadioRx();
@@ -1793,6 +1809,13 @@ bool App::startRadioRx() {
17931809
return true;
17941810
}
17951811

1812+
#ifdef _WIN32
1813+
if (!modem_.isSynchronousMode()) {
1814+
guiLog("startRadioRx guard: enabling synchronous modem RX mode");
1815+
modem_.setSynchronousMode(true);
1816+
}
1817+
#endif
1818+
17961819
std::string input_dev = getInputDeviceName();
17971820
if (!audio_.openInput(input_dev)) {
17981821
guiLog("startRadioRx: openInput failed for '%s'",
@@ -1811,6 +1834,9 @@ bool App::startRadioRx() {
18111834
return false;
18121835
}
18131836
radio_rx_enabled_ = true;
1837+
radio_rx_started_ms_ = SDL_GetTicks();
1838+
radio_rx_warmup_logged_ = false;
1839+
radio_rx_first_chunk_logged_ = false;
18141840
guiLog("startRadioRx: capture started on '%s'",
18151841
input_dev.empty() ? "Default" : input_dev.c_str());
18161842
return true;
@@ -1821,13 +1847,27 @@ void App::stopRadioRx() {
18211847
audio_.closeInput();
18221848
audio_.setRxCallback(AudioEngine::RxCallback{});
18231849
radio_rx_enabled_ = false;
1850+
radio_rx_started_ms_ = 0;
1851+
radio_rx_warmup_logged_ = false;
1852+
radio_rx_first_chunk_logged_ = false;
18241853
}
18251854

18261855
void App::pollRadioRx() {
18271856
if (!audio_initialized_ || simulation_enabled_ || !radio_rx_enabled_) {
18281857
return;
18291858
}
18301859

1860+
uint32_t now_ms = SDL_GetTicks();
1861+
if (radio_rx_started_ms_ > 0 && (now_ms - radio_rx_started_ms_) < 200) {
1862+
if (!radio_rx_warmup_logged_) {
1863+
guiLog("pollRadioRx warm-up: delaying modem feed for 200ms after capture start");
1864+
radio_rx_warmup_logged_ = true;
1865+
}
1866+
// Drain a small amount during warm-up to avoid unbounded growth.
1867+
(void)audio_.getRxSamples(2048);
1868+
return;
1869+
}
1870+
18311871
// Bounded drain per frame to keep UI responsive while preventing RX backlog.
18321872
constexpr size_t kChunkSamples = 2048;
18331873
constexpr int kMaxChunksPerFrame = 8;
@@ -1837,8 +1877,18 @@ void App::pollRadioRx() {
18371877
break;
18381878
}
18391879

1880+
if (!radio_rx_first_chunk_logged_) {
1881+
guiLog("pollRadioRx: first RX chunk=%zu samples", samples.size());
1882+
}
18401883
modem_.feedAudio(samples);
1884+
if (!radio_rx_first_chunk_logged_) {
1885+
guiLog("pollRadioRx: first RX chunk fed to modem");
1886+
}
18411887
modem_.processRxBuffer();
1888+
if (!radio_rx_first_chunk_logged_) {
1889+
guiLog("pollRadioRx: first RX chunk modem processing complete");
1890+
radio_rx_first_chunk_logged_ = true;
1891+
}
18421892
if (waterfall_) {
18431893
waterfall_->addSamples(samples.data(), samples.size());
18441894
}

src/gui/app.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ class App {
8686
std::vector<std::string> output_devices_;
8787
bool ptt_active_ = false; // Push-to-talk state
8888
bool radio_rx_enabled_ = false; // RX capture running
89+
uint32_t radio_rx_started_ms_ = 0;
90+
bool radio_rx_warmup_logged_ = false;
91+
bool radio_rx_first_chunk_logged_ = false;
8992

9093
// ARQ Protocol state
9194
protocol::ProtocolEngine protocol_;

0 commit comments

Comments
 (0)