gets buffersize range and allows to set buffersize for alsa
This commit is contained in:
parent
7081c3bbd6
commit
d72b546dca
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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())?,
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
42
src/lib.rs
42
src/lib.rs
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue