You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
78 lines
4.3 KiB
78 lines
4.3 KiB
#ifndef CALL_AUDIO_H |
|
#define CALL_AUDIO_H |
|
|
|
// call_audio.h — сервисный аудио-движок P2P-звонка (единый для desktop/Android/headless). |
|
// |
|
// Владеет Opus codec, адаптивным джиттер-буфером (voice_jitter: кодированные |
|
// кадры + SoundTouch time-stretch на pull) и тонами (глитч при сталле / завершение). |
|
// Излишек голоса держится до декодирования — декодируется только то, что готово |
|
// к воспроизведению. Потребитель (desktop miniaudio / Android AudioTrack) получает |
|
// финальный PCM через call_audio_pull_pcm и отдаёт захваченный PCM через |
|
// call_audio_feed_pcm. |
|
// |
|
// Потоки: |
|
// - call_audio_start / begin_end / release — GUI-поток (по ACCEPTED/ENDED); |
|
// - call_audio_feed_pcm / pull_pcm — аудио-поток (single-writer); |
|
// - call_audio_on_media / get_stats — uasync-поток (из call.c). |
|
// Общие указатели (encoder/decoder/vj/tones) защищены мьютексом; encoder и |
|
// decoder — только аудио-поток (decoder дёргается из vj_pull через коллбэк), |
|
// vj_push — только uasync-поток. |
|
|
|
#include <stdint.h> |
|
|
|
struct UTUN_INSTANCE; |
|
|
|
#ifdef __cplusplus |
|
extern "C" { |
|
#endif |
|
|
|
#define CALL_AUDIO_SAMPLE_RATE 48000 |
|
#define CALL_AUDIO_FRAME_MS 20 |
|
#define CALL_AUDIO_FRAME_SAMPLES (CALL_AUDIO_SAMPLE_RATE * CALL_AUDIO_FRAME_MS / 1000) /* 960 */ |
|
|
|
/* Зарегистрировать аудио-движок в call.c (идемпотентно). */ |
|
int call_audio_init(struct UTUN_INSTANCE* inst); |
|
void call_audio_destroy(struct UTUN_INSTANCE* inst); |
|
|
|
/* GUI-поток: создать codec + jitter + tones для звонка. 0 = успех. */ |
|
int call_audio_start(uint64_t call_id); |
|
|
|
/* GUI-поток: по CALL_ENDED — начать тон завершения (pull_pcm выдаст 450мс тона). */ |
|
void call_audio_begin_end(uint64_t call_id); |
|
|
|
/* GUI-поток (после остановки аудиоустройства): освободить все объекты. */ |
|
void call_audio_release(uint64_t call_id); |
|
|
|
/* GUI-поток: остановить текущий активный звонок (удобная обёртка release). */ |
|
void call_audio_stop(void); |
|
|
|
/* аудио-поток: закодировать PCM-кадр (ровно CALL_AUDIO_FRAME_SAMPLES) и отправить пиру. */ |
|
int call_audio_feed_pcm(uint64_t call_id, const int16_t* pcm, int count); |
|
|
|
/* аудио-поток: выдать до max_samples финального PCM (jitter + stretch + тоны). |
|
* Возвращает число сэмплов (может быть < max — андерфлоу/конец тона). */ |
|
int call_audio_pull_pcm(uint64_t call_id, int16_t* out, int max_samples); |
|
|
|
/* uasync-поток (из call.c): принятый Opus-кадр — кладём в джиттер-буфер (vj_push, |
|
* декодирование произойдёт на pull в аудио-потоке). */ |
|
void call_audio_on_media(struct UTUN_INSTANCE* inst, uint64_t call_id, |
|
uint16_t seq, uint32_t ts_ms, const uint8_t* opus, int len); |
|
|
|
/* uasync-поток: метрики джиттер-буфера для CALL_STATS (dropped/underruns — необязательные). */ |
|
int call_audio_get_stats(uint64_t call_id, int* buffer_ms, int* tempo_x100, |
|
uint32_t* dropped, uint32_t* underruns); |
|
|
|
/* Включить/выключить AEC (SpeexDSP) в рантайме. desktop — по настройке GUI, |
|
* Android — по спикерфону (route == SPEAKER). Работает и в активном звонке. */ |
|
void call_audio_set_aec_enabled(int enabled); |
|
|
|
/* Задать задержку рендер→захват AEC в кадрах (20 мс). Android измеряет через |
|
* AudioTrack/AudioRecord getTimestamp, desktop использует дефолт. Если AEC уже |
|
* активен — пересоздаётся с новой задержкой. */ |
|
void call_audio_set_aec_delay_frames(int frames); |
|
|
|
#ifdef __cplusplus |
|
} |
|
#endif |
|
|
|
#endif /* CALL_AUDIO_H */
|
|
|