diff --git a/CHANGELOG.md b/CHANGELOG.md index c7a418f..bb557a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## v2.0.1 +Bugfixes: +- Ignore capture_samplerate when resampling is disabled. +- Increase Alsa device buffer sizes to avoid errors. + ## v2.0.0 New features: - Add dynamic range compressor. diff --git a/Cargo.toml b/Cargo.toml index 582a232..8659abd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "camilladsp" -version = "2.0.0" +version = "2.0.1" authors = ["Henrik Enquist "] edition = "2021" description = "A flexible tool for processing audio" @@ -63,7 +63,7 @@ lazy_static = "1.4.0" log = "0.4.14" flexi_logger = { version = "0.27.2", features = ["async", "colors"] } chrono = "0.4" -tungstenite = { version = "0.16.0", optional = true, default-features = false } +tungstenite = { version = "0.21.0", optional = true } native-tls = { version = "0.2.7", optional = true } libpulse-binding = { version = "2.0", optional = true } libpulse-simple-binding = { version = "2.0", optional = true } diff --git a/src/alsadevice_buffermanager.rs b/src/alsadevice_buffermanager.rs index 503d34b..33258e2 100644 --- a/src/alsadevice_buffermanager.rs +++ b/src/alsadevice_buffermanager.rs @@ -15,30 +15,44 @@ pub trait DeviceBufferManager { fn apply_start_threshold(&mut self, swp: &SwParams) -> Res<()>; - // Calculate a power-of-two buffer size that is large enough to accommodate any changes due to resampling. - fn calculate_buffer_size(&self) -> Frames { + // Calculate a power-of-two buffer size that is large enough to accommodate any changes due to resampling, + // and at least 4 times the minimum period size to avoid random broken pipes. + fn calculate_buffer_size(&self, min_period: Frames) -> Frames { let data = self.data(); - 2.0f32.powi( - (1.2 * data.chunksize as f32 / data.resampling_ratio) - .log2() - .ceil() as i32, - ) as Frames + let mut frames_needed = 3.0 * data.chunksize as f32 / data.resampling_ratio; + if frames_needed < 4.0 * min_period as f32 { + frames_needed = 4.0 * min_period as f32; + debug!( + "Minimum period is {} frames, buffer size is minimum {} frames", + min_period, frames_needed + ); + } + 2.0f32.powi(frames_needed.log2().ceil() as i32) as Frames } - // Calculate an alternative buffer size that is 3 multiplied by a power-of-two. - // This is for some devices that cannot wotk with the default setting, + // Calculate an alternative buffer size that is 3 multiplied by a power-of-two, + // and at least 4 times the minimum period size to avoid random broken pipes. + // This is for some devices that cannot work with the default setting, // and when set_buffer_size_near() does not return a working alternative near the requested one. // Caused by driver bugs? - fn calculate_buffer_size_alt(&self) -> Frames { + fn calculate_buffer_size_alt(&self, min_period: Frames) -> Frames { let data = self.data(); - let frames_needed = 1.2 * data.chunksize as f32 / data.resampling_ratio; + let mut frames_needed = 3.0 * data.chunksize as f32 / data.resampling_ratio; + if frames_needed < 4.0 * min_period as f32 { + frames_needed = 4.0 * min_period as f32; + debug!( + "Minimum period is {} frames, alternate buffer size is minimum {} frames", + min_period, frames_needed + ); + } 3 * 2.0f32.powi((frames_needed / 3.0).log2().ceil() as i32) as Frames } // Calculate a buffer size and apply it to a hwp container. Only for use when opening a device. fn apply_buffer_size(&mut self, hwp: &HwParams) -> Res<()> { - let buffer_frames = self.calculate_buffer_size(); - let alt_buffer_frames = self.calculate_buffer_size_alt(); + let min_period = hwp.get_period_size_min().unwrap_or(0); + let buffer_frames = self.calculate_buffer_size(min_period); + let alt_buffer_frames = self.calculate_buffer_size_alt(min_period); let data = self.data_mut(); debug!("Setting buffer size to {} frames", buffer_frames); match hwp.set_buffer_size_near(buffer_frames) { @@ -53,7 +67,6 @@ pub trait DeviceBufferManager { data.bufsize = hwp.set_buffer_size_near(alt_buffer_frames)?; } } - //data.bufsize = hwp.set_buffer_size_near(buffer_frames)?; debug!("Device is using a buffer size of {} frames", data.bufsize); Ok(()) } diff --git a/src/audiodevice.rs b/src/audiodevice.rs index d8346ce..e94bd70 100644 --- a/src/audiodevice.rs +++ b/src/audiodevice.rs @@ -505,12 +505,18 @@ pub fn new_resampler( /// Create a capture device. pub fn new_capture_device(conf: config::Devices) -> Box { - //let resampler = new_resampler(&conf); + // Use `capture_samplerate` from config if given, and resampling is enabled. + // Else, use `samplerate`. let capture_samplerate = if conf.capture_samplerate.is_some() && conf.resampler.is_some() { conf.capture_samplerate.unwrap() } else { conf.samplerate }; + if let Some(cr) = conf.capture_samplerate { + if cr != conf.samplerate && conf.resampler.is_none() { + warn!("Resampling is disabled and capture_samplerate is different than samplerate, ignoring capture_samplerate."); + } + } let diff_rates = capture_samplerate != conf.samplerate; // Check for non-optimal resampling settings if !diff_rates && conf.resampler.is_some() && !conf.rate_adjust() { diff --git a/src/config.rs b/src/config.rs index f838621..9e117f6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1683,14 +1683,6 @@ pub fn validate_config(conf: &mut Configuration, filename: Option<&str>) -> Res< return Err(ConfigError::new("silence_timeout cannot be negative").into()); } } - if let Some(rate) = conf.devices.capture_samplerate { - if rate != conf.devices.samplerate && conf.devices.resampler.is_none() { - return Err(ConfigError::new( - "capture_samplerate must match samplerate when resampling is disabled", - ) - .into()); - } - } if conf.devices.ramp_time() < 0.0 { return Err(ConfigError::new("Volume ramp time cannot be negative").into()); } diff --git a/src/countertimer.rs b/src/countertimer.rs index 676ef27..175e1b5 100644 --- a/src/countertimer.rs +++ b/src/countertimer.rs @@ -351,11 +351,11 @@ impl ValueHistory { } pub fn last(&self) -> Option { - self.buffer.get(0).cloned() + self.buffer.front().cloned() } pub fn last_sqrt(&self) -> Option { - let mut result = self.buffer.get(0).cloned(); + let mut result = self.buffer.front().cloned(); if let Some(ref mut record) = result { record.values.iter_mut().for_each(|val| *val = val.sqrt()) }; diff --git a/src/socketserver.rs b/src/socketserver.rs index c54c5f5..145661d 100644 --- a/src/socketserver.rs +++ b/src/socketserver.rs @@ -480,7 +480,7 @@ macro_rules! make_handler { ) { match websocket_res { Ok(mut websocket) => loop { - let msg_res = websocket.read_message(); + let msg_res = websocket.read(); match msg_res { Ok(msg) => { trace!("received: {:?}", msg); @@ -493,9 +493,8 @@ macro_rules! make_handler { }), }; if let Some(rep) = reply { - let write_result = websocket.write_message(Message::text( - serde_json::to_string(&rep).unwrap(), - )); + let write_result = websocket + .send(Message::text(serde_json::to_string(&rep).unwrap())); if let Err(err) = write_result { warn!("Failed to write: {}", err); break;