Reduce Linux voice capture latency and verify device timing
This commit is contained in:
1 parent
3276204196
commit
7477da42a5
11 files changed
+342
-38
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user