Reduce Linux voice capture latency and verify device timing

This commit is contained in:
evgeny committed 2026-10-15 17:26:09 +02:00
1 parent 3276204196
commit 7477da42a5
11 files changed
+342 -38

No files matched your search

+14
View File
@@ -12,6 +12,18 @@ extern "C" void audio_stream_log_route(ma_device* device, int capture);
AudioDevice::AudioDevice() { m_clock.start(); }
AudioDevice::~AudioDevice() { close(); }
void AudioDevice::requestLowLatency(ma_context* context, ma_device_config& config) {
#ifdef __linux__
if (context && context->backend == ma_backend_pulseaudio) {
// Период I/O не зависит от размера кадра AEC/кодека; сервер согласует фактический буфер.
config.periodSizeInFrames = 0;
config.periodSizeInMilliseconds = 10;
}
#else
(void)context; (void)config;
#endif
}
bool AudioDevice::init(ma_context* context, ma_device_config config, const char* role, uint64_t session, Callback callback) {
close();
m_role = role;
@@ -22,6 +34,8 @@ bool AudioDevice::init(ma_context* context, ma_device_config config, const char*
config.noFixedSizedCallback = MA_TRUE; // Аппаратные чанки не требуют скрытого накопителя miniaudio.
config.notificationCallback = notification;
config.pUserData = this;
DEBUG_INFO(DEBUG_CATEGORY_CALL, "audio: %s requested backend=%s rate=%u period_frames=%u period_ms=%u",
role, ma_get_backend_name(context->backend), config.sampleRate, config.periodSizeInFrames, config.periodSizeInMilliseconds);
ma_result result = ma_device_init(context, &config, device);
if (result != MA_SUCCESS) {
DEBUG_ERROR(DEBUG_CATEGORY_CALL, "audio: %s init failed result=%d", role, result);
+1
View File
@@ -14,6 +14,7 @@ public:
~AudioDevice();
AudioDevice(const AudioDevice&) = delete;
AudioDevice& operator=(const AudioDevice&) = delete;
static void requestLowLatency(ma_context* context, ma_device_config& config);
bool init(ma_context* context, ma_device_config config, const char* role, uint64_t session, Callback callback);
bool start();
void pause(); // GUI: завершает текущий callback, сохраняя backend stream и его физический route.
+2 -2
View File
@@ -59,8 +59,8 @@ bool CallAudioEngine::openCapture() {
if (!context) return false;
ma_device_config config = ma_device_config_init(ma_device_type_capture);
config.capture.format = ma_format_s16; config.capture.channels = 1; config.sampleRate = CALL_AUDIO_SAMPLE_RATE;
config.periodSizeInMilliseconds = CALL_AUDIO_FRAME_MS;
DEBUG_INFO(DEBUG_CATEGORY_CALL, "CallAudio: capture requested period=%dms; actual period reported by device", CALL_AUDIO_FRAME_MS);
config.periodSizeInMilliseconds = 20; // Прежний запрос для остальных платформ/backends.
AudioDevice::requestLowLatency(context, config);
ma_device_id id;
bool selected = SoundManager::deviceId(m_captureId, &id);
if (selected) config.capture.pDeviceID = &id;
+1
View File
@@ -232,6 +232,7 @@ void RadioAudioEngine::openCapture() {
config.capture.format = ma_format_s16;
config.capture.channels = channels;
config.sampleRate = RADIO_AUDIO_SAMPLE_RATE;
AudioDevice::requestLowLatency(context, config);
auto callback = [this](const void* in, void*, unsigned int frames) { captureCallback(in, frames); };
ma_device_id id;
bool selected = SoundManager::deviceId(m_captureId, &id);