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.
 
 
 
 
 
 

91 lines
5.6 KiB

#ifndef CALL_AUDIO_H
#define CALL_AUDIO_H
// call_audio.h — сервисный аудио-движок P2P-звонка (единый для desktop/Android/headless).
//
// Владеет Opus codec, адаптивным джиттер-буфером (call_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 — по одному аудио-потоку на направление;
// - call_audio_on_media / get_stats — uasync-поток (из call.c).
// Общие указатели (encoder/decoder/vj/tones) защищены мьютексом; encoder и
// decoder — только аудио-поток (decoder дёргается из call_jitter_pull через коллбэк),
// call_jitter_push — только uasync-поток.
#include <stdint.h>
#include "call_jitter.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. Старый API принимает raw PCM и использует core AEC.
* Для desktop нужен start_prepared: AEC и stereo reference принадлежат VoiceAudioIo. 0 = успех. */
int call_audio_start(uint64_t call_id);
/* AEC принадлежит платформенному захвату; pull больше не подаёт собственный референс. */
int call_audio_start_prepared(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);
/* Mute после AEC/AGC: фильтр получает настоящий микрофон, Opus — нулевой PCM. */
/* Подготовленный PCM и маска mute (960 элементов); AEC уже выполнен до этого API. */
int call_audio_feed_prepared_pcm(uint64_t call_id, const int16_t* pcm, const uint8_t* mute_mask);
int call_audio_feed_pcm_muted(uint64_t call_id, const int16_t* pcm, int count, int muted);
/* аудио-поток: выдать до 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-кадр — кладём в джиттер-буфер (call_jitter_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, struct call_jitter_range* range);
/* После остановки указанного направления: сбросить AEC, для playback также устаревший jitter/PCM.
* Capture и playback могут работать в разных потоках, по одному writer на направление.
* Release допустим только после остановки обоих. */
void call_audio_reset_io(uint64_t call_id, int playback);
/* Core AEC для raw capture: Android — по спикерфону (route == SPEAKER).
* Prepared capture не создаёт core AEC; desktop передаёт настройку в VoiceAudioIo. */
void call_audio_set_aec_enabled(int enabled);
/* Задать задержку рендер→захват AEC в кадрах (20 мс). Android измеряет через
* AudioTrack/AudioRecord getTimestamp. Prepared desktop выравнивает референс по времени. Если core AEC уже
* активен — пересоздаётся с новой задержкой. */
void call_audio_set_aec_delay_frames(int frames);
#ifdef __cplusplus
}
#endif
#endif /* CALL_AUDIO_H */