Fix call gap tone to follow 500ms of missing jitter PCM

This commit is contained in:
evgeny committed 2026-09-30 21:14:37 +03:00
1 parent 9e3a417059
commit 1c51df039f
2 files changed
+68 -36

No files matched your search

+32 -20
View File
@@ -25,7 +25,7 @@
#define CALL_AUDIO_ID "call_audio"
#define CALL_AUDIO_BITRATE 32000
#define CALL_STALL_TB 5000 /* 500мс без медиа и недобор PCM → глитч-тон */
#define CALL_STALL_SAMPLES (CALL_AUDIO_SAMPLE_RATE / 2) /* 500мс без PCM из jitter → глитч-тон */
#define CALL_AEC_FILTER_SAMPLES 14400 /* хвост эха 300мс @48кГц */
#define CALL_AEC_DELAY_FRAMES 2 /* desktop: минимальная задержка duplex */
@@ -36,7 +36,7 @@ static int g_ending = 0;
static int g_glitch_started = 0; /* только аудиопоток */
static int g_ended_started = 0; /* только аудио-поток: тон завершения запущен */
static uint64_t g_call_id = 0;
static uint64_t g_last_media_tb = 0;
static int g_gap_samples = 0; /* только аудиопоток; насыщение на пороге */
static opus_codec_encoder_t* g_encoder = NULL;
static opus_codec_decoder_t* g_decoder = NULL;
static struct call_jitter* g_vj = NULL;
@@ -85,7 +85,6 @@ void call_audio_on_media(struct UTUN_INSTANCE* inst, uint64_t call_id,
pthread_mutex_lock(&g_mtx);
if (g_active && call_id == g_call_id && g_vj && opus && len > 0) {
call_jitter_push(g_vj, opus, len);
g_last_media_tb = get_time_tb();
}
pthread_mutex_unlock(&g_mtx);
}
@@ -185,7 +184,7 @@ int call_audio_start(uint64_t call_id) {
g_ending = 0;
g_ended_started = 0;
g_glitch_started = 0;
g_last_media_tb = 0;
g_gap_samples = 0;
pthread_mutex_unlock(&g_mtx);
DEBUG_INFO(DEBUG_CATEGORY_CALL, "%s: started call=0x%016llx aec=%d delay=%d compressor=%s gain=%d", CALL_AUDIO_ID,
@@ -220,7 +219,7 @@ void call_audio_release(uint64_t call_id) {
g_ending = 0;
g_ended_started = 0;
g_call_id = 0;
g_last_media_tb = 0;
g_gap_samples = 0;
enc = g_encoder; g_encoder = NULL;
dec = g_decoder; g_decoder = NULL;
j = g_vj; g_vj = NULL;
@@ -347,7 +346,6 @@ int call_audio_pull_pcm(uint64_t call_id, int16_t* out, int max_samples) {
int active = 0, ending = 0;
struct call_jitter* j = NULL;
struct call_tones* tones = NULL;
uint64_t last_media = 0;
pthread_mutex_lock(&g_mtx);
if (g_active && call_id == g_call_id) {
@@ -355,7 +353,6 @@ int call_audio_pull_pcm(uint64_t call_id, int16_t* out, int max_samples) {
ending = g_ending;
j = g_vj;
tones = g_tones;
last_media = g_last_media_tb;
}
pthread_mutex_unlock(&g_mtx);
@@ -375,21 +372,36 @@ int call_audio_pull_pcm(uint64_t call_id, int16_t* out, int max_samples) {
n = call_tones_render(tones, out, max_samples);
} else {
n = call_jitter_pull(j, out, max_samples);
uint64_t now = get_time_tb();
int stalled = n < max_samples && last_media != 0 && now - last_media >= CALL_STALL_TB;
if (stalled != g_glitch_started) {
g_glitch_started = stalled;
DEBUG_INFO(DEBUG_CATEGORY_CALL, "%s: gap tone %s call=%016llx media_gap=%llums pcm=%d/%d",
CALL_AUDIO_ID, stalled ? "started" : "stopped", (unsigned long long)call_id,
(unsigned long long)((now - last_media) / 10), n, max_samples);
}
if (stalled) {
call_tones_glitch_start(tones);
n += call_tones_render(tones, out + n, max_samples - n);
} else {
int previous_gap = g_gap_samples;
if (n > 0) g_gap_samples = 0;
int missing = max_samples - n;
int quiet = CALL_STALL_SAMPLES - g_gap_samples;
if (quiet > missing) quiet = missing;
int tone_samples = missing - quiet;
if (n > 0 && previous_gap > 0)
DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "%s: PCM resumed call=%016llx gap=%dms pcm=%d/%d", CALL_AUDIO_ID,
(unsigned long long)call_id, previous_gap * 1000 / CALL_AUDIO_SAMPLE_RATE, n, max_samples);
if (missing > 0 && g_gap_samples == 0)
DEBUG_DEBUG(DEBUG_CATEGORY_CALL, "%s: PCM gap started call=%016llx pcm=%d/%d", CALL_AUDIO_ID,
(unsigned long long)call_id, n, max_samples);
g_gap_samples += quiet;
/* Новый PCM прерывает предыдущий цикл тона, даже если хвост блока снова пуст. */
if (g_glitch_started && (n > 0 || tone_samples == 0)) {
g_glitch_started = 0;
call_tones_glitch_stop(tones);
DEBUG_INFO(DEBUG_CATEGORY_CALL, "%s: gap tone stopped call=%016llx pcm=%d/%d", CALL_AUDIO_ID,
(unsigned long long)call_id, n, max_samples);
}
memset(out + n, 0, (size_t)quiet * sizeof(*out));
if (tone_samples > 0) {
if (!g_glitch_started) {
g_glitch_started = 1;
DEBUG_INFO(DEBUG_CATEGORY_CALL, "%s: gap tone started call=%016llx pcm_gap=500ms pcm=%d/%d", CALL_AUDIO_ID,
(unsigned long long)call_id, n, max_samples);
}
call_tones_glitch_start(tones);
call_tones_render(tones, out + n + quiet, tone_samples);
}
for (int i = n; i < max_samples; i++) out[i] = 0;
n = max_samples;
}