more hardware detection and adjustment
All checks were successful
Generic zig build / build (push) Successful in 23s

This commit is contained in:
Emil Lerch 2025-10-27 15:38:03 -07:00
parent 1363b2bfc2
commit b1c2ee20ff
Signed by: lobo
GPG key ID: A7B62D657EF764F8

View file

@ -454,19 +454,56 @@ pub const AlsaCapture = struct {
self.sample_rate = actual_rate;
}
// Set buffer size
// Get hardware constraints for buffer size
// SAFETY: this is set immediately as an out parameter in c API
var min_buffer: c.snd_pcm_uframes_t = undefined;
// SAFETY: this is set immediately as an out parameter in c API
var max_buffer: c.snd_pcm_uframes_t = undefined;
_ = c.snd_pcm_hw_params_get_buffer_size_min(hw_params, &min_buffer);
_ = c.snd_pcm_hw_params_get_buffer_size_max(hw_params, &max_buffer);
// Calculate minimum buffer size for ~40ms of audio
const calculated_min: u32 = @intCast((self.sample_rate * 40) / 1000);
const target_buffer = @max(self.buffer_size, calculated_min);
if (target_buffer < min_buffer) {
std.log.info("Buffer size {} too small, using minimum {}", .{ target_buffer, min_buffer });
self.buffer_size = @intCast(min_buffer);
} else if (target_buffer > max_buffer) {
std.log.info("Buffer size {} too large, using maximum {}", .{ target_buffer, max_buffer });
self.buffer_size = @intCast(max_buffer);
} else {
self.buffer_size = @intCast(target_buffer);
}
// Set buffer size first
var actual_buffer_size: c.snd_pcm_uframes_t = self.buffer_size;
err = c.snd_pcm_hw_params_set_buffer_size_near(self.pcm_handle, hw_params, &actual_buffer_size);
if (err < 0) return Error.SetBufferSizeError;
self.buffer_size = @intCast(actual_buffer_size);
// Set period size
var actual_period_size: c.snd_pcm_uframes_t = self.period_size;
err = c.snd_pcm_hw_params_set_period_size_near(self.pcm_handle, hw_params, &actual_period_size, null);
// Set period time (in microseconds) instead of period size for better compatibility
// Target ~10ms periods (10000 microseconds)
var period_time: c_uint = std.time.us_per_ms * 10;
var dir: c_int = 0;
err = c.snd_pcm_hw_params_set_period_time_near(self.pcm_handle, hw_params, &period_time, &dir);
if (err < 0) return Error.SetPeriodSizeError;
// Get the actual period size that was set
// SAFETY: this is set immediately as an out parameter in c API
var actual_period_size: c.snd_pcm_uframes_t = undefined;
err = c.snd_pcm_hw_params_get_period_size(hw_params, &actual_period_size, null);
if (err >= 0) {
self.period_size = @intCast(actual_period_size);
}
std.log.debug("ALSA params: rate={}, channels={}, buffer={}, period={}", .{ self.sample_rate, self.channels, actual_buffer_size, self.period_size });
// Apply hardware parameters
err = c.snd_pcm_hw_params(self.pcm_handle, hw_params);
if (err < 0) return Error.ApplyParametersError;
if (err < 0) {
std.log.err("snd_pcm_hw_params failed with error code: {}", .{err});
return Error.ApplyParametersError;
}
// Prepare the PCM for use
err = c.snd_pcm_prepare(self.pcm_handle);