gets buffersize range and allows to set buffersize for alsa

This commit is contained in:
JoshuaBatty 2020-05-21 09:41:23 +02:00
parent 7081c3bbd6
commit d72b546dca
5 changed files with 46 additions and 27 deletions

View File

@ -22,8 +22,8 @@ hound = "3.4"
ringbuf = "0.1.6" ringbuf = "0.1.6"
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
winapi = { path = "../winapi-rs", version = "0.3", features = ["audiosessiontypes", "audioclient", "coml2api", "combaseapi", "debug", "devpkey", "errhandlingapi", "handleapi", "ksmedia", "mmdeviceapi", "objbase", "std", "synchapi", "winbase", "winuser"] } # winapi = { path = "../winapi-rs", version = "0.3", features = ["audiosessiontypes", "audioclient", "coml2api", "combaseapi", "debug", "devpkey", "errhandlingapi", "handleapi", "ksmedia", "mmdeviceapi", "objbase", "std", "synchapi", "winbase", "winuser"] }
# winapi = { version = "0.3", features = ["audiosessiontypes", "audioclient", "coml2api", "combaseapi", "debug", "devpkey", "handleapi", "ksmedia", "mmdeviceapi", "objbase", "profileapi", "std", "synchapi", "winbase", "winuser"] } winapi = { version = "0.3", features = ["audiosessiontypes", "audioclient", "coml2api", "combaseapi", "debug", "devpkey", "handleapi", "ksmedia", "mmdeviceapi", "objbase", "profileapi", "std", "synchapi", "winbase", "winuser"] }
asio-sys = { version = "0.1", path = "asio-sys", optional = true } asio-sys = { version = "0.1", path = "asio-sys", optional = true }
parking_lot = "0.9" parking_lot = "0.9"

View File

@ -9,7 +9,7 @@ fn main() -> Result<(), anyhow::Error> {
.default_output_device() .default_output_device()
.expect("failed to find a default output device"); .expect("failed to find a default output device");
let config = device.default_output_config()?; let config = device.default_output_config()?;
println!("{:#?}", &config);
match config.sample_format() { match config.sample_format() {
cpal::SampleFormat::F32 => run::<f32>(&device, &config.into())?, cpal::SampleFormat::F32 => run::<f32>(&device, &config.into())?,
cpal::SampleFormat::I16 => run::<i16>(&device, &config.into())?, cpal::SampleFormat::I16 => run::<i16>(&device, &config.into())?,

View File

@ -29,8 +29,9 @@ fn main() -> Result<(), anyhow::Error> {
println!("Using default output device: \"{}\"", output_device.name()?); println!("Using default output device: \"{}\"", output_device.name()?);
// We'll try and use the same configuration between streams to keep it simple. // We'll try and use the same configuration between streams to keep it simple.
let config: cpal::StreamConfig = input_device.default_input_config()?.into(); let mut config: cpal::StreamConfig = input_device.default_input_config()?.into();
config.buffer_size = cpal::BufferSize::Fixed(1024);
// Create a delay in case the input and output devices aren't synced. // Create a delay in case the input and output devices aren't synced.
let latency_frames = (LATENCY_MS / 1_000.0) * config.sample_rate.0 as f32; let latency_frames = (LATENCY_MS / 1_000.0) * config.sample_rate.0 as f32;
let latency_samples = latency_frames as usize * config.channels as usize; let latency_samples = latency_frames as usize * config.channels as usize;
@ -47,6 +48,7 @@ fn main() -> Result<(), anyhow::Error> {
} }
let input_data_fn = move |data: &[f32], _: &cpal::InputCallbackInfo| { let input_data_fn = move |data: &[f32], _: &cpal::InputCallbackInfo| {
println!("data len = {}", data.len());
let mut output_fell_behind = false; let mut output_fell_behind = false;
for &sample in data { for &sample in data {
if producer.push(sample).is_err() { if producer.push(sample).is_err() {

View File

@ -3,10 +3,10 @@ extern crate libc;
use self::alsa::poll::Descriptors; use self::alsa::poll::Descriptors;
use crate::{ use crate::{
BackendSpecificError, BufferSize, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError, BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError,
DeviceNameError, DevicesError, InputCallbackInfo, OutputCallbackInfo, PauseStreamError, BufferSize, DeviceNameError, DevicesError, InputCallbackInfo, OutputCallbackInfo, PauseStreamError,
PlayStreamError, SampleFormat, SampleRate, StreamConfig, StreamError, SupportedBufferSizeRange, SupportedStreamConfig, PlayStreamError, SampleFormat, SampleRate, StreamConfig, StreamError, SupportedBufferSizeRange,
SupportedStreamConfigRange, SupportedStreamConfigsError, SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError,
}; };
use std::convert::TryInto; use std::convert::TryInto;
use std::sync::Arc; use std::sync::Arc;
@ -343,8 +343,8 @@ impl Device {
let max_buffer_size = hw_params.get_buffer_size_max()?; let max_buffer_size = hw_params.get_buffer_size_max()?;
let buffer_size_range = SupportedBufferSizeRange { let buffer_size_range = SupportedBufferSizeRange {
min: min_buffer_size, min: min_buffer_size as u32,
max: max_buffer_size, max: max_buffer_size as u32,
requires_power_of_two: false, requires_power_of_two: false,
}; };
@ -358,7 +358,7 @@ impl Device {
channels: channels.clone(), channels: channels.clone(),
min_sample_rate: SampleRate(min_rate as u32), min_sample_rate: SampleRate(min_rate as u32),
max_sample_rate: SampleRate(max_rate as u32), max_sample_rate: SampleRate(max_rate as u32),
buffer_size: buffer_size_range, buffer_size: buffer_size_range.clone(),
sample_format: sample_format, sample_format: sample_format,
}); });
} }
@ -900,6 +900,11 @@ fn set_hw_params_from_format<'a>(
hw_params.set_rate(config.sample_rate.0, alsa::ValueOr::Nearest)?; hw_params.set_rate(config.sample_rate.0, alsa::ValueOr::Nearest)?;
hw_params.set_channels(config.channels as u32)?; hw_params.set_channels(config.channels as u32)?;
match config.buffer_size {
BufferSize::Fixed(v) => hw_params.set_buffer_size(v as i64)?,
BufferSize::Default => (),
}
// If this isn't set manually a overlarge buffer may be used causing audio delay // If this isn't set manually a overlarge buffer may be used causing audio delay
let mut hw_params_copy = hw_params.clone(); let mut hw_params_copy = hw_params.clone();
if let Err(_) = hw_params.set_buffer_time_near(100_000, alsa::ValueOr::Nearest) { if let Err(_) = hw_params.set_buffer_time_near(100_000, alsa::ValueOr::Nearest) {

View File

@ -181,7 +181,13 @@ pub type ChannelCount = u16;
pub struct SampleRate(pub u32); pub struct SampleRate(pub u32);
/// The desired number of frames for the hardware buffer. /// The desired number of frames for the hardware buffer.
pub type BufferSize = u32; pub type FrameCount = u32;
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum BufferSize {
Default,
Fixed(FrameCount),
}
/// The set of parameters used to describe how to open a stream. /// The set of parameters used to describe how to open a stream.
/// ///
@ -197,8 +203,8 @@ pub struct StreamConfig {
/// and if requested buffersize must be a power of 2 value. /// and if requested buffersize must be a power of 2 value.
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct SupportedBufferSizeRange { pub struct SupportedBufferSizeRange {
pub min: BufferSize, pub min: FrameCount,
pub max: BufferSize, pub max: FrameCount,
pub requires_power_of_two: bool, pub requires_power_of_two: bool,
} }
@ -223,7 +229,7 @@ pub struct SupportedStreamConfigRange {
pub struct SupportedStreamConfig { pub struct SupportedStreamConfig {
channels: ChannelCount, channels: ChannelCount,
sample_rate: SampleRate, sample_rate: SampleRate,
buffer_size: BufferSize, buffer_size: SupportedBufferSizeRange,
sample_format: SampleFormat, sample_format: SampleFormat,
} }
@ -305,8 +311,8 @@ impl SupportedStreamConfig {
self.sample_rate self.sample_rate
} }
pub fn buffer_size(&self) -> BufferSize { pub fn buffer_size(&self) -> &SupportedBufferSizeRange {
self.buffer_size &self.buffer_size
} }
pub fn sample_format(&self) -> SampleFormat { pub fn sample_format(&self) -> SampleFormat {
@ -317,7 +323,7 @@ impl SupportedStreamConfig {
StreamConfig { StreamConfig {
channels: self.channels, channels: self.channels,
sample_rate: self.sample_rate, sample_rate: self.sample_rate,
buffer_size: self.buffer_size, buffer_size: BufferSize::Default,
} }
} }
} }
@ -523,23 +529,29 @@ impl SupportedStreamConfigRange {
/// Retrieve a `SupportedStreamConfig` with the given sample rate and buffer size. /// Retrieve a `SupportedStreamConfig` with the given sample rate and buffer size.
/// ///
/// **panic!**s if the given `sample_rate` or the give `buffer_size` is outside the range specified within this /// **panic!**s if the given `sample_rate` is outside the range specified within this
/// `SupportedStreamConfigRange` instance. /// `SupportedStreamConfigRange` instance.
pub fn with_sample_rate_and_buffer_size( pub fn with_sample_rate(
self, self,
sample_rate: SampleRate, sample_rate: SampleRate,
buffer_size: BufferSize,
) -> SupportedStreamConfig { ) -> SupportedStreamConfig {
assert!(self.min_sample_rate <= sample_rate && sample_rate <= self.max_sample_rate); assert!(self.min_sample_rate <= sample_rate && sample_rate <= self.max_sample_rate);
assert!(self.buffer_size.min <= buffer_size && buffer_size <= self.buffer_size.max);
if self.buffer_size.requires_power_of_two {
assert!(buffer_size.is_power_of_two());
}
SupportedStreamConfig { SupportedStreamConfig {
channels: self.channels, channels: self.channels,
sample_rate: self.max_sample_rate, sample_rate: self.max_sample_rate,
sample_format: self.sample_format, sample_format: self.sample_format,
buffer_size, buffer_size: self.buffer_size,
}
}
/// Turns this `SupportedStreamConfigRange` into a `SupportedStreamConfig` corresponding to the maximum samples rate.
#[inline]
pub fn with_max_sample_rate(self) -> SupportedStreamConfig {
SupportedStreamConfig {
channels: self.channels,
sample_rate: self.max_sample_rate,
sample_format: self.sample_format,
buffer_size: self.buffer_size,
} }
} }