Skip to content

Commit cc7e608

Browse files
committed
Add automatic HDMI sample rate change detection
Implement periodic polling (every ~1 second) to detect HDMI audio sample rate changes and trigger automatic reconfiguration. This prevents audio distortion when switching between 44.1kHz and 48kHz sources. Key changes: - Poll TC358743 V4L2 control every 50 frames in capture hot path - Trigger reconnection when sample rate changes - Optimize logging to only output on rate changes (reduces log spam) - Add proper state tracking to prevent duplicate logging - Fix comment accuracy and ensure all state updates are consistent Performance impact: ~100-500μs overhead every second (~0.01-0.05% CPU)
1 parent 8debd07 commit cc7e608

File tree

1 file changed

+36
-10
lines changed

1 file changed

+36
-10
lines changed

internal/audio/c/audio.c

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -267,23 +267,34 @@ static unsigned int get_hdmi_audio_sample_rate(void) {
267267
close(fd);
268268

269269
unsigned int detected_rate = (unsigned int)ext_ctrl.value;
270+
static unsigned int last_logged_rate = 0; // Track last logged rate to suppress duplicate messages
270271

271272
if (detected_rate == 0) {
272-
fprintf(stdout, "INFO: TC358743 reports 0 Hz (no HDMI signal or audio not detected yet)\n");
273-
fprintf(stdout, " Will use 48kHz default and resample if needed when signal detected\n");
274-
fflush(stdout);
275-
return 0; // No signal or rate not detected - this is expected during hotplug
273+
if (last_logged_rate != 0) {
274+
fprintf(stdout, "INFO: TC358743 reports 0 Hz (no HDMI signal or audio not detected yet)\n");
275+
fprintf(stdout, " Will use 48kHz default and resample if needed when signal detected\n");
276+
fflush(stdout);
277+
last_logged_rate = 0;
278+
}
279+
return 0;
276280
}
277281

278-
// Validate detected rate is reasonable
282+
// Validate detected rate is reasonable (log warning only on rate changes)
279283
if (detected_rate < 8000 || detected_rate > 192000) {
280-
fprintf(stderr, "WARNING: TC358743 reported unusual sample rate: %u Hz (expected 32k-192k)\n", detected_rate);
281-
fprintf(stderr, " Using detected rate anyway, but audio may not work correctly\n");
282-
fflush(stderr);
284+
if (detected_rate != last_logged_rate) {
285+
fprintf(stderr, "WARNING: TC358743 reported unusual sample rate: %u Hz (expected 32k-192k)\n", detected_rate);
286+
fprintf(stderr, " Using detected rate anyway, but audio may not work correctly\n");
287+
fflush(stderr);
288+
last_logged_rate = detected_rate;
289+
}
283290
}
284291

285-
fprintf(stdout, "INFO: TC358743 detected HDMI audio sample rate: %u Hz\n", detected_rate);
286-
fflush(stdout);
292+
// Log rate changes and update tracking state to suppress duplicate logging
293+
if (detected_rate != last_logged_rate) {
294+
fprintf(stdout, "INFO: TC358743 detected HDMI audio sample rate: %u Hz\n", detected_rate);
295+
fflush(stdout);
296+
last_logged_rate = detected_rate;
297+
}
287298

288299
return detected_rate;
289300
}
@@ -800,6 +811,7 @@ __attribute__((hot)) int jetkvm_audio_read_encode(void * __restrict__ opus_buf)
800811
// Two buffers: hardware buffer + resampled buffer (at 48kHz)
801812
static short CACHE_ALIGN pcm_hw_buffer[MAX_HARDWARE_FRAME_SIZE * 2]; // Max hardware rate * stereo
802813
static short CACHE_ALIGN pcm_opus_buffer[960 * 2]; // 48kHz @ 20ms * 2 channels
814+
static uint16_t sample_rate_check_counter = 0;
803815
unsigned char * __restrict__ out = (unsigned char*)opus_buf;
804816
int32_t pcm_rc, nb_bytes;
805817
int32_t err = 0;
@@ -852,6 +864,20 @@ __attribute__((hot)) int jetkvm_audio_read_encode(void * __restrict__ opus_buf)
852864
}
853865
}
854866

867+
// Periodic sample rate change detection (every 50 frames = ~1 second)
868+
if (__builtin_expect(++sample_rate_check_counter >= 50, 0)) {
869+
sample_rate_check_counter = 0;
870+
unsigned int current_rate = get_hdmi_audio_sample_rate();
871+
if (current_rate != 0 && current_rate != hardware_sample_rate) {
872+
fprintf(stderr, "ERROR: capture: HDMI sample rate changed from %u to %u Hz\n",
873+
hardware_sample_rate, current_rate);
874+
fprintf(stderr, " Triggering reconnection for automatic reconfiguration\n");
875+
fflush(stderr);
876+
pthread_mutex_unlock(&capture_mutex);
877+
return -1;
878+
}
879+
}
880+
855881
if (__builtin_expect(pcm_rc < hardware_frame_size, 0)) {
856882
uint32_t remaining_samples = (hardware_frame_size - pcm_rc) * capture_channels;
857883
simd_clear_samples_s16(&pcm_hw_buffer[pcm_rc * capture_channels], remaining_samples);

0 commit comments

Comments
 (0)