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"
[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 = { version = "0.3", features = ["audiosessiontypes", "audioclient", "coml2api", "combaseapi", "debug", "devpkey", "handleapi", "ksmedia", "mmdeviceapi", "objbase", "profileapi", "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"] }
asio-sys = { version = "0.1", path = "asio-sys", optional = true }
parking_lot = "0.9"

View File

@ -9,7 +9,7 @@ fn main() -> Result<(), anyhow::Error> {
.default_output_device()
.expect("failed to find a default output device");
let config = device.default_output_config()?;
println!("{:#?}", &config);
match config.sample_format() {
cpal::SampleFormat::F32 => run::<f32>(&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()?);
// 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.
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;
@ -47,6 +48,7 @@ fn main() -> Result<(), anyhow::Error> {
}
let input_data_fn = move |data: &[f32], _: &cpal::InputCallbackInfo| {
println!("data len = {}", data.len());
let mut output_fell_behind = false;
for &sample in data {
if producer.push(sample).is_err() {

View File

@ -3,10 +3,10 @@ extern crate libc;
use self::alsa::poll::Descriptors;
use crate::{
BackendSpecificError, BufferSize, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError,
DeviceNameError, DevicesError, InputCallbackInfo, OutputCallbackInfo, PauseStreamError,
PlayStreamError, SampleFormat, SampleRate, StreamConfig, StreamError, SupportedBufferSizeRange, SupportedStreamConfig,
SupportedStreamConfigRange, SupportedStreamConfigsError,
BackendSpecificError, BuildStreamError, ChannelCount, Data, DefaultStreamConfigError,
BufferSize, DeviceNameError, DevicesError, InputCallbackInfo, OutputCallbackInfo, PauseStreamError,
PlayStreamError, SampleFormat, SampleRate, StreamConfig, StreamError, SupportedBufferSizeRange,
SupportedStreamConfig, SupportedStreamConfigRange, SupportedStreamConfigsError,
};
use std::convert::TryInto;
use std::sync::Arc;
@ -343,8 +343,8 @@ impl Device {
let max_buffer_size = hw_params.get_buffer_size_max()?;
let buffer_size_range = SupportedBufferSizeRange {
min: min_buffer_size,
max: max_buffer_size,
min: min_buffer_size as u32,
max: max_buffer_size as u32,
requires_power_of_two: false,
};
@ -358,7 +358,7 @@ impl Device {
channels: channels.clone(),
min_sample_rate: SampleRate(min_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,
});
}
@ -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_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
let mut hw_params_copy = hw_params.clone();
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);
/// 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.
///
@ -197,8 +203,8 @@ pub struct StreamConfig {
/// and if requested buffersize must be a power of 2 value.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SupportedBufferSizeRange {
pub min: BufferSize,
pub max: BufferSize,
pub min: FrameCount,
pub max: FrameCount,
pub requires_power_of_two: bool,
}
@ -223,7 +229,7 @@ pub struct SupportedStreamConfigRange {
pub struct SupportedStreamConfig {
channels: ChannelCount,
sample_rate: SampleRate,
buffer_size: BufferSize,
buffer_size: SupportedBufferSizeRange,
sample_format: SampleFormat,
}
@ -305,8 +311,8 @@ impl SupportedStreamConfig {
self.sample_rate
}
pub fn buffer_size(&self) -> BufferSize {
self.buffer_size
pub fn buffer_size(&self) -> &SupportedBufferSizeRange {
&self.buffer_size
}
pub fn sample_format(&self) -> SampleFormat {
@ -317,7 +323,7 @@ impl SupportedStreamConfig {
StreamConfig {
channels: self.channels,
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.
///
/// **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.
pub fn with_sample_rate_and_buffer_size(
pub fn with_sample_rate(
self,
sample_rate: SampleRate,
buffer_size: BufferSize,
) -> SupportedStreamConfig {
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 {
channels: self.channels,
sample_rate: self.max_sample_rate,
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,
}
}