From 52942adb58c0027e48bc6f30cc2fd9fa5d5c5c36 Mon Sep 17 00:00:00 2001 From: Jackson Goode <54308792+jacksongoode@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:36:35 +0900 Subject: [PATCH 1/5] Remove non-inference files from libDF --- libDF/src/augmentations.rs | 1537 ------------------- libDF/src/bin/enhance_wav.rs | 186 --- libDF/src/bin/sample-dataset.rs | 180 --- libDF/src/bin/sample-hdf5.rs | 29 - libDF/src/capi.rs | 253 ---- libDF/src/dataloader.rs | 741 ---------- libDF/src/dataset.rs | 2449 ------------------------------- libDF/src/hdf5_key_cache.rs | 67 - libDF/src/logging.rs | 53 - libDF/src/transforms.rs | 711 --------- libDF/src/util.rs | 98 -- libDF/src/wasm.rs | 88 -- libDF/src/wav_utils.rs | 160 -- 13 files changed, 6552 deletions(-) delete mode 100644 libDF/src/augmentations.rs delete mode 100644 libDF/src/bin/enhance_wav.rs delete mode 100644 libDF/src/bin/sample-dataset.rs delete mode 100644 libDF/src/bin/sample-hdf5.rs delete mode 100644 libDF/src/capi.rs delete mode 100644 libDF/src/dataloader.rs delete mode 100644 libDF/src/dataset.rs delete mode 100644 libDF/src/hdf5_key_cache.rs delete mode 100644 libDF/src/logging.rs delete mode 100644 libDF/src/transforms.rs delete mode 100644 libDF/src/util.rs delete mode 100644 libDF/src/wasm.rs delete mode 100644 libDF/src/wav_utils.rs diff --git a/libDF/src/augmentations.rs b/libDF/src/augmentations.rs deleted file mode 100644 index 5bde02b72..000000000 --- a/libDF/src/augmentations.rs +++ /dev/null @@ -1,1537 +0,0 @@ -use std::collections::BTreeMap; -use std::ops::Range; -#[cfg(feature = "timings")] -use std::time::Instant; - -use ndarray::{concatenate, prelude::*, Slice}; -use ndarray_rand::rand::{prelude::IteratorRandom, seq::SliceRandom, Rng}; -use ndarray_rand::{rand_distr::Normal, rand_distr::Uniform, RandomExt}; -use thiserror::Error; - -use self::BiquadFilter::*; -use crate::transforms::*; -pub use crate::util::seed_from_u64; -use crate::util::*; -use crate::*; - -type Result = std::result::Result; - -#[derive(Error, Debug)] -pub enum AugmentationError { - #[error("DF UtilsError")] - UtilsError(#[from] UtilsError), - #[error("DF Transforms Error")] - TransformError(#[from] crate::transforms::TransformError), - #[error("Wrong input")] - WrongInput, - #[error("Transform {transform} not initalized: {msg}")] - NotInitialized { transform: String, msg: String }, - #[error("DF error: {0}")] - DfError(String), - #[error("Ndarray Shape Error")] - NdarrayShapeError(#[from] ndarray::ShapeError), - #[error("Wav Reader Error")] - WavReadError(#[from] crate::wav_utils::WavUtilsError), -} - -pub enum TransformInput<'a> { - Audio(&'a mut Array2), - Spectrum(&'a mut Array3), -} -impl<'a> From<&'a mut Array2> for TransformInput<'a> { - fn from(audio: &'a mut Array2) -> Self { - TransformInput::Audio(audio) - } -} -impl<'a> From<&'a mut Array3> for TransformInput<'a> { - fn from(spec: &'a mut Array3) -> Self { - TransformInput::Spectrum(spec) - } -} - -pub trait Transform { - fn transform(&self, x: &mut TransformInput) -> Result<()>; - fn default_with_prob(p: f32) -> Self - where - Self: Sized; - fn box_clone(&self) -> Box; - fn name(&self) -> &str; -} - -impl Clone for Box { - fn clone(&self) -> Box { - self.box_clone() - } -} - -pub struct Compose { - pub transforms: Vec>, - log_timings: bool, -} -unsafe impl Send for Compose {} -unsafe impl Sync for Compose {} - -impl Compose { - pub fn new(transforms: Vec>) -> Self { - Compose { - transforms, - log_timings: false, - } - } - - pub fn log_timings(&mut self) { - self.log_timings = true - } - - pub fn push(&mut self, t: Box) { - self.transforms.push(t); - } - - pub fn transform(&self, x: &mut TransformInput) -> Result<()> { - #[cfg(feature = "timings")] - let mut t0 = Instant::now(); - #[cfg(feature = "timings")] - let mut timings = Vec::new(); - for t in self.transforms.iter() { - match t.transform(x) { - Ok(()) => (), - Err(e) => log::error!("{:?}", e), - }; - #[cfg(feature = "timings")] - { - let t1 = Instant::now(); - let d = (t1 - t0).as_micros(); - if d > 10 { - timings.push(format!("{}: {} ms", t.name(), d / 1000)); - } - t0 = t1; - } - } - #[cfg(feature = "timings")] - if log::log_enabled!(log::Level::Trace) && !timings.is_empty() { - log::trace!( - "Calculated augmentation transforms in {:?}", - timings.join(", ") - ); - } - Ok(()) - } - pub fn len(&self) -> usize { - self.transforms.len() - } - pub fn is_empty(&self) -> bool { - self.transforms.is_empty() - } -} -impl Clone for Compose { - fn clone(&self) -> Self { - Compose { - transforms: self.transforms.iter().map(|t| t.box_clone()).collect(), - log_timings: self.log_timings, - } - } -} - -// Adopted from RNNoise/PercepNet -#[derive(Clone)] -pub struct RandLFilt { - prob: f32, - uniform: Uniform, -} -impl RandLFilt { - pub fn new(p: f32, a: f32, b: f32) -> Self { - let uniform = Uniform::new_inclusive(a, b); - RandLFilt { prob: p, uniform } - } - fn sample_ab(&self) -> Result<[f32; 2]> { - let mut rng = thread_rng()?; - Ok([rng.sample(self.uniform), rng.sample(self.uniform)]) - } -} -impl Transform for RandLFilt { - fn transform(&self, inp: &mut TransformInput) -> Result<()> { - if self.prob == 0. || (self.prob < 1. && thread_rng()?.uniform(0f32, 1f32) > self.prob) { - return Ok(()); - } - let a: [f32; 2] = self.sample_ab()?; - let b: [f32; 2] = self.sample_ab()?; - let mut mem = [0f32; 2]; - let x = match inp { - TransformInput::Spectrum(_) => return Err(AugmentationError::WrongInput), - TransformInput::Audio(a) => a, - }; - for x_ch in x.axis_iter_mut(Axis(0)) { - biquad_norm_inplace(x_ch, &mut mem, &b, &a); - } - Ok(()) - } - fn default_with_prob(p: f32) -> Self { - Self::new(p, -3. / 8., 3. / 8.) - } - fn box_clone(&self) -> Box { - Box::new((*self).clone()) - } - fn name(&self) -> &str { - "RandLFilt" - } -} - -fn high_shelf(center_freq: f32, gain_db: f32, q_factor: f32, sr: usize) -> ([f32; 3], [f32; 3]) { - let w0 = 2. * std::f32::consts::PI * center_freq / sr as f32; - let amp = 10f32.powf(gain_db / 40.); - let alpha = w0.sin() / 2. / q_factor; - - let b0 = amp * ((amp + 1.) + (amp - 1.) * w0.cos() + 2. * amp.sqrt() * alpha); - let b1 = -2. * amp * ((amp - 1.) + (amp + 1.) * w0.cos()); - let b2 = amp * ((amp + 1.) + (amp - 1.) * w0.cos() - 2. * amp.sqrt() * alpha); - let a0 = (amp + 1.) - (amp - 1.) * w0.cos() + 2. * amp.sqrt() * alpha; - let a1 = 2. * ((amp - 1.) - (amp + 1.) * w0.cos()); - let a2 = (amp + 1.) - (amp - 1.) * w0.cos() - 2. * amp.sqrt() * alpha; - ([b0, b1, b2], [a0, a1, a2]) -} -fn high_pass(center_freq: f32, q_factor: f32, sr: usize) -> ([f32; 3], [f32; 3]) { - let w0 = 2. * std::f32::consts::PI * center_freq / sr as f32; - let alpha = w0.sin() / 2. / q_factor; - - let b0 = (1. + w0.cos()) / 2.; - let b1 = -(1. + w0.cos()); - let b2 = (1. + w0.cos()) / 2.; - let a0 = 1. + alpha; - let a1 = -2. * w0.cos(); - let a2 = 1. - alpha; - ([b0, b1, b2], [a0, a1, a2]) -} -fn low_shelf(center_freq: f32, gain_db: f32, q_factor: f32, sr: usize) -> ([f32; 3], [f32; 3]) { - let w0 = 2. * std::f32::consts::PI * center_freq / sr as f32; - let amp = 10f32.powf(gain_db / 40.); - let alpha = w0.sin() / 2. / q_factor; - - let b0 = amp * ((amp + 1.) - (amp - 1.) * w0.cos() + 2. * amp.sqrt() * alpha); - let b1 = 2. * amp * ((amp - 1.) - (amp + 1.) * w0.cos()); - let b2 = amp * ((amp + 1.) - (amp - 1.) * w0.cos() - 2. * amp.sqrt() * alpha); - let a0 = (amp + 1.) + (amp - 1.) * w0.cos() + 2. * amp.sqrt() * alpha; - let a1 = -2. * ((amp - 1.) + (amp + 1.) * w0.cos()); - let a2 = (amp + 1.) + (amp - 1.) * w0.cos() - 2. * amp.sqrt() * alpha; - ([b0, b1, b2], [a0, a1, a2]) -} -pub fn low_pass(center_freq: f32, q_factor: f32, sr: usize) -> ([f32; 3], [f32; 3]) { - let w0 = 2. * std::f32::consts::PI * center_freq / sr as f32; - let alpha = w0.sin() / 2. / q_factor; - - let b0 = (1. - w0.cos()) / 2.; - let b1 = 1. - w0.cos(); - let b2 = b0; - let a0 = 1. + alpha; - let a1 = -2. * w0.cos(); - let a2 = 1. - alpha; - ([b0, b1, b2], [a0, a1, a2]) -} -fn peaking_eq(center_freq: f32, gain_db: f32, q_factor: f32, sr: usize) -> ([f32; 3], [f32; 3]) { - let w0 = 2. * std::f32::consts::PI * center_freq / sr as f32; - let amp = 10f32.powf(gain_db / 40.); - let alpha = w0.sin() / 2. / q_factor; - - let b0 = 1. + alpha * amp; - let b1 = -2. * w0.cos(); - let b2 = 1. - alpha * amp; - let a0 = 1. + alpha / amp; - let a1 = -2. * w0.cos(); - let a2 = 1. - alpha / amp; - ([b0, b1, b2], [a0, a1, a2]) -} -fn notch(center_freq: f32, q_factor: f32, sr: usize) -> ([f32; 3], [f32; 3]) { - let w0 = 2. * std::f32::consts::PI * center_freq / sr as f32; - let alpha = w0.sin() / 2. / q_factor; - - let b0 = 1.; - let b1 = -2. * w0.cos(); - let b2 = 1.; - let a0 = 1. + alpha; - let a1 = -2. * w0.cos(); - let a2 = 1. - alpha; - ([b0, b1, b2], [a0, a1, a2]) -} -fn biquad_filter(x: &mut Array2, b: &[f32; 3], a: &[f32; 3]) { - for x_ch in x.axis_iter_mut(Axis(0)) { - let mut mem = [0.; 2]; - biquad_inplace(x_ch, &mut mem, b, a); - } -} - -#[derive(Clone, Copy, Debug)] -pub(crate) enum BiquadFilter { - HighShelf, - LowShelf, - HighPass, - LowPass, - PeakingEQ, - Notch, -} -impl BiquadFilter { - pub fn iterator() -> impl Iterator { - [HighShelf, LowShelf, HighPass, LowPass, PeakingEQ, Notch].iter().copied() - } -} - -/// Apply random biquad filters based on https://www.w3.org/TR/audio-eq-cookbook/ -/// -/// # Available filters: -/// * LowPass -/// * LowShelf -/// * HighPass -/// * HighShelf -/// * PeakingEQ -/// * Notch -#[derive(Clone)] -pub struct RandBiquadFilter { - prob: f32, - sr: Option, - n_freqs: usize, - gain_db_low: f32, - gain_db_high: f32, - q_low: f32, - q_high: f32, - filters: Vec, - equalize_rms: bool, -} -impl RandBiquadFilter { - pub fn with_sr(mut self, sr: usize) -> Self { - self.sr = Some(sr); - self - } - pub(crate) fn apply( - &self, - x: &mut Array2, - filter: BiquadFilter, - freq: f32, - q: f32, - gain_db: Option, - ) { - let sr = self.sr.unwrap(); - if log::log_enabled!(log::Level::Trace) { - log::trace!( - "Augmentation RandBiquadFilter (filter: {:?}, freq: {}, q: {}, db: {})", - filter, - freq, - q, - gain_db.unwrap_or_default() - ); - } - let (b, a) = match filter { - HighShelf => high_shelf(freq, gain_db.unwrap(), q, sr), - LowShelf => low_shelf(freq, gain_db.unwrap(), q, sr), - HighPass => high_pass(freq, q, sr), - LowPass => low_pass(freq, q, sr), - PeakingEQ => peaking_eq(freq, gain_db.unwrap(), q, sr), - Notch => notch(freq, q, sr), - }; - biquad_filter(x, &b, &a); - } -} -impl Transform for RandBiquadFilter { - fn transform(&self, x: &mut TransformInput) -> Result<()> { - let x = match x { - TransformInput::Spectrum(_) => return Err(AugmentationError::WrongInput), - TransformInput::Audio(a) => a, - }; - if self.sr.is_none() { - return Err(AugmentationError::NotInitialized { - transform: "RandBiquadFilter".into(), - msg: "No sampling rate provided.".into(), - }); - } - let mut rng = thread_rng()?; - if self.prob == 0. || (self.prob < 1. && rng.uniform(0f32, 1f32) > self.prob) { - return Ok(()); - } - let rms = x.map(|&x| x.powi(2)).mean().unwrap().sqrt(); - for _ in 0..rng.uniform_inclusive(1, self.n_freqs) { - let filter = self.filters.choose(&mut rng).unwrap(); - let (f_low, f_high) = match filter { - LowPass => (4000, 8000), - HighShelf => (1000, 8000), - HighPass => (40, 400), - LowShelf => (40, 1000), - _ => (40, 4000), - }; - let freq = rng.log_uniform(f_low as f32, f_high as f32); - let gain_db = rng.uniform_inclusive(self.gain_db_low, self.gain_db_high); - let q = rng.uniform_inclusive(self.q_low, self.q_high); - self.apply(x, *filter, freq, q, Some(gain_db)); - } - if self.equalize_rms { - let rms_new = x.map(|&x| x.powi(2)).mean().unwrap().sqrt(); - x.mapv_inplace(|s| s * rms / rms_new); - } - // Guard against clipping - let max = find_max_abs(x.iter()).unwrap(); - if (max - 1.) > 1e-10 { - let f = 1. / (max + 1e-10); - log::debug!( - "RandBiquadFilter: Clipping detected. Reducing gain by: {}", - max - ); - x.mapv_inplace(|s| s * f); - } - Ok(()) - } - fn default_with_prob(p: f32) -> Self { - RandBiquadFilter { - prob: p, - sr: None, - n_freqs: 3, - gain_db_high: 15., - gain_db_low: -15., - q_low: 0.5, - q_high: 1.5, - filters: BiquadFilter::iterator().collect(), - equalize_rms: true, - } - } - fn box_clone(&self) -> Box { - Box::new((*self).clone()) - } - fn name(&self) -> &str { - "RandBiquadFilter" - } -} - -#[derive(Clone)] -pub struct RandResample { - prob: f32, - sr: Option, - r_low: f32, - r_high: f32, - chunk_size: usize, -} -impl RandResample { - pub fn new(p: f32, sr: usize, r_low: f32, r_high: f32, chunk_size: usize) -> Self { - RandResample { - prob: p, - sr: Some(sr), - r_low, - r_high, - chunk_size, - } - } - pub fn with_sr(mut self, sr: usize) -> Self { - self.sr = Some(sr); - self - } -} -impl Transform for RandResample { - fn transform(&self, x: &mut TransformInput) -> Result<()> { - let x = match x { - TransformInput::Spectrum(_) => return Err(AugmentationError::WrongInput), - TransformInput::Audio(a) => a, - }; - if self.sr.is_none() { - return Err(AugmentationError::NotInitialized { - transform: "RandEQ".into(), - msg: "No sampling rate provided.".into(), - }); - } - let mut rng = thread_rng()?; - let sr = self.sr.unwrap(); - if self.prob == 0. || (self.prob < 1. && rng.uniform(0f32, 1f32) > self.prob) { - return Ok(()); - } - let ch = x.len_of(Axis(0)); - let len = x.len_of(Axis(1)); - let new_sr = rng.uniform_inclusive(self.r_low, self.r_high) * sr as f32; - // round so we get a better gcd - let new_sr = ((new_sr / 500.).round() * 500.) as usize; - if new_sr == sr { - return Ok(()); - } - let out = resample(x.view(), sr, new_sr, Some(self.chunk_size))?; - let new_len = out.len_of(Axis(1)); - if new_len > len { - x.append(Axis(1), Array2::zeros((ch, new_len - len)).view())?; - } else { - x.slice_axis_inplace(Axis(1), Slice::from(0..new_len)); - } - x.clone_from(&out); - // out.move_into(x); - Ok(()) - } - fn default_with_prob(p: f32) -> Self { - RandResample { - prob: p, - sr: None, - r_low: 0.9, - r_high: 1.1, - chunk_size: 1024, - } - } - fn box_clone(&self) -> Box { - Box::new((*self).clone()) - } - fn name(&self) -> &str { - "RandResample" - } -} - -#[derive(Clone)] -pub struct RandClipping { - prob: f32, - db_range: Option>, - c_range: Option>, - eps: f32, - eps_c: f32, -} -impl RandClipping { - pub fn new(p: f32, eps: f32, convergence_eps: f32) -> Self { - RandClipping { - prob: p, - db_range: None, - c_range: None, - eps, - eps_c: convergence_eps, - } - } - pub fn with_snr(mut self, db_range: Range) -> Self { - self.db_range = Some(db_range); - self.c_range = None; - self - } - pub fn with_c(mut self, c_range: Range) -> Self { - self.db_range = None; - self.c_range = Some(c_range); - self - } - fn clip_inplace(&self, x: &mut Array2, c: f32) { - x.mapv_inplace(|x| x.clamp(-c, c)) - } - fn clip(&self, x: ArrayView2, c: f32) -> Array2 { - x.map(|x| x.clamp(-c, c)) - } - pub fn sdr(&self, orig: ArrayView2, processed: ArrayView2) -> f32 { - debug_assert_eq!(orig.shape(), processed.shape()); - let numel = orig.len(); - debug_assert!(numel > 0); - let noise = orig.to_owned() - processed; - let a = orig.fold(0., |acc, x| acc + x.powi(2)) / numel as f32; - let b = noise.fold(0., |acc, x| acc + x.powi(2)) / numel as f32; - (a / (b + self.eps)).log10() * 20. - } - fn find_root(&self, x: ArrayView2, target_snr: f32, max: Option) -> Option { - let max = max.unwrap_or(1.0); - let f = |c| self.sdr(x.view(), self.clip(x.view(), c).view()) - target_snr; - let (a, b) = (0.01 * max, 0.99 * max); - match roots::find_root_brent(a, b, f, &mut self.eps_c.clone()) { - Ok(c) => Some(c), - Err(e) => { - log::warn!("RandClipping: Failed to find root: {:?}", e); - dbg!(max, f(0.01 * max), f(0.99 * max)); - None - } - } - } -} -impl Transform for RandClipping { - fn transform(&self, x: &mut TransformInput) -> Result<()> { - let x = match x { - TransformInput::Spectrum(_) => return Err(AugmentationError::WrongInput), - TransformInput::Audio(a) => a, - }; - let mut rng = thread_rng()?; - if self.prob == 0. || (self.prob < 1. && rng.uniform(0f32, 1f32) > self.prob) { - return Ok(()); - } - let max = x.fold(0.0, |acc, x| x.abs().max(acc)); - let c = if let Some(db_range) = self.db_range.as_ref() { - let target_snr = rng.uniform(db_range.start, db_range.end); - if let Some(c) = self.find_root(x.view(), target_snr, Some(max)) { - c - } else { - return Ok(()); - } - } else { - let c_range = self.c_range.as_ref().unwrap(); - rng.uniform_inclusive(c_range.start * max, c_range.end * max) - }; - if log::log_enabled!(log::Level::Trace) { - log::trace!("Augmentation RandClipping (c: {})", c); - } - self.clip_inplace(x, c); - Ok(()) - } - fn default_with_prob(p: f32) -> Self { - RandClipping { - prob: p, - db_range: None, - c_range: Some(0.01..0.25), - eps: 1e-10, - eps_c: 0.001, - } - } - fn box_clone(&self) -> Box { - Box::new((*self).clone()) - } - fn name(&self) -> &str { - "RandClipping" - } -} -#[derive(Clone)] -pub struct RandZeroingTD { - prob: f32, - max_percent: f32, - min_sequential_samples: usize, - max_sequential_samples: usize, -} -impl RandZeroingTD { - pub fn with_n_samples(mut self, min: usize, max: usize) -> Self { - self.min_sequential_samples = min; - self.max_sequential_samples = max; - self - } - pub fn with_max_percent(mut self, p: f32) -> Self { - assert!(p < 100.); - assert!(p >= 1.); - self.max_percent = p; - self - } -} -impl Transform for RandZeroingTD { - fn transform(&self, x: &mut TransformInput) -> Result<()> { - let x = match x { - TransformInput::Spectrum(_) => return Err(AugmentationError::WrongInput), - TransformInput::Audio(a) => a, - }; - let mut rng = thread_rng()?; - if self.prob == 0. || (self.prob < 1. && rng.uniform(0f32, 1f32) > self.prob) { - return Ok(()); - } - // Loop as long as we dropped up to `perc` samples - let a_len = x.len_of(Axis(1)); - let p = rng.uniform(0.01f32, self.max_percent / 100.); - let mut cur = 0.; - let min = self.min_sequential_samples; - let max = self.max_sequential_samples; - while cur < p { - let pos = rng.uniform(0, a_len - max); - let z_len = rng.uniform(min, max); - x.slice_mut(s![.., pos..pos + z_len]).map_inplace(|s| *s = 0.); - cur += z_len as f32 / a_len as f32; - } - Ok(()) - } - fn default_with_prob(p: f32) -> Self { - Self { - prob: p, - max_percent: 10., - min_sequential_samples: 120, - max_sequential_samples: 1800, - } - } - fn box_clone(&self) -> Box { - Box::new((*self).clone()) - } - fn name(&self) -> &str { - "RandZeroing" - } -} - -#[derive(Clone)] -pub struct RandRemoveDc { - prob: f32, -} -impl Transform for RandRemoveDc { - fn transform(&self, x: &mut TransformInput) -> Result<()> { - let x = match x { - TransformInput::Spectrum(_) => return Err(AugmentationError::WrongInput), - TransformInput::Audio(a) => a, - }; - if self.prob == 0. || (self.prob < 1. && thread_rng()?.uniform(0f32, 1f32) > self.prob) { - return Ok(()); - } - let mean = x.sum() / x.len() as f32; - for x_s in x.iter_mut() { - *x_s -= mean; - } - Ok(()) - } - fn default_with_prob(p: f32) -> Self { - RandRemoveDc { prob: p } - } - fn box_clone(&self) -> Box { - Box::new((*self).clone()) - } - fn name(&self) -> &str { - "RandRemoveDc" - } -} - -pub(crate) fn gen_noise( - f_decay: f32, - num_channels: u16, - num_samples: usize, - sr: u32, -) -> Result> { - let mut fft = RealFftPlanner::new(); - let fft_forward = fft.plan_fft_forward(sr as usize); - let fft_inverse = fft.plan_fft_inverse(sr as usize); - let mut scratch_forward = fft_forward.make_scratch_vec(); - let mut scratch_inverse = fft_inverse.make_scratch_vec(); - gen_noise_with_scratch( - f_decay, - num_channels, - num_samples, - sr, - fft_forward.as_ref(), - fft_inverse.as_ref(), - &mut scratch_forward, - &mut scratch_inverse, - ) -} -#[allow(clippy::too_many_arguments)] -fn gen_noise_with_scratch( - f_decay: f32, - num_channels: u16, - num_samples: usize, - sr: u32, - fft_forward: &dyn RealToComplex, - fft_inverse: &dyn ComplexToReal, - scratch_forward: &mut [Complex32], - scratch_inverse: &mut [Complex32], -) -> Result> { - // Adopted from torch_audiomentations - let sr = sr as usize; - let ch = num_channels as usize; - let mut noise = if f_decay != 0. { - let mut noise = Array::random((ch, sr), Normal::new(0., 1.).unwrap()); - let spec = Array2::uninit([ch, sr / 2 + 1]); - // Safety: Will be fully overwritten by fft transform. - let mut spec = unsafe { spec.assume_init() }; - fft_with_output(&mut noise, fft_forward, scratch_forward, &mut spec)?; - let mut mask = Array::linspace(1., ((sr / 2 + 1) as f32).sqrt(), spec.len_of(Axis(1))); - mask.mapv_inplace(|x| x.powf(f_decay)); - spec = spec / mask.to_shape([1, sr / 2 + 1]).unwrap(); - ifft_with_output(&mut spec, fft_inverse, scratch_inverse, &mut noise)?; - if log::log_enabled!(log::Level::Trace) { - log::trace!("Generated random noise (f_decay : {})", f_decay); - } - noise - } else { - // Fast path for white noise - Array::random((ch, sr), Normal::new(0., 1.).unwrap()) - }; - let f = thread_rng()?.uniform(0.01, 0.95) / find_max_abs(&noise).unwrap().max(1.); - noise *= f; - let mut noises = concatenate( - Axis(1), - &vec![noise.view(); (num_samples as f32 / sr as f32).ceil() as usize], - )?; - noises.slice_axis_inplace(Axis(1), Slice::from(..num_samples)); - Ok(noises) -} - -pub(crate) struct NoiseGenerator { - p: f32, - sr: u32, - fft_forward: Arc>, - fft_inverse: Arc>, -} - -impl NoiseGenerator { - pub fn new(sr: usize, p: f32) -> Self { - let mut fft = RealFftPlanner::new(); - let fft_forward = fft.plan_fft_forward(sr); - let fft_inverse = fft.plan_fft_inverse(sr); - NoiseGenerator { - p, - sr: sr as u32, - fft_forward, - fft_inverse, - } - } - /// Generate a random noise signal. - /// - /// # Arguments - /// - /// * `f_decay`: Decay variable. Typical values for common noises are: - /// - white: `0.0` - /// - pink: `1.0` - /// - brown: `2.0` - /// - blue: `-1.0` - /// - purple: `-2.0` - /// * `num_channels`: Number of output channels. - /// * `num_samples`: Number of output samples. - /// - /// # Returns - /// - /// * `noise`: 2D array of shape `(num_channels, num_samples)`. - pub fn generate( - &self, - f_decay: f32, - num_channels: u16, - num_samples: usize, - ) -> Result> { - gen_noise_with_scratch( - f_decay, - num_channels, - num_samples, - self.sr, - self.fft_forward.as_ref(), - self.fft_inverse.as_ref(), - &mut self.fft_forward.make_scratch_vec(), - &mut self.fft_inverse.make_scratch_vec(), - ) - } - pub fn generate_random_noise( - &self, - f_decay_min: f32, - f_decay_max: f32, - num_channels: u16, - num_samples: usize, - ) -> Result>> { - debug_assert!(f_decay_min < f_decay_max); - let mut rng = thread_rng()?; - let f_decay = rng.uniform(f_decay_min, f_decay_max); - Ok(Some(self.generate(f_decay, num_channels, num_samples)?)) - } - pub fn maybe_generate_random_noise( - &self, - f_decay_min: f32, - f_decay_max: f32, - num_channels: u16, - num_samples: usize, - ) -> Result>> { - debug_assert!(f_decay_min < f_decay_max); - let mut rng = thread_rng()?; - if self.p == 0. || self.p < rng.uniform(0., 1.) { - return Ok(None); - } - self.generate_random_noise(f_decay_min, f_decay_max, num_channels, num_samples) - } -} - -pub(crate) struct RandReverbSim { - prob_speech: f32, - prob_noise: f32, - prob_resample: f32, - prob_decay: f32, - sr: usize, - rt60: f32, - offset_late: usize, - drr_f: Option, // Direct-to-Reverberant-Ratio -} -impl RandReverbSim { - fn supress_late( - &self, - mut rir: Array2, - sr: usize, - offset: usize, - rt60: f32, - ) -> Result> { - let len = rir.len_of(Axis(1)); - let mut decay: Array2 = Array2::ones((1, len)); - let dt = 1. / sr as f32; - let rt60_level = 10f32.powi(-60 / 20); - let tau = -rt60 / rt60_level.log10(); - if offset >= len { - return Ok(rir); - } - decay.slice_mut(s![0, offset..]).assign(&Array1::from_iter( - (0..(len - offset)).map(|v| 10f32.powf(-(v as f32) * dt / tau)), - )); - rir = rir * decay; - Ok(rir) - } - /// Trim the RIR based on the maximum reference level -80dB. - /// - /// Returns the trimed RIR and the index of the absolute maximum used as reference level. - fn trim(&self, mut rir: Array2, ref_idx: usize) -> Result> { - let min_db = -80.; - let len = rir.len_of(Axis(1)); - let rir_mono = rir.mean_axis(Axis(0)).unwrap(); - let ref_level: f32 = rir_mono[ref_idx]; - let min_level = 10f32.powf((min_db + ref_level.log10() * 20.) / 20.); - let mut idx = len; - for (i, v) in rir_mono.iter().rev().enumerate() { - if v.abs() < min_level { - idx = len - i; - } else { - break; - } - } - rir.slice_collapse(s![.., ..idx]); - Ok(rir) - } - fn good_fft_size(&self, len: usize) -> usize { - // Zero pad RIR for better FFT efficiency by finding prime factors up to a limit of 11. - let mut missing = len; - let primes = [2, 3, 5, 7, 11]; - let mut factors = [0u32; 5]; - for (p, f) in primes.iter().zip(factors.iter_mut()) { - while missing % p == 0 { - missing /= p; - *f += 1; - } - } - if missing > 1 { - factors[0] += (missing as f32).log2().ceil() as u32; - } - let fft_size = primes.iter().zip(factors).fold(1, |acc, (p, f)| acc * p.pow(f)); - debug_assert!(fft_size >= len); - fft_size - } - fn pad(&self, x: &mut Array2, pad_front: usize, pad_back: usize) -> Result<()> { - if pad_front == 0 && pad_back == 0 { - return Ok(()); - } - let ch = x.len_of(Axis(0)); - x.append(Axis(1), Array2::zeros((ch, pad_front + pad_back)).view())?; - if pad_front > 0 { - for mut x_ch in x.outer_iter_mut() { - x_ch.as_slice_memory_order_mut().unwrap().rotate_right(pad_front); - } - } - Ok(()) - } - pub fn transform_single(&self, sample: &mut Array2, mut rir: Array2) -> Result<()> { - let mut fft_t = FftTransform::new(); - let rir_mono = rir.mean_axis(Axis(0)).unwrap(); - let max_idx = argmax_abs(rir_mono.iter()).unwrap(); - // Normalize and flip RIR for convolution - rir = self.trim(rir, max_idx)?; - let rir_e = rir.map(|v| v * v).sum().sqrt(); - let rir = rir / rir_e; - self.convolve(sample, rir, &mut fft_t, None)?; - Ok(()) - } - /// Applies random reverberation to either noise or speech or both. - /// - /// We have 3 scenarious: - /// - /// 1. Only noise will get some reverberation. No `speech_rev` will be returned. - /// 2. Only speech will get some reverberation. The return value`speech_rev` will contain the - /// reverberant speech to be used for generating a noisy mixture and `speech` will be - /// modified inplace to be a less reverberant version of `speech_rev` to be used as training - /// target. - /// 3. Speech and noise will get reverberation. - /// - /// # Arguments - /// - /// * `speech` - A speech signal of shape `[C, N]`. Will be modified in place. - /// * `noise` - A noise signal of shape `[C, N]`. Will be modified in place. - /// * `rir_callback` - A callback which will generate a room impulse response. - /// - /// # Returns - /// - /// * `speech_rev` - An optional reverberant speech sample for mixing. This will contain a - /// more reverberation then the in place modified `speech` signal. - pub fn transform( - &self, - speech: &mut Array2, - noise: &mut Array2, - rir_callback: F, - ) -> Result>> - where - F: FnOnce() -> std::result::Result, Box>, - { - if self.prob_noise == 0. && self.prob_speech == 0. { - return Ok(None); - } - let mut rng = thread_rng()?; - let apply_speech = self.prob_speech > rng.uniform(0f32, 1f32); - let apply_noise = self.prob_noise > rng.uniform(0f32, 1f32); - if !(apply_speech || apply_noise) { - return Ok(None); - } - #[cfg(feature = "timings")] - let t0 = Instant::now(); - let mut fft_t = FftTransform::new(); - // Get room impulse response - let mut rir = match rir_callback() { - Ok(r) => r, - Err(e) => { - return Err(AugmentationError::DfError(format!( - "Error getting RIR in RandReverbSim::transform() {e:?}" - ))); - } - }; - let orig_len = speech.len_of(Axis(1)); - // Maybe resample RIR as augmentation - if self.prob_resample > rng.uniform(0f32, 1f32) { - let new_sr: f32 = rng.uniform(0.8, 1.2) * self.sr as f32; - let new_sr = ((new_sr / 500.).round() * 500.) as usize; - rir = resample(rir.view(), self.sr, new_sr, Some(512))?; - } - let rir_mono = rir.mean_axis(Axis(0)).unwrap(); - let max_idx = argmax_abs(rir_mono.iter()).unwrap(); - if self.prob_decay > rng.uniform(0f32, 1f32) { - let rt60 = rng.uniform(0.2, 1.); - rir = self.supress_late(rir, self.sr, max_idx, rt60)?; - } - rir = self.trim(rir, max_idx)?; - // Normalize and flip RIR for convolution - let rir_e = rir.map(|v| v * v).sum().sqrt(); - let rir_noise = rir / rir_e; - - // speech_rev contains reverberant speech for mixing with noise - let speech_rev = if apply_speech { - let speech_rms = rms(speech.iter()); - // self.pad(speech, pad_front, pad_back)?; // Pad since STFT will truncate at the end - let mut speech_rev = speech.clone(); - self.convolve( - &mut speech_rev, - rir_noise.clone(), - &mut fft_t, - Some(orig_len), - )?; - // Speech should be a slightly dereverberant signal as target - // TODO: Make dereverberation parameters configurable. - // - // Add extra offset since these are releveant for speech intelligibility - let offset = max_idx + self.offset_late * self.sr / 1000; - let mut rir_speech = - self.supress_late(rir_noise.clone(), self.sr, offset, self.rt60)?; - let rir_e = rir_speech.map(|v| v * v).sum().sqrt(); - rir_speech *= 1. / rir_e; - // Generate target speech signal containing less reverberation - let mut speech_little_rev = speech.clone(); - self.convolve( - &mut speech_little_rev, - rir_speech, - &mut fft_t, - Some(orig_len), - )?; - // Maybe mix in some original clean speech as target - if let Some(f) = self.drr_f { - // speech.slice_axis_inplace(Axis(1), Slice::from(pad_front..pad_front + orig_len)); - *speech *= f; - speech.scaled_add(1. - f, &speech_little_rev); - } else { - *speech = speech_little_rev; - } - let speech_rms_after = rms(speech.iter()); - *speech *= speech_rms / (speech_rms_after + 1e-10); - debug_assert_eq!(speech.shape(), speech_rev.shape()); - debug_assert_eq!(speech.len_of(Axis(1)), noise.len_of(Axis(1))); - Some(speech_rev) - } else { - None - }; - if apply_noise { - // Noisy contains reverberant noise - self.convolve(noise, rir_noise, &mut fft_t, Some(orig_len))?; - debug_assert_eq!(speech.len_of(Axis(1)), noise.len_of(Axis(1))); - } - #[cfg(feature = "timings")] - if log::log_enabled!(log::Level::Trace) { - log::trace!("Calculated RandReverbSim in {:?}", Instant::now() - t0); - } - Ok(speech_rev) - } - fn convolve( - &self, - x: &mut Array2, - mut rir: Array2, - fft_transform: &mut FftTransform, - truncate: Option, - ) -> Result<()> { - let x_len = x.len_of(Axis(1)); - let rir_len = rir.len_of(Axis(1)); - let fft_size = self.good_fft_size(rir.len_of(Axis(1)) + x.len_of(Axis(1)) - 1); - let forward = fft_transform.planer.plan_fft_forward(fft_size); - let inverse = fft_transform.planer.plan_fft_inverse(fft_size); - self.pad(x, 0, fft_size - x_len)?; - self.pad(&mut rir, 0, fft_size - rir_len)?; - let mut x_fd = fft(x, forward.as_ref(), &mut fft_transform.scratch)?; - let rir_fd = fft(&mut rir, forward.as_ref(), &mut fft_transform.scratch)?; - x_fd = x_fd * rir_fd / fft_size as f32; - ifft_with_output(&mut x_fd, inverse.as_ref(), &mut fft_transform.scratch, x)?; - let max_len = truncate.unwrap_or(x_len); - debug_assert!(max_len <= x_len); - x.slice_collapse(s![.., ..max_len]); - Ok(()) - } - pub fn new(p: f32, sr: usize) -> Self - where - Self: Sized, - { - RandReverbSim { - prob_speech: p, - prob_noise: p, - prob_resample: p, - prob_decay: p.max(0.5), - sr, - rt60: 0.5, - offset_late: 20, - drr_f: None, - } - } - // Include the original signal within the target by specifying the Direct-to-Reverberant ratio - // in [dB]. - pub fn with_drr(mut self, f: f32) -> Self { - assert!((0.0..=1.0).contains(&f)); - self.drr_f = Some(f); - self - } - pub fn with_rt60(mut self, rt60: f32) -> Self { - assert!(rt60 > 0.); - self.rt60 = rt60; - self - } - pub fn with_offset_late_reflections(mut self, offset: usize) -> Self { - self.offset_late = offset; - self - } - pub fn with_prob_resample(mut self, p: f32) -> Self { - self.prob_resample = p; - self - } - pub fn with_prob_decay(mut self, p: f32) -> Self { - self.prob_decay = p; - self - } -} - -#[derive(Clone)] -pub(crate) struct BandwidthLimiterAugmentation { - prob: f32, - sr: usize, - cut_off_freqs: Vec, -} - -impl BandwidthLimiterAugmentation { - pub fn name(&self) -> &str { - "BandwidthLimiter" - } - pub fn new(p: f32, sr: usize) -> Self { - BandwidthLimiterAugmentation { - prob: p, - sr, - cut_off_freqs: vec![4000, 6000, 8000, 10000, 12000, 16000, 20000, 22050], - } - } - pub fn transform(&self, audio: &mut Array2, max_freq: usize) -> Result { - #[cfg(feature = "timings")] - let t0 = Instant::now(); - let mut rng = thread_rng()?; - let &f = self.cut_off_freqs.iter().filter(|&f| *f < max_freq).choose(&mut rng).unwrap(); - let d = low_pass_resample(audio.view(), f, self.sr).unwrap(); - audio.clone_from(&d); - #[cfg(feature = "timings")] - if log::log_enabled!(log::Level::Trace) { - log::trace!( - "Calculated BandwidthLimiterAugmentation in {:?}", - Instant::now() - t0 - ); - } - Ok(f) - } -} - -/// Implement a low pass filterbank in frequency domain. Adopted from audiomentations. -/// Absorption coefs based on pyroomacoustics. -/// -/// Absorption is given by: -/// -/// `att = exp(- distance * absorption_coefficient)` -#[derive(Clone)] -pub(crate) struct AirAbsorptionAugmentation { - prob: f32, - sr: Option, - pub air_absorption: BTreeMap, - center_freqs: [usize; 9], - distance_low: f32, - distance_high: f32, -} -/// Concat 3 slices into a Vec. -pub fn concat3(a: &[T], b: &[T], c: &[T]) -> Vec { - [a, b, c].concat() -} -/// Linear interpolation between two points at x=0 and x=1 -fn interp_lin(x: f32, yvals: &[f32; 2]) -> f32 { - (1. - x) * yvals[0] + x * yvals[1] -} -impl AirAbsorptionAugmentation { - fn insert_coefs(map: &mut BTreeMap, key: &str, scaled_coefs: [f32; 9]) { - map.insert(key.to_string(), scaled_coefs.map(|x| x * 1e-3)); - } - pub fn new(sr: usize, prob: f32) -> Self { - let center_freqs = [125, 250, 500, 1000, 2000, 4000, 8000, 16000, 24000]; - let mut air_absorption = BTreeMap::new(); - Self::insert_coefs( - &mut air_absorption, - "10C_30-50%", - [0.1, 0.2, 0.5, 1.1, 2.7, 9.4, 29.0, 91.5, 289.0], - ); - Self::insert_coefs( - &mut air_absorption, - "10C_50-70%", - [0.1, 0.2, 0.5, 0.8, 1.8, 5.9, 21.1, 76.6, 280.2], - ); - Self::insert_coefs( - &mut air_absorption, - "10C_70-90%", - [0.1, 0.2, 0.5, 0.7, 1.4, 4.4, 15.8, 58.0, 214.9], - ); - Self::insert_coefs( - &mut air_absorption, - "20C_30-50", - [0.1, 0.3, 0.6, 1.0, 1.9, 5.8, 20.3, 72.3, 259.9], - ); - Self::insert_coefs( - &mut air_absorption, - "20C_50-70%", - [0.1, 0.3, 0.6, 1.0, 1.7, 4.1, 13.5, 44.4, 148.7], - ); - Self::insert_coefs( - &mut air_absorption, - "20C_70-90%", - [0.1, 0.3, 0.6, 1.1, 1.7, 3.5, 10.6, 31.2, 93.8], - ); - // The following coefficients are artificial to produce strong absorption - Self::insert_coefs( - &mut air_absorption, - "Strong-High-1", - [0.1, 0.2, 0.7, 1.5, 3.9, 8.1, 21.6, 80.2, 213.1], - ); - Self::insert_coefs( - &mut air_absorption, - "Strong-High-2", - [0.1, 0.3, 0.9, 3.8, 8.9, 21.1, 44.6, 80.2, 153.1], - ); - Self { - center_freqs, - air_absorption, - distance_low: 1.0, - distance_high: 20.0, - sr: Some(sr), - prob, - } - } - /// Interpolate frequency attenuation from center bands stft frequency bins. - /// - /// Args: - /// - `atten_vals`: Attenuation values of shape [8] - /// - `n_freqs`: Number of stft frequency bins. - fn interp_atten(&self, atten_vals: &[f32], n_freqs: usize) -> Array1 { - let atten_vals = concat3(&[atten_vals[0]], atten_vals, &[atten_vals[8]]); - let sr = self.sr.unwrap(); - let freqs = Array1::linspace(0., (sr / 2) as f32, n_freqs); - let mut atten_vals_interp = Array1::zeros(n_freqs); - let center_freqs = concat3(&[0], &self.center_freqs, &[sr / 2]); - let mut i = 0; - for (c, a) in center_freqs.windows(2).zip(atten_vals.windows(2)) { - let (c0, c1) = (c[0] as f32, c[1] as f32); - let (a0, a1) = (a[0], a[1]); - while i < n_freqs && freqs[i] <= c1 { - let x = (freqs[i] - c1) / (c0 - c1); - atten_vals_interp[i] = a0 * x + a1 * (1. - x); - i += 1; - } - } - atten_vals_interp - } - /// Get available absorption coefficient keys - pub fn keys(&self) -> Vec { - self.air_absorption.keys().map(|k| k.to_owned()).collect() - } - /// Get absorption coefficients for a predifined key - pub fn get_coefs(&self, key: &str) -> Option<&[f32; 9]> { - self.air_absorption.get(key) - } - pub fn apply(&self, spec: &mut Array3, coefs: &[f32; 9], d: f32) { - #[cfg(feature = "timings")] - let t0 = Instant::now(); - let atten_vals = coefs.map(|c| (-d * c).exp()); - let n_freqs = spec.len_of(Axis(2)); - let atten_vals = self.interp_atten(&atten_vals, n_freqs); - for (mut f, a) in spec.axis_iter_mut(Axis(2)).zip(atten_vals) { - f.mapv_inplace(|x| x.scale(a)); - } - #[cfg(feature = "timings")] - if log::log_enabled!(log::Level::Trace) { - log::trace!( - "Calculated AirAbsorptionAugmentation in {:?}", - Instant::now() - t0 - ); - } - } -} - -impl Transform for AirAbsorptionAugmentation { - fn default_with_prob(p: f32) -> Self { - Self::new(0, p) - } - fn box_clone(&self) -> Box { - Box::new((*self).clone()) - } - fn name(&self) -> &str { - "RandLFilt" - } - fn transform(&self, inp: &mut TransformInput) -> Result<()> { - let spec = match inp { - TransformInput::Spectrum(s) => s, - TransformInput::Audio(_) => return Err(AugmentationError::WrongInput), - }; - // Spec shape: [C, T, F] - let mut rng = thread_rng()?; - if self.prob == 0. || (self.prob < 1. && rng.uniform(0f32, 1f32) > self.prob) { - return Ok(()); - } - let d = rng.uniform_inclusive(self.distance_low, self.distance_high); - let coefs = self.air_absorption.iter().choose(&mut rng).unwrap(); - self.apply(spec, coefs.1, d); - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use std::sync::Once; - - use super::*; - use crate::wav_utils::*; - - static INIT: Once = Once::new(); - - /// Setup function that is only run once, even if called multiple times. - fn setup() -> (Array2, usize) { - seed_from_u64(42); - create_out_dir().expect("Could not create output directory"); - - INIT.call_once(|| { - let _ = env_logger::builder() - // Include all events in tests - .filter_module("df", log::LevelFilter::max()) - // Ensure events are captured by `cargo test` - .is_test(true) - // Ignore errors initializing the logger if tests race to configure it - .try_init(); - }); - let reader = ReadWav::new("../assets/clean_freesound_33711.wav").unwrap(); - let sr = reader.sr; - let test_sample = reader.samples_arr2().unwrap(); - (test_sample, sr) - } - - fn create_out_dir() -> std::io::Result<()> { - match std::fs::create_dir("../out") { - Err(ref e) if e.kind() == std::io::ErrorKind::AlreadyExists => Ok(()), - r => r, - } - } - - #[test] - pub fn test_compose() -> Result<()> { - let (test_sample, sr) = setup(); - let ch = test_sample.len_of(Axis(0)) as u16; - let transforms = Compose::new(vec![ - Box::new(RandRemoveDc::default_with_prob(1.)), - Box::new(RandLFilt::default_with_prob(1.)), - Box::new(RandBiquadFilter::default_with_prob(1.).with_sr(sr)), - Box::new(RandResample::default_with_prob(1.).with_sr(sr)), - ]); - let mut out = test_sample.clone(); - let mut out_manual = test_sample.clone(); - write_wav_iter("../out/original.wav", test_sample.iter(), sr as u32, ch)?; - seed_from_u64(42); - transforms.transform(&mut (&mut out).into())?; - write_wav_iter("../out/compose_all.wav", out.iter(), sr as u32, ch)?; - seed_from_u64(42); - for (i, t) in transforms.transforms.iter().enumerate() { - t.transform(&mut (&mut out_manual).into())?; - write_wav_iter( - format!("../out/compose_{i}.wav").as_str(), - out_manual.iter(), - sr as u32, - ch, - )?; - } - assert_eq!(out.sum(), out_manual.sum()); - assert_eq!(out.var(1.), out_manual.var(1.)); - - Ok(()) - } - - #[test] - pub fn test_rand_resample() -> Result<()> { - let (mut test_sample, sr) = setup(); - let ch = test_sample.len_of(Axis(0)) as u16; - seed_from_u64(42); - let rand_resample = RandResample::new(1., sr, 0.8, 1.2, 1024); - rand_resample.transform(&mut (&mut test_sample).into()).unwrap(); - write_wav_iter("../out/resampled.wav", test_sample.iter(), sr as u32, ch)?; - Ok(()) - } - - #[test] - pub fn test_low_pass() -> Result<()> { - let (sample, sr) = setup(); - let sr = sr as u32; - let mut lowpass_res = sample.clone(); - let mut lowpass_biquad = sample.clone(); - let ch = sample.len_of(Axis(0)) as u16; - let f = 8000.; - let mut mem = [0.; 2]; - let (b, a) = low_pass(f, 0.707, sr as usize); - biquad_inplace(&mut lowpass_biquad, &mut mem, &b, &a); - write_wav_iter("../out/lowpass_biquad.wav", lowpass_biquad.iter(), sr, ch).unwrap(); - let xx: f64 = sample.iter().map(|&n| n as f64 * n as f64).sum(); - let yy: f64 = lowpass_biquad.iter().map(|&n| n as f64 * n as f64).sum(); - let xy: f64 = sample.iter().zip(lowpass_biquad).map(|(&n, m)| n as f64 * m as f64).sum(); - let corr = xy / (xx.sqrt() * yy.sqrt()); - dbg!(corr); - - lowpass_res = low_pass_resample(lowpass_res.view(), f as usize, sr as usize).unwrap(); - write_wav_iter("../out/lowpass_resample.wav", lowpass_res.iter(), sr, ch).unwrap(); - - let xx: f64 = sample.iter().map(|&n| n as f64 * n as f64).sum(); - let yy: f64 = lowpass_res.iter().map(|&n| n as f64 * n as f64).sum(); - let xy: f64 = sample.iter().zip(lowpass_res).map(|(&n, m)| n as f64 * m as f64).sum(); - let corr = xy / (xx.sqrt() * yy.sqrt()); - dbg!(corr); - Ok(()) - } - - #[test] - pub fn test_reverb() -> Result<()> { - let (mut speech, sr) = setup(); - let len = 4 * sr; - speech.slice_collapse(s![0..1, 0..len]); - let mut noise = ReadWav::new("../assets/noise_freesound_573577.wav")?.samples_arr2()?; - noise.slice_axis_inplace(Axis(1), Slice::from(0..len)); - let rir = ReadWav::new("../assets/rir_sim_1001_w11.7_l2.6_h2.5_rt60_0.7919.wav")? - .samples_arr2()?; - let reverb = RandReverbSim::new(1., sr) - .with_drr(0.2) - .with_rt60(0.1) - .with_offset_late_reflections(20); - write_wav_arr2("../out/speech_noreverb.wav", speech.view(), sr as u32)?; - write_wav_arr2("../out/noise_noreverb.wav", noise.view(), sr as u32)?; - let speech_rev = reverb.transform(&mut speech, &mut noise, move || Ok(rir))?.unwrap(); - write_wav_arr2("../out/speech_target.wav", speech.view(), sr as u32)?; - write_wav_arr2("../out/speech_reverb.wav", speech_rev.view(), sr as u32)?; - write_wav_arr2("../out/noise_reverb.wav", noise.view(), sr as u32)?; - Ok(()) - } - - #[test] - pub fn test_clipping() -> Result<()> { - let (test_sample, sr) = setup(); - let sr = sr as u32; - let mut test_sample_c = test_sample.clone(); - let ch = test_sample.len_of(Axis(0)) as u16; - let tsnr = 3.; // Test with 3dB - let transform = RandClipping::new(1.0, 1e-10, 0.001).with_snr(tsnr..tsnr); - transform.transform(&mut (&mut test_sample_c).into())?; - let resulting_snr = transform.sdr(test_sample.view(), test_sample_c.view()); - write_wav_iter("../out/original.wav", test_sample.iter(), sr, ch)?; - write_wav_iter("../out/clipped_snr.wav", test_sample_c.iter(), sr, ch)?; - log::info!("Expecting target SNR {}, got SNR {}", tsnr, resulting_snr); - // Test relative difference - assert!(((resulting_snr - tsnr) / tsnr).abs() < 0.05); - - let mut test_sample_c = test_sample.clone(); - let c = 0.05; - let transform = RandClipping::new(1.0, 1e-10, 0.001).with_c(c..c); - transform.transform(&mut (&mut test_sample_c).into())?; - let resulting_snr = transform.sdr(test_sample.view(), test_sample_c.view()); - write_wav_iter("../out/clipped.wav", test_sample_c.iter(), sr, ch)?; - dbg!(c, resulting_snr); - Ok(()) - } - - #[test] - pub fn test_zeroing() -> Result<()> { - let (test_sample, sr) = setup(); - let sr = sr as u32; - let mut test_sample_c = test_sample.clone(); - let ch = test_sample.len_of(Axis(0)) as u16; - let transform = RandZeroingTD::default_with_prob(1.0).with_n_samples(420, 1800); - transform.transform(&mut (&mut test_sample_c).into())?; - write_wav_iter("../out/original.wav", test_sample.iter(), sr, ch)?; - write_wav_iter("../out/zeroed.wav", test_sample_c.iter(), sr, ch)?; - Ok(()) - } - - #[test] - pub fn test_gen_noise() -> Result<()> { - setup(); - - let sr = 48000; - let ch = 2; - let n = sr as usize * 3; // 3 seconds - let white_noise = gen_noise(0., ch, n, sr)?; - let pink_noise = gen_noise(1., ch, n, sr)?; - let brown_noise = gen_noise(2., ch, n, sr)?; - let blue_noise = gen_noise(-1., ch, n, sr)?; - let violet_noise = gen_noise(-1., ch, n, sr)?; - write_wav_iter("../out/white_noise.wav", white_noise.iter(), sr, ch)?; - write_wav_iter("../out/pink_noise.wav", pink_noise.iter(), sr, ch)?; - write_wav_iter("../out/brown_noise.wav", brown_noise.iter(), sr, ch)?; - write_wav_iter("../out/blue_noise.wav", blue_noise.iter(), sr, ch)?; - write_wav_iter("../out/violet_noise.wav", violet_noise.iter(), sr, ch)?; - Ok(()) - } - - #[test] - pub fn test_filters() -> Result<()> { - let (s_orig, sr) = setup(); - let ch = s_orig.len_of(Axis(0)) as u16; - let f = 1000.; - let gain = -18.; - let q = 0.5; - // Low pass - let (b, a) = low_pass(f, q, sr); - let mut s_filt = s_orig.clone(); - biquad_filter(&mut s_filt, &b, &a); - write_wav_iter("../out/filt_lowpass.wav", s_filt.iter(), sr as u32, ch)?; - // High pass - let (b, a) = high_pass(f, q, sr); - let mut s_filt = s_orig.clone(); - biquad_filter(&mut s_filt, &b, &a); - write_wav_iter("../out/filt_higpass.wav", s_filt.iter(), sr as u32, ch)?; - // Low shelf - let (b, a) = low_shelf(f, gain, q, sr); - let mut s_filt = s_orig.clone(); - biquad_filter(&mut s_filt, &b, &a); - write_wav_iter("../out/filt_lowshelf.wav", s_filt.iter(), sr as u32, ch)?; - // High shelf - let (b, a) = high_shelf(f, gain, q, sr); - let mut s_filt = s_orig.clone(); - biquad_filter(&mut s_filt, &b, &a); - write_wav_iter("../out/filt_highshelf.wav", s_filt.iter(), sr as u32, ch)?; - // Peaking eq - let (b, a) = peaking_eq(f, gain, q, sr); - let mut s_filt = s_orig.clone(); - biquad_filter(&mut s_filt, &b, &a); - write_wav_iter("../out/filt_peaking_eq.wav", s_filt.iter(), sr as u32, ch)?; - // Notch - let (b, a) = notch(f, q, sr); - let mut s_filt = s_orig.clone(); - biquad_filter(&mut s_filt, &b, &a); - write_wav_iter("../out/filt_notch.wav", s_filt.iter(), sr as u32, ch)?; - // Test augmentation transform - seed_from_u64(43); - let aug = RandBiquadFilter::default_with_prob(1.0).with_sr(sr); - let mut s_aug = s_orig; - aug.transform(&mut (&mut s_aug).into())?; - write_wav_iter("../out/filt_aug.wav", s_aug.iter(), sr as u32, ch)?; - Ok(()) - } - - #[test] - pub fn test_air_absorption() -> Result<()> { - let (sample, sr) = setup(); - let fft_size = sr / 50; - let hop_size = fft_size / 2; - let mut state = DFState::new(sr, fft_size, hop_size, 1, 1); - write_wav_arr2("../out/original.wav", sample.view(), sr as u32).unwrap(); - let x = stft(sample.view(), &mut state, false); - let airabs = AirAbsorptionAugmentation::new(sr, 1.0); - for (n, c) in airabs.air_absorption.iter() { - let mut x_aug = x.clone(); - airabs.apply(&mut x_aug, c, 20.); - let sample = istft(x_aug.view_mut(), &mut state, true); - write_wav_arr2(&format!("../out/air_abs_{n}.wav"), sample.view(), sr as u32).unwrap(); - } - Ok(()) - } -} diff --git a/libDF/src/bin/enhance_wav.rs b/libDF/src/bin/enhance_wav.rs deleted file mode 100644 index b37592660..000000000 --- a/libDF/src/bin/enhance_wav.rs +++ /dev/null @@ -1,186 +0,0 @@ -use std::{path::PathBuf, process::exit, time::Instant}; - -use anyhow::Result; -use clap::{Parser, ValueHint}; -use df::{tract::*, transforms::resample, wav_utils::*}; -use ndarray::{prelude::*, Axis}; - -#[cfg(all( - not(windows), - not(target_os = "android"), - not(target_os = "macos"), - not(target_os = "freebsd"), - not(target_env = "musl"), - not(target_arch = "riscv64"), - feature = "use-jemalloc" -))] -#[global_allocator] -static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; - -/// Simple program to sample from a hd5 dataset directory -#[derive(Parser)] -#[command(author, version, about, long_about = None)] -struct Args { - /// Path to model tar.gz - #[arg(short, long, value_hint = ValueHint::FilePath)] - model: Option, - /// Enable post-filter - #[arg(long = "pf")] - post_filter: bool, - /// Post-filter beta. Higher beta results in stronger attenuation. - #[arg(long = "pf-beta", default_value_t = 0.02)] - post_filter_beta: f32, - /// Compensate delay of STFT and model lookahead - #[arg(short = 'D', long)] - compensate_delay: bool, - /// Attenuation limit in dB by mixing the enhanced signal with the noisy signal. - /// An attenuation limit of 0 dB means no noise reduction will be performed, 100 dB means full - /// noise reduction, i.e. no attenuation limit. - #[arg(short, long, default_value_t = 100.)] - atten_lim_db: f32, - /// Min dB local SNR threshold for running the decoder DNN side - #[arg(long, value_parser, allow_negative_numbers = true, default_value_t = -15.)] - min_db_thresh: f32, - /// Max dB local SNR threshold for running ERB decoder - #[arg( - long, - value_parser, - allow_negative_numbers = true, - default_value_t = 35. - )] - max_db_erb_thresh: f32, - /// Max dB local SNR threshold for running DF decoder - #[arg( - long, - value_parser, - allow_negative_numbers = true, - default_value_t = 35. - )] - max_db_df_thresh: f32, - /// If used with multiple channels, reduce the mask with max (1) or mean (2) - #[arg(long, value_parser, default_value_t = 1)] - reduce_mask: i32, - /// Logging verbosity - #[arg( - long, - short = 'v', - action = clap::ArgAction::Count, - global = true, - help = "Increase logging verbosity with multiple `-vv`", - )] - verbose: u8, - // Output directory with enhanced audio files. Defaults to 'out' - #[arg(short, long, default_value = "out", value_hint = ValueHint::DirPath)] - output_dir: PathBuf, - // Audio files - #[arg(required = true)] - files: Vec, -} - -fn main() -> Result<()> { - let args = Args::parse(); - - let level = match args.verbose { - 0 => log::LevelFilter::Warn, - 1 => log::LevelFilter::Info, - 2 => log::LevelFilter::Debug, - _ => log::LevelFilter::Trace, - }; - let tract_level = match args.verbose { - 0..=3 => log::LevelFilter::Error, - 4 => log::LevelFilter::Info, - 5 => log::LevelFilter::Debug, - _ => log::LevelFilter::Trace, - }; - env_logger::Builder::from_env(env_logger::Env::default()) - .filter_level(level) - .filter_module("tract_onnx", tract_level) - .filter_module("tract_hir", tract_level) - .filter_module("tract_core", tract_level) - .filter_module("tract_linalg", tract_level) - .init(); - - // Initialize with 1 channel - let mut r_params = RuntimeParams::default(); - r_params = r_params.with_atten_lim(args.atten_lim_db).with_thresholds( - args.min_db_thresh, - args.max_db_erb_thresh, - args.max_db_df_thresh, - ); - if args.post_filter { - r_params = r_params.with_post_filter(args.post_filter_beta); - } - if let Ok(red) = args.reduce_mask.try_into() { - r_params = r_params.with_mask_reduce(red); - } else { - log::warn!("Input not valid for `reduce_mask`.") - } - let df_params = if let Some(tar) = args.model.as_ref() { - match DfParams::new(tar.clone()) { - Ok(p) => p, - Err(e) => { - log::error!("Error opening model {}: {}", tar.display(), e); - exit(1) - } - } - } else if cfg!(any(feature = "default-model", feature = "default-model-ll")) { - DfParams::default() - } else { - log::error!("deep-filter was not compiled with a default model. Please provide a model via '--model '"); - exit(2) - }; - let mut model: DfTract = DfTract::new(df_params.clone(), &r_params)?; - let mut sr = model.sr; - let mut delay = model.fft_size - model.hop_size; // STFT delay - delay += model.lookahead * model.hop_size; // Add model latency due to lookahead - if !args.output_dir.is_dir() { - log::info!("Creating output directory: {}", args.output_dir.display()); - std::fs::create_dir_all(args.output_dir.clone())? - } - for file in args.files { - let reader = ReadWav::new(file.to_str().unwrap())?; - // Check if we need to adjust to multiple channels - if r_params.n_ch != reader.channels { - r_params.n_ch = reader.channels; - model = DfTract::new(df_params.clone(), &r_params)?; - sr = model.sr; - } - let sample_sr = reader.sr; - let mut noisy = reader.samples_arr2()?; - if sr != sample_sr { - noisy = resample(noisy.view(), sample_sr, sr, None).expect("Error during resample()"); - } - let noisy = noisy.as_standard_layout(); - let mut enh: Array2 = ArrayD::default(noisy.shape()).into_dimensionality()?; - let t0 = Instant::now(); - for (ns_f, enh_f) in noisy - .view() - .axis_chunks_iter(Axis(1), model.hop_size) - .zip(enh.view_mut().axis_chunks_iter_mut(Axis(1), model.hop_size)) - { - if ns_f.len_of(Axis(1)) < model.hop_size { - break; - } - model.process(ns_f, enh_f)?; - } - let elapsed = t0.elapsed().as_secs_f32(); - let t_audio = noisy.len_of(Axis(1)) as f32 / sr as f32; - log::info!( - "Enhanced audio file {} in {:.2} (RTF: {})", - file.display(), - elapsed, - elapsed / t_audio - ); - let mut enh_file = args.output_dir.clone(); - enh_file.push(file.file_name().unwrap()); - if args.compensate_delay { - enh.slice_axis_inplace(Axis(1), ndarray::Slice::from(delay..)); - } - if sr != sample_sr { - enh = resample(enh.view(), sr, sample_sr, None).expect("Error during resample()"); - } - write_wav_arr2(enh_file.to_str().unwrap(), enh.view(), sample_sr as u32)?; - } - - Ok(()) -} diff --git a/libDF/src/bin/sample-dataset.rs b/libDF/src/bin/sample-dataset.rs deleted file mode 100644 index cc6196c44..000000000 --- a/libDF/src/bin/sample-dataset.rs +++ /dev/null @@ -1,180 +0,0 @@ -use std::fs; -use std::path::Path; -use std::path::PathBuf; -use std::{io, io::Write}; - -use anyhow::Result; -use clap::{Parser, ValueEnum}; -use df::{ - dataset::{Dataset, DatasetBuilder, DatasetConfigJson, Split}, - hdf5_key_cache::*, - transforms::istft, - util::{seed_from_u64, thread_rng}, - wav_utils::write_wav_iter, - DFState, -}; -use ini::Ini; -use ndarray::Axis; -use rand::prelude::IteratorRandom; - -/// Simple program to sample from a hd5 dataset directory -#[derive(Parser)] -#[command(author, version, about, long_about = None)] -struct Args { - df_cfg: PathBuf, - /// Dataset directory containing the hdf5 datasets - /// Dataset configuration file - ds_cfg: PathBuf, - /// DeepFilterNet framework configuration file - ds_dir: PathBuf, - /// Save directory for sampled output wavs - out_dir: PathBuf, - /// Dataset split - #[arg(long, value_enum)] - split: Option, - /// Dataset indices - #[arg(short, long)] - idx: Vec, - /// Number of samples to generate - #[arg(short, long)] - num: Option, - /// Random seed - #[arg(short, long)] - seed: Option, - /// Random seed - #[arg(short, long)] - epoch: Option, - /// Randomize sampling - #[arg(short, long)] - randomize: bool, - #[arg(short, long)] - verbose: bool, -} - -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] -enum DsSplit { - Train, - Valid, - Test, -} - -fn main() -> Result<()> { - let args = Args::parse(); - - let level = match args.verbose { - true => log::LevelFilter::max(), - _ => log::LevelFilter::Info, - }; - env_logger::builder().filter_level(level).init(); - - // Load configs - let ds_cfg_path = args.ds_cfg.to_str().unwrap(); - let mut ds_cfg = DatasetConfigJson::open(ds_cfg_path).unwrap(); - load_hdf5_key_cache(ds_cfg_path, &mut ds_cfg); - let ini = Ini::load_from_file(args.df_cfg)?; - let df_cfg = ini.section(Some("df")).unwrap(); - let distortion_cfg = ini.section(Some("distortion")).unwrap(); - let train_cfg = ini.section(Some("train")).unwrap(); - - let global_seed = args.seed.unwrap_or(train_cfg.get("seed").unwrap().parse::()?); - seed_from_u64(global_seed); - - let split = match args.split.unwrap_or(DsSplit::Train) { - DsSplit::Train => Split::Train, - DsSplit::Valid => Split::Valid, - DsSplit::Test => Split::Test, - }; - - // Setup variables and dataset - let out_dir = args.out_dir.to_str().unwrap(); - if !Path::new(out_dir).is_dir() { - fs::create_dir(out_dir)?; - } - let sr = df_cfg.get("sr").unwrap().parse::()?; - let hop_size = df_cfg.get("hop_size").unwrap().parse::()?; - let fft_size = df_cfg.get("fft_size").unwrap().parse::()?; - let min_nb_erb_freqs = df_cfg.get("min_nb_erb_freqs").unwrap().parse::()?; - let nb_erb = df_cfg.get("nb_erb").unwrap().parse::()?; - let nb_df = df_cfg.get("nb_df").unwrap().parse::()?; - let snrs = train_cfg - .get("dataloader_snrs") - .unwrap() - .split(',') - .map(|x| x.parse::().unwrap()) - .collect(); - let mut state = DFState::new(sr, fft_size, hop_size, nb_erb, min_nb_erb_freqs); - let ds_dir = args.ds_dir.to_str().unwrap(); - let mut ds_builder = DatasetBuilder::new(ds_dir, sr).df_params( - fft_size, - Some(hop_size), - Some(nb_erb), - Some(nb_df), - None, - ); - ds_builder = ds_builder - .seed(global_seed) - .max_len(train_cfg.get("max_sample_len_s").unwrap().parse::()?) - .snrs(snrs) - .global_sample_factor(train_cfg.get("global_ds_sampling_f").unwrap().parse::()?) - .prob_reverberation(distortion_cfg.get("p_reverb").unwrap().parse::()?) - .clipping_distortion(distortion_cfg.get("p_clipping").unwrap().parse::()?) - .zeroing_distortion(distortion_cfg.get("p_zeroing").unwrap().parse::()?) - .interfer_distortion(distortion_cfg.get("p_interfer_sp").unwrap().parse::()?) - .air_absorption_distortion(distortion_cfg.get("p_air_absorption").unwrap().parse::()?) - .bandwidth_extension(distortion_cfg.get("p_bandwidth_ext").unwrap().parse::()?); - if split == Split::Train { - ds_builder = ds_builder.p_sample_full_speech(1.0); - } - log::info!("Opening dataset with config {}", args.ds_cfg.display()); - io::stdout().flush()?; - let mut ds = ds_builder.dataset(ds_cfg.split_config(split)).build_fft_dataset()?; - log::info!("Opened dataset with config {}", args.ds_cfg.display()); - for s in Split::iter() { - fetch_hdf5_keys_from_ds(ds_dir, ds_cfg.get_mut(s), &ds); - } - write_hdf5_key_cache(ds_cfg_path, &ds_cfg); - let epoch_seed = args.epoch.unwrap_or_default() as u64; - ds.generate_keys(Some(epoch_seed))?; - let mut rng = thread_rng().unwrap(); - let indices = { - if !args.idx.is_empty() { - args.idx - } else { - let n_samples = args.num.unwrap_or_else(|| ds.len()); - if args.randomize { - (0..ds.len()).choose_multiple(&mut rng, n_samples) - } else { - (0..n_samples).collect() - } - } - }; - for &idx in indices.iter() { - log::info!("Loading sample {}", idx); - let mut sample = ds.get_sample(idx, Some(epoch_seed + idx as u64)).unwrap(); - let ch = sample.speech.len_of(Axis(0)) as u16; - log::info!("Got sample with idx {}", sample.idx); - let speech = istft( - sample.speech.view_mut().into_dimensionality().unwrap(), - &mut state, - true, - ); - write_wav_iter( - &format!("{}/{}_speech.wav", out_dir, sample.idx), - speech.iter(), - sr as u32, - ch, - )?; - let noisy = istft( - sample.noisy.view_mut().into_dimensionality().unwrap(), - &mut state, - true, - ); - write_wav_iter( - &format!("{}/{}_noisy.wav", out_dir, sample.idx), - noisy.iter(), - sr as u32, - ch, - )?; - } - Ok(()) -} diff --git a/libDF/src/bin/sample-hdf5.rs b/libDF/src/bin/sample-hdf5.rs deleted file mode 100644 index d67ecf5fd..000000000 --- a/libDF/src/bin/sample-hdf5.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::env::args; -use std::process::exit; - -use anyhow::Result; -use df::dataset::Hdf5Dataset; -use df::wav_utils::write_wav_arr2; -use rand::seq::SliceRandom; - -fn main() -> Result<()> { - let args = args().collect::>(); - let p = match args.get(1) { - Some(p) => p, - None => { - eprintln!("HDF5 dataset path expected"); - exit(1); - } - }; - let ds = Hdf5Dataset::new(p)?; - let k = match args.get(2) { - Some(k) => k.to_string(), - None => ds.keys()?.choose(&mut rand::thread_rng()).unwrap().to_string(), - }; - let data = ds.read(&k).unwrap(); - let out_dir = args.get(3).cloned().unwrap_or_else(|| "out".to_owned()); - let name = format!("{out_dir}/{k}"); - println!("{name}"); - write_wav_arr2(&name, data.view(), ds.sr.unwrap_or(24000) as u32).unwrap(); - Ok(()) -} diff --git a/libDF/src/capi.rs b/libDF/src/capi.rs deleted file mode 100644 index 37f9afd7c..000000000 --- a/libDF/src/capi.rs +++ /dev/null @@ -1,253 +0,0 @@ -use std::boxed::Box; -use std::ffi::{c_char, c_float, c_uint, CStr, CString}; -use std::path::PathBuf; -use std::str::FromStr; - -use crossbeam_channel::TryRecvError; -use ndarray::prelude::*; - -use crate::logging::*; -use crate::tract::*; - -pub struct DFState { - m: crate::tract::DfTract, - logger: Option, -} - -impl DFState { - fn new(model_path: &str, channels: usize, atten_lim: f32, log_level: Option<&str>) -> Self { - let logger = if let Some(level) = log_level { - let (logger, log_receiver) = - DfLogger::build(log::Level::from_str(level).expect("Could not parse log level")); - init_logger(logger); - Some(log_receiver) - } else { - None - }; - let mut r_params = RuntimeParams::default_with_ch(channels); //channel - r_params = r_params.with_atten_lim(atten_lim).with_thresholds( - -15.0f32, //min_db_thresh - 35.0f32, //max_db_erb_thresh - 35.0f32, //max_db_df_thresh - ); - r_params = r_params.with_post_filter(0.0f32); //post_filter_beta - r_params = r_params.with_mask_reduce(ReduceMask::MAX); //reduce_mask - let df_params = - DfParams::new(PathBuf::from(model_path)).expect("Could not load model from path"); - let m = - DfTract::new(df_params, &r_params).expect("Could not initialize DeepFilter runtime."); - DFState { m, logger } - } - /// Returns the next log message as String - fn get_next_log_message(&mut self) -> Option { - if let Some(logger) = self.logger.as_ref() { - match logger.try_recv() { - Ok(m) => { - let mut prefix: String = String::new(); - if let Some(module) = m.2 { - prefix.push_str(&module); - if let Some(lineno) = m.3 { - prefix.push(':'); - prefix.push_str(&lineno.to_string()) - } - } - let mut message = m.0.as_str().to_owned() + " | " + &m.1; - if !prefix.is_empty() { - message = prefix + " | " + &message - } - return Some(message); - } - Err(TryRecvError::Empty) => return None, - Err(TryRecvError::Disconnected) => { - eprintln!("DF logger disconnected unexpectetly!"); - return None; - } - } - } - None - } - fn boxed(self) -> Box { - Box::new(self) - } -} - -/// Create a DeepFilterNet Model -/// -/// Args: -/// - path: File path to a DeepFilterNet tar.gz onnx model -/// - atten_lim: Attenuation limit in dB. -/// -/// Returns: -/// - DF state doing the full processing: stft, DNN noise reduction, istft. -#[no_mangle] -pub unsafe extern "C" fn df_create( - path: *const c_char, - // channels: usize, - atten_lim: f32, - log_level: *const c_char, -) -> *mut DFState { - let c_str = CStr::from_ptr(path); - let path = c_str.to_str().unwrap(); - let log_level = if log_level.is_null() { - None - } else { - match CStr::from_ptr(log_level).to_str() { - Ok(a) => Some(a), - Err(e) => { - eprintln!("Could not parse log_level {}", e); - None - } - } - }; - let df = DFState::new(path, 1, atten_lim, log_level); - Box::into_raw(df.boxed()) -} - -/// Get DeepFilterNet frame size in samples. -#[no_mangle] -pub unsafe extern "C" fn df_get_frame_length(st: *mut DFState) -> usize { - let state = st.as_mut().expect("Invalid pointer"); - state.m.hop_size -} - -/// Get the next log message. Must be freed via `df_free_log_msg(ptr)` -#[no_mangle] -pub unsafe extern "C" fn df_next_log_msg(st: *mut DFState) -> *mut c_char { - let state = st.as_mut().expect("Invalid pointer"); - let msg = state.get_next_log_message(); - if let Some(msg) = msg { - let c_msg = CString::new(msg).expect("Failed to convert log message to CString"); - c_msg.into_raw() - } else { - std::ptr::null_mut() - } -} - -#[no_mangle] -pub unsafe extern "C" fn df_free_log_msg(ptr: *mut c_char) { - let _ = CString::from_raw(ptr); -} - -/// Set DeepFilterNet attenuation limit. -/// -/// Args: -/// - lim_db: New attenuation limit in dB. -#[no_mangle] -pub unsafe extern "C" fn df_set_atten_lim(st: *mut DFState, lim_db: f32) { - let state = st.as_mut().expect("Invalid pointer"); - state.m.set_atten_lim(lim_db) -} - -/// Set DeepFilterNet post filter beta. A beta of 0 disables the post filter. -/// -/// Args: -/// - beta: Post filter attenuation. Suitable range between 0.05 and 0; -#[no_mangle] -pub unsafe extern "C" fn df_set_post_filter_beta(st: *mut DFState, beta: f32) { - let state = st.as_mut().expect("Invalid pointer"); - state.m.set_pf_beta(beta) -} - -/// Processes a chunk of samples. -/// -/// Args: -/// - df_state: Created via df_create() -/// - input: Input buffer of length df_get_frame_length() -/// - output: Output buffer of length df_get_frame_length() -/// -/// Returns: -/// - Local SNR of the current frame. -#[no_mangle] -pub unsafe extern "C" fn df_process_frame( - st: *mut DFState, - input: *mut c_float, - output: *mut c_float, -) -> c_float { - let state = st.as_mut().expect("Invalid pointer"); - let input = ArrayView2::from_shape_ptr((1, state.m.hop_size), input); - let output = ArrayViewMut2::from_shape_ptr((1, state.m.hop_size), output); - - state.m.process(input, output).expect("Failed to process DF frame") -} - -/// Processes a filter bank sample and return raw gains and DF coefs. -/// -/// Args: -/// - df_state: Created via df_create() -/// - input: Spectrum of shape `[n_freqs, 2]`. -/// - out_gains_p: Output buffer of real-valued ERB gains of shape `[nb_erb]`. This function -/// may set this pointer to NULL if the local SNR is greater 30 dB. No gains need to be -/// applied then. -/// - out_coefs_p: Output buffer of complex-valued DF coefs of shape `[df_order, nb_df_freqs, 2]`. -/// This function may set this pointer to NULL if the local SNR is greater 20 dB. No DF -/// coefficients need to be applied. -/// -/// Returns: -/// - Local SNR of the current frame. -#[no_mangle] -pub unsafe extern "C" fn df_process_frame_raw( - st: *mut DFState, - input: *mut c_float, - out_gains_p: *mut *mut c_float, - out_coefs_p: *mut *mut c_float, -) -> c_float { - let state = st.as_mut().expect("Invalid pointer"); - let input = ArrayView2::from_shape_ptr((1, state.m.n_freqs), input); - state.m.set_spec_buffer(input).expect("Failed to set input spectrum"); - let (lsnr, gains, coefs) = state.m.process_raw().expect("Failed to process DF spectral frame"); - let mut out_gains = ArrayViewMut2::from_shape_ptr((1, state.m.nb_erb), *out_gains_p); - let mut out_coefs = - ArrayViewMut4::from_shape_ptr((1, state.m.df_order, state.m.nb_df, 2), *out_coefs_p); - if let Some(gains) = gains { - out_gains.assign(&gains.to_array_view().unwrap()); - } else { - *out_gains_p = std::ptr::null_mut(); - } - if let Some(coefs) = coefs { - out_coefs.assign(&coefs.to_array_view().unwrap()); - } else { - *out_coefs_p = std::ptr::null_mut(); - } - lsnr -} - -// file.rs -#[repr(C)] -pub struct DynArray { - array: *mut c_uint, - length: c_uint, -} - -/// Get size of DeepFilter coefficients -pub unsafe extern "C" fn df_coef_size(st: *const DFState) -> DynArray { - let state = st.as_ref().expect("Invalid pointer"); - let mut shape = vec![ - state.m.ch as u32, - state.m.df_order as u32, - state.m.n_freqs as u32, - 2, - ]; - let ret = DynArray { - array: shape.as_mut_ptr(), - length: shape.len() as u32, - }; - std::mem::forget(shape); - ret -} -/// Get size ERB gains -pub unsafe extern "C" fn df_gain_size(st: *const DFState) -> DynArray { - let state = st.as_ref().expect("Invalid pointer"); - let mut shape = vec![state.m.ch as u32, state.m.nb_erb as u32]; - let ret = DynArray { - array: shape.as_mut_ptr(), - length: shape.len() as u32, - }; - std::mem::forget(shape); - ret -} - -/// Free a DeepFilterNet Model -#[no_mangle] -pub unsafe extern "C" fn df_free(model: *mut DFState) { - let _ = Box::from_raw(model); -} diff --git a/libDF/src/dataloader.rs b/libDF/src/dataloader.rs deleted file mode 100644 index e1a4e831f..000000000 --- a/libDF/src/dataloader.rs +++ /dev/null @@ -1,741 +0,0 @@ -use std::collections::BTreeMap; -use std::collections::VecDeque; -use std::fmt; -use std::sync::mpsc::{sync_channel, Receiver}; -use std::sync::{Arc, Mutex}; -use std::thread; -use std::time::Duration; -use std::time::Instant; - -use crossbeam_channel::unbounded; -use ndarray::prelude::*; -use ndarray_rand::rand::prelude::SliceRandom; -use rayon::{current_num_threads, prelude::*, ThreadPoolBuildError, ThreadPoolBuilder}; -use thiserror::Error; - -type Result = std::result::Result; - -use crate::{dataset::*, util::*, Complex32}; - -#[derive(Error, Debug)] -pub enum DfDataloaderError { - #[error("Dataloading Timeout")] - TimeoutError, - #[error("Channels not initialized. Have you already called start_epoch()?")] - ChannelsNotInitializedError, - #[error( - "Dataset {split} size ({dataset_size}) smaller than batch size ({batch_size}). Try increasing the dataset sampling factor or decreasing the batch size." - )] - DatasetTooSmall { - split: Split, - dataset_size: usize, - batch_size: usize, - }, - #[error("Dataset Drained")] - DatasetDrained, - #[error("Multithreading Send Error: {0:?}")] - SendError(String), - #[error("Thread Join Error: {0:?}")] - ThreadJoinError(String), - #[error("Threadpool Builder Error")] - ThreadPoolBuildError(#[from] ThreadPoolBuildError), - #[error("DF Transforms Error")] - TransformError(#[from] crate::transforms::TransformError), - #[error("DF Augmentation Error")] - AugmentationError(#[from] crate::augmentations::AugmentationError), - #[error("DF Utils Error")] - UtilsError(#[from] crate::util::UtilsError), - #[error("DF Dataset Error")] - DatasetError(#[from] crate::dataset::DfDatasetError), - #[error("Ndarray Shape Error")] - NdarrayShapeError(#[from] ndarray::ShapeError), -} - -impl From> for DfDataloaderError { - fn from(error: std::sync::mpsc::SendError) -> Self { - DfDataloaderError::SendError(error.to_string()) - } -} - -pub struct DataLoader { - ds_train: Option>, // Option is needed to retake ownership via option.take() - ds_valid: Option>, - ds_test: Option>, - batch_size_train: usize, - batch_size_eval: usize, - num_workers: usize, - num_prefech: usize, - idcs: Arc>>, - current_split: Split, - fill_thread: Option>>, - out_receiver: Option>)>>, - out_buf: BTreeMap>, - cur_out_idx: usize, - drop_last: bool, - drained: bool, - overfit: bool, -} - -#[derive(Default)] -pub struct DataLoaderBuilder { - _ds: Option, - _batch_size: Option, - _batch_size_eval: Option, - _prefetch: Option, - _num_threads: Option, - _drop_last: bool, - _overfit: bool, -} - -impl DataLoaderBuilder { - pub fn new(ds: Datasets) -> Self { - DataLoaderBuilder { - _ds: Some(ds), - _batch_size: None, - _batch_size_eval: None, - _prefetch: None, - _num_threads: None, - _drop_last: false, - _overfit: false, - } - } - pub fn batch_size(mut self, batch_size: usize) -> Self { - self._batch_size = Some(batch_size); - self - } - pub fn batch_size_eval(mut self, batch_size: usize) -> Self { - self._batch_size_eval = Some(batch_size); - self - } - pub fn prefetch(mut self, prefetch: usize) -> Self { - self._prefetch = Some(prefetch); - self - } - pub fn num_threads(mut self, num_threads: usize) -> Self { - self._num_threads = Some(num_threads); - self - } - pub fn overfit(mut self) -> Self { - self._overfit = true; - self - } - pub fn drop_last(mut self) -> Self { - self._drop_last = true; - self - } - pub fn build(self) -> Result { - let bs_train = self._batch_size.unwrap_or(1); - let prefetch = self._prefetch.unwrap_or(bs_train * self._num_threads.unwrap_or(4)); - let mut loader = DataLoader::new( - self._ds.unwrap(), - bs_train, - self._batch_size_eval, - prefetch, - self._num_threads, - self._drop_last, - )?; - loader.overfit = self._overfit; - Ok(loader) - } -} - -impl DataLoader { - pub fn builder(ds: Datasets) -> DataLoaderBuilder { - DataLoaderBuilder::new(ds) - } - pub fn new( - datasets: Datasets, - batch_size_train: usize, - batch_size_eval: Option, - num_prefech: usize, - num_threads: Option, - drop_last: bool, - ) -> Result { - // Register global rayon threadpool. It will only be used for data loader workers. - hdf5::sync::sync(|| {}); - let num_workers = num_threads.unwrap_or_else(current_num_threads); - hdf5::sync::sync(|| {}); - ThreadPoolBuilder::new() - .num_threads(num_workers) - .thread_name(|idx| format!("DataLoader Worker {idx}")) - .start_handler(|_| hdf5::sync::sync(|| {})) - .build_global() - .unwrap_or(()); - let batch_size_eval = batch_size_eval.unwrap_or(batch_size_train); - Ok(DataLoader { - ds_train: Some(Arc::new(datasets.train)), - ds_valid: Some(Arc::new(datasets.valid)), - ds_test: Some(Arc::new(datasets.test)), - batch_size_train, - batch_size_eval, - num_workers, - num_prefech, - idcs: Arc::new(Mutex::new(VecDeque::new())), - current_split: Split::Train, - fill_thread: None, - out_receiver: None, - out_buf: BTreeMap::new(), - cur_out_idx: 0, - drop_last, - drained: false, - overfit: false, - }) - } - - pub fn get_ds_arc>(&self, split: S) -> Arc { - match split.into() { - Split::Train => self.ds_train.as_ref().unwrap().clone(), - Split::Valid => self.ds_valid.as_ref().unwrap().clone(), - Split::Test => self.ds_test.as_ref().unwrap().clone(), - } - } - - pub fn set_ds>(&mut self, split: S, ds: FftDataset) { - match split.into() { - Split::Train => self.ds_train.replace(Arc::new(ds)), - Split::Valid => self.ds_valid.replace(Arc::new(ds)), - Split::Test => self.ds_test.replace(Arc::new(ds)), - }; - } - - pub fn dataset_len>(&self, split: S) -> usize { - let split = split.into(); - let len = self.get_ds_arc(split).len(); - if self.overfit && split != Split::Train { - // During valid/test only return one batch for each epoch. - // All batches will be the same and result in same metrics/loss anyways. - return len.min(self.batch_size_eval); - } - len - } - - pub fn dataloader_len + Copy>(&self, split: S) -> usize { - let bs = self.batch_size(split); - if self.drop_last { - self.dataset_len(split) / bs - } else { - (self.dataset_len(split) as f32 / bs as f32).ceil() as usize - } - } - - pub fn batch_size>(&self, split: S) -> usize { - if split.into() == Split::Train { - self.batch_size_train - } else { - self.batch_size_eval - } - } - - pub fn set_batch_size>(&mut self, batch_size: usize, split: S) { - if split.into() == Split::Train { - self.batch_size_train = batch_size; - } else { - self.batch_size_eval = batch_size; - } - } - - pub fn start_idx_worker( - &mut self, - split: Split, - epoch_seed: u64, - ) -> Result>> { - let bs = self.batch_size(split); - if self.num_prefech < bs { - eprintln!( - "Warning: Prefetch size ({}) is smaller then batch size ({}).", - self.num_prefech, bs - ) - } - let (out_sender, out_receiver) = sync_channel(self.num_prefech); - self.out_receiver = Some(out_receiver); - let ds = self.get_ds_arc(split); - let (in_sender, in_receiver) = unbounded(); - let idcs = self.idcs.lock().unwrap().drain(..).collect::>(); - for idx in idcs { - in_sender.send(idx).expect("Could not send index"); - } - in_sender.send((0, -1)).expect("Could not send index"); - - let worker_recievers: Vec<_> = (0..self.num_workers).map(|_| in_receiver.clone()).collect(); - let overfit = self.overfit; - let is_train = self.current_split == Split::Train; - let handle = thread::spawn(move || -> Result<()> { - worker_recievers.par_iter().try_for_each(|r| { - while let Ok((sample_idx, ordering_idx)) = r.recv() { - if ordering_idx == -1 { - out_sender.send((0, Err(DfDataloaderError::DatasetDrained)))?; - return Ok(()); - } - assert!(ordering_idx >= 0); - let seed = if overfit { - 0 - } else if is_train { - // Only during training, provide a new seed for each epoch - epoch_seed + sample_idx as u64 - } else { - // During valid/test, only use sample_idx as seed - sample_idx as u64 - }; - log::trace!("Worker: Getting sample {} with seed {}", sample_idx, seed); - let sample = match ds.get_sample(sample_idx, Some(seed)) { - Ok(s) => Ok(s), - Err(e) => { - eprintln!( - "Error during get_sample() (idx: {sample_idx}, seed {seed:?}): {e:?}" - ); - Err(e.into()) - } - }; - out_sender.send((ordering_idx as usize, sample))?; - } - Ok(()) - }) - }); - Ok(handle) - } - - pub fn start_epoch>(&mut self, split: S, mut epoch_seed: usize) -> Result<()> { - let split: Split = split.into(); - // Drop fill thread if exits - if self.fill_thread.is_some() { - self.join_fill_thread()?; - } - if self.overfit { - log::trace!("Overfitting epoch. Using train set for all splits."); - epoch_seed = 0; - } - log::trace!("Start {} epoch with seed {}", split, epoch_seed); - // Check whether we need to regenerate. Typically only required for a custom sampling factor. - if self.get_ds_arc(split).need_generate_keys(self.overfit) { - for s in Split::iter() { - let mut ds = match Arc::try_unwrap( - match s { - Split::Train => self.ds_train.take(), - Split::Valid => self.ds_valid.take(), - Split::Test => self.ds_test.take(), - } - .unwrap(), - ) { - Ok(ds) => ds, - Err(_) => panic!("Could not regain ownership over dataset"), - }; - ds.generate_keys(Some(epoch_seed as u64))?; - log::trace!("Generated dataset keys for {}", s); - self.set_ds(s, ds); - } - } - // Output buffers for ordering analogue to self.idcs - self.out_buf = BTreeMap::new(); - self.cur_out_idx = 0; - // Prepare for new epoch - self.current_split = if !self.overfit { split } else { Split::Train }; - { - // Recreate indices to index into the dataset and shuffle them - let n_samples = self.dataset_len(self.current_split); - let sample_idcs: Vec = if self.overfit { - log::warn!("Overfitting on one batch."); - (0..n_samples).cycle().take(n_samples).collect() - } else { - let mut tmp = (0..n_samples).collect::>(); - tmp.shuffle(&mut thread_rng()?); - tmp - }; - // Concatenate an ordering index - let idcs: VecDeque<(usize, isize)> = sample_idcs - .into_iter() - .zip(0..self.dataset_len(self.current_split) as isize) - .collect(); - self.idcs.lock().unwrap().clone_from(&idcs); - } - // Start thread to submit dataset jobs for the pool workers - self.fill_thread = Some(self.start_idx_worker(self.current_split, epoch_seed as u64)?); - log::trace!( - "Started dataloader worker for split {} with epoch_seed {}", - self.current_split, - epoch_seed - ); - #[cfg(feature = "timings")] - log::trace!("Logging timings"); - self.drained = false; - Ok(()) - } - - pub fn get_batch(&mut self) -> Result>> - where - C: Collate, - { - #[cfg(feature = "timings")] - let t0 = Instant::now(); - let bs = self.batch_size(self.current_split); - let mut timings = Vec::with_capacity(bs); - let mut samples = Vec::with_capacity(bs); - let target_idx = self.dataset_len(self.current_split).min(self.cur_out_idx + bs); - if self.cur_out_idx >= self.dataset_len(self.current_split) { - self.drained = true; - } - let mut tries = 0; - let mut ids = Vec::with_capacity(self.batch_size(self.current_split)); - let reciever = match self.out_receiver.as_ref() { - None => { - return Err(DfDataloaderError::ChannelsNotInitializedError); - } - Some(r) => r, - }; - let mut ts0 = Instant::now(); - 'outer: while self.cur_out_idx < target_idx { - // Check if we have some buffered samples - if let Some(s) = self.out_buf.remove(&self.cur_out_idx) { - ids.push(s.idx); - samples.push(s); - let ts1 = Instant::now(); - timings.push((ts1 - ts0).as_secs_f32()); - ts0 = ts1; - self.cur_out_idx += 1; - } else { - // Or check worker threads - match reciever.recv_timeout(Duration::from_millis(100)) { - Err(_e) => { - log::trace!("Dataloader worker timeount. Retrying ({})", tries); - if tries > 1000 { - return Err(DfDataloaderError::TimeoutError); - } - tries += 1; - continue 'outer; - } - Ok((_, Err(DfDataloaderError::DatasetDrained))) => { - self.drained = true; - } - Ok((_, Err(e))) => { - return Err(e); - } - Ok((o_idx, Ok(s))) => { - if o_idx == self.cur_out_idx { - ids.push(s.idx); - samples.push(s); - let ts1 = Instant::now(); - timings.push((ts1 - ts0).as_secs_f32()); - ts0 = ts1; - self.cur_out_idx += 1; - } else { - assert!(self.out_buf.insert(o_idx, s).is_none()); - } - } - } - } - tries = 0; - } - #[cfg(feature = "timings")] - let t1 = Instant::now(); - - let out = if self.drained && (self.drop_last || samples.is_empty()) { - assert!(self.cur_out_idx >= target_idx); - assert!(self.out_buf.is_empty()); - self.join_fill_thread()?; - None - } else { - let mut batch = C::collate( - samples.as_mut_slice(), - self.get_ds_arc(self.current_split).max_sample_len(), - )?; - batch.ids.extend(ids); - debug_assert!(batch.batch_size() <= self.batch_size(self.current_split)); - if !self.drained && self.cur_out_idx < target_idx { - debug_assert_eq!(batch.batch_size(), self.batch_size(self.current_split)); - } - batch.timings = timings; - Some(batch) - }; - #[cfg(feature = "timings")] - if log::log_enabled!(log::Level::Trace) { - let t2 = Instant::now(); - log::trace!( - "Returning batch in {} ms, (got samples in {} ms)", - (t2 - t0).as_millis(), - (t1 - t0).as_millis() - ); - } - Ok(out) - } - - pub fn join_fill_thread(&mut self) -> Result<()> { - // Drop out_receiver so that parallel iter in fill thread will return - drop(self.out_receiver.take()); - if let Some(thread) = self.fill_thread.take() { - let e = thread.join(); - match e { - Err(e) => { - eprint!("Error during worker shutdown"); - return Err(DfDataloaderError::ThreadJoinError(format!("{e:?}"))); - } - Ok(r) => match r { - Ok(()) => (), - Err(DfDataloaderError::SendError(_)) => (), - Err(e) => { - // Not expected send error due to out_channel closing - return Err(e); - } - }, - } - } - Ok(()) - } -} - -pub trait Collate { - fn collate(samples: &mut [Sample], len: usize) -> Result>; -} -impl Collate for f32 { - fn collate(samples: &mut [Sample], len: usize) -> Result> { - let lengths = samples.iter().map(|s| s.speech.len_of(Axis(1))).collect(); - let speech = unpack_pad(|s: &mut Sample| &mut s.speech, samples, len)?; - let noisy = unpack_pad(|s: &mut Sample| &mut s.noisy, samples, len)?; - let max_freq = samples.iter().map(|s| s.max_freq).collect(); - let snr = samples.iter().map(|s| s.snr).collect(); - let gain = samples.iter().map(|s| s.gain).collect(); - Ok(DsBatch { - speech, - noisy, - feat_erb: None, - feat_spec: None, - lengths, - max_freq, - snr, - gain, - ids: Vec::new(), - timings: Vec::new(), - }) - } -} -impl Collate for Complex32 { - fn collate(samples: &mut [Sample], len: usize) -> Result> { - let lengths = samples.iter().map(|s| s.speech.len_of(Axis(1))).collect(); - let speech = unpack_pad(|s: &mut Sample| &mut s.speech, samples, len)?; - let noisy = unpack_pad(|s: &mut Sample| &mut s.noisy, samples, len)?; - let feat_erb = if samples.first().unwrap().feat_erb.is_some() { - Some(unpack_pad( - |s: &mut Sample| s.feat_erb.as_mut().unwrap(), - samples, - len, - )?) - } else { - None - }; - let feat_spec = if samples.first().unwrap().feat_spec.is_some() { - Some(unpack_pad( - |s: &mut Sample| s.feat_spec.as_mut().unwrap(), - samples, - len, - )?) - } else { - None - }; - let max_freq = samples.iter().map(|s| s.max_freq).collect(); - let snr = samples.iter().map(|s| s.snr).collect(); - let gain = samples.iter().map(|s| s.gain).collect(); - Ok(DsBatch { - speech, - noisy, - feat_erb, - feat_spec, - lengths, - max_freq, - snr, - gain, - ids: Vec::new(), - timings: Vec::new(), - }) - } -} - -impl Drop for DataLoader { - fn drop(&mut self) { - self.join_fill_thread().unwrap(); // Stop out_receiver and join fill thread - for split in Split::iter() { - let ds = match Arc::try_unwrap( - match split { - Split::Train => self.ds_train.take(), - Split::Valid => self.ds_valid.take(), - Split::Test => self.ds_test.take(), - } - .unwrap_or_else(|| { - panic!("No {split} dataset found. Could not stop dataloader worker.") - }), - ) { - Ok(ds) => ds, - Err(_) => panic!("Could not regain ownership over dataset"), - }; - self.set_ds(split, ds); - } - } -} - -pub struct DsBatch -where - T: Data, -{ - pub speech: ArrayD, - pub noisy: ArrayD, - pub feat_erb: Option>, - pub feat_spec: Option>, - pub lengths: Array1, - pub max_freq: Array1, - pub snr: Vec, - pub gain: Vec, - pub ids: Vec, - pub timings: Vec, -} -impl DsBatch -where - T: Data, -{ - pub fn batch_size(&self) -> usize { - self.speech.len_of(Axis(0)) - } - pub fn sample_len(&self) -> usize { - self.speech.len_of(Axis(2)) - } -} -impl fmt::Debug for DsBatch -where - T: Data, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_fmt(format_args!( - "Dataset Batch with batch_size: '{}, len: '{}', snrs: '{:?}', gain: '{:?}')", - self.batch_size(), - self.sample_len(), - self.snr, - self.gain - )) - } -} - -fn unpack_pad(mut f: F, samples: &mut [Sample], len: usize) -> Result> -where - Ts: Data, - To: Data, - F: FnMut(&mut Sample) -> &mut ArrayD, -{ - let mut out: Vec> = Vec::with_capacity(samples.len()); - for sample in samples.iter_mut() { - let x: &mut ArrayD = f(sample); - - let missing = len.saturating_sub(x.len_of(Axis(1))); - if missing > 0 { - let mut shape: Vec = x.shape().into(); - shape[1] = missing; - let tmp: ArrayD = ArrayD::::zeros(shape); - x.append(Axis(1), tmp.into_dimensionality()?.view())?; - } - out.push(x.view_mut()); - } - let out: Vec> = out.iter().map(|s| s.view()).collect(); - if !out.windows(2).all(|w| w[0].shape() == w[1].shape()) { - eprintln!("Shapes do not match!"); - for outs in out.iter() { - eprintln!(" shape: {:?}", outs.shape()); - } - } - Ok(ndarray::stack(Axis(0), out.as_slice())?.into_dyn()) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::dataset::DatasetConfigJson; - use crate::util::seed_from_u64; - - #[test] - pub fn test_data_loader() -> Result<()> { - println!("******** Start test_data_loader() ********"); - seed_from_u64(42); - let fft_size = 960; - let hop_size = 480; - let nb_erb = Some(32); - let nb_spec = None; - let norm_alpha = None; - let sr = 48000; - let ds_dir = "../assets/"; - let max_len_s = 1.0; - let mut cfg = DatasetConfigJson::open("../assets/dataset.cfg")?; - let builder = DatasetBuilder::new(ds_dir, sr) - .df_params(fft_size, Some(hop_size), nb_erb, nb_spec, norm_alpha) - .max_len(max_len_s); - for dataset_size in [1, 2, 4, 17] { - for c in cfg.train.iter_mut() { - c.1 = dataset_size as f32; // Set sampling factor - assert_eq!(c.sampling_factor(), dataset_size as f32); - } - for c in cfg.valid.iter_mut() { - c.1 = dataset_size as f32; // Set sampling factor - assert_eq!(c.sampling_factor(), dataset_size as f32); - } - for c in cfg.test.iter_mut() { - c.1 = dataset_size as f32; // Set sampling factor - assert_eq!(c.sampling_factor(), dataset_size as f32); - } - 'inner: for batch_size in [1, 2, 16] { - let ds = Datasets { - train: builder - .clone() - .dataset(cfg.split_config(Split::Train)) - .build_fft_dataset()?, - valid: builder - .clone() - .dataset(cfg.split_config(Split::Valid)) - .build_fft_dataset()?, - test: builder - .clone() - .dataset(cfg.split_config(Split::Valid)) - .build_fft_dataset()?, - }; - let mut loader = match DataLoader::builder(ds) - .num_threads(1) - .batch_size(batch_size) - .batch_size_eval(1) - .build() - { - Ok(loader) => loader, - Err(e) => match e { - DfDataloaderError::DatasetTooSmall { - split: s_, - dataset_size: ds_, - batch_size: bs_, - } => { - if dataset_size < batch_size { - continue 'inner; // This is expected - } - return Err(DfDataloaderError::DatasetTooSmall { - split: s_, - dataset_size: ds_, - batch_size: bs_, - }); - } - e => return Err(e), - }, - }; - for split in Split::iter() { - for epoch in 0..2 { - println!( - "***** Test: Loader with dataset_size {dataset_size}, batch_size {batch_size}, epoch {epoch} ******" - ); - loader.start_epoch(split, epoch)?; - let mut n_samples = 0; - dbg!(dataset_size); - while let Some(batch) = loader.get_batch::().unwrap() { - n_samples += batch.batch_size(); - dbg!(n_samples, batch.speech.shape()); - debug_assert_eq!( - batch.speech.len_of(Axis(2)), - (max_len_s * (sr / hop_size) as f32).round() as usize - ); - assert!(n_samples <= dataset_size); - } - dbg!(n_samples, dataset_size); - } - } - } - } - Ok(()) - } -} diff --git a/libDF/src/dataset.rs b/libDF/src/dataset.rs deleted file mode 100644 index cb81f5f1b..000000000 --- a/libDF/src/dataset.rs +++ /dev/null @@ -1,2449 +0,0 @@ -use std::collections::{hash_map::DefaultHasher, HashMap}; -use std::env; -use std::ffi::OsStr; -use std::fmt; -use std::fmt::Display; -#[cfg(feature = "timings")] -use std::fmt::Write as _; -use std::fs; -use std::hash::{Hash, Hasher}; -use std::io::{BufReader, BufWriter}; -#[cfg(feature = "vorbis")] -use std::io::{Cursor, Read, Seek}; -use std::marker::Copy; -use std::ops::Range; -use std::path::Path; -use std::str::FromStr; -use std::sync::mpsc::sync_channel; -#[cfg(feature = "timings")] -use std::time::Instant; -use std::time::SystemTime; - -use anyhow::Context; -#[cfg(feature = "flac")] -use claxon; -use hdf5::{types::VarLenUnicode, File}; -use ndarray::concatenate; -use ndarray::{prelude::*, Slice}; -use ndarray_rand::rand::prelude::{IteratorRandom, SliceRandom}; -use rayon::prelude::*; -use realfft::num_traits::Zero; -use serde::{Deserialize, Serialize}; -use thiserror::Error; -#[cfg(feature = "vorbis")] -use {lewton::inside_ogg::OggStreamReader, ogg::reading::PacketReader as OggPacketReader}; - -use crate::{augmentations::*, transforms::*, util::*, *}; - -type Result = std::result::Result; - -#[derive(Error, Debug)] -pub enum DfDatasetError { - #[error("No Hdf5 datasets found: {0}")] - NoDatasetFoundError(String), - #[error("No Hdf5 dataset type found")] - Hdf5DsTypeNotFoundError, - #[error("{codec:?} codec not supported in dataset {ds:?}")] - CodecNotSupportedError { codec: Codec, ds: String }, - #[error("Unsupported during PCM decode: {0}")] - PcmUnspportedDimension(usize), - #[error("Wav Reader Error")] - WavReadError(#[from] crate::wav_utils::WavUtilsError), - #[error("Input Range ({range:?}) larger than dataset size ({size:?})")] - PcmRangeToLarge { - range: Range, - size: Vec, - }, - #[error("Data Processing Error: {0:?}")] - DataProcessingError(String), - #[error("DF Transforms Error")] - TransformError(#[from] crate::transforms::TransformError), - #[error("DF Augmentation Error")] - AugmentationError(#[from] crate::augmentations::AugmentationError), - #[error("DF Utils Error")] - UtilsError(#[from] crate::util::UtilsError), - #[error("Error Detail")] - ErrorDetail { source: Box, msg: String }, - #[error("Ndarray Shape Error")] - NdarrayShapeError(#[from] ndarray::ShapeError), - #[error("Hdf5 Error")] - Hdf5Error(#[from] hdf5::Error), - #[error("Hdf5 Error Detail")] - Hdf5ErrorDetail { source: hdf5::Error, msg: String }, - #[error("IO Error")] - IoError(#[from] std::io::Error), - #[error("Json Decoding Error")] - JsonDecode(#[from] serde_json::Error), - #[cfg(feature = "vorbis")] - #[error("Vorbis Decode Error")] - VorbisError(#[from] lewton::VorbisError), - #[cfg(feature = "vorbis")] - #[error("Ogg Decode Error")] - OggReadError(#[from] ogg::reading::OggReadError), - #[cfg(feature = "flac")] - #[error("Flac Decode Error")] - FlacError(#[from] claxon::Error), - #[error("Multithreading Send Error: {0:?}")] - SendError(String), - #[error("Multithreading Recv Error: {0:?}")] - RecvError(String), - #[error("Thread Join Error: {0:?}")] - ThreadJoinError(String), - #[error("Crossbeam Multithreading Send Error: {0:?}")] - CrossbeamSendError(String), - #[error("Not enough {0} samples in the dataset.")] - NotEnoughSamplesError(String), - #[error(transparent)] - Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error -} - -impl From> for DfDatasetError { - fn from(error: crossbeam_channel::SendError) -> Self { - DfDatasetError::CrossbeamSendError(error.to_string()) - } -} - -impl From for DfDatasetError { - fn from(error: std::sync::mpsc::RecvError) -> Self { - DfDatasetError::RecvError(error.to_string()) - } -} - -impl From> for DfDatasetError { - fn from(error: std::sync::mpsc::SendError) -> Self { - DfDatasetError::SendError(error.to_string()) - } -} - -type Signal = Array2; - -fn one() -> f32 { - 1. -} -/// Struct to check if a dataset was modified on disk. -/// This is used for caching the HDF5 keys, i.e. speech and noise file names. -/// The modification is checked via last modification time and file size. -#[derive(Hash, Debug, Clone)] -pub struct DatasetModified(SystemTime, u64); -impl DatasetModified { - fn new(file_name: &str) -> Result { - let meta_data = fs::metadata(file_name)?; - let modified = meta_data.modified()?; - let size = meta_data.len(); - log::trace!( - "Checking HDF5 key cache for {} (m: {:?}, s: {})", - file_name, - modified, - size - ); - Ok(DatasetModified(modified, size)) - } -} -/// HDF5 config for each dataset. -/// -/// Contains: -/// - file name of the HDF5 dataset on disk. -/// - sampling factor to over/under sample the dataset during training. -/// - fallback sampling rate if the HDF5 dataset does not store the sampling rate. -/// - fallback max_freq (unused) -/// - cached key list may additionally be used for loading the HDF5 keys from a cache file. -/// - modified hash is used to indicate if the cached key list is up to date. -#[derive(Deserialize, Debug, Clone)] -pub struct Hdf5Cfg( - pub String, // file name - #[serde(default = "one")] pub f32, // dataset sampling factor - #[serde(default = "Option::default")] pub Option, // fallback sampling rate - #[serde(default = "Option::default")] pub Option, // fallback max freq - #[serde(default = "Option::default")] pub Option, // cached key list - #[serde(default = "Option::default")] pub Option, // modified hash -); -impl Hdf5Cfg { - pub fn filename(&self) -> &str { - self.0.as_str() - } - pub fn sampling_factor(&self) -> f32 { - self.1 - } - pub fn set_sampling_factor(&mut self, f: f32) { - self.1 = f - } - pub fn fallback_sr(&self) -> Option { - self.2 - } - pub fn fallback_max_freq(&self) -> Option { - self.3 - } - pub fn keys_unchecked(&self) -> Option<&Hdf5Keys> { - self.4.as_ref() - } - pub fn hash(&self) -> Option { - self.5 - } - pub fn store_modified_hash(&mut self, hash: u64) { - self.5 = Some(hash); - } - pub fn hash_from_ds_path(&self, ds_path: &str) -> Result { - Ok(calculate_hash(&DatasetModified::new(ds_path)?)) - } - pub fn load_keys(&self, hash: u64) -> Result> { - if let Some(keys) = self.keys_unchecked() { - if keys.hash == hash { - return Ok(Some(keys)); - } - log::warn!( - "Hash does not match for {} (found {}, expected {})", - self.filename(), - keys.hash, - hash - ); - return Ok(None); - } - Ok(None) - } - pub fn set_keys_new(&mut self, hash: u64, keys: Vec) -> Result<()> { - self.set_keys(Hdf5Keys { - filename: self.filename().to_string(), - hash, - keys, - }) - } - pub fn set_keys(&mut self, keys: Hdf5Keys) -> Result<()> { - self.4.replace(keys); - Ok(()) - } -} -fn calculate_hash(t: &T) -> u64 { - let mut s = DefaultHasher::new(); - t.hash(&mut s); - s.finish() -} - -/// Keys within a HDF5 dataset. -/// -/// - filename: File name of the HDF5 dataset. -/// - hash: Modified hash of the dataset corresponding to loaded keys. -/// - keys: Speech/noise file names contained in the dataset. -#[derive(Deserialize, Serialize, Debug, Clone)] -pub struct Hdf5Keys { - pub filename: String, - hash: u64, - keys: Vec, -} -/// Dataset Configuration for train, validation, and test. -#[derive(Deserialize, Debug)] -pub struct DatasetConfigJson { - pub train: Vec, - pub valid: Vec, - pub test: Vec, -} -impl DatasetConfigJson { - pub fn open(cfg_path: &str) -> Result { - let file = fs::File::open(cfg_path)?; - let reader = BufReader::new(file); - let cfg = serde_json::from_reader(reader)?; - Ok(cfg) - } - pub fn set_keys>(&mut self, split: S, keys: &[Hdf5Keys]) -> Result<()> { - let s = self.get_mut(split); - for cfg in s.iter_mut() { - if let Some(key_cache) = keys.iter().find(|c| c.filename == cfg.filename()) { - cfg.set_keys(key_cache.clone())?; - } else { - log::warn!("Could not find cached keys for {}", cfg.filename()); - } - } - Ok(()) - } - pub fn split_config(&self, split: Split) -> DatasetSplitConfig { - DatasetSplitConfig { - hdf5s: self.get(split).clone(), - split, - } - } - pub fn get>(&self, split: S) -> &Vec { - match split.into() { - Split::Train => &self.train, - Split::Valid => &self.valid, - Split::Test => &self.test, - } - } - pub fn get_mut>(&mut self, split: S) -> &mut Vec { - match split.into() { - Split::Train => &mut self.train, - Split::Valid => &mut self.valid, - Split::Test => &mut self.test, - } - } -} -/// Helper struct to load cached HDF5 keys from a JSON file. -#[derive(Deserialize, Serialize, Debug, Clone)] -pub struct DatasetConfigCacheJson(Vec); -impl DatasetConfigCacheJson { - pub fn new(keys: Vec) -> Self { - DatasetConfigCacheJson(keys) - } - pub fn keys(&self) -> &Vec { - &self.0 - } - pub fn open(cache_path: &str) -> Result { - let file = fs::File::open(cache_path)?; - let reader = BufReader::new(file); - log::trace!("Opening HDF5 json key cache {}", cache_path); - let cfg = serde_json::from_reader(reader)?; - Ok(cfg) - } - pub fn write(&self, cache_path: &str) -> Result<()> { - let file = fs::OpenOptions::new() - .create(true) - .write(true) - .truncate(true) - .open(cache_path)?; - let writer = BufWriter::new(file); - log::trace!("Writing HDF5 keys to cache {}", cache_path); - serde_json::to_writer(writer, &self)?; - Ok(()) - } -} - -/// Helper struct containing all `Hdf5Cfg`s of a single split (train/valid/test). -#[derive(Debug, Clone)] -pub struct DatasetSplitConfig { - pub hdf5s: Vec, - split: Split, -} - -impl DatasetSplitConfig { - pub fn extend(&mut self, other: DatasetSplitConfig) { - assert_eq!(self.split, other.split); - self.hdf5s.extend(other.hdf5s); - } - pub fn is_empty(&self) -> bool { - self.hdf5s.is_empty() - } - pub fn iter(&self) -> impl Iterator { - self.hdf5s.iter() - } -} - -/// Dataset base struct for the `DataLoader`. -/// Contains all (train, valid, test) `FftDataset`s. -pub struct Datasets { - pub train: FftDataset, - pub valid: FftDataset, - pub test: FftDataset, -} - -impl Datasets { - pub fn get>(&self, split: S) -> &FftDataset { - match split.into() { - Split::Train => &self.train, - Split::Valid => &self.valid, - Split::Test => &self.test, - } - } -} - -#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] -pub enum Split { - Train = 0, - Valid = 1, - Test = 2, -} - -impl Split { - pub fn iter() -> impl Iterator { - [Split::Train, Split::Valid, Split::Test].iter().cloned() - } -} - -impl fmt::Display for Split { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Train => write!(f, "train"), - Self::Valid => write!(f, "valid"), - Self::Test => write!(f, "test"), - } - } -} - -impl From<&str> for Split { - fn from(split: &str) -> Self { - match split { - "train" => Split::Train, - "valid" => Split::Valid, - "test" => Split::Test, - s => panic!("Split '{s}' does not exist."), - } - } -} - -pub trait Data: Sized + Clone + Default + Send + Sync + Zero + 'static {} -impl Data for f32 {} -impl Data for Complex32 {} - -/// A dataset sample containing a noisy/clean pair for training. -/// -/// This struct is used for holding the augmented time-domain signal as well as the complex -/// STFT-domain signal from `FftDataset`. -#[derive(Clone, Serialize, Deserialize)] -pub struct Sample -where - T: Data, -{ - pub speech: ArrayD, - pub noisy: ArrayD, - pub feat_erb: Option>, - pub feat_spec: Option>, - pub max_freq: usize, - pub snr: i8, - pub gain: i8, - pub idx: usize, - pub downsample_freq: Option, -} -impl Sample { - fn get_speech_view(&self) -> Result> { - Ok(self.speech.view().into_dimensionality()?) - } - fn get_noisy_view(&self) -> Result> { - Ok(self.noisy.view().into_dimensionality()?) - } - fn dim(&self) -> usize { - 2 - } -} -impl Sample { - fn get_speech_view(&self) -> Result> { - Ok(self.speech.view().into_dimensionality()?) - } - fn get_noisy_view(&self) -> Result> { - Ok(self.noisy.view().into_dimensionality()?) - } - fn dim(&self) -> usize { - 3 - } -} - -impl fmt::Debug for Sample -where - T: Data, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_fmt(format_args!( - "Dataset Sample {} with len: '{}', snr: '{}', gain: '{}')", - self.idx, - self.speech.shape().last().unwrap(), - self.snr, - self.gain - )) - } -} - -pub trait Dataset -where - T: Data, -{ - fn get_sample(&self, idx: usize, seed: Option) -> Result>; - fn sr(&self) -> usize; - fn len(&self) -> usize; - fn is_empty(&self) -> bool { - self.len() == 0 - } - fn max_sample_len(&self) -> usize; - fn set_seed(&mut self, seed: u64); - fn need_generate_keys(&self, overfit: bool) -> bool; - fn generate_keys(&mut self, epoch_seed: Option) -> Result<()>; -} - -#[derive(Clone)] -pub struct DatasetBuilder { - ds_dir: String, - sr: usize, - fft_size: Option, - datasets: Option, - max_len_s: Option, - hop_size: Option, - nb_erb: Option, - nb_spec: Option, - norm_alpha: Option, - p_reverb: Option, - p_fill_speech: Option, - seed: Option, - min_nb_freqs: Option, - global_sampling_f: Option, - snrs: Option>, - gains: Option>, - num_threads: Option, - p_bandwidth_ext: Option, - p_clipping: Option, - p_zeroing: Option, - p_air_absorption: Option, - p_interfer_sp: Option, -} -impl DatasetBuilder { - pub fn new(ds_dir: &str, sr: usize) -> Self { - DatasetBuilder { - ds_dir: ds_dir.to_string(), - sr, - datasets: None, - max_len_s: None, - fft_size: None, - hop_size: None, - nb_erb: None, - nb_spec: None, - norm_alpha: None, - p_reverb: None, - p_fill_speech: None, - seed: None, - min_nb_freqs: None, - global_sampling_f: None, - snrs: None, - gains: None, - num_threads: None, - p_bandwidth_ext: None, - p_clipping: None, - p_zeroing: None, - p_air_absorption: None, - p_interfer_sp: None, - } - } - pub fn build_fft_dataset(self) -> Result { - if self.datasets.is_none() { - panic!("No datasets provided") - } - let ds = self.clone().build_td_dataset()?; - let split = self.datasets.unwrap().split; - log::trace!("Building FftDataset {}", split); - if self.fft_size.is_none() { - panic!("No fft size provided when building FFT dataset.") - } - let fft_size = self.fft_size.unwrap(); - let hop_size = self.hop_size.unwrap_or(fft_size / 2); - let nb_erb = self.nb_erb.unwrap_or(32); - if let Some(b) = self.nb_spec { - let nfreqs = fft_size / 2 + 1; - if b > nfreqs { - let msg = format!("Number of spectrogram bins ({b}) is larger then number of available frequency bins ({nfreqs})"); - return Err(DfDatasetError::DataProcessingError(msg)); - } - } - Ok(FftDataset { - ds, - fft_size, - hop_size, - nb_erb: Some(nb_erb), - nb_spec: self.nb_spec, - norm_alpha: self.norm_alpha, - min_nb_freqs: self.min_nb_freqs, - }) - } - pub fn build_td_dataset(self) -> Result { - let datasets = match self.datasets { - None => panic!("No datasets provided"), - Some(ds) => ds, - }; - // TODO: Return all sample by default and not only 10 seconds - let max_samples: usize = (self.max_len_s.unwrap_or(10.) * self.sr as f32).round() as usize; - // Get dataset handles and keys. Each key is a unique String. - let ds_path = Path::new(&self.ds_dir); - let (sender, receiver) = sync_channel(datasets.hdf5s.len() + 1); - if let Some(n) = self.num_threads { - hdf5::sync::sync(|| {}); - rayon::ThreadPoolBuilder::new() - .num_threads(n) - .thread_name(|idx| format!("DataLoader Worker {idx}")) - .start_handler(|_| hdf5::sync::sync(|| {})) - .build_global() - .unwrap_or(()); - } - datasets.hdf5s.par_iter().try_for_each(|cfg| -> Result<()> { - let path = ds_path.join(cfg.filename()); - log::trace!("Opening hdf5 dataset {}", path.display()); - if (!path.is_file()) && path.read_link().is_err() { - log::warn!("Dataset {:?} not found. Skipping.", path); - return Ok(()); - } - let mut cfg = cfg.clone(); - let ds = match Hdf5Dataset::new(path.to_str().unwrap()) { - Err(e) => { - log::error!("Error opening dataset {:?}: {:?}", path, e); - return Ok(()); - } - Ok(ds) => ds, - }; - let modified_hash = cfg.hash_from_ds_path(path.to_str().unwrap())?; - cfg.store_modified_hash(modified_hash); - let keys = cfg.load_keys(modified_hash)?.cloned(); - match keys { - Some(keys) => { - log::trace!("Found cached hdf5 keys for {}", cfg.filename()); - cfg.set_keys(keys)? - } - None => { - log::trace!("No cached hdf5 keys found for {}", cfg.filename()); - cfg.set_keys_new(modified_hash, ds.keys()?)? - } - }; - if let Some(f) = self.global_sampling_f { - cfg.set_sampling_factor(cfg.sampling_factor() * f) - } - sender.send(Some((cfg, ds))).unwrap(); - Ok(()) - })?; - sender.send(None).unwrap(); - let mut config = HashMap::new(); - let mut hdf5_handles = HashMap::new(); - let mut ds_keys = Vec::new(); - let mut has_rirs = false; - let mut ds_len: usize = 0; - let mut ns_len: usize = 0; - while let Some((cfg, ds)) = receiver.try_recv().unwrap() { - has_rirs = has_rirs || ds.dstype == DsType::RIR; - let keys = cfg.keys_unchecked().unwrap().keys.clone(); - if ds.dstype == DsType::Speech { - ds_len += ((keys.len() as f32 * cfg.sampling_factor()).round() as usize).max(1); - } else if ds.dstype == DsType::Noise { - ns_len += ((keys.len() as f32 * cfg.sampling_factor()).round() as usize).max(1); - } - ds_keys.push((ds.dstype, ds.name(), keys)); - assert!( - !config.contains_key(&ds.name()), - "Config does not contain ds {}", - ds.name() - ); - config.insert(ds.name(), cfg); - log::debug!( - "Opened {} {} dataset {} with {} samples", - &ds.dstype, - datasets.split, - ds.name(), - ds.len() - ); - hdf5_handles.insert(ds.name(), ds); - } - ds_keys.sort_by(|a, b| a.1.cmp(&b.1)); - if hdf5_handles.is_empty() { - return Err(DfDatasetError::NoDatasetFoundError( - "Please check your dataset folder and configuration.".to_string(), - )); - } - if ds_len == 0 { - return Err(DfDatasetError::NoDatasetFoundError( - "Could not found any speech datasets.".to_string(), - )); - } - if ns_len == 0 { - return Err(DfDatasetError::NoDatasetFoundError( - "Could not found any noise datasets.".to_string(), - )); - } - let snrs = self.snrs.unwrap_or_else(|| vec![-5, 0, 5, 10, 20, 40]); - let gains = self.gains.unwrap_or_else(|| vec![-6, 0, 6]); - let p_fill_speech = self.p_fill_speech.unwrap_or(0.); - let p_interfer_sp = self.p_interfer_sp.unwrap_or(0.); - let ds_split = datasets.split; - let sp_augmentations = Compose::new(vec![ - Box::new(RandRemoveDc::default_with_prob( - get_env("DF_P_REMVOE_DC").unwrap_or(0.25), - )), - Box::new(RandLFilt::default_with_prob( - get_env("DF_P_LFILT").unwrap_or(0.25), - )), - Box::new( - RandBiquadFilter::default_with_prob(get_env("DF_P_BIQUAD").unwrap_or(0.0)) - .with_sr(self.sr), - ), - Box::new( - RandResample::default_with_prob(get_env("DF_P_RESAMPLE").unwrap_or(0.1)) - .with_sr(self.sr), - ), - ]); - let mut sp_distortions_td = Compose::new(Vec::new()); - let mut sp_distortions_fd = Compose::new(Vec::new()); - if ds_split == Split::Train { - let p_clipping: Option = match get_env("DF_P_CLIPPING") { - Some(p) => Some(p), - None => self.p_clipping, - }; - if let Some(p) = p_clipping { - if p > 0. { - sp_distortions_td.push(Box::new( - RandClipping::default_with_prob(p).with_c(0.05..0.9), - )) - } - } - let p_zeroing: Option = match get_env("DF_P_ZEROING") { - Some(p) => Some(p), - None => self.p_zeroing, - }; - if let Some(p) = p_zeroing { - sp_distortions_td.push(Box::new(RandZeroingTD::default_with_prob(p))) - } - let p_air_absorption: Option = match get_env("DF_P_AIR_AUG") { - Some(p) => Some(p), - None => self.p_air_absorption, - }; - if let Some(p) = p_air_absorption { - if p > 0. { - sp_distortions_fd - .push(Box::new(AirAbsorptionAugmentation::default_with_prob(p))); - } - } - } - let mut ns_augmentations = Compose::new(vec![ - Box::new(RandLFilt::default_with_prob( - get_env("DF_P_LFILT").unwrap_or(0.25), - )), - Box::new( - RandBiquadFilter::default_with_prob(get_env("DF_P_BIQUAD").unwrap_or(0.0)) - .with_sr(self.sr), - ), - Box::new( - RandResample::default_with_prob(get_env("DF_P_RESAMPLE").unwrap_or(0.1)) - .with_sr(self.sr), - ), - ]); - if ds_split == Split::Train { - let p_clipping: f32 = get_env("DF_P_CLIPPING_NOISE").unwrap_or(0.1); - ns_augmentations.push(Box::new( - RandClipping::default_with_prob(p_clipping).with_c(0.01..0.5), - )) - } - let p_reverb = self.p_reverb.unwrap_or(0.); - if p_reverb > 0. && !has_rirs { - log::warn!("Reverb augmentation enabled but no RIRs provided!",); - } - let reverb = RandReverbSim::new(p_reverb, self.sr) - .with_drr(get_env("DF_REVERB_DRR").unwrap_or(0.3)) - .with_rt60(get_env("DF_REVERB_RT60").unwrap_or(0.5)) - .with_offset_late_reflections(get_env("DF_REVERB_OFFSET_LATE").unwrap_or(20)); - let seed = self.seed.unwrap_or(0); - // 5% of noises used for mixing will contain randomly generated noise. - // This has the advantage that the noise will actually contain frequencies up 24 kHz. - let p_noise_gen = get_env("DF_P_NOISE_GEN").unwrap_or(0.05); - let noise_generator = NoiseGenerator::new( - self.sr, - if ds_split == Split::Train { - p_noise_gen - } else { - 0.0 - }, - ); - let bw_limiter = if let Some(p) = self.p_bandwidth_ext { - if p > 0. { - Some(BandwidthLimiterAugmentation::new(p, self.sr)) - } else { - None - } - } else { - None - }; - log::trace!("Built TdDataset {}", ds_split); - Ok(TdDataset { - config, - hdf5_handles, - max_samples, - sr: self.sr, - ds_keys, - ds_split, - sp_keys: Vec::new(), - ns_keys: Vec::new(), - rir_keys: Vec::new(), - snrs, - gains, - p_fill_speech, - p_interfer_sp, - sp_augmentations, - sp_distortions_td, - sp_distortions_fd, - ns_augmentations, - noise_generator, - reverb, - seed, - ds_len, - bw_limiter, - }) - } - pub fn dataset(mut self, datasets: DatasetSplitConfig) -> Self { - let has_ds = self.datasets.is_some(); - if has_ds { - self.datasets.as_mut().unwrap().extend(datasets) - } else { - self.datasets = Some(datasets) - } - self - } - pub fn max_len(mut self, max_len_s: f32) -> Self { - self.max_len_s = Some(max_len_s); - self - } - pub fn df_params( - mut self, - fft_size: usize, - hop_size: Option, - nb_erb: Option, - nb_spec: Option, - norm_alpha: Option, - ) -> Self { - self.fft_size = Some(fft_size); - self.hop_size = hop_size; - self.nb_erb = nb_erb; - self.nb_spec = nb_spec; - self.norm_alpha = norm_alpha; - self - } - pub fn global_sample_factor(mut self, f: f32) -> Self { - self.global_sampling_f = Some(f); - self - } - pub fn prob_reverberation(mut self, p_reverb: f32) -> Self { - assert!((0. ..=1.).contains(&p_reverb)); - self.p_reverb = Some(p_reverb); - self - } - pub fn seed(mut self, seed: u64) -> Self { - self.seed = Some(seed); - self - } - pub fn p_sample_full_speech(mut self, p_full: f32) -> Self { - self.p_fill_speech = Some(p_full); - self - } - pub fn min_nb_erb_freqs(mut self, n: usize) -> Self { - self.min_nb_freqs = Some(n); - self - } - pub fn snrs(mut self, snrs: Vec) -> Self { - self.snrs = Some(snrs); - self - } - pub fn gains(mut self, gains: Vec) -> Self { - self.gains = Some(gains); - self - } - pub fn num_threads(mut self, n: usize) -> Self { - self.num_threads = Some(n); - self - } - pub fn bandwidth_extension(mut self, p: f32) -> Self { - self.p_bandwidth_ext = Some(p); - self - } - pub fn clipping_distortion(mut self, p: f32) -> Self { - self.p_clipping = Some(p); - self - } - pub fn zeroing_distortion(mut self, p: f32) -> Self { - self.p_zeroing = Some(p); - self - } - pub fn interfer_distortion(mut self, p: f32) -> Self { - self.p_interfer_sp = Some(p); - self - } - pub fn air_absorption_distortion(mut self, p: f32) -> Self { - self.p_air_absorption = Some(p); - self - } -} - -pub struct FftDataset { - ds: TdDataset, - fft_size: usize, - hop_size: usize, - nb_erb: Option, - nb_spec: Option, - norm_alpha: Option, - min_nb_freqs: Option, -} -impl FftDataset { - pub fn get_hdf5cfg(&self, filename: &str) -> Option<&Hdf5Cfg> { - self.ds.config.values().find(|&cfg| cfg.filename() == filename) - } -} -impl Dataset for FftDataset { - fn get_sample(&self, idx: usize, seed: Option) -> Result> { - #[cfg(feature = "timings")] - let t0 = Instant::now(); - let sample: Sample = self.ds.get_sample(idx, seed)?; - - // To frequency domain - let nb_erb = self.nb_erb.unwrap_or(1); - let min_nb_erb = self.min_nb_freqs.unwrap_or(1); - let sr = self.sr(); - let fft_size = self.fft_size; - let mut state = DFState::new(sr, fft_size, self.hop_size, nb_erb, min_nb_erb); - - let speech = stft(sample.get_speech_view()?, &mut state, false); - let mut noisy = stft(sample.get_noisy_view()?, &mut state, true); - if let Some(f) = sample.downsample_freq { - let max_bin = (f as f32 / (sr as f32 / fft_size as f32)) as usize; - ext_bandwidth_spectral(&mut noisy, max_bin, sr, Some(4)); - } - - // Feature calculation (normalization) - let erb = if let Some(_b) = self.nb_erb { - let mut erb = erb(&noisy.view(), true, &state.erb)?; - if let Some(alpha) = self.norm_alpha { - erb_norm(&mut erb.view_mut(), None, alpha)?; - } - Some(erb.into_dyn()) - } else { - None - }; - let spec = if let Some(b) = self.nb_spec { - let mut spec = noisy.slice_axis(Axis(2), Slice::from(..b)).into_owned(); - if let Some(alpha) = self.norm_alpha { - unit_norm(&mut spec.view_mut(), None, alpha)?; - } - Some(spec.into_dyn()) - } else { - None - }; - let sample = Sample { - speech: speech.into_dyn(), - noisy: noisy.into_dyn(), - feat_erb: erb, - feat_spec: spec, - max_freq: sample.max_freq, - gain: sample.gain, - snr: sample.snr, - idx: sample.idx, - downsample_freq: sample.downsample_freq, - }; - #[cfg(feature = "timings")] - log::trace!( - "FD sample: {:?} ms", - (std::time::Instant::now() - t0).as_millis() - ); - Ok(sample) - } - - fn len(&self) -> usize { - self.ds.len() - } - - fn sr(&self) -> usize { - self.ds.sr - } - - fn max_sample_len(&self) -> usize { - self.ds.max_samples / self.hop_size - } - - fn set_seed(&mut self, seed: u64) { - self.ds.set_seed(seed) - } - - fn need_generate_keys(&self, overfit: bool) -> bool { - self.ds.need_generate_keys(overfit) - } - - fn generate_keys(&mut self, epoch_seed: Option) -> Result<()> { - self.ds.generate_keys(epoch_seed) - } -} - -pub struct TdDataset { - config: HashMap, // config - hdf5_handles: HashMap, // Handles to access opened Hdf5 datasets - max_samples: usize, // Number of samples in time domain - sr: usize, // Sampling rate - ds_keys: Vec<(DsType, String, Vec)>, // Dataset keys as a vector of [DS Type, hdf5 index, Vec]. - ds_split: Split, // Train/Valid/Test - sp_keys: Vec<(String, String)>, // Pair of hdf5 name and dataset keys. Will be generated at each epoch start - ns_keys: Vec<(String, String)>, - rir_keys: Vec<(String, String)>, - snrs: Vec, // in dB; SNR to sample from - gains: Vec, // in dB; Speech (loudness) to sample from - p_fill_speech: f32, // Probability to completely fill the speech signal to `max_samples` with a different speech sample - p_interfer_sp: f32, // Probability of mixing in 1-3 interfering speakers not included in the target signal - noise_generator: NoiseGenerator, // Create random noises - sp_augmentations: Compose, // Transforms to augment speech samples - sp_distortions_td: Compose, // Transforms to distort speech samples in time domain for used generating the mixture - sp_distortions_fd: Compose, // Transforms to distort speech samples in frequency domain for used generating the mixture - ns_augmentations: Compose, // Transforms to augment noise samples - reverb: RandReverbSim, // Separate reverb transform that may be applied to both speech and noise - seed: u64, - ds_len: usize, - bw_limiter: Option, // Extend bandwidth via spectal translation -} - -impl TdDataset { - fn _read_from_hdf5( - &self, - key: &str, - name: &str, - max_len: Option, - ) -> Result> { - let h = &self.hdf5_handles.get(name).unwrap(); - let sr = - h.sr.unwrap_or_else(|| self.config.get(name).unwrap().fallback_sr().unwrap_or(self.sr)); - let slc = if let Some(l) = max_len { - let l_sr = l * sr / self.sr; - let sample_len = h.sample_len(key)?; - let max_len = sample_len.min(l_sr); - let s = sample_len as i64 - max_len as i64; - if s > 0 { - let s = thread_rng()?.uniform(0, s as usize); - Some(s..s + l_sr) - } else { - None - } - } else { - None - }; - let mut x = if let Some(slc) = slc { - h.read_slc(key, slc) - } else { - h.read(key) - } - .map_err(move |e: DfDatasetError| -> DfDatasetError { - DfDatasetError::ErrorDetail { - source: Box::new(e), - msg: format!("Error reading sample '{key}' from dataset {name}",), - } - })?; - if sr != self.sr { - x = resample(x.view(), sr, self.sr, None)?; - if let Some(l) = max_len { - if x.len_of(Axis(1)) > l { - x.slice_axis_inplace(Axis(1), Slice::from(0..l)) - } - } - return Ok(x); - } - Ok(x) - } - - fn read(&self, name: &str, key: &str) -> Result> { - let x = self._read_from_hdf5(key, name, None)?; - Ok(x) - } - - fn read_all_channels(&self, name: &str, key: &str) -> Result> { - let x = self._read_from_hdf5(key, name, None)?; - Ok(x) - } - - fn read_max_len( - &self, - ds_name: &str, - key: &str, - max_samples: Option, - ) -> Result> { - #[cfg(feature = "timings")] - let t0 = Instant::now(); - let max_samples = max_samples.unwrap_or(self.max_samples); - let x = match self._read_from_hdf5(key, ds_name, Some(max_samples)) { - Err(e) => { - log::warn!( - "Error during {} read_max_len() for key '{}' from dataset {}: {:?}", - self.ds_type(ds_name), - key, - ds_name, - e - ); - let e_str = e.to_string(); - if e_str.contains("inflate") || e_str.contains("Flac") { - // Get a different speech then - let idx = thread_rng()?.uniform(0, self.len()); - let (sp_idx, sp_key) = &self.sp_keys[idx]; - log::warn!( - "Returning a different speech sample from {} due to {}", - ds_name, - e_str - ); - self.read_max_len(sp_idx, sp_key, Some(max_samples))? - } else { - return Err(e); - } - } - Ok(s) => s, - }; - if log::log_enabled!(log::Level::Trace) { - #[allow(unused_mut)] - let mut msg = format!( - "Loaded sample {} with codec {:?}", - key, - self.ds_codec(ds_name) - ); - #[cfg(feature = "timings")] - let _ = write!(msg, " in {} ms", (Instant::now() - t0).as_millis()); - log::trace!("{}", msg); - } - debug_assert!(x.len_of(Axis(1)) <= max_samples); - Ok(x) - } - - fn max_freq(&self, name: &str) -> Result { - let ds = &self.hdf5_handles.get(name).unwrap(); - let max_freq = match ds.max_freq { - Some(x) if x > 0 => x, - _ => { - let cfg = self.config.get(name).unwrap(); - cfg.fallback_max_freq().unwrap_or_else(|| { - ds.sr.unwrap_or_else(|| cfg.fallback_sr().unwrap_or(self.sr)) / 2 - }) - } - }; - Ok(max_freq) - } - - fn ds_type(&self, name: &str) -> String { - self.hdf5_handles.get(name).unwrap().ds_type() - } - - fn ds_codec(&self, name: &str) -> Codec { - self.hdf5_handles.get(name).unwrap().codec.clone().unwrap_or_default() - } - - fn load_aug_speech(&self, idx: usize, rng: &mut SeededRng) -> Result<(Array2, usize)> { - let (mut sp_name, mut sp_key) = self.sp_keys[idx].clone(); - let mut max_freq = self.sr / 2; - let mut cur_len = 0; - let mut speech_samples = Vec::new(); - // Used for bandwidth extension - let fft_size = 2048; - let mut state = if self.bw_limiter.is_some() { - Some(DFState::new(self.sr, fft_size, fft_size / 2, 1, 1)) - } else { - None - }; - loop { - // Read 10% more samples since augmentation might shorten the signal - let n_read = (self.max_samples as f32 * 1.1) as usize - cur_len; - let mut sample = self.read_max_len(&sp_name, &sp_key, Some(n_read))?; - if sample.len_of(Axis(0)) > 1 { - sample.slice_axis_inplace(Axis(0), Slice::from(0usize..1)); - } - max_freq = max_freq.min(self.max_freq(&sp_name)?); - if self.bw_limiter.is_some() { - if sample.len_of(Axis(1)) < 2048 { - log::debug!( - "Found sample with length {}. Skipping.", - sample.len_of(Axis(1)) - ); - (sp_name, sp_key) = - self.sp_keys.choose(rng).context("Failed to sample speech signal")?.clone(); - continue; - } - // Extend clean speech to make sure it covers the full spectrum - let mut spec = stft(sample.view(), state.as_mut().unwrap(), false); - let max_bin = estimate_bandwidth(spec.view(), self.sr, -120., 10); - let n_bins = fft_size / 2 + 1; - if max_bin < n_bins { - ext_bandwidth_spectral(&mut spec, max_bin, self.sr, Some(16)); - sample = istft(spec.view_mut(), state.as_mut().unwrap(), false); - } - } - if crate::rms(sample.iter()) < 1e-10 { - log::debug!( - "Speech sample before augmentation {} is zero! Choosing new one.", - idx - ); - (sp_name, sp_key) = - self.sp_keys.choose(rng).context("Failed to sample speech signal")?.clone(); - continue; - } - self.sp_augmentations.transform(&mut (&mut sample).into())?; - if crate::rms(sample.iter()) < 1e-10 { - log::debug!( - "Speech sample after augmentation {} is zero! Choosing new one.", - idx - ); - (sp_name, sp_key) = - self.sp_keys.choose(rng).context("Failed to sample speech signal")?.clone(); - continue; - } - cur_len += sample.len_of(Axis(1)); - speech_samples.push(sample); - if cur_len < self.max_sample_len() { - (sp_name, sp_key) = - self.sp_keys.choose(rng).context("Failed to sample speech signal")?.clone(); - } else { - break; - } - } - let speech_views: Vec> = speech_samples.iter().map(|s| s.view()).collect(); - let mut speech = concatenate(Axis(1), speech_views.as_slice())?; - let len = speech.len_of(Axis(1)); - if len > self.max_samples { - let start = rng.uniform(0, len - self.max_samples); - speech.slice_axis_inplace(Axis(1), Slice::from(start..(start + self.max_samples))) - } - Ok((speech, max_freq)) - } - - fn load_aug_noise(&self, rng: &mut SeededRng) -> Result<(Array2, f32)> { - // In 5% us a randomly generated noise signal instead of a real noise. - if let Some(ns) = - self.noise_generator.maybe_generate_random_noise(-2., 2., 1, self.max_samples)? - { - return Ok((ns, *[-24., -12., -6., 0.].choose(rng).unwrap())); - } - loop { - let (ns_name, ns_key) = - self.ns_keys.iter().choose(rng).context("Failed to sample noise signal")?; - let mut ns = match self.read_max_len(ns_name, ns_key, None) { - Err(e) => { - log::warn!("Error during noise reading get_sample(): {}", e); - continue; - } - Ok(n) => n, - }; - if ns.len_of(Axis(1)) < 100 { - continue; - } - if find_max_abs(ns.as_slice().unwrap()).expect("NaN") < 1e-10 { - log::debug!("No energy found in noise {}, ds {}", ns_key, ns_name); - continue; - } - self.ns_augmentations.transform(&mut (&mut ns).into())?; - if ns.len_of(Axis(1)) > self.max_samples { - ns.slice_axis_inplace(Axis(1), Slice::from(..self.max_samples)); - } - return Ok((ns, *self.gains.choose(rng).unwrap() as f32)); - } - } -} - -impl Dataset for TdDataset { - fn get_sample(&self, idx: usize, seed: Option) -> Result> { - #[cfg(feature = "timings")] - let t0 = Instant::now(); - let sample_seed = seed.unwrap_or(idx as u64); - seed_from_u64(self.seed + seed.unwrap_or(idx as u64)); - let mut rng = thread_rng()?; - // Sample SNR and gain - let &snr = self.snrs.choose(&mut rng).unwrap(); - let &gain = self.gains.choose(&mut rng).unwrap(); - log::trace!( - "get_sample() idx {} with seed {:?}, snr {}, gain {}", - idx, - sample_seed, - snr, - gain - ); - let (mut speech, max_freq) = if snr <= -100 { - (Array2::zeros((1, self.max_samples)), self.sr / 2) - } else { - let (speech, max_freq) = self.load_aug_speech(idx, &mut rng)?; - if crate::rms(speech.iter()) < 1e-10 { - log::warn!( - "No speech signal found for idx {}, seed {}", - idx, - sample_seed - ); - } - (speech, max_freq) - }; - #[cfg(feature = "timings")] - let t_sp = Instant::now(); - // Apply low pass to the noise as well - let mut noise_low_pass = if max_freq < self.sr / 2 { - Some(LpParam { - cut_off: max_freq, - sr: self.sr, - }) - } else { - None - }; - let ch = speech.len_of(Axis(0)); - let len = speech.len_of(Axis(1)); - // Sample 2-5 noises and augment each - let n_noises = rng.uniform(2, 6); - let mut noises = Vec::with_capacity(n_noises); - let mut noise_gains = Vec::with_capacity(n_noises); - for _ in 0..n_noises { - let (ns, gain) = self.load_aug_noise(&mut rng)?; - noises.push(ns); - noise_gains.push(gain); - } - // Truncate to speech len, combine noises and mix to noisy - let mut noise = combine_noises(ch, len, &mut noises, Some(noise_gains.as_slice()))?; - #[cfg(feature = "timings")] - let t_ns = Instant::now(); - // Optionally we may also introduce some distortions to the speech signal. - // These distortions will be only present in the noisy mixture, with the aim to reconstruce - // the original undistorted signal. Example distortions are reverberation, or clipping. - // - // Apply reverberation using a randomly sampled RIR - let mut speech_distorted = { - if !self.rir_keys.is_empty() { - self.reverb.transform(&mut speech, &mut noise, || { - let (rir_name, rir_key) = self.rir_keys.iter().choose(&mut rng).unwrap(); - let rir = self.read(rir_name, rir_key)?; - log::trace!("Sampled RIR {} with shape {:?}", rir_key, rir.shape()); - Ok(rir) - })? - } else { - None - } - } - .unwrap_or_else(|| speech.clone()); - // TD distortions like clipping - if !self.sp_distortions_td.is_empty() { - self.sp_distortions_td.transform(&mut (&mut speech_distorted).into())?; - } - // Bandwidth limitation - let downsample_freq = if let Some(limiter) = self.bw_limiter.as_ref() { - let f = limiter.transform(&mut speech_distorted, max_freq)?; - noise_low_pass = Some(LpParam { - cut_off: f, - sr: self.sr, - }); - Some(f) - } else { - None - }; - if let Some(re) = noise_low_pass { - // Low pass filtering via resampling to match speech cut off frequency - noise = low_pass_resample(noise.view(), re.cut_off, re.sr)?; - noise.slice_axis_inplace(Axis(1), Slice::from(..len)); - } - // FD distortions - if !self.sp_distortions_fd.is_empty() { - let fft_size = 2048; - let mut state = DFState::new(self.sr, fft_size, fft_size / 2, 1, 1); - let mut x = stft(speech_distorted.view(), &mut state, false); - self.sp_distortions_fd.transform(&mut (&mut x).into())?; - speech_distorted = istft(x.view_mut(), &mut state, false); - speech_distorted.slice_axis_inplace(Axis(1), Slice::from(0..speech.len_of(Axis(1)))); - } - if self.p_interfer_sp > 0. && self.p_interfer_sp > rng.uniform(0f32, 1f32) { - // Add an interfering speaker to noise - let mut interferers = Vec::new(); - let mut interferer_gains = Vec::new(); - for _ in 0..rng.uniform(1, 3) { - let (sp_name, sp_key) = self - .sp_keys - .choose(&mut rng) - .context("Failed to sample speech signal")? - .clone(); - let n_read = (self.max_samples as f32 * 1.1) as usize; - let mut sample = self.read_max_len(&sp_name, &sp_key, Some(n_read))?; - if let Some((rir_name, rir_key)) = self.rir_keys.iter().choose(&mut rng) { - let rir = self.read(rir_name, rir_key)?; - self.reverb.transform_single(&mut speech, rir)?; - } - if sample.len_of(Axis(1)) > speech.len_of(Axis(1)) { - sample.slice_axis_inplace(Axis(1), Slice::from(0..speech.len_of(Axis(1)))); - } - // mix clean with an interfering speech - interferers.push(sample); - interferer_gains.push(*self.gains.choose(&mut rng).unwrap() as f32); - } - let interferers = - combine_noises(ch, len, &mut interferers, Some(interferer_gains.as_slice()))?; - let snr_interfer = [30., 20., 15.].choose(&mut rng).unwrap(); - (speech, _, speech_distorted) = mix_audio_signal( - speech, - Some(speech_distorted), - interferers, - *snr_interfer, - 0., - )?; - } - #[cfg(feature = "timings")] - let t_d = Instant::now(); // distortions - let (speech, _, noisy) = mix_audio_signal( - speech, - Some(speech_distorted), - noise, - snr as f32, - gain as f32, - )?; - #[cfg(feature = "timings")] - if log::log_enabled!(log::Level::Trace) { - let te = std::time::Instant::now(); - log::trace!( - "TD sample: {:?} ms (speech: {:?} ms, noise: {:?} ms, distortions: {:?}, mix: {:?} ms)", - (te - t0).as_millis(), - (t_sp - t0).as_millis(), - (t_ns - t_sp).as_millis(), - (t_d - t_ns).as_millis(), - (te - t_d).as_millis(), - ); - } - Ok(Sample { - speech: speech.into_dyn(), - noisy: noisy.into_dyn(), - feat_erb: None, - feat_spec: None, - max_freq, - snr, - gain, - idx, - downsample_freq, - }) - } - - fn len(&self) -> usize { - self.ds_len - } - - fn sr(&self) -> usize { - self.sr - } - - fn max_sample_len(&self) -> usize { - self.max_samples - } - - fn set_seed(&mut self, seed: u64) { - self.seed = seed - } - - fn need_generate_keys(&self, overfit: bool) -> bool { - if self.sp_keys.is_empty() { - return true; - } - if overfit { - return false; - } - if self.ds_split == Split::Train { - for (_, name, _) in self.ds_keys.iter() { - let f = self.config.get(name).unwrap().sampling_factor(); - // if not a natural number, then we need to regenerate. - if f != f.round() { - return true; - } - } - } - false - } - - fn generate_keys(&mut self, epoch_seed: Option) -> Result<()> { - log::trace!("Generating dataset keys with seed {:?}", epoch_seed); - self.sp_keys.clear(); - self.ns_keys.clear(); - self.rir_keys.clear(); - - if let Some(s) = epoch_seed { - seed_from_u64(s) - } - - for (dstype, name, keys) in self.ds_keys.iter() { - debug_assert_eq!(&self.hdf5_handles.get(name).unwrap().keys().unwrap(), keys); - let len = keys.len(); - let n_samples = - ((self.config.get(name).unwrap().sampling_factor() * len as f32).round() as usize) - .max(1); - let mut keys = keys.clone(); - if self.ds_split == Split::Train { - keys.shuffle(&mut thread_rng()?); - } - let keys: Vec<(String, String)> = - keys.iter().cycle().take(n_samples).map(|k| (name.clone(), k.clone())).collect(); - match dstype { - DsType::Speech => self.sp_keys.extend(keys), - DsType::Noise => self.ns_keys.extend(keys), - DsType::RIR => self.rir_keys.extend(keys), - } - } - if self.sp_keys.is_empty() { - return Err(DfDatasetError::NotEnoughSamplesError("speech".to_string())); - } - if self.ns_keys.is_empty() { - return Err(DfDatasetError::NotEnoughSamplesError("noise".to_string())); - } - Ok(()) - } -} - -#[derive(Debug, Eq, PartialEq, PartialOrd, Ord, Clone, Copy)] -pub enum DsType { - Speech = 0, - Noise = 1, - RIR = 2, -} -impl fmt::Display for DsType { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{self:?}") - } -} -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum Codec { - PCM = 0, - Vorbis = 1, - FLAC = 2, -} -impl Default for &Codec { - fn default() -> Self { - &Codec::PCM - } -} -impl Default for Codec { - fn default() -> Self { - Codec::PCM - } -} -#[derive(Debug)] -pub enum DType { - I16 = 0, - F32 = 1, -} - -#[derive(Debug)] -pub struct Hdf5Dataset { - file: File, - pub dstype: DsType, - pub sr: Option, - pub codec: Option, - max_freq: Option, - dtype: Option, -} - -fn get_dstype(file: &File) -> Option { - for g in file.member_names().unwrap_or_default() { - match g.to_lowercase().as_str() { - "speech" => return Some(DsType::Speech), - "noise" => return Some(DsType::Noise), - "rir" => return Some(DsType::RIR), - _ => (), - }; - } - None -} - -impl Hdf5Dataset { - pub fn new(path: &str) -> Result { - let file = Self::open_file(path, false)?; - Self::init_impl(file) - } - pub fn new_rw(path: &str) -> Result { - let file = Self::open_file(path, true)?; - Self::init_impl(file) - } - fn open_file(path: &str, rw: bool) -> Result { - let file = if rw { - File::open_rw(path) - } else { - File::open(path) - }; - file.map_err(move |e: hdf5::Error| -> DfDatasetError { - DfDatasetError::Hdf5ErrorDetail { - source: e, - msg: format!("Error during File::open of dataset {path}"), - } - }) - } - pub fn inner(&self) -> &hdf5::File { - &self.file - } - pub fn inner_mut(&mut self) -> &mut hdf5::File { - &mut self.file - } - fn init_impl(file: File) -> Result { - let n = file.filename(); - log::trace!("Init Dataset {}", n); - match get_dstype(&file) { - None => Err(DfDatasetError::Hdf5DsTypeNotFoundError), - Some(dstype) => { - let sr = match file.attr("sr") { - Err(_e) => { - log::warn!("Failed to get sr from {}", n); - None - } - Ok(attr) => Some(attr.read_scalar::().unwrap()), - }; - let max_freq = match file.attr("max_freq") { - Err(_e) => { - log::warn!("Failed to get max_freq from {}", n); - None - } - Ok(attr) => Some(attr.read_scalar::().unwrap()), - }; - let codec = match file.attr("codec") { - Err(_e) => { - log::warn!("Failed to get codec from {}", n); - None - } - Ok(attr) => match attr.read_scalar::().unwrap().as_str() { - "pcm" => Some(Codec::PCM), - "vorbis" => Some(Codec::Vorbis), - "flac" => Some(Codec::FLAC), - _ => None, - }, - }; - let dtype = match file.attr("dtype") { - Err(_e) => { - log::warn!("Failed to get dtype from {}", n); - None - } - Ok(attr) => match attr.read_scalar::().unwrap().as_str() { - "float32" => Some(DType::F32), - "int16" => Some(DType::I16), - _ => None, - }, - }; - Ok(Hdf5Dataset { - file, - dstype, - sr, - max_freq, - codec, - dtype, - }) - } - } - } - fn name(&self) -> String { - self.file.filename() - } - pub fn ds_type(&self) -> String { - self.dstype.to_string().to_lowercase() - } - fn group(&self) -> Result { - Ok(self.file.group(&self.ds_type())?) - } - pub fn len(&self) -> usize { - self.group().unwrap().len() as usize - } - pub fn is_empty(&self) -> bool { - self.group().unwrap().is_empty() - } - pub fn keys(&self) -> Result> { - Ok(self.group()?.member_names()?) - } - pub fn attributes(&self) -> Result> { - Ok(self.file.attr_names()?) - } - pub fn ds(&self, key: &str) -> Result { - Ok(self.group()?.dataset(key)?) - } - #[cfg(not(feature = "flac"))] - fn sample_len_flac(&self, _ds: hdf5::Dataset) -> Result { - Err(DfDatasetError::CodecNotSupportedError { - codec: Codec::FLAC, - ds: format!("{:?}", self.file), - }) - } - #[cfg(feature = "flac")] - /// Get the sample length of a Flac encoded dataset - /// - /// Arguments: - /// - /// * `ds`: `hdf5::Dataset` containing a flac encoded audio sample. - fn sample_len_flac(&self, ds: hdf5::Dataset) -> Result { - let reader = claxon::FlacReader::new(ds.as_byte_reader()?)?; - Ok(reader.streaminfo().samples.unwrap_or(0) as usize) - } - #[cfg(not(feature = "vorbis"))] - fn sample_len_vorbis(&self, _ds: hdf5::Dataset) -> Result { - Err(DfDatasetError::CodecNotSupportedError { - codec: Codec::Vorbis, - ds: format!("{:?}", self.file), - }) - } - #[cfg(feature = "vorbis")] - fn sample_len_vorbis_rdr(&self, rdr: &mut OggPacketReader) -> Result { - // Seek almost to end to get the last ogg package - rdr.seek_bytes(std::io::SeekFrom::End(-4096))?; - let mut pkg = rdr.read_packet(); - if pkg.is_err() { - // Maybe seek a little further or start entirely from the beginning. - rdr.seek_bytes(std::io::SeekFrom::End(-8192))?; - pkg = rdr.read_packet(); - if pkg.is_err() { - rdr.seek_absgp(None, 0)?; - pkg = rdr.read_packet(); - }; - } - // Also check if there are some packges left - let mut absgp = 0; - while let Some(p) = pkg? { - absgp = p.absgp_page(); - pkg = rdr.read_packet(); - } - Ok(absgp as usize) - } - #[cfg(feature = "vorbis")] - /// Get the sample length of a vorbis encoded dataset - /// - /// Arguments: - /// - /// * `ds`: `hdf5::Dataset` containing a vorbis (ogg) encoded audio sample. - fn sample_len_vorbis(&self, ds: hdf5::Dataset) -> Result { - let mut rdr = OggPacketReader::new(ds.as_byte_reader()?); - self.sample_len_vorbis_rdr(&mut rdr) - } - fn sample_len_from_ds(&self, ds: hdf5::Dataset) -> Result { - Ok(match self.codec.as_ref().unwrap_or(&Codec::PCM) { - Codec::PCM => *ds.shape().last().unwrap_or(&0), - Codec::Vorbis => self.sample_len_vorbis(ds)?, - Codec::FLAC => self.sample_len_flac(ds)?, - }) - } - pub fn sample_len(&self, key: &str) -> Result { - let ds = self.ds(key)?; - let n = match ds.attr("n_samples") { - Ok(a) => { - let n: usize = match a.ndim() { - 0 => a.read_scalar::()?, - 1 => a.read_1d()?[0], - _ => unreachable!(), - }; - if n < 100 { - self.sample_len_from_ds(ds)? - } else { - n - } - } - Err(_) => self.sample_len_from_ds(ds)?, - }; - Ok(n) - } - fn match_ch( - &self, - mut x: Array, - ch_dim: usize, - ch_idx: Option, - ) -> Result> { - Ok(match x.ndim() { - 1 => { - // Return in channels first - let len = x.len_of(Axis(0)); - x.into_shape((1, len))? - } - 2 => match ch_idx { - Some(-1) => { - let idx = thread_rng()?.uniform(0, x.len_of(Axis(ch_dim))); - x.slice_axis_inplace(Axis(ch_dim), Slice::from(idx..idx + 1)); - x - } - Some(idx) => { - x.slice_axis_inplace(Axis(ch_dim), Slice::from(idx..idx + 1)); - x - } - None => x, - } - .into_dimensionality()?, - n => return Err(DfDatasetError::PcmUnspportedDimension(n)), - }) - } - /// Read a PCM encoded sample from an `hdf5::Dataset`. - /// - /// Arguments: - /// - /// * `key`: String idendifier to load the dataset. - /// * `channel`: Optional channel. `-1` will load a random channel, `None` will return all channels. - /// * `r`: Optional range in samples (time axis). `None` will return all samples. - pub fn read_pcm( - &self, - key: &str, - channel: Option, - r: Option>, - ) -> Result> { - let ds = self.ds(key)?; - let arr = if let Some(r) = r { - // Directly to a sliced dataset read - if r.end > *ds.shape().last().unwrap_or(&0) { - return Err(DfDatasetError::PcmRangeToLarge { - range: r, - size: ds.shape(), - }); - } - match ds.ndim() { - 1 => ds.read_slice(s![r])?, - 2 => match channel { - Some(-1) => { - let nch = ds.shape()[1]; - ds.read_slice(s![thread_rng()?.uniform(0, nch), r]) - } // rand ch - Some(channel) => ds.read_slice(s![channel, r]), // specified channel - None => ds.read_slice(s![.., r]), // all channels - }?, - n => return Err(DfDatasetError::PcmUnspportedDimension(n)), - } - } else { - ds.read_dyn::()? - }; - let mut arr = self.match_ch(arr, 0, channel)?; - match self.dtype { - Some(DType::I16) => arr /= i16::MAX as f32, - Some(DType::F32) => (), - None => { - if ds.dtype()?.is::() { - arr /= i16::MAX as f32 - } - } - } - Ok(arr) - } - #[cfg(not(feature = "flac"))] - fn read_flac( - &self, - _key: &str, - _channel: Option, - _r: Option>, - ) -> Result> { - Err(DfDatasetError::CodecNotSupportedError { - codec: Codec::FLAC, - ds: format!("{:?}", self.file), - }) - } - #[cfg(feature = "flac")] - fn _read_flac( - &self, - key: &str, - mut reader: claxon::FlacReader, - ) -> Result> { - let info = reader.streaminfo(); - assert_eq!( - info.bits_per_sample, 16, - "Flac decoding is only supported for 16 bit samples" - ); - let ch = info.channels as usize; - let samples = info.samples.unwrap_or_default() as usize; - let mut frame_reader = reader.blocks(); - let mut out: Array2 = Array2::zeros((ch, samples)); - let mut block = claxon::Block::empty(); - let mut idx = 0; - loop { - let next = match frame_reader.read_next_or_eof(block.into_buffer()) { - Ok(Some(n)) => n, - Ok(None) => break, - Err(e) => { - log::warn!("Error decoding flac dataset {} {:?}", key, e); - if e.to_string().contains("CRC") { - break; - } else { - return Err(e.into()); - } - } - }; - let numel = (next.len() / next.channels()) as usize; - debug_assert_eq!(ch, next.channels() as usize); - for i in 0..ch { - debug_assert!(out.len_of(Axis(1)) >= idx + numel); - let mut out_ch = out.slice_mut(s![i, idx..idx + numel]); - debug_assert_eq!(out_ch.len(), next.channel(i as u32).len()); - for (i_s, o_s) in next.channel(i as u32).iter().zip(out_ch.iter_mut()) { - *o_s = *i_s as f32 / i16::MAX as f32 - } - } - idx += numel; - block = next - } - Ok(out) - } - #[cfg(feature = "flac")] - fn read_flac_byte_reader(&self, key: &str) -> Result> { - let ds = self.ds(key)?; - let reader = claxon::FlacReader::new(ds.as_byte_reader()?)?; - self._read_flac(key, reader) - } - #[cfg(feature = "flac")] - fn read_flac_ds(&self, key: &str) -> Result> { - let ds = self.ds(key)?; - let encoded = ds.read_1d()?; - let reader = claxon::FlacReader::new(encoded.as_slice().unwrap())?; - self._read_flac(key, reader) - } - /// Read a Flac encoded sample from an `hdf5::Dataset`. - /// - /// Arguments: - /// - /// * `key`: String idendifier to load the dataset. - /// * `channel`: Optional channel. `-1` will load a random channel, `None` will return all channels. - /// * `r`: Optional range in samples (time axis). `None` will return all samples. - #[cfg(feature = "flac")] - fn read_flac( - &self, - key: &str, - channel: Option, - r: Option>, - ) -> Result> { - let out = self.read_flac_ds(key)?; - let mut out = self.match_ch(out, 0, channel)?; - if let Some(r) = r { - out.slice_axis_inplace(Axis(1), Slice::from(r)); - } - Ok(out) - } - #[cfg(not(feature = "vorbis"))] - fn read_vorbis( - &self, - _key: &str, - _channel: Option, - _r: Option>, - ) -> Result> { - Err(DfDatasetError::CodecNotSupportedError { - codec: Codec::Vorbis, - ds: format!("{:?}", self.file), - }) - } - #[inline(never)] - #[cfg(feature = "vorbis")] - /// Read a vorbis encoded sample from an `hdf5::Dataset`. - /// - /// Arguments: - /// - /// * `key`: String idendifier to load the dataset. - /// * `channel`: Optional channel. `-1` will load a random channel, `None` will return all channels. - /// * `r`: Optional range in samples (time axis). `None` will return all samples. - fn read_vorbis( - &self, - key: &str, - channel: Option, - r: Option>, - ) -> Result> { - let ds = self.ds(key)?; - let encoded = ds.read_1d()?; - let mut rdr = OggPacketReader::new(Cursor::new(encoded.as_slice().unwrap())); - let (start, end) = if let Some(r) = r.as_ref() { - (r.start, r.end) - } else { - (0, self.sample_len_vorbis_rdr(&mut rdr)?) - }; - let len = end - start; - rdr.seek_absgp(None, 0)?; - let mut srr = OggStreamReader::from_ogg_reader(rdr)?; - if start > 0 { - match srr.seek_absgp_pg(start as u64) { - Ok(()) => (), - Err(e) => { - log::trace!("Error seeking in vorbis file {}: {:?}", key, e); - // Decode the vorbis file from start and truncate at the end. - } - } - } - let ch = srr.ident_hdr.audio_channels as usize; - let mut pck = loop { - match srr.read_dec_packet_itl() { - Ok(p) => break p, - Err(lewton::VorbisError::BadAudio( - lewton::audio::AudioReadError::AudioIsHeader, - )) => (), - Err(e) => return Err(e.into()), - } - }; - - let mut out: Vec = Vec::with_capacity((len + 1024) * ch); // Allocate a little extra - while let Some(mut p) = pck { - out.append(&mut p); - if let Some(pos) = srr.get_last_absgp().map(|p| p as usize) { - if pos >= end && out.len() > len { - // We might get some extra samples at the end. - out.truncate((out.len() - (pos - end) * ch).max(len * ch)); - break; - } - } - pck = srr.read_dec_packet_itl()?; - } - let start_pos = (out.len() / ch).saturating_sub(len); - let mut out = Array2::from_shape_vec((out.len() / ch, ch), out)?; - // We already have a coarse range. The start may contain more samples from its - // corresponding ogg page. The end is already exact. Thus, truncate the beginning. - let cur_len = out.len_of(Axis(0)); - out.slice_axis_inplace( - Axis(0), - Slice::from(start_pos..(len + start_pos).min(cur_len)), - ); - // Select channel - let out = self.match_ch(out, 1, channel)?; - // Transpose to channels first and convert to float - let out = out.t().mapv(|x| x as f32 / i16::MAX as f32); - Ok(out) - } - - pub fn read(&self, key: &str) -> Result> { - match *self.codec.as_ref().unwrap_or_default() { - Codec::PCM => self.read_pcm(key, Some(0), None), - Codec::Vorbis => self.read_vorbis(key, Some(0), None), - Codec::FLAC => self.read_flac(key, Some(0), None), - } - } - pub fn read_slc(&self, key: &str, r: Range) -> Result> { - match *self.codec.as_ref().unwrap_or_default() { - Codec::PCM => self.read_pcm(key, Some(0), Some(r)), - Codec::Vorbis => self.read_vorbis(key, Some(0), Some(r)), - Codec::FLAC => self.read_flac(key, Some(0), Some(r)), - } - } - pub fn read_all_channels(&self, key: &str) -> Result> { - match *self.codec.as_ref().unwrap_or_default() { - Codec::PCM => self.read_pcm(key, None, None), - Codec::Vorbis => self.read_vorbis(key, None, None), - Codec::FLAC => self.read_flac(key, None, None), - } - } -} - -struct LpParam { - sr: usize, - cut_off: usize, -} - -fn combine_noises( - ch: usize, - len: usize, - noises: &mut [Array2], - noise_gains: Option<&[f32]>, -) -> Result { - let mut rng = thread_rng()?; - // Adjust length of noises to clean length - for ns in noises.iter_mut() { - loop { - if len.checked_sub(ns.len_of(Axis(1))).is_some() { - // TODO: Remove this clone if ndarray supports repeat - ns.append(Axis(1), ns.clone().view())?; - } else { - break; - } - } - let too_large = ns.len_of(Axis(1)).checked_sub(len); - if let Some(too_large) = too_large { - let start: usize = rng.uniform(0, too_large); - ns.slice_collapse(s![.., start..start + len]); - } - } - // Adjust number of noise channels to clean channels - for ns in noises.iter_mut() { - while ns.len_of(Axis(0)) > ch { - ns.remove_index(Axis(0), rng.uniform(0, ns.len_of(Axis(0)))) - } - while ns.len_of(Axis(0)) < ch { - let r = rng.uniform(0, ns.len_of(Axis(0))); - let slc = ns.slice(s![r..r + 1, ..]).to_owned(); - ns.append(Axis(0), slc.view())?; - } - } - // Apply gain to noises - if let Some(ns_gains) = noise_gains { - for (ns, &g) in noises.iter_mut().zip(ns_gains) { - *ns *= 10f32.powf(g / 20.); - } - } - // Average noises - let noise = Array2::zeros((ch, len)); - let noise = noises.iter().fold(noise, |acc, x| acc + x) / ch as f32; - Ok(noise) -} - -/// Mix a clean signal with noise signal at given SNR. -/// -/// Arguments -/// -/// * `clean` - A clean speech signal of shape `[C, N]`. -/// * `clean_distorted` - An optional distorted speech signal of shape `[C, N]`. If provided, this signal -/// will be used for creating the noisy mixture. `clean` may be used as a training -/// target and usually contains no or less distortions. This can be used to learn -/// some dereverberation or declipping. -/// * `noise` - A noise signal of shape `[C, N]`. Will be modified in place. -/// * `snr_db` - Signal to noise ratio in decibel used for mixing. -/// * `gain_db` - Gain to apply to the clean signal in decibel before mixing. -/// * `noise_resample`: Optional resample parameters which will be used to apply a low-pass via -/// resampling to the noise signal. This may be used to make sure a speech -/// signal with a lower sampling rate will also be mixed with noise having the -/// same sampling rate. -/// -/// Returns -/// -/// * `clean` - Clean target after applying snr and gain factors -/// * `noise` - Noise signal after applying snr and gain factors -/// * `mixture` - Mixture signal of clean_distorted and noise. -fn mix_audio_signal( - clean: Array2, - clean_distorted: Option>, - mut noise: Array2, - snr_db: f32, - gain_db: f32, -) -> Result<(Signal, Signal, Signal)> { - // Apply gain to speech - let g = 10f32.powf(gain_db / 20.); - let mut clean_out = &clean * g; - // clean_mix may contain distorted speech - let clean_mix = clean_distorted.map(|c| &c * g).unwrap_or_else(|| clean_out.clone()); - // For energy calculation use clean speech to also consider direct-to-reverberant ratio - noise *= mix_f(clean_out.view(), noise.view(), snr_db); - let mut mixture = clean_mix + &noise; - // Guard against clipping - let max = &([&clean_out, &noise, &mixture].iter().map(|x| find_max_abs(x.iter()))) - .collect::>>() - .expect("Found NaN"); - let max = find_max(max).expect("Found NaN"); - if (max - 1.) > 1e-10 { - let f = 1. / (max + 1e-10); - clean_out *= f; - noise *= f; - mixture *= f; - } - Ok((clean_out, noise, mixture)) -} - -fn get_env(var: K) -> Option -where - K: AsRef + Display + Copy, - T: FromStr + Display, - ::Err: std::fmt::Debug, -{ - match env::var(var) { - Ok(e) => { - let e = e.parse::().expect("Failed to parse env {var}: {e}"); - log::debug!("Running with env '{}={}'", var, e); - Some(e) - } - Err(_) => None, - } -} - -#[cfg(test)] -mod tests { - use std::collections::BTreeSet; - use std::sync::Once; - - use rstest::rstest; - - use super::*; - use crate::util::seed_from_u64; - use crate::wav_utils::*; - - static INIT: Once = Once::new(); - - /// Setup function that is only run once, even if called multiple times. - fn setup() { - INIT.call_once(|| { - let _ = env_logger::builder() - // Include all events in tests - .filter_module("df", log::LevelFilter::max()) - // Ensure events are captured by `cargo test` - .is_test(true) - // Ignore errors initializing the logger if tests race to configure it - .try_init(); - }); - } - - fn calc_rms(x: &[f32]) -> f32 { - let n = x.len() as f32; - (x.iter().map(|x| x.powi(2)).sum::() * (1. / n)).sqrt() - } - /// Calculates the SNR for a given clean signal and a noisy mixture. - /// - /// Arguments - /// - /// * `y` - A clean signal iterator. - /// * `v` - A noise signal iterator. - /// - /// `x = s + v`, where x is the resulting mixture. - fn calc_snr<'a, I>(s: I, v: I) -> f32 - where - I: IntoIterator, - { - let e_clean = s.into_iter().fold(0f32, |acc, x| acc + x.powi(2)); - let e_noise = v.into_iter().fold(0f32, |acc, x| acc + x.powi(2)); - 10. * (e_clean / e_noise).log10() - } - /// Calculates the SNR for a given mixture signal and the noise signal. - /// - /// Arguments - /// - /// * `x` - A noisy mixture signal iterator. - /// * `v` - A noise signal iterator. - /// - /// `x = s + v`, where `y` is the clean signal component. - fn calc_snr_xv<'a, I>(x: I, v: I) -> f32 - where - I: IntoIterator, - { - let mut e_clean = 0.; - let mut e_noise = 0.; - for (xx, xv) in x.into_iter().zip(v) { - e_clean += (xx - xv).powi(2); - e_noise += xv.powi(2); - } - 10. * (e_clean / e_noise).log10() - } - /// Calculates the SNR for a given clean signal and a noise/clean mixture. - /// - /// Arguments - /// - /// * `s` - A clean signal iterator. - /// * `x` - A noisy signal iterator. - /// - /// `x = s + v`, where v is the noise component. - fn calc_snr_sx<'a, I>(s: I, x: I) -> f32 - where - I: IntoIterator, - { - let mut e_clean = 0.; - let mut e_noise = 0.; - for (xs, xx) in s.into_iter().zip(x) { - e_clean += xs.powi(2); - e_noise += (xx - xs).powi(2); - } - 10. * (e_clean / e_noise).log10() - } - #[inline] - fn is_close(a: &[f32], b: &[f32], rtol: f32, atol: f32) -> Vec { - // like numpy - assert_eq!(a.len(), b.len()); - let mut out = vec![true; b.len()]; - for ((a_s, b_s), o) in a.iter().zip(b.iter()).zip(out.iter_mut()) { - *o = (a_s - b_s).abs() <= atol + rtol * b_s.abs() - } - out - } - fn hdf5_noise_keys<'a>() -> BTreeSet<&'a str> { - BTreeSet::from([ - "assets_noise_freesound_573577.wav", - "assets_noise_freesound_2530.wav", - ]) - } - - #[test] - pub fn test_hdf5_read_pcm() -> Result<()> { - setup(); - seed_from_u64(0); - let hdf5 = Hdf5Dataset::new("../assets/noise.hdf5")?; - for key in hdf5.keys()?.iter() { - dbg!(key); - assert!(hdf5_noise_keys().contains(key.as_str())); - let mut samples_raw = - ReadWav::new(&str::replace(key, "assets_", "../assets/"))?.samples_arr2()?; - dbg!(samples_raw.shape()); - assert_eq!(hdf5.sample_len(key)?, samples_raw.len_of(Axis(1))); - samples_raw.slice_axis_inplace(Axis(0), Slice::from(0..1)); - let sample_hdf5 = hdf5.read(key)?; - dbg!(sample_hdf5.shape()); - assert_eq!(sample_hdf5.shape(), samples_raw.shape()); - assert_eq!(sample_hdf5, samples_raw); - assert!(dbg!(calc_snr_sx(samples_raw.iter(), sample_hdf5.iter())) > 100.); - } - Ok(()) - } - #[test] - pub fn test_hdf5_read_vorbis() -> Result<()> { - setup(); - seed_from_u64(0); - let hdf5 = Hdf5Dataset::new("../assets/noise_vorbis.hdf5")?; - for key in hdf5.keys()?.iter() { - dbg!(key); - assert!(hdf5_noise_keys().contains(key.as_str())); - let mut samples_raw = - ReadWav::new(&str::replace(key, "assets_", "../assets/"))?.samples_arr2()?; - dbg!(samples_raw.shape()); - assert_eq!(dbg!(hdf5.sample_len(key)?), samples_raw.len_of(Axis(1))); - samples_raw.slice_axis_inplace(Axis(0), Slice::from(0..1)); - let sample_hdf5 = hdf5.read(key)?; - dbg!(sample_hdf5.shape()); - assert_eq!(sample_hdf5.shape(), samples_raw.shape()); - assert!(dbg!(calc_snr_sx(samples_raw.iter(), sample_hdf5.iter())) > 25.); - let filename = &str::replace(key, "assets_", "../out/").replace(".wav", "_vorbis.wav"); - write_wav_arr2(filename, sample_hdf5.view(), hdf5.sr.unwrap() as u32)?; - } - Ok(()) - } - #[test] - pub fn test_hdf5_read_flac() -> Result<()> { - setup(); - seed_from_u64(0); - let hdf5 = Hdf5Dataset::new("../assets/noise_flac.hdf5")?; - for key in hdf5.keys()?.iter() { - dbg!(key); - assert!(hdf5_noise_keys().contains(key.as_str())); - let mut samples_raw = - ReadWav::new(&str::replace(key, "assets_", "../assets/"))?.samples_arr2()?; - dbg!(samples_raw.shape()); - assert_eq!(hdf5.sample_len(key)?, samples_raw.len_of(Axis(1))); - samples_raw.slice_axis_inplace(Axis(0), Slice::from(0..1)); - let sample_hdf5 = hdf5.read(key)?; - dbg!(sample_hdf5.shape()); - assert_eq!(sample_hdf5.shape(), samples_raw.shape()); - assert_eq!(sample_hdf5, samples_raw); - assert!(dbg!(calc_snr_sx(samples_raw.iter(), sample_hdf5.iter())) > 100.); - let filename = &str::replace(key, "assets_", "../out/").replace(".wav", "_flac.wav"); - write_wav_arr2(filename, sample_hdf5.view(), hdf5.sr.unwrap() as u32)?; - } - Ok(()) - } - #[rstest] - #[case("../assets/noise.hdf5", "assets_noise_freesound_573577.wav", 3..4, 100.)] - #[case("../assets/noise_flac.hdf5", "assets_noise_freesound_573577.wav", 3..4, 100.)] - #[case("../assets/noise_vorbis.hdf5", "assets_noise_freesound_573577.wav", 3..4, 20.)] - #[should_panic(expected = "snr")] - #[case("../assets/noise_vorbis.hdf5", "assets_noise_freesound_573577.wav", 3..4, 40.)] - #[should_panic(expected = "Slice end")] - #[case("../assets/noise.hdf5", "assets_noise_freesound_573577.wav", 4..5, 0.)] - #[should_panic(expected = "Slice end")] - #[case("../assets/noise_flac.hdf5", "assets_noise_freesound_573577.wav", 4..5, 0.)] - #[should_panic(expected = "Slice end")] - #[case("../assets/noise_vorbis.hdf5", "assets_noise_freesound_573577.wav", 4..5, 0.)] - // 2 channel sample - #[case("../assets/noise.hdf5", "assets_noise_freesound_2530.wav", 1..4, 100.)] - #[case("../assets/noise_flac.hdf5", "assets_noise_freesound_2530.wav", 1..4, 100.)] - #[case("../assets/noise_vorbis.hdf5", "assets_noise_freesound_2530.wav", 1..4, 20.)] - pub fn test_hdf5_slice( - #[case] ds: &str, - #[case] key: &str, - #[case] r: Range, - #[case] snr: f32, - ) { - setup(); - seed_from_u64(0); - let hdf5 = Hdf5Dataset::new(ds).unwrap(); - // "assets_noise_freesound_573577.wav" has a length of approx 4.8s - // "assets_noise_freesound_2530.wav" has a length of approx 34.2s and 2 channels - let sr = hdf5.sr.unwrap(); - let r = r.start * sr..r.end * sr; - dbg!(&r); - let samples_raw = ReadWav::new(&str::replace(key, "assets_", "../assets/")) - .unwrap() - .samples_arr2() - .unwrap() - .slice_move(s![0..1, r.clone()]); - let samples_hdf5 = hdf5.read_slc(key, r.clone()).unwrap(); - dbg!(samples_hdf5.shape(), samples_raw.shape()); - { - // Write to disk for debugging - let basen = &str::replace(key, "assets_", "../out/"); - let filename = - &str::replace(basen, ".wav", &format!("_{}_{}_raw.wav", &r.start, &r.end)); - dbg!(hdf5.sample_len(key).unwrap()); - write_wav_arr2(filename, samples_raw.view(), hdf5.sr.unwrap() as u32).unwrap(); - let dsn = - &str::replace(ds, "../assets/noise", "").replace('_', "").replace(".hdf5", ""); - let filename = &str::replace( - basen, - ".wav", - &format!("_{}_{}_{}.wav", &r.start, &r.end, dsn), - ); - dbg!(&filename); - write_wav_arr2(filename, samples_raw.view(), hdf5.sr.unwrap() as u32).unwrap(); - } - assert_eq!(samples_hdf5.shape(), samples_raw.shape()); - assert!(dbg!(calc_snr_sx(samples_raw.iter(), samples_hdf5.iter())) > dbg!(snr)); - } - #[test] - pub fn test_mix_audio_signal() -> Result<()> { - setup(); - seed_from_u64(0); - let sr = 48_000; - let n = sr; - let clean = arr1(rng_uniform(n, -0.1, 0.1)?.as_slice()).into_shape([1, n])?; - let noise = arr1(rng_uniform(n, -0.1, 0.1)?.as_slice()).into_shape([1, n])?; - let gains = [-6., 0., 6.]; - let snrs = [-10., -5., 0., 5., 10., 20., 40.]; - let atol = 1e-4; - for clean_rev in [None, Some(clean.clone())] { - for gain in gains { - for snr in snrs { - let (c, n, m) = mix_audio_signal( - clean.clone(), - clean_rev.clone(), - noise.clone(), - snr, - gain, - )?; - assert_eq!(&c + &n, m); - dbg!(clean_rev.is_some(), gain, snr); - // Input SNR of mixture - let snr_inp_m = calc_snr_xv(m.iter(), n.iter()); - assert!( - (snr_inp_m - snr).abs() < atol, - "Input SNR does not match: {snr_inp_m}, {snr}" - ); - // Target SNR between noise and target (clean) speech. - let snr_target_c = calc_snr(c.iter(), n.iter()); - assert!( - (snr_target_c - snr).abs() < atol, - "Target SNR does not match: {snr_target_c}, {snr}", - ); - // Test the SNR difference between input and target - assert!((snr_inp_m - snr_target_c).abs() < atol); - } - } - } - Ok(()) - } - #[test] - pub fn test_td_dataset() -> Result<()> { - setup(); - seed_from_u64(0); - let sr = 48_000; - let dir = "../assets/"; - let cfg = DatasetConfigJson::open("../assets/dataset.cfg").unwrap(); - let mut ds = DatasetBuilder::new(dir, sr) - .dataset(cfg.split_config(Split::Train)) - .bandwidth_extension(1.0) - .build_td_dataset() - .unwrap(); - ds.generate_keys(Some(0))?; - let mut rng = thread_rng()?; - let sample = ds.get_sample(rng.uniform(0, ds.len()), Some(0)).unwrap(); - write_wav_arr2( - "../out/speech.wav", - sample.speech.view().into_dimensionality()?, - sr as u32, - ) - .unwrap(); - write_wav_arr2( - "../out/noisy.wav", - sample.noisy.view().into_dimensionality()?, - sr as u32, - ) - .unwrap(); - Ok(()) - } - #[test] - pub fn test_fft_dataset() -> Result<()> { - setup(); - seed_from_u64(0); - let (sr, n_fft, n_hop) = (48_000, 1024, 512); - let nb = 1; - let dir = "../assets/"; - let cfg = DatasetConfigJson::open("../assets/dataset.cfg").unwrap(); - let mut ds = DatasetBuilder::new(dir, sr) - .dataset(cfg.split_config(Split::Train)) - .df_params(n_fft, Some(n_hop), Some(nb), Some(1), Some(0.1)) - .build_fft_dataset()?; - ds.generate_keys(Some(0))?; - let mut rng = thread_rng()?; - let mut sample = ds.get_sample(rng.uniform(0, ds.len()), Some(0)).unwrap(); - let mut state = DFState::new(sr, n_fft, n_hop, nb, 1); - let speech = istft( - sample.speech.view_mut().into_dimensionality().unwrap(), - &mut state, - false, - ); - let noisy = istft( - sample.noisy.view_mut().into_dimensionality().unwrap(), - &mut state, - false, - ); - write_wav_arr2("../out/speech.wav", speech.view(), sr as u32).unwrap(); - write_wav_arr2("../out/noisy.wav", noisy.view(), sr as u32).unwrap(); - Ok(()) - } - #[test] - pub fn test_interfering_spk() -> Result<()> { - setup(); - seed_from_u64(0); - let sr = 48_000; - let dir = "../assets/"; - let cfg = DatasetConfigJson::open("../assets/dataset.cfg").unwrap(); - let mut ds = DatasetBuilder::new(dir, sr) - .dataset(cfg.split_config(Split::Train)) - .interfer_distortion(1.0) - .snrs(vec![100]) - .build_td_dataset() - .unwrap(); - ds.generate_keys(Some(0))?; - let mut rng = thread_rng()?; - let sample = ds.get_sample(rng.uniform(0, ds.len()), Some(0)).unwrap(); - write_wav_arr2( - "../out/speech.wav", - sample.speech.view().into_dimensionality()?, - sr as u32, - ) - .unwrap(); - write_wav_arr2( - "../out/noisy.wav", - sample.noisy.view().into_dimensionality()?, - sr as u32, - ) - .unwrap(); - Ok(()) - } -} diff --git a/libDF/src/hdf5_key_cache.rs b/libDF/src/hdf5_key_cache.rs deleted file mode 100644 index 3d42c59e8..000000000 --- a/libDF/src/hdf5_key_cache.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::path::{Path, PathBuf}; - -use crate::dataset::*; - -/// Generate path of json cache file containing the HDF5 keys. -pub fn cache_path(cfg_path: &str) -> PathBuf { - let mut p = Path::new(cfg_path).to_path_buf(); - let cache_file_name = p.file_stem().unwrap().to_str().unwrap().to_owned(); - p.set_file_name(".cache_".to_owned() + &cache_file_name); - p.set_extension("cfg"); - p -} -/// Load HDF5 keys into DatasetConfigJson using the json cache file. -/// This function validates the topicality by hashing the modified timestamp and file size. -pub fn load_hdf5_key_cache(cfg_path: &str, cfg: &mut DatasetConfigJson) { - let cache_path = cache_path(cfg_path); - if !cache_path.is_file() { - return; - } - log::info!( - "Loading HDF5 key cache from {}", - cache_path.to_str().unwrap_or_default() - ); - match DatasetConfigCacheJson::open(cache_path.to_str().unwrap()) { - Err(e) => log::warn!("Could not load dataset keys cache: {}", e), - Ok(cache) => { - cfg.set_keys(Split::Train, cache.keys()).expect("Could not set cached keys"); - cfg.set_keys(Split::Valid, cache.keys()).expect("Could not set cached keys"); - cfg.set_keys(Split::Test, cache.keys()).expect("Could not set cached keys"); - } - } -} -/// Write all combined (train/valid/test) Hdf5Cfgs to a json file. This may be used for the next -/// TdDataset initialization. -pub fn write_hdf5_key_cache(cfg_path: &str, cfg: &DatasetConfigJson) { - let cache_path = cache_path(cfg_path); - let mut cache = Vec::new(); - cache.extend(cfg.train.iter().filter_map(|x| x.keys_unchecked().cloned())); - cache.extend(cfg.valid.iter().filter_map(|x| x.keys_unchecked().cloned())); - cache.extend(cfg.test.iter().filter_map(|x| x.keys_unchecked().cloned())); - let cache = DatasetConfigCacheJson::new(cache); - log::trace!("Writing HDF5 json key cache to {}", cache_path.display()); - cache.write(cache_path.to_str().unwrap()).expect("Failed to write cache."); -} -/// Fetch latest HDF5 keys and update the corresponding Hdf5Cfgs. -/// -/// This method is supposed to be called after TdDataset initialization so that the HDF5 keys are -/// stored within each Hdf5Cfg. Thus, we can serialize Hdf5Cfg to json and reuse the cached keys for -/// the next initialization. -pub fn fetch_hdf5_keys_from_ds(ds_dir: &str, cfgs: &mut [Hdf5Cfg], ds: &FftDataset) { - for hdf5cfg in cfgs.iter_mut() { - let ds_path = ds_dir.to_owned() + "/" + hdf5cfg.filename(); - let cfg = match ds.get_hdf5cfg(hdf5cfg.filename()) { - Some(cfg) => cfg, - None => { - log::warn!("Could not get hdf5cfg for filename {}", hdf5cfg.filename()); - continue; - } - }; - let hash = cfg - .hash() - .unwrap_or_else(|| cfg.hash_from_ds_path(&ds_path).expect("Could not calculate hash")); - if let Some(ds_keys) = cfg.load_keys(hash).expect("Could not load Hdf5Keys.") { - hdf5cfg.set_keys(ds_keys.clone()).expect("Could not update keys"); - } - } -} diff --git a/libDF/src/logging.rs b/libDF/src/logging.rs deleted file mode 100644 index 7960b1ba5..000000000 --- a/libDF/src/logging.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::sync::Once; - -use crossbeam_channel::{unbounded, Receiver, Sender}; -use log::{Level, Metadata, Record}; - -pub type DfLogReceiver = Receiver; - -pub type LogMessage = (Level, String, Option, Option); // level, message, module, lineno -pub struct DfLogger { - sender: Sender, - level: Level, -} - -static LOGGER_INIT: Once = Once::new(); - -impl DfLogger { - pub fn build(level: Level) -> (DfLogger, DfLogReceiver) { - let (sender, receiver) = unbounded(); - let logger = DfLogger { sender, level }; - (logger, receiver) - } -} - -impl log::Log for DfLogger { - fn enabled(&self, metadata: &Metadata) -> bool { - metadata.level() <= self.level && metadata.target().starts_with("df:") - } - - fn log(&self, record: &Record) { - if self.enabled(record.metadata()) { - self.sender - .send(( - record.level(), - format!("{}", record.args()), - record.module_path().map(|f| f.replace("::reexport_dataset_modules:", "")), - record.line(), - )) - .unwrap_or_else(|_| { - println!("DfDataloader | {} | {}", record.level(), record.args()) - }); - } - } - - fn flush(&self) {} -} - -pub fn init_logger(logger: DfLogger) { - LOGGER_INIT.call_once(|| { - let level = logger.level; - log::set_boxed_logger(Box::new(logger)).expect("Could not set logger"); - log::set_max_level(level.to_level_filter()); - }); -} diff --git a/libDF/src/transforms.rs b/libDF/src/transforms.rs deleted file mode 100644 index 7d6b1175e..000000000 --- a/libDF/src/transforms.rs +++ /dev/null @@ -1,711 +0,0 @@ -use std::mem::MaybeUninit; - -use ndarray::{prelude::*, Slice}; -use rubato::{FftFixedInOut, Resampler}; -use thiserror::Error; - -use crate::*; - -type Result = std::result::Result; - -#[derive(Error, Debug)] -pub enum TransformError { - #[error("DF error: {0}")] - DfError(String), - #[error("Ndarray Shape Error")] - NdarrayShapeError(#[from] ndarray::ShapeError), - #[error("Resample Error")] - ResampleError(#[from] rubato::ResampleError), -} - -pub(crate) fn biquad_norm_inplace<'a, I>(xs: I, mem: &mut [f32; 2], b: &[f32; 2], a: &[f32; 2]) -where - I: IntoIterator, -{ - // a0 and b0 are assumed to be 1 - let a1 = a[0] as f64; - let a2 = a[1] as f64; - let b1 = b[0] as f64; - let b2 = b[1] as f64; - for x in xs.into_iter() { - let x64 = *x as f64; - let y64 = x64 + mem[0] as f64; - mem[0] = (mem[1] as f64 + (b1 * x64 - a1 * y64)) as f32; - mem[1] = (b2 * x64 - a2 * y64) as f32; - *x = y64 as f32; - } -} - -pub(crate) fn biquad_inplace<'a, I>(xs: I, mem: &mut [f32; 2], b: &[f32; 3], a: &[f32; 3]) -where - I: IntoIterator, -{ - let a0 = a[0] as f64; - let a1 = a[1] as f64 / a0; - let a2 = a[2] as f64 / a0; - let b0 = b[0] as f64 / a0; - let b1 = b[1] as f64 / a0; - let b2 = b[2] as f64 / a0; - for x in xs.into_iter() { - let x64 = *x as f64; - let y64 = b0 * x64 + mem[0] as f64; - mem[0] = (mem[1] as f64 + (b1 * x64 - a1 * y64)) as f32; - mem[1] = (b2 * x64 - a2 * y64) as f32; - *x = y64 as f32; - } -} - -pub(crate) fn mix_f(clean: ArrayView2, noise: ArrayView2, snr_db: f32) -> f32 { - let e_clean = clean.iter().fold(0f32, |acc, x| acc + x.powi(2)) + 1e-10; - let e_noise = noise.iter().fold(0f32, |acc, x| acc + x.powi(2)) + 1e-10; - let snr = 10f32.powf(snr_db / 10.); - (1f64 / (((e_noise / e_clean) * snr + 1e-10) as f64).sqrt()) as f32 -} - -#[inline] -pub(crate) fn rms_normalize(x: Array2) -> Array2 { - let rms = x.map(|x| x.powi(2)).mean_axis(Axis(1)).unwrap().map(|x| x.sqrt() + 1e-8); - let ch = x.len_of(Axis(0)); - x / rms.to_shape([ch, 1]).unwrap() -} - -pub(crate) struct FftTransform { - pub planer: RealFftPlanner, - pub scratch: Vec, -} - -impl FftTransform { - pub fn new() -> Self { - FftTransform { - planer: RealFftPlanner::::new(), - scratch: Vec::new(), - } - } -} - -pub fn fft( - input: &mut Array2, - fft_transform: &dyn RealToComplex, - scratch: &mut Vec, -) -> Result> { - let scratch_len = fft_transform.get_scratch_len(); - if scratch.len() < scratch_len { - scratch.resize(scratch_len, Complex32::default()); - } - let mut output = Array2::zeros((input.len_of(Axis(0)), fft_transform.len() / 2 + 1)); - fft_with_output(input, fft_transform, scratch, &mut output)?; - Ok(output) -} - -pub fn fft_with_output( - input: &mut Array2, - fft_transform: &dyn RealToComplex, - scratch: &mut [Complex32], - output: &mut Array2, -) -> Result<()> { - debug_assert_eq!(fft_transform.len(), input.len_of(Axis(1))); - for (mut input_ch, mut output_ch) in input.outer_iter_mut().zip(output.outer_iter_mut()) { - let i = input_ch.as_slice_mut().unwrap(); - let o = output_ch.as_slice_mut().unwrap(); - fft_transform - .process_with_scratch(i, o, scratch) - .map_err(|e| TransformError::DfError(format!("Error in fft(): {e:?}")))?; - } - Ok(()) -} - -pub fn ifft( - input: &mut Array2, - fft_transform: &dyn ComplexToReal, - scratch: &mut Vec, -) -> Result> { - let scratch_len = fft_transform.get_scratch_len(); - if scratch.len() < scratch_len { - scratch.resize(scratch_len, Complex32::default()); - } - let mut output = Array2::zeros((input.len_of(Axis(0)), fft_transform.len())); - ifft_with_output(input, fft_transform, scratch, &mut output).unwrap(); - Ok(output) -} - -pub fn ifft_with_output( - input: &mut Array2, - fft_transform: &dyn ComplexToReal, - scratch: &mut [Complex32], - output: &mut Array2, -) -> Result<()> { - for (mut input_ch, mut output_ch) in input.outer_iter_mut().zip(output.outer_iter_mut()) { - let i = input_ch.as_slice_mut().unwrap(); - let o = output_ch.as_slice_mut().unwrap(); - fft_transform - .process_with_scratch(i, o, scratch) - .map_err(|e| TransformError::DfError(format!("Error in ifft(): {e:?}")))?; - } - Ok(()) -} - -/// Short time Fourier transform. -/// -/// Args: -/// - `input`: array of shape (C, T) -/// - `state`: DFState -/// - `reset`: Whether to reset STFT buffers -/// -/// Returns: -/// - `spectrum`: complex array of shape (C, T', F) -pub fn stft(input: ArrayView2, state: &mut DFState, reset: bool) -> Array3 { - if reset { - state.reset(); - } - let ch = input.len_of(Axis(0)); - let ttd = input.len_of(Axis(1)); - let n_pad = state.window_size / state.frame_size - 1; - let tfd = (ttd as f32 / state.frame_size as f32).ceil() as usize + n_pad; - let mut output: Array3 = Array3::zeros((ch, tfd, state.freq_size)); - for (input_ch, mut output_ch) in input.outer_iter().zip(output.outer_iter_mut()) { - for (ichunk, mut ochunk) in input_ch - .axis_chunks_iter(Axis(0), state.frame_size) - .zip(output_ch.outer_iter_mut()) - { - let ichunk = ichunk.as_slice().expect("stft ichunk has wrong shape"); - if ichunk.len() == state.frame_size { - frame_analysis( - ichunk, - ochunk.as_slice_mut().expect("stft ochunk has wrong shape"), - state, - ) - } else { - let pad = vec![0.; state.frame_size - ichunk.len()]; - frame_analysis( - &[ichunk, pad.as_slice()].concat(), - ochunk.as_slice_mut().expect("stft ochunk has wrong shape"), - state, - ) - }; - } - } - output.slice_axis_inplace(Axis(1), Slice::from(n_pad..)); - output -} - -/// .Inverse short time Fourier transform. -/// -/// # Args: -/// - `input`: Complex array of shape (C, T, F) -/// - `state`: DFState -/// - `reset`: Whether to reset ISTFT buffers before transfrorm. -/// -/// # Returns -pub fn istft(mut input: ArrayViewMut3, state: &mut DFState, reset: bool) -> Array2 { - if reset { - state.reset(); - } - let ch = input.len_of(Axis(0)); - let tfd = input.len_of(Axis(1)); - let ttd = tfd * state.frame_size; - let mut output: Array2 = Array2::zeros((ch, ttd)); - for (mut input_ch, mut output_ch) in input.outer_iter_mut().zip(output.outer_iter_mut()) { - for (mut ichunk, mut ochunk) in - input_ch.outer_iter_mut().zip(output_ch.exact_chunks_mut(state.frame_size)) - { - frame_synthesis( - ichunk.as_slice_mut().unwrap(), - ochunk.as_slice_mut().unwrap(), - state, - ) - } - } - output -} - -pub fn erb_compr_with_output( - input: &ArrayView3, - output: &mut ArrayViewMut3, - erb_fb: &[usize], -) -> Result<()> { - for (in_ch, mut out_ch) in input.outer_iter().zip(output.outer_iter_mut()) { - for (in_t, mut out_t) in in_ch.outer_iter().zip(out_ch.outer_iter_mut()) { - let ichunk = in_t.as_slice().unwrap(); - let ochunk = out_t.as_slice_mut().unwrap(); - band_compr(ochunk, ichunk, erb_fb); - } - } - Ok(()) -} - -pub fn erb_with_output( - input: &ArrayView3, - db: bool, - output: &mut ArrayViewMut3, - erb_fb: &[usize], -) -> Result<()> { - for (in_ch, mut out_ch) in input.outer_iter().zip(output.outer_iter_mut()) { - for (in_t, mut out_t) in in_ch.outer_iter().zip(out_ch.outer_iter_mut()) { - let ichunk = in_t.as_slice().unwrap(); - let ochunk = out_t.as_slice_mut().unwrap(); - compute_band_corr(ochunk, ichunk, ichunk, erb_fb); - } - } - if db { - output.mapv_inplace(|v| (v + 1e-10).log10() * 10.); - } - Ok(()) -} - -pub fn erb(input: &ArrayView3, db: bool, erb_fb: &[usize]) -> Result> { - // input shape: [C, T, F] - let ch = input.len_of(Axis(0)); - let t = input.len_of(Axis(1)); - let mut output = Array3::::zeros((ch, t, erb_fb.len())); - - erb_with_output(input, db, &mut output.view_mut(), erb_fb)?; - Ok(output) -} - -pub fn apply_erb_gains( - gains: &ArrayView3, - input: &mut ArrayViewMut3, - erb_fb: &[usize], -) -> Result<()> { - // gains shape: [C, T, E] - // input shape: [C, T, F] - // erb_fb shape: [N_erb] - for (g_ch, mut in_ch) in gains.outer_iter().zip(input.outer_iter_mut()) { - for (g_t, mut in_t) in g_ch.outer_iter().zip(in_ch.outer_iter_mut()) { - apply_interp_band_gain( - in_t.as_slice_mut().unwrap(), - g_t.as_slice().unwrap(), - erb_fb, - ); - } - } - Ok(()) -} - -pub fn erb_inv_with_output( - gains: &ArrayView3, - output: &mut ArrayViewMut3, - erb_fb: &[usize], -) -> Result<()> { - // gains shape: [C, T, E] - // output shape: [C, T, F] - // erb_fb shape: [N_erb] - for (g_ch, mut o_ch) in gains.outer_iter().zip(output.outer_iter_mut()) { - for (g_t, mut o_t) in g_ch.outer_iter().zip(o_ch.outer_iter_mut()) { - interp_band_gain(o_t.as_slice_mut().unwrap(), g_t.as_slice().unwrap(), erb_fb); - } - } - Ok(()) -} - -pub fn erb_norm( - input: &mut ArrayViewMut3, - state: Option>, - alpha: f32, -) -> Result> { - // input shape: [C, T, F] - // state shape: [C, F] - let mut state = state.unwrap_or_else(|| { - let b = input.len_of(Axis(2)); - let state_ch0 = Array1::::linspace(MEAN_NORM_INIT[0], MEAN_NORM_INIT[1], b) - .into_shape([1, b]) - .unwrap(); - let mut state = state_ch0.clone(); - for _ in 1..input.len_of(Axis(0)) { - state.append(Axis(0), state_ch0.view()).unwrap() - } - state - }); - debug_assert_eq!(state.len_of(Axis(0)), input.len_of(Axis(0))); - for (mut in_ch, mut s_ch) in input.outer_iter_mut().zip(state.outer_iter_mut()) { - for mut in_step in in_ch.outer_iter_mut() { - band_mean_norm_erb( - in_step.as_slice_mut().unwrap(), - s_ch.as_slice_mut().unwrap(), - alpha, - ) - } - } - Ok(state) -} - -pub fn unit_norm( - input: &mut ArrayViewMut3, - state: Option>, - alpha: f32, -) -> Result> { - // input shape: [C, T, F] - // state shape: [C, F] - let mut state = state.unwrap_or_else(|| { - let f = input.len_of(Axis(2)); - let state_ch0 = Array1::::linspace(UNIT_NORM_INIT[0], UNIT_NORM_INIT[1], f) - .into_shape([1, f]) - .unwrap(); - let mut state = state_ch0.clone(); - for _ in 1..input.len_of(Axis(0)) { - state.append(Axis(0), state_ch0.view()).unwrap() - } - state - }); - debug_assert_eq!(state.len_of(Axis(0)), input.len_of(Axis(0))); - for (mut in_ch, mut s_ch) in input.outer_iter_mut().zip(state.outer_iter_mut()) { - for mut in_step in in_ch.outer_iter_mut() { - band_unit_norm( - in_step.as_slice_mut().unwrap(), - s_ch.as_slice_mut().unwrap(), - alpha, - ) - } - } - Ok(state) -} - -/// Low pass by resampling the data to `f_cut_off*2`. -pub(crate) fn low_pass_resample( - x: ArrayView2, - f_cut_off: usize, - sr: usize, -) -> Result> { - let orig_len = x.len_of(Axis(1)); - let x = resample(x, sr, f_cut_off * 2, None)?; - let mut x = resample(x.view(), f_cut_off * 2, sr, None)?; - x.slice_axis_inplace(Axis(1), Slice::from(0..orig_len)); - Ok(x) -} -/// Resample using a synchronous resample from rubato -pub fn resample( - x: ArrayView2, - sr: usize, - new_sr: usize, - chunk_size: Option, -) -> Result> { - let channels = x.len_of(Axis(0)); - let len = x.len_of(Axis(1)); - let out_len = (len as f32 * new_sr as f32 / sr as f32).ceil() as usize; - let chunk_size = chunk_size.unwrap_or(2048); - let mut resampler = FftFixedInOut::::new(sr, new_sr, chunk_size, channels) - .expect("Could not initialize resampler"); - let chunk_size = resampler.input_frames_max(); - // One extra to get the remaining resampler state buffer - let num_chunks = (len as f32 / chunk_size as f32).ceil() as usize + 1; - let chunk_size_out = resampler.output_frames_max(); - let mut out = Array2::uninit((channels, chunk_size_out * num_chunks)); - let mut inbuf = resampler.input_buffer_allocate(true); - let mut outbuf = resampler.output_buffer_allocate(true); - let mut out_chunk_iter = out.axis_chunks_iter_mut(Axis(1), chunk_size_out); - for chunk in x.axis_chunks_iter(Axis(1), chunk_size) { - for (chunk_ch, buf_ch) in chunk.axis_iter(Axis(0)).zip(inbuf.iter_mut()) { - if chunk_ch.len() == chunk_size { - chunk_ch.assign_to(buf_ch); - } else { - chunk_ch.assign_to(&mut buf_ch[..chunk_ch.len()]); - for b in buf_ch[chunk_ch.len()..].iter_mut() { - *b = 0. // Zero pad - } - } - } - resampler.process_into_buffer(&inbuf, &mut outbuf, None)?; - for (res_ch, mut out_ch) in - outbuf.iter().zip(out_chunk_iter.next().unwrap().axis_iter_mut(Axis(0))) - { - debug_assert_eq!(res_ch.len(), out_ch.len()); - for (&x, y) in res_ch.iter().zip(out_ch.iter_mut()) { - *y = MaybeUninit::new(x); - } - } - } - // Another round with zeros to get remaining state buffer - for in_ch in inbuf.iter_mut() { - in_ch.fill(0.) - } - resampler.process_into_buffer(&inbuf, &mut outbuf, None)?; - for (res_ch, mut out_ch) in - outbuf.iter().zip(out_chunk_iter.next().unwrap().axis_iter_mut(Axis(0))) - { - debug_assert_eq!(res_ch.len(), out_ch.len()); - for (&x, y) in res_ch.iter().zip(out_ch.iter_mut()) { - *y = MaybeUninit::new(x); - } - } - let mut out = unsafe { out.assume_init() }; - out.slice_axis_inplace( - Axis(1), - Slice::from(chunk_size_out / 2..chunk_size_out / 2 + out_len), - ); - Ok(out) -} - -/// Bandwidth extension via spectral translation. -/// That is, copy spectrum from lower frequencies into higher frequencies. -/// -/// Args: -/// - `x`: Spectrogram of shape (C, T, F) -/// - `cbin`: Bin of cut-of-frequency. Frequencies above will get extended based on lower Frequencies. -/// - `sr`: Original time-domain sampling rate. -/// - `n_bins_overlap`: Instead of starting at bin correspinging to `freq` start `n_bins_overlap` lower. -pub(crate) fn ext_bandwidth_spectral( - x: &mut Array3, - mut cbin: usize, - sr: usize, - n_bins_overlap: Option, -) { - let n_bins_all = x.len_of(Axis(2)); // Number of bins of non-downampled signal - let n_fft = (n_bins_all - 1) * 2; - if n_bins_all - cbin <= 1 { - // If only one bin is missing don't do nothin - return; - } - cbin -= n_bins_overlap.unwrap_or(0); // Overlap at the edge of the downsampled spectrum - let mut min_bin = 4000 / (sr / n_fft); // Only start from 4 kHz - if cbin <= min_bin { - min_bin = 3000 / (sr / n_fft); // Use 3kHz then - } - let max_copy_bins = cbin - min_bin; // Number of bins to copy per iteration - let missing_bins = n_bins_all - cbin; - let n_copies = (missing_bins as f32 / max_copy_bins as f32).ceil() as usize; - let mut start_bin_tgt = cbin; - let start_bin_src = min_bin.max(cbin.saturating_sub(missing_bins)); - debug_assert!(start_bin_tgt > start_bin_src); - for _ in 0..n_copies { - let cur_n_copy = max_copy_bins.min(n_bins_all - start_bin_tgt); - let (src, target) = x.multi_slice_mut(( - s![.., .., start_bin_src..(start_bin_src + cur_n_copy)], - s![.., .., start_bin_tgt..(start_bin_tgt + cur_n_copy)], - )); - src.assign_to(target); - start_bin_tgt += cur_n_copy; - } -} - -fn bw_filterbank(center_freqs: &[f32], cutoff_bins: &[f32; 8]) -> Result> { - // fb for bands [0-8, 8-10, 10-12, 12-16, 16-18, 18-20, 20-22, 22-24] kHz. - // assumes 48 kHz sampling rate. - let n_freqs = center_freqs.len(); - let mut out = Array2::zeros((n_freqs, 8)); - for (&f, mut o) in center_freqs.iter().zip(out.outer_iter_mut()) { - let o = o.as_slice_mut().unwrap(); - if f <= cutoff_bins[0] { - o[0] += 1. - } else if f <= cutoff_bins[1] { - o[1] += 1. - } else if f <= cutoff_bins[2] { - o[2] += 1. - } else if f <= cutoff_bins[3] { - o[3] += 1. - } else if f <= cutoff_bins[4] { - o[4] += 1. - } else if f <= cutoff_bins[5] { - o[5] += 1. - } else if f <= cutoff_bins[6] { - o[6] += 1. - } else { - o[7] += 1. - } - } - let sum = out.sum_axis(Axis(0)).into_shape((1, 8))?; - Ok(out / sum) -} - -/// Compute r2c FFT frequency of given the number of frequencies (`n_fft/2+1`). -pub fn rfftfreqs(n: usize, sr: usize) -> Vec { - (0..n) - .map(|x| x as f32 * (sr / 2) as f32 / (n - 1) as f32) - .collect::>() -} - -/// Estimate bandwidth by finding the highest frequency bin containing a sufficient amount of energy. -/// A minimum sampling rate of 16 kHz is assumed. -/// -/// The algorithm works as follows: -/// 1. Reduce the frequency bins into the following bands `[0-8,8-10,10-12,12-16,16-18,18-20,20-22,22-24]` kHz. -/// This matches the following sampling rates: `[16,20,24,32,36,40,44,48]` kHz. -/// Note, that non-standard srs like 36 kHz with 18 kHz cut off frequency is included since -/// codecs like mp3 may cut off some speech parts at 18 kHz. -/// 2. Compute mapping from bw-filterbank to frequency bins -/// 3. Within non-overlapping chhunks of size `window_size` compute max energy in [dB]. -/// If max < `db_cut_off`, assume sampling rate corresponding to the bw-filterbank band. -/// 4. Return median of indices found in 3. -/// -/// Args: -/// - `input`: Complex spectrum of shape (C, T, F) -/// - `sr`: Sampling rate of the non-downampled time-domain signal -/// - `db_cut_off`: Energy threshold (e.g. `120.`) -/// - `window_size`: Window length in samples to estimate bandwidth -pub(crate) fn estimate_bandwidth( - input: ArrayView3, - sr: usize, - mut db_cut_off: f32, - mut window_size: usize, -) -> usize { - assert_eq!(sr, 48000, "bw_filterbank() assumes 48 kHz sampling rate."); - if input.len_of(Axis(1)) < window_size { - // Make sure to have at least one window - window_size = input.len_of(Axis(1)) - } - if db_cut_off > 0. { - db_cut_off *= -1.; - } - // 1. Init bandwidth filterbank - let b_c = [ - 8000., 10000., 12000., 16000., 18000., 20000., 22000., 24000., - ]; - let sr = 48000; - let n_freqs = input.len_of(Axis(2)); - let center_freqs = rfftfreqs(n_freqs, sr); - let fb = bw_filterbank(¢er_freqs, &b_c).unwrap(); - let mut f_db = input - .map(|x| (x.norm() + 1e-16).log10() * 20.) - .mean_axis(Axis(0)) - .unwrap() - .dot(&fb); - // 2. Compute mapping of bw-filterbank bins to original frequency bins. - let mut c_map = [0; 8]; - for (i, fb_r) in fb.outer_iter().enumerate() { - for (&fb_v, c) in fb_r.iter().zip(c_map.iter_mut()) { - if fb_v > 0. { - *c = i - } - } - } - // 3. Find cutoff indice for each frame of size `window_size`. - let mut idcs: Vec = Vec::with_capacity(input.len_of(Axis(1)) / window_size + 1); - for w in f_db.axis_chunks_iter_mut(Axis(0), window_size) { - let m = w.axis_iter(Axis(1)).map(|x| find_max(x).unwrap()); - let c = m.skip(1).position(|x| x < db_cut_off).unwrap_or(7); - idcs.push(c_map[c]); - } - // 4. Return median of found indices - median(&mut idcs) -} - -#[cfg(test)] -mod tests { - use std::sync::Once; - - use super::*; - use crate::util::seed_from_u64; - use crate::wav_utils::*; - - static INIT: Once = Once::new(); - - /// Setup function that is only run once, even if called multiple times. - fn setup() -> (Array2, usize) { - seed_from_u64(42); - create_out_dir().expect("Could not create output directory"); - - INIT.call_once(|| { - let _ = env_logger::builder() - // Include all events in tests - .filter_module("df", log::LevelFilter::max()) - // Ensure events are captured by `cargo test` - .is_test(true) - // Ignore errors initializing the logger if tests race to configure it - .try_init(); - }); - let reader = ReadWav::new("../assets/clean_freesound_33711.wav").unwrap(); - let sr = reader.sr; - let test_sample = reader.samples_arr2().unwrap(); - (test_sample, sr) - } - - fn create_out_dir() -> std::io::Result<()> { - match std::fs::create_dir("../out") { - Err(ref e) if e.kind() == std::io::ErrorKind::AlreadyExists => Ok(()), - r => r, - } - } - - #[test] - pub fn test_stft_istft_delay() -> Result<()> { - let (sample, sr) = setup(); - let ch = sample.len_of(Axis(0)) as u16; - let fft_size = sr / 50; - let hop_size = fft_size / 2; - let mut state = DFState::new(sr, fft_size, hop_size, 1, 1); - let mut x = stft(sample.view(), &mut state, true); - let out = istft(x.view_mut(), &mut state, true); - for (ich, och) in sample.outer_iter().zip(out.outer_iter()) { - let xx: f32 = ich.iter().map(|&s| s * s).sum(); - let yy: f32 = ich.iter().map(|&s| s * s).sum(); - let xy: f32 = ich.iter().zip(och).map(|(&a, &b)| a * b).sum(); - let corr = xy / (xx.sqrt() * yy.sqrt()); - dbg!(corr); - assert!((corr - 1.).abs() < 1e-6) - } - write_wav_iter("../out/original.wav", sample.iter(), sr as u32, ch).unwrap(); - write_wav_iter("../out/stft_istft.wav", out.iter(), sr as u32, ch).unwrap(); - Ok(()) - } - - #[test] - fn test_estimate_bandwidth() -> Result<()> { - let (sample, sr) = setup(); - write_wav_arr2("../out/original.wav", sample.view(), sr as u32).unwrap(); - - let fft_size = 960; - assert!(sr % fft_size == 0); // So that we have nice center freqs - let hop_size = fft_size / 2; - let mut state = DFState::new(sr, fft_size, hop_size, 1, 1); - let x = stft(sample.view(), &mut state, true); - let ws = 200; // window size - let c_db = 120.; //cut of db - let cf = rfftfreqs(fft_size / 2 + 1, sr); // center frequencies - let idx = estimate_bandwidth(x.view(), sr, c_db, ws); - assert_eq!(cf[idx], 22000.); - - let sample_f2 = low_pass_resample(sample.view(), sr / 4, sr).unwrap(); - write_wav_arr2("../out/resampled_f2.wav", sample_f2.view(), sr as u32).unwrap(); - let x_f2 = stft(sample_f2.view(), &mut state, true); - let idx = estimate_bandwidth(x_f2.view(), sr, c_db, ws); - assert_eq!(cf[idx], 12000.); - - let sample_f3 = low_pass_resample(sample.view(), sr / 6, sr).unwrap(); - write_wav_arr2("../out/resampled_f3.wav", sample_f3.view(), sr as u32).unwrap(); - let x_f3 = stft(sample_f3.view(), &mut state, true); - let idx = estimate_bandwidth(x_f3.view(), sr, c_db, ws); - assert_eq!(cf[idx], 8000.); - - Ok(()) - } - - #[test] - fn test_ext_bandwidth_spectral() { - let (sample, sr) = setup(); - let fft_size = sr / 50; - dbg!(fft_size); - let hop_size = fft_size / 2; - let mut state = DFState::new(sr, fft_size, hop_size, 1, 1); - let mut x = stft(sample.view(), &mut state, true); - - let cf = rfftfreqs(fft_size / 2 + 1, sr); - let idx = estimate_bandwidth(x.view(), sr, -120., 5); - let f_cut_off = cf[idx]; - let max_bin = (f_cut_off / (sr as f32 / fft_size as f32)) as usize; - dbg!(idx, f_cut_off); - let mut x2 = x.clone(); - ext_bandwidth_spectral(&mut x2, max_bin, sr, Some(4)); - let sample_ext = istft(x2.view_mut(), &mut state, true); - write_wav_arr2("../out/sample_ext.wav", sample_ext.view(), sr as u32).unwrap(); - - let f_cut_off = 12000; - let max_bin = (f_cut_off as f32 / (sr as f32 / fft_size as f32)) as usize; - let sample_f2 = low_pass_resample(sample.view(), f_cut_off, sr).unwrap(); - let mut x3 = stft(sample_f2.view(), &mut state, true); - ext_bandwidth_spectral(&mut x3, max_bin, sr, Some(4)); - let sample_f2_ext = istft(x3.view_mut(), &mut state, true); - write_wav_arr2("../out/sample_f2_ext.wav", sample_f2_ext.view(), sr as u32).unwrap(); - - let sample = istft(x.view_mut(), &mut state, true); - write_wav_arr2("../out/original.wav", sample.view(), sr as u32).unwrap(); - } - - #[test] - fn test_find_max_abs() -> Result<()> { - let mut x = vec![vec![0f32; 10]; 1]; - x[0][2] = 3f32; - x[0][5] = -10f32; - let max = find_max_abs(x.iter().flatten()).expect("NaN"); - assert_eq!(max, 10.); - Ok(()) - } -} diff --git a/libDF/src/util.rs b/libDF/src/util.rs deleted file mode 100644 index 40444d98b..000000000 --- a/libDF/src/util.rs +++ /dev/null @@ -1,98 +0,0 @@ -use std::cell::{RefCell, UnsafeCell}; -use std::rc::Rc; -use std::thread_local; - -use ndarray_rand::rand::distributions::{ - uniform::{SampleUniform, Uniform}, - Distribution, -}; -use ndarray_rand::rand::{Error as RandError, Rng, RngCore}; -use rand_xoshiro::rand_core::SeedableRng; -use rand_xoshiro::Xoshiro256PlusPlus; -use thiserror::Error; - -pub use crate::logging::*; - -type Result = std::result::Result; - -#[derive(Error, Debug)] -pub enum UtilsError { - #[error("Random seed is not initialized using seed_from_u64(x)")] - SeedNotInitialized, - #[error("Could not inititalize logger")] - SetLoggerError(#[from] log::SetLoggerError), -} - -pub struct SeededRng { - rng: Rc>, -} -thread_local!( - static THREAD_SEEDED_RNG: Rc> = - Rc::new(UnsafeCell::new(Xoshiro256PlusPlus::seed_from_u64(0))); - static SEEDED: RefCell = const { RefCell::new(false) }; -); - -pub fn seed_from_u64(x: u64) { - SEEDED.with(|s| s.replace(true)); - unsafe { THREAD_SEEDED_RNG.with(|rng| *rng.get() = Xoshiro256PlusPlus::seed_from_u64(x)) } -} - -impl RngCore for SeededRng { - fn next_u32(&mut self) -> u32 { - unsafe { (*self.rng.get()).next_u32() } - } - fn next_u64(&mut self) -> u64 { - unsafe { (*self.rng.get()).next_u64() } - } - fn fill_bytes(&mut self, slice: &mut [u8]) { - unsafe { (*self.rng.get()).fill_bytes(slice) } - } - fn try_fill_bytes(&mut self, slice: &mut [u8]) -> std::result::Result<(), RandError> { - unsafe { (*self.rng.get()).try_fill_bytes(slice) } - } -} - -pub fn thread_rng() -> Result { - if !(SEEDED.with(|s| *s.borrow())) { - return Err(UtilsError::SeedNotInitialized); - } - Ok(SeededRng { - rng: THREAD_SEEDED_RNG.with(|rng| rng.clone()), - }) -} - -impl SeededRng { - #[inline] - pub fn log_uniform(&mut self, low: f32, high: f32) -> f32 { - self.gen_range(low.ln()..=high.ln()).exp() - } - #[inline] - pub fn uniform(&mut self, low: T, high: T) -> T { - if low >= high { - low - } else { - self.gen_range(low..high) - } - } - #[inline] - pub fn uniform_inclusive(&mut self, low: T, high: T) -> T { - if low >= high { - low - } else { - self.gen_range(low..=high) - } - } -} - -pub(crate) fn rng_uniform(n: usize, low: T, high: T) -> Result> -where - T: Default + Clone + SampleUniform, -{ - let mut rng = thread_rng()?; - let mut v = vec![T::default(); n]; - let dist = Uniform::new_inclusive(low, high); - for x in v.iter_mut() { - *x = dist.sample(&mut rng); - } - Ok(v) -} diff --git a/libDF/src/wasm.rs b/libDF/src/wasm.rs deleted file mode 100644 index 2e02095b7..000000000 --- a/libDF/src/wasm.rs +++ /dev/null @@ -1,88 +0,0 @@ -use std::boxed::Box; - -use ndarray::prelude::*; -use wasm_bindgen::prelude::*; - -use crate::tract::*; - -#[wasm_bindgen] -pub struct DFState(crate::tract::DfTract); - -#[wasm_bindgen] -impl DFState { - fn new(model_bytes: &[u8], channels: usize, atten_lim: f32) -> Self { - let r_params = RuntimeParams::default_with_ch(channels).with_atten_lim(atten_lim); - let df_params = DfParams::from_bytes(model_bytes).expect("Could not load model from path"); - let m = - DfTract::new(df_params, &r_params).expect("Could not initialize DeepFilter runtime."); - DFState(m) - } - fn boxed(self) -> Box { - Box::new(self) - } -} - -/// Create a DeepFilterNet Model -/// -/// Args: -/// - path: File path to a DeepFilterNet tar.gz onnx model -/// - atten_lim: Attenuation limit in dB. -/// -/// Returns: -/// - DF state doing the full processing: stft, DNN noise reduction, istft. -#[wasm_bindgen] -pub unsafe fn df_create( - model_bytes: &[u8], - // channels: usize, - atten_lim: f32, -) -> *mut DFState { - let df = DFState::new(model_bytes, 1, atten_lim); - Box::into_raw(df.boxed()) -} - -/// Get DeepFilterNet frame size in samples. -#[wasm_bindgen] -pub unsafe fn df_get_frame_length(st: *mut DFState) -> usize { - let state = st.as_mut().expect("Invalid pointer"); - state.0.hop_size -} - -/// Set DeepFilterNet attenuation limit. -/// -/// Args: -/// - lim_db: New attenuation limit in dB. -#[wasm_bindgen] -pub unsafe fn df_set_atten_lim(st: *mut DFState, lim_db: f32) { - let state = st.as_mut().expect("Invalid pointer"); - state.0.set_atten_lim(lim_db) -} - -/// Set DeepFilterNet post filter beta. A beta of 0 disables the post filter. -/// -/// Args: -/// - beta: Post filter attenuation. Suitable range between 0.05 and 0; -#[wasm_bindgen] -pub unsafe fn df_set_post_filter_beta(st: *mut DFState, beta: f32) { - let state = st.as_mut().expect("Invalid pointer"); - state.0.set_pf_beta(beta) -} - -/// Processes a chunk of samples. -/// -/// Args: -/// - df_state: Created via df_create() -/// - input: Input buffer of length df_get_frame_length() -/// - output: Output buffer of length df_get_frame_length() -/// -/// Returns: -/// - Local SNR of the current frame. -#[wasm_bindgen] -pub unsafe fn df_process_frame(st: *mut DFState, input: &[f32]) -> js_sys::Float32Array { - let state = st.as_mut().expect("Invalid pointer"); - let input = ArrayView2::from_shape((1, state.0.hop_size), input).unwrap(); - - let mut output = Array2::zeros((1, state.0.hop_size)); - let output_view = output.view_mut(); - let _lsnr = state.0.process(input, output_view).expect("Failed to process DF frame"); - js_sys::Float32Array::from(output.as_slice().unwrap()) -} diff --git a/libDF/src/wav_utils.rs b/libDF/src/wav_utils.rs deleted file mode 100644 index 99e2cbc56..000000000 --- a/libDF/src/wav_utils.rs +++ /dev/null @@ -1,160 +0,0 @@ -use std::result::Result; -use std::{ - fs::File, - io::{BufReader, Read}, -}; - -use hound::{WavReader, WavWriter}; -#[cfg(any(feature = "dataset", feature = "wav-utils"))] -use ndarray::prelude::*; -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum WavUtilsError { - #[error("Hound Error")] - HoundError(#[from] hound::Error), - #[error("Hound Error Detail")] - HoundErrorDetail { source: hound::Error, msg: String }, - #[error("Ndarray Shape Error")] - NdarrayShapeError(#[from] ndarray::ShapeError), -} - -pub struct ReadWav { - reader: WavReader>, - pub channels: usize, - pub sr: usize, - pub len: usize, - pub dtype: hound::SampleFormat, -} - -impl ReadWav { - pub fn new(path: &str) -> Result - where - Self: Sized, - { - let reader = match WavReader::open(path) { - Err(e) => { - return Err(WavUtilsError::HoundErrorDetail { - source: e, - msg: format!("Could not find audio file {path}"), - }) - } - Ok(r) => r, - }; - let spec = reader.spec(); - let channels = spec.channels as usize; - let sr = spec.sample_rate as usize; - let len = reader.len() as usize / channels; - let dtype = spec.sample_format; - Ok(ReadWav { - reader, - channels, - sr, - len, - dtype, - }) - } - pub fn iter(&mut self) -> Box + '_> { - match self.dtype { - hound::SampleFormat::Int => Box::new(read_wav_raw_i16(&mut self.reader)), - hound::SampleFormat::Float => Box::new(read_wav_raw_f32(&mut self.reader)), - } - } - pub fn samples_vec(mut self) -> Result>, WavUtilsError> { - let mut out = vec![Vec::::new(); self.channels]; - let mut samples = self.iter(); - 'outer: loop { - for out_ch in out.iter_mut() { - match samples.next() { - None => break 'outer, - Some(x) => out_ch.push(x), - } - } - } - Ok(out) - } - #[cfg(any(feature = "dataset", feature = "wav-utils"))] - pub fn samples_arr2(mut self) -> Result, WavUtilsError> { - Ok( - Array2::from_shape_vec((self.len, self.channels), self.iter().collect())? - .t() - .to_owned(), - ) - } -} - -fn read_wav_raw_i16(reader: &mut WavReader) -> impl Iterator + '_ { - reader.samples::().map(|s| s.unwrap() as f32 / 32767.0) -} -fn read_wav_raw_f32(reader: &mut WavReader) -> impl Iterator + '_ { - reader.samples::().map(|s| s.unwrap()) -} - -pub fn read_wav(path: &str) -> Result<(Vec>, u32), WavUtilsError> { - let mut reader = WavReader::open(path)?; - let ch = reader.spec().channels as usize; - let sr = reader.spec().sample_rate; - let mut out = vec![Vec::::new(); ch]; - let mut samples = read_wav_raw_i16(&mut reader); - 'outer: loop { - for out_ch in out.iter_mut() { - match samples.next() { - None => break 'outer, - Some(x) => out_ch.push(x), - } - } - } - Ok((out, sr)) -} - -pub fn write_wav_iter<'a, I>(path: &str, iter: I, sr: u32, ch: u16) -> Result<(), WavUtilsError> -where - I: IntoIterator, -{ - let spec = hound::WavSpec { - channels: ch, - sample_rate: sr, - bits_per_sample: 16, - sample_format: hound::SampleFormat::Int, - }; - let mut writer = WavWriter::create(path, spec)?; - - for &sample in iter.into_iter() { - writer.write_sample((sample * i16::MAX as f32) as i16)?; - } - Ok(()) -} - -pub fn write_wav(path: &str, x: &[Vec], sr: u32) -> Result<(), WavUtilsError> { - let spec = hound::WavSpec { - channels: x.len() as u16, - sample_rate: sr, - bits_per_sample: 16, - sample_format: hound::SampleFormat::Int, - }; - let mut writer = WavWriter::create(path, spec)?; - - for t in 0..x[0].len() { - for ch in x.iter() { - writer.write_sample((ch[t] * i16::MAX as f32) as i16)?; - } - } - Ok(writer.finalize()?) -} - -#[cfg(any(feature = "dataset", feature = "wav-utils"))] -pub fn write_wav_arr2(path: &str, x: ArrayView2, sr: u32) -> Result<(), WavUtilsError> { - let spec = hound::WavSpec { - channels: x.len_of(Axis(0)) as u16, - sample_rate: sr, - bits_per_sample: 16, - sample_format: hound::SampleFormat::Int, - }; - let mut writer = WavWriter::create(path, spec)?; - for xt in x.axis_iter(Axis(1)) { - for s in xt.iter() { - writer.write_sample((s * i16::MAX as f32) as i16)?; - } - } - Ok(writer.finalize()?) -} From 555e00c1c7e6c7bbf53677568fd470e617bafd8f Mon Sep 17 00:00:00 2001 From: Jackson Goode <54308792+jacksongoode@users.noreply.github.com> Date: Fri, 14 Nov 2025 10:37:21 +0900 Subject: [PATCH 2/5] Only keep libDF as a member in the workspace --- Cargo.toml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1019dbedd..b332df5d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,11 +2,7 @@ resolver = "2" members = [ - "libDF", - "pyDF", - "pyDF-data", - "ladspa", - "demo", + "libDF" ] [profile.dev] From dc0b57cb0d0da8eacde755ad5a040b05c1ac3489 Mon Sep 17 00:00:00 2001 From: Jackson Goode <54308792+jacksongoode@users.noreply.github.com> Date: Fri, 14 Nov 2025 11:14:07 +0900 Subject: [PATCH 3/5] Cleanup (see commit msg): - Remove unused packages, bump Rust version & packages - Cleanup & compat fixes for new libs - Add model path in input - Remove some logging and lower info to debug --- Cargo.lock | 6139 +++++++------------------------------------- libDF/Cargo.toml | 175 +- libDF/src/lib.rs | 263 +- libDF/src/tract.rs | 276 +- 4 files changed, 984 insertions(+), 5869 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 886c82549..47a96d2f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5897 +1,1472 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] -name = "DeepFilterDataLoader" -version = "0.5.7-pre" -dependencies = [ - "crossbeam-channel", - "deep_filter", - "log", - "ndarray", - "numpy", - "pyo3", -] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] -name = "DeepFilterLib" -version = "0.5.7-pre" +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ - "deep_filter", - "ndarray", - "numpy", - "pyo3", + "cfg-if", + "once_cell", + "version_check", + "zerocopy", ] [[package]] -name = "ab_glyph" -version = "0.2.25" +name = "aho-corasick" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f90148830dac590fac7ccfe78ec4a8ea404c60f75a24e16407a71f0f40de775" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", + "memchr", ] [[package]] -name = "ab_glyph_rasterizer" -version = "0.1.8" +name = "anyhow" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] -name = "addr2line" -version = "0.21.0" +name = "anymap2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] +checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" [[package]] -name = "adler" -version = "1.0.2" +name = "anymap3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "170433209e817da6aae2c51aa0dd443009a613425dd041ebfb2492d1c4c11a25" [[package]] -name = "ahash" -version = "0.8.11" +name = "autocfg" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] -name = "aho-corasick" -version = "1.1.3" +name = "bit-set" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" dependencies = [ - "memchr", + "bit-vec", ] [[package]] -name = "aliasable" -version = "0.1.3" +name = "bit-vec" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" [[package]] -name = "allocator-api2" -version = "0.2.18" +name = "bitflags" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] -name = "alsa" -version = "0.9.0" +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37fe60779335388a88c01ac6c3be40304d1e349de3ada3b15f7808bb90fa9dce" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "alsa-sys", - "bitflags 2.5.0", - "libc", + "generic-array", ] [[package]] -name = "alsa-sys" -version = "0.3.1" +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cc" +version = "1.2.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35900b6c8d709fb1d854671ae27aeaa9eec2f8b01b364e1619a40da3e6fe2afe" dependencies = [ - "libc", - "pkg-config", + "find-msvc-tools", + "shlex", ] [[package]] -name = "android-activity" -version = "0.4.3" +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "const-random" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64529721f27c2314ced0890ce45e469574a73e5e6fdd6e9da1860eb29285f5e0" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" dependencies = [ - "android-properties", - "bitflags 1.3.2", - "cc", - "jni-sys", - "libc", - "log", - "ndk 0.7.0", - "ndk-context", - "ndk-sys 0.4.1+23.1.7779620", - "num_enum 0.6.1", + "const-random-macro", ] [[package]] -name = "android-properties" -version = "0.2.2" +name = "const-random-macro" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", +] [[package]] -name = "android_system_properties" -version = "0.1.5" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] -name = "anstream" -version = "0.6.14" +name = "crc32fast" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", + "cfg-if", ] [[package]] -name = "anstyle" -version = "1.0.7" +name = "crunchy" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] -name = "anstyle-parse" -version = "0.2.4" +name = "crypto-common" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ - "utf8parse", + "generic-array", + "typenum", ] [[package]] -name = "anstyle-query" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +name = "deep_filter" +version = "0.5.7-pre" dependencies = [ - "windows-sys 0.52.0", + "anyhow", + "flate2", + "itertools 0.10.5", + "log", + "ndarray", + "num-complex", + "rand", + "realfft", + "rust-ini", + "rustfft", + "tar", + "tract-core", + "tract-hir", + "tract-onnx", + "tract-pulse", ] [[package]] -name = "anstyle-wincon" -version = "3.0.3" +name = "deranged" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ - "anstyle", - "windows-sys 0.52.0", + "powerfmt", ] [[package]] -name = "anyhow" -version = "1.0.82" +name = "derive-new" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" dependencies = [ - "backtrace", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "anymap2" -version = "0.13.0" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] [[package]] -name = "approx" -version = "0.5.1" +name = "dlv-list" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" dependencies = [ - "num-traits", + "const-random", ] [[package]] -name = "arrayref" -version = "0.3.7" +name = "downcast-rs" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] -name = "arrayvec" -version = "0.7.4" +name = "dyn-clone" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] -name = "ascii" -version = "1.1.0" +name = "dyn-hash" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" +checksum = "15401da73a9ed8c80e3b2d4dc05fe10e7b72d7243b9f614e516a44fa99986e88" [[package]] -name = "ash" -version = "0.37.3+1.3.251" +name = "either" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" -dependencies = [ - "libloading 0.7.4", -] +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] -name = "async-broadcast" -version = "0.5.1" +name = "errno" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ - "event-listener 2.5.3", - "futures-core", + "libc", + "windows-sys 0.61.2", ] [[package]] -name = "async-channel" -version = "2.2.1" +name = "filetime" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d4d23bcc79e27423727b36823d86233aad06dfea531837b038394d11e9928" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" dependencies = [ - "concurrent-queue", - "event-listener 5.3.0", - "event-listener-strategy 0.5.2", - "futures-core", - "pin-project-lite", + "cfg-if", + "libc", + "libredox", + "windows-sys 0.60.2", ] [[package]] -name = "async-executor" -version = "1.11.0" +name = "find-msvc-tools" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b10202063978b3351199d68f8b22c4e47e4b1b822f8d43fd862d5ea8c006b29a" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand 2.1.0", - "futures-lite 2.3.0", - "slab", -] +checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" [[package]] -name = "async-fs" -version = "1.6.0" +name = "flate2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ - "async-lock 2.8.0", - "autocfg", - "blocking", - "futures-lite 1.13.0", + "crc32fast", + "miniz_oxide", ] [[package]] -name = "async-io" -version = "1.13.0" +name = "generic-array" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "async-lock 2.8.0", - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-lite 1.13.0", - "log", - "parking", - "polling 2.8.0", - "rustix 0.37.27", - "slab", - "socket2", - "waker-fn", + "typenum", + "version_check", ] [[package]] -name = "async-io" -version = "2.3.2" +name = "getrandom" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "async-lock 3.3.0", "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite 2.3.0", - "parking", - "polling 3.7.0", - "rustix 0.38.34", - "slab", - "tracing", - "windows-sys 0.52.0", + "libc", + "wasi", ] [[package]] -name = "async-lock" -version = "2.8.0" +name = "half" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ - "event-listener 2.5.3", + "cfg-if", + "crunchy", + "num-traits", + "zerocopy", ] [[package]] -name = "async-lock" -version = "3.3.0" +name = "hashbrown" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "event-listener 4.0.3", - "event-listener-strategy 0.4.0", - "pin-project-lite", + "ahash", ] [[package]] -name = "async-process" -version = "1.8.1" +name = "itertools" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ - "async-io 1.13.0", - "async-lock 2.8.0", - "async-signal", - "blocking", - "cfg-if", - "event-listener 3.1.0", - "futures-lite 1.13.0", - "rustix 0.38.34", - "windows-sys 0.48.0", + "either", ] [[package]] -name = "async-recursion" -version = "1.1.1" +name = "itertools" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", + "either", ] [[package]] -name = "async-signal" -version = "0.2.6" +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afe66191c335039c7bb78f99dc7520b0cbb166b3a1cb33a03f53d8a1c6f2afda" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ - "async-io 2.3.2", - "async-lock 3.3.0", - "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix 0.38.34", - "signal-hook-registry", - "slab", - "windows-sys 0.52.0", + "either", ] [[package]] -name = "async-task" -version = "4.7.1" +name = "itoa" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] -name = "async-trait" -version = "0.1.80" +name = "kstring" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", + "serde", + "static_assertions", ] [[package]] -name = "atomic-waker" -version = "1.1.2" +name = "lazy_static" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] -name = "autocfg" -version = "1.3.0" +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "libm" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] -name = "backtrace" -version = "0.3.71" +name = "libredox" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ - "addr2line", - "cc", - "cfg-if", + "bitflags", "libc", - "miniz_oxide", - "object", - "rustc-demangle", + "redox_syscall", ] [[package]] -name = "bindgen" -version = "0.69.4" +name = "linux-raw-sys" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" -dependencies = [ - "bitflags 2.5.0", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.60", -] +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] -name = "bit-set" -version = "0.5.3" +name = "liquid" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +checksum = "2a494c3f9dad3cb7ed16f1c51812cbe4b29493d6c2e5cd1e2b87477263d9534d" dependencies = [ - "bit-vec", + "liquid-core", + "liquid-derive", + "liquid-lib", + "serde", ] [[package]] -name = "bit-vec" -version = "0.6.3" +name = "liquid-core" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +checksum = "fc623edee8a618b4543e8e8505584f4847a4e51b805db1af6d9af0a3395d0d57" +dependencies = [ + "anymap2", + "itertools 0.14.0", + "kstring", + "liquid-derive", + "pest", + "pest_derive", + "regex", + "serde", + "time", +] [[package]] -name = "bit_field" -version = "0.10.2" +name = "liquid-derive" +version = "0.26.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +checksum = "de66c928222984aea59fcaed8ba627f388aaac3c1f57dcb05cc25495ef8faefe" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] [[package]] -name = "bitflags" -version = "0.8.2" +name = "liquid-lib" +version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" +checksum = "9befeedd61f5995bc128c571db65300aeb50d62e4f0542c88282dbcb5f72372a" +dependencies = [ + "itertools 0.14.0", + "liquid-core", + "percent-encoding", + "regex", + "time", + "unicode-segmentation", +] [[package]] -name = "bitflags" -version = "1.3.2" +name = "lock_api" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] [[package]] -name = "bitflags" -version = "2.5.0" +name = "log" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] -name = "block" -version = "0.1.6" +name = "maplit" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] -name = "block-buffer" -version = "0.10.4" +name = "matrixmultiply" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" dependencies = [ - "generic-array", + "autocfg", + "rawpointer", ] [[package]] -name = "block-sys" -version = "0.1.0-beta.1" +name = "memchr" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa55741ee90902547802152aaf3f8e5248aab7e21468089560d4c8840561146" -dependencies = [ - "objc-sys", -] +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] -name = "block2" -version = "0.2.0-alpha.6" +name = "memmap2" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd9e63c1744f755c2f60332b88de39d341e5e86239014ad839bd71c106dec42" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" dependencies = [ - "block-sys", - "objc2-encode", + "libc", ] [[package]] -name = "blocking" -version = "1.6.0" +name = "miniz_oxide" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "495f7104e962b7356f0aeb34247aca1fe7d2e783b346582db7f2904cb5717e88" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "async-channel", - "async-lock 3.3.0", - "async-task", - "futures-io", - "futures-lite 2.3.0", - "piper", + "adler2", + "simd-adler32", ] [[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "by_address" -version = "1.2.1" +name = "ndarray" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" +checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" +dependencies = [ + "matrixmultiply", + "num-complex", + "num-integer", + "num-traits", + "portable-atomic", + "portable-atomic-util", + "rawpointer", +] [[package]] -name = "bytemuck" -version = "1.15.0" +name = "nom" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" dependencies = [ - "bytemuck_derive", + "memchr", ] [[package]] -name = "bytemuck_derive" -version = "1.6.0" +name = "nom-language" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" +checksum = "2de2bc5b451bfedaef92c90b8939a8fff5770bdcc1fafd6239d086aab8fa6b29" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", + "nom", ] [[package]] -name = "byteorder" -version = "1.5.0" +name = "num-complex" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", + "serde", +] [[package]] -name = "bytes" -version = "1.6.0" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] -name = "calloop" -version = "0.10.6" +name = "num-integer" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e0d00eb1ea24371a97d2da6201c6747a633dc6dc1988ef503403b4c59504a8" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "bitflags 1.3.2", - "log", - "nix 0.25.1", - "slotmap", - "thiserror", - "vec_map 0.8.2", + "num-traits", ] [[package]] -name = "calloop" -version = "0.12.4" +name = "num-traits" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "bitflags 2.5.0", - "log", - "polling 3.7.0", - "rustix 0.38.34", - "slab", - "thiserror", + "autocfg", + "libm", ] [[package]] -name = "calloop-wayland-source" -version = "0.2.0" +name = "once_cell" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" -dependencies = [ - "calloop 0.12.4", - "rustix 0.38.34", - "wayland-backend 0.3.3", - "wayland-client 0.31.2", -] +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] -name = "cc" -version = "1.0.96" +name = "ordered-multimap" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" +checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" dependencies = [ - "jobserver", - "libc", - "once_cell", + "dlv-list", + "hashbrown", ] [[package]] -name = "cesu8" -version = "1.1.0" +name = "parking_lot" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] [[package]] -name = "cexpr" -version = "0.6.0" +name = "parking_lot_core" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ - "nom", + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", ] [[package]] -name = "cfg-if" -version = "1.0.0" +name = "pastey" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" [[package]] -name = "cfg_aliases" -version = "0.1.1" +name = "percent-encoding" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] -name = "clang-sys" -version = "1.7.0" +name = "pest" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" dependencies = [ - "glob", - "libc", - "libloading 0.8.3", + "memchr", + "ucd-trie", ] [[package]] -name = "clap" -version = "4.5.4" +name = "pest_derive" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" dependencies = [ - "clap_builder", - "clap_derive", + "pest", + "pest_generator", ] [[package]] -name = "clap_builder" -version = "4.5.2" +name = "pest_generator" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.110", ] [[package]] -name = "clap_derive" -version = "4.5.4" +name = "pest_meta" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.60", + "pest", + "sha2", ] [[package]] -name = "clap_lex" -version = "0.7.0" +name = "portable-atomic" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] -name = "claxon" -version = "0.4.3" +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] -name = "clipboard-win" -version = "4.5.0" +name = "ppv-lite86" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "error-code", - "str-buf", - "winapi", + "zerocopy", ] [[package]] -name = "clipboard_macos" -version = "0.1.0" +name = "primal-check" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145a7f9e9b89453bc0a5e32d166456405d389cea5b578f57f1274b1397588a95" +checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08" dependencies = [ - "objc", - "objc-foundation", - "objc_id", + "num-integer", ] [[package]] -name = "clipboard_wayland" -version = "0.2.2" +name = "proc-macro2" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003f886bc4e2987729d10c1db3424e7f80809f3fc22dbc16c685738887cb37b8" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ - "smithay-clipboard", + "unicode-ident", ] [[package]] -name = "clipboard_x11" -version = "0.4.2" +name = "prost" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4274ea815e013e0f9f04a2633423e14194e408a0576c943ce3d14ca56c50031c" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ - "thiserror", - "x11rb 0.13.1", + "bytes", + "prost-derive", ] [[package]] -name = "cmake" -version = "0.1.50" +name = "prost-derive" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ - "cc", + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] -name = "cocoa" -version = "0.24.1" +name = "quote" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ - "bitflags 1.3.2", - "block", - "cocoa-foundation", - "core-foundation", - "core-graphics", - "foreign-types", - "libc", - "objc", + "proc-macro2", ] [[package]] -name = "cocoa-foundation" -version = "0.1.2" +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "bitflags 1.3.2", - "block", - "core-foundation", - "core-graphics-types", "libc", - "objc", + "rand_chacha", + "rand_core", ] [[package]] -name = "codespan-reporting" -version = "0.11.1" +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "termcolor", - "unicode-width", + "ppv-lite86", + "rand_core", ] [[package]] -name = "color_quant" -version = "1.1.0" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] [[package]] -name = "colorchoice" -version = "1.0.1" +name = "rand_distr" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +dependencies = [ + "num-traits", + "rand", +] [[package]] -name = "com-rs" +name = "rawpointer" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf43edc576402991846b093a7ca18a3477e0ef9c588cde84964b5d3e43016642" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] -name = "combine" -version = "4.6.7" +name = "realfft" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +checksum = "f821338fddb99d089116342c46e9f1fbf3828dba077674613e734e01d6ea8677" dependencies = [ - "bytes", - "memchr", + "rustfft", ] [[package]] -name = "concurrent-queue" -version = "2.5.0" +name = "redox_syscall" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "crossbeam-utils", + "bitflags", ] [[package]] -name = "console_error_panic_hook" -version = "0.1.7" +name = "regex" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ - "cfg-if", - "wasm-bindgen", + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", ] [[package]] -name = "const-random" -version = "0.1.18" +name = "regex-automata" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ - "const-random-macro", + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] -name = "const-random-macro" -version = "0.1.16" +name = "regex-syntax" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" -dependencies = [ - "getrandom", - "once_cell", - "tiny-keccak", -] +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] -name = "core-foundation" -version = "0.9.4" +name = "rust-ini" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "796e8d2b6696392a43bea58116b667fb4c29727dc5abd27d6acf338bb4f688c7" dependencies = [ - "core-foundation-sys", - "libc", + "cfg-if", + "ordered-multimap", ] [[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - -[[package]] -name = "core-graphics" -version = "0.22.3" +name = "rustfft" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +checksum = "21db5f9893e91f41798c88680037dba611ca6674703c1a18601b01a72c8adb89" dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types", - "libc", + "num-complex", + "num-integer", + "num-traits", + "primal-check", + "strength_reduce", + "transpose", ] [[package]] -name = "core-graphics-types" -version = "0.1.3" +name = "rustix" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 1.3.2", - "core-foundation", + "bitflags", + "errno", "libc", + "linux-raw-sys", + "windows-sys 0.61.2", ] [[package]] -name = "coreaudio-rs" -version = "0.11.3" +name = "ryu" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" -dependencies = [ - "bitflags 1.3.2", - "core-foundation-sys", - "coreaudio-sys", -] +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] -name = "coreaudio-sys" -version = "0.2.15" +name = "safetensors" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f01585027057ff5f0a5bf276174ae4c1594a2c5bde93d5f46a016d76270f5a9" +checksum = "172dd94c5a87b5c79f945c863da53b2ebc7ccef4eca24ac63cca66a41aab2178" dependencies = [ - "bindgen", + "serde", + "serde_json", ] [[package]] -name = "cosmic-text" -version = "0.9.0" +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b68966c2543609f8d92f9d33ac3b719b2a67529b0c6c0b3e025637b477eef9" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "aliasable", - "fontdb", - "libm", - "log", - "rangemap", - "rustybuzz", - "swash", - "sys-locale", - "unicode-bidi", - "unicode-linebreak", - "unicode-script", - "unicode-segmentation", + "winapi-util", ] [[package]] -name = "cpal" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" -dependencies = [ - "alsa", - "core-foundation-sys", - "coreaudio-rs", - "dasp_sample", - "jni", - "js-sys", - "libc", - "mach2", - "ndk 0.8.0", - "ndk-context", - "oboe", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows 0.54.0", -] - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "ctrlc" -version = "3.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" -dependencies = [ - "nix 0.28.0", - "windows-sys 0.52.0", -] - -[[package]] -name = "cursor-icon" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" - -[[package]] -name = "d3d12" -version = "0.6.0" +name = "scan_fmt" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8f0de2f5a8e7bd4a9eec0e3c781992a4ce1724f68aec7d7a3715344de8b39da" +checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248" dependencies = [ - "bitflags 1.3.2", - "libloading 0.7.4", - "winapi", + "regex", ] [[package]] -name = "dasp_sample" -version = "0.11.0" +name = "scopeguard" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" - -[[package]] -name = "deep-filter-ladspa" -version = "0.5.7-pre" -dependencies = [ - "deep_filter", - "env_logger 0.10.2", - "event-listener 2.5.3", - "ladspa", - "log", - "ndarray", - "uuid", - "zbus", -] - -[[package]] -name = "deep_filter" -version = "0.5.7-pre" -dependencies = [ - "anyhow", - "clap", - "claxon", - "console_error_panic_hook", - "crossbeam-channel", - "ctrlc", - "env_logger 0.11.3", - "flate2", - "getrandom", - "hdf5", - "hound", - "itertools 0.12.1", - "jemallocator", - "js-sys", - "lewton", - "log", - "ndarray", - "ndarray-rand", - "num-complex", - "ogg", - "rand", - "rand_xoshiro", - "rayon", - "realfft", - "roots", - "rstest", - "rubato", - "rust-ini", - "rustfft", - "serde", - "serde_json", - "tar", - "thiserror", - "tract-core", - "tract-hir", - "tract-onnx", - "tract-pulse", - "wasm-bindgen", -] +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "deranged" -version = "0.3.11" +name = "serde" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ - "powerfmt", + "serde_core", + "serde_derive", ] [[package]] -name = "derivative" -version = "2.2.0" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "serde_derive", ] [[package]] -name = "derive-new" -version = "0.5.9" +name = "serde_derive" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", -] - -[[package]] -name = "df-demo" -version = "0.5.7-pre" -dependencies = [ - "anyhow", - "clap", - "cpal", - "crossbeam-channel", - "deep_filter", - "env_logger 0.10.2", - "iced", - "image", - "itertools 0.11.0", - "log", - "ndarray", - "ringbuf", - "rubato", + "syn 2.0.110", ] [[package]] -name = "digest" -version = "0.10.7" +name = "serde_json" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ - "block-buffer", - "crypto-common", + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", ] [[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dlib" -version = "0.5.2" +name = "sha2" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "libloading 0.8.3", + "cfg-if", + "cpufeatures", + "digest", ] [[package]] -name = "dlv-list" -version = "0.5.2" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" -dependencies = [ - "const-random", -] +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "doc-comment" -version = "0.3.3" +name = "simd-adler32" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] -name = "downcast-rs" -version = "1.2.1" +name = "smallvec" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] -name = "dyn-clone" -version = "1.0.17" +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "either" -version = "1.11.0" +name = "strength_reduce" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" [[package]] -name = "enumflags2" -version = "0.7.9" +name = "string-interner" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d" +checksum = "07f9fdfdd31a0ff38b59deb401be81b73913d76c9cc5b1aed4e1330a223420b9" dependencies = [ - "enumflags2_derive", + "cfg-if", + "hashbrown", "serde", ] [[package]] -name = "enumflags2_derive" -version = "0.7.9" +name = "syn" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", -] - -[[package]] -name = "env_filter" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "env_logger" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "humantime", - "log", + "unicode-ident", ] [[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.8" +name = "syn" +version = "2.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" dependencies = [ - "libc", - "windows-sys 0.52.0", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] -name = "error-code" -version = "2.3.1" +name = "tar" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" +checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" dependencies = [ + "filetime", "libc", - "str-buf", -] - -[[package]] -name = "etagere" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306960881d6c46bd0dd6b7f07442a441418c08d0d3e63d8d080b0f64c6343e4e" -dependencies = [ - "euclid", - "svg_fmt", -] - -[[package]] -name = "euclid" -version = "0.22.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f253bc5c813ca05792837a0ff4b3a580336b224512d48f7eda1d7dd9210787" -dependencies = [ - "num-traits", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "event-listener" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener 4.0.3", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" -dependencies = [ - "event-listener 5.3.0", - "pin-project-lite", + "xattr", ] [[package]] -name = "exr" -version = "1.72.0" +name = "time" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ - "bit_field", - "flume", - "half", - "lebe", - "miniz_oxide", - "rayon-core", - "smallvec", - "zune-inflate", -] - -[[package]] -name = "fast-srgb8" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - -[[package]] -name = "fdeflate" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "filetime" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", -] - -[[package]] -name = "flate2" -version = "1.0.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "flume" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" -dependencies = [ - "spin", -] - -[[package]] -name = "font-types" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf6aa1de86490d8e39e04589bd04eb5953cc2a5ef0c25e389e807f44fd24e41" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "fontdb" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af8d8cbea8f21307d7e84bca254772981296f058a1d36b461bf4d83a7499fc9e" -dependencies = [ - "log", - "memmap2 0.6.2", - "slotmap", - "tinyvec", - "ttf-parser 0.19.2", -] - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", - "num_cpus", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-lite" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" -dependencies = [ - "fastrand 2.1.0", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "gethostname" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "gethostname" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" -dependencies = [ - "libc", - "windows-targets 0.48.5", -] - -[[package]] -name = "getrandom" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "gif" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" -dependencies = [ - "color_quant", - "weezl", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "glam" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "glow" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0fe580e4b60a8ab24a868bc08e2f03cbcb20d3d676601fa909386713333728" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glyphon" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e87caa7459145f5e5f167bf34db4532901404c679e62339fb712a0e3ccf722a" -dependencies = [ - "cosmic-text", - "etagere", - "lru", - "wgpu", -] - -[[package]] -name = "gpu-alloc" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22beaafc29b38204457ea030f6fb7a84c9e4dd1b86e311ba0542533453d87f62" -dependencies = [ - "bitflags 1.3.2", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "gpu-allocator" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce95f9e2e11c2c6fadfce42b5af60005db06576f231f5c92550fdded43c423e8" -dependencies = [ - "backtrace", - "log", - "thiserror", - "winapi", - "windows 0.44.0", -] - -[[package]] -name = "gpu-descriptor" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c" -dependencies = [ - "bitflags 2.5.0", - "gpu-descriptor-types", - "hashbrown 0.14.5", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c" -dependencies = [ - "bitflags 2.5.0", -] - -[[package]] -name = "guillotiere" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" -dependencies = [ - "euclid", - "svg_fmt", -] - -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if", - "crunchy", - "num-traits", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] - -[[package]] -name = "hassle-rs" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1397650ee315e8891a0df210707f0fc61771b0cc518c3023896064c5407cb3b0" -dependencies = [ - "bitflags 1.3.2", - "com-rs", - "libc", - "libloading 0.7.4", - "thiserror", - "widestring", - "winapi", -] - -[[package]] -name = "hdf5" -version = "0.8.1" -source = "git+https://github.com/aldanor/hdf5-rust.git?rev=26046fb#26046fb4900ec38afd2a1c0494cff688b288662e" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "hdf5-derive", - "hdf5-sys", - "hdf5-types", - "lazy_static", - "libc", - "ndarray", - "parking_lot 0.12.2", - "paste", -] - -[[package]] -name = "hdf5-derive" -version = "0.8.1" -source = "git+https://github.com/aldanor/hdf5-rust.git?rev=26046fb#26046fb4900ec38afd2a1c0494cff688b288662e" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "hdf5-src" -version = "0.8.1" -source = "git+https://github.com/aldanor/hdf5-rust.git?rev=26046fb#26046fb4900ec38afd2a1c0494cff688b288662e" -dependencies = [ - "cmake", -] - -[[package]] -name = "hdf5-sys" -version = "0.8.1" -source = "git+https://github.com/aldanor/hdf5-rust.git?rev=26046fb#26046fb4900ec38afd2a1c0494cff688b288662e" -dependencies = [ - "hdf5-src", - "libc", - "libloading 0.8.3", - "pkg-config", - "regex", - "serde", - "serde_derive", - "winreg", -] - -[[package]] -name = "hdf5-types" -version = "0.8.1" -source = "git+https://github.com/aldanor/hdf5-rust.git?rev=26046fb#26046fb4900ec38afd2a1c0494cff688b288662e" -dependencies = [ - "ascii", - "cfg-if", - "hdf5-sys", - "libc", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[package]] -name = "hound" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "iced" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c708807ec86f99dd729dc4d42db5239acf118cec14d3c5f57679dcfdbbc472b1" -dependencies = [ - "iced_core", - "iced_futures", - "iced_renderer", - "iced_widget", - "iced_winit", - "image", - "thiserror", -] - -[[package]] -name = "iced_core" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d0bc4fbf018576d08d93f838e6058cc6f10bbc05e04ae249a2a44dffb4ebc8" -dependencies = [ - "bitflags 1.3.2", - "instant", - "log", - "palette", - "thiserror", - "twox-hash", -] - -[[package]] -name = "iced_futures" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dab0054a9c7a1cbce227a8cd9ee4a094497b3d06094551ac6c1488d563802e" -dependencies = [ - "futures", - "iced_core", - "log", - "tokio", - "wasm-bindgen-futures", - "wasm-timer", -] - -[[package]] -name = "iced_graphics" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ff14447a221e9e9205a13d84d7bbdf0636a3b1daa02cfca690ed09689c4d2b" -dependencies = [ - "bitflags 1.3.2", - "bytemuck", - "glam", - "half", - "iced_core", - "image", - "kamadak-exif", - "log", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "iced_renderer" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1033385b0db0099a0d13178c9ff93c1ce11e7d0177522acf578bf79febdb2af8" -dependencies = [ - "iced_graphics", - "iced_tiny_skia", - "iced_wgpu", - "log", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "iced_runtime" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c6c89853e1250c6fac82c5015fa2144517be9b33d4b8e456f10e198b23e28bd" -dependencies = [ - "iced_core", - "iced_futures", - "thiserror", -] - -[[package]] -name = "iced_style" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d85c47d9d13e2281f75ddf98c865daf2101632bd2b855c401dd0b1c8b81a31a0" -dependencies = [ - "iced_core", - "once_cell", - "palette", -] - -[[package]] -name = "iced_tiny_skia" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7715f6222c9470bbbd75a39f70478fa0d1bdfb81a377a34fd1b090ffccc480b" -dependencies = [ - "bytemuck", - "cosmic-text", - "iced_graphics", - "kurbo", - "log", - "raw-window-handle", - "rustc-hash", - "softbuffer", - "tiny-skia 0.10.0", - "twox-hash", -] - -[[package]] -name = "iced_wgpu" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f7c5de46b997ed7b18e05ec67059dcdf3beeac51e917c21071b021bb848b9" -dependencies = [ - "bitflags 1.3.2", - "bytemuck", - "futures", - "glam", - "glyphon", - "guillotiere", - "iced_graphics", - "log", - "once_cell", - "raw-window-handle", - "rustc-hash", - "twox-hash", - "wgpu", -] - -[[package]] -name = "iced_widget" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a177219ae51c3ba08f228ab932354b360cc669e94aec50c01e7c9b675f074c7c" -dependencies = [ - "iced_renderer", - "iced_runtime", - "iced_style", - "num-traits", - "ouroboros", - "thiserror", - "unicode-segmentation", -] - -[[package]] -name = "iced_winit" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0c884bcb14722a57192b40a5ef6b5e170fa2f01fe2ff28d6cdd9efe37acf70" -dependencies = [ - "iced_graphics", - "iced_runtime", - "iced_style", - "log", - "raw-window-handle", - "thiserror", - "web-sys", - "winapi", - "window_clipboard", - "winit", -] - -[[package]] -name = "image" -version = "0.24.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "exr", - "gif", - "jpeg-decoder", - "num-traits", - "png", - "qoi", - "tiff", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" -dependencies = [ - "equivalent", - "hashbrown 0.14.5", -] - -[[package]] -name = "indoc" -version = "2.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "is-terminal" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "jemalloc-sys" -version = "0.5.4+5.3.0-patched" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac6c1946e1cea1788cbfde01c993b52a10e2da07f4bac608228d1bed20bfebf2" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "jemallocator" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0de374a9f8e63150e6f5e8a60cc14c668226d7a347d8aee1a45766e3c4dd3bc" -dependencies = [ - "jemalloc-sys", - "libc", -] - -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" -dependencies = [ - "libc", -] - -[[package]] -name = "jpeg-decoder" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" -dependencies = [ - "rayon", -] - -[[package]] -name = "js-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "kamadak-exif" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4fc70d0ab7e5b6bafa30216a6b48705ea964cdfc29c050f2412295eba58077" -dependencies = [ - "mutate_once", -] - -[[package]] -name = "khronos-egl" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" -dependencies = [ - "libc", - "libloading 0.7.4", - "pkg-config", -] - -[[package]] -name = "kstring" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747" -dependencies = [ - "serde", - "static_assertions", -] - -[[package]] -name = "kurbo" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd85a5776cd9500c2e2059c8c76c3b01528566b7fcbaf8098b55a33fc298849b" -dependencies = [ - "arrayvec", -] - -[[package]] -name = "ladspa" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6197e2fb8a3da99eca216e9689b47465b23cfe09e1a1ddc720fa1acdd54aa267" -dependencies = [ - "bitflags 0.8.2", - "libc", - "vec_map 0.7.0", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lebe" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" - -[[package]] -name = "lewton" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] - -[[package]] -name = "libc" -version = "0.2.154" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" - -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - -[[package]] -name = "libloading" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" -dependencies = [ - "cfg-if", - "windows-targets 0.52.5", -] - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "libredox" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" -dependencies = [ - "bitflags 2.5.0", - "libc", - "redox_syscall 0.4.1", -] - -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" - -[[package]] -name = "liquid" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f68ae1011499ae2ef879f631891f21c78e309755f4a5e483c4a8f12e10b609" -dependencies = [ - "doc-comment", - "liquid-core", - "liquid-derive", - "liquid-lib", - "serde", -] - -[[package]] -name = "liquid-core" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e0724dfcaad5cfb7965ea0f178ca0870b8d7315178f4a7179f5696f7f04d5f" -dependencies = [ - "anymap2", - "itertools 0.10.5", - "kstring", - "liquid-derive", - "num-traits", - "pest", - "pest_derive", - "regex", - "serde", - "time", -] - -[[package]] -name = "liquid-derive" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2fb41a9bb4257a3803154bdf7e2df7d45197d1941c9b1a90ad815231630721" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "liquid-lib" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2a17e273a6fb1fb6268f7a5867ddfd0bd4683c7e19b51084f3d567fad4348c0" -dependencies = [ - "itertools 0.10.5", - "liquid-core", - "once_cell", - "percent-encoding", - "regex", - "time", - "unicode-segmentation", -] - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" - -[[package]] -name = "lru" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a83fb7698b3643a0e34f9ae6f2e8f0178c0fd42f8b59d493aa271ff3a5bf21" -dependencies = [ - "hashbrown 0.14.5", -] - -[[package]] -name = "mach2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" -dependencies = [ - "libc", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - -[[package]] -name = "matrixmultiply" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2" -dependencies = [ - "autocfg", - "rawpointer", -] - -[[package]] -name = "memchr" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[package]] -name = "memmap2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] - -[[package]] -name = "memmap2" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d28bba84adfe6646737845bc5ebbfa2c08424eb1c37e94a1fd2a82adb56a872" -dependencies = [ - "libc", -] - -[[package]] -name = "memmap2" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[package]] -name = "metal" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de11355d1f6781482d027a3b4d4de7825dcedb197bf573e0596d00008402d060" -dependencies = [ - "bitflags 1.3.2", - "block", - "core-graphics-types", - "foreign-types", - "log", - "objc", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" -dependencies = [ - "adler", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "mutate_once" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16cf681a23b4d0a43fc35024c176437f9dcd818db34e0f42ab456a0ee5ad497b" - -[[package]] -name = "naga" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbcc2e0513220fd2b598e6068608d4462db20322c0e77e47f6f488dfcfc279cb" -dependencies = [ - "bit-set", - "bitflags 1.3.2", - "codespan-reporting", - "hexf-parse", - "indexmap 1.9.3", - "log", - "num-traits", - "rustc-hash", - "spirv", - "termcolor", - "thiserror", - "unicode-xid", -] - -[[package]] -name = "ndarray" -version = "0.15.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32" -dependencies = [ - "matrixmultiply", - "num-complex", - "num-integer", - "num-traits", - "rawpointer", - "serde", -] - -[[package]] -name = "ndarray-rand" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65608f937acc725f5b164dcf40f4f0bc5d67dc268ab8a649d3002606718c4588" -dependencies = [ - "ndarray", - "rand", - "rand_distr", -] - -[[package]] -name = "ndk" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" -dependencies = [ - "bitflags 1.3.2", - "jni-sys", - "ndk-sys 0.4.1+23.1.7779620", - "num_enum 0.5.11", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "ndk" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" -dependencies = [ - "bitflags 2.5.0", - "jni-sys", - "log", - "ndk-sys 0.5.0+25.2.9519653", - "num_enum 0.7.2", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.4.1+23.1.7779620" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "ndk-sys" -version = "0.5.0+25.2.9519653" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.6.5", -] - -[[package]] -name = "nix" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.6.5", -] - -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.7.1", - "pin-utils", -] - -[[package]] -name = "nix" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num-complex" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" -dependencies = [ - "num-traits", - "serde", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" -dependencies = [ - "num_enum_derive 0.5.11", -] - -[[package]] -name = "num_enum" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" -dependencies = [ - "num_enum_derive 0.6.1", -] - -[[package]] -name = "num_enum" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" -dependencies = [ - "num_enum_derive 0.7.2", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num_enum_derive" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" -dependencies = [ - "proc-macro-crate 3.1.0", - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "numpy" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef41cbb417ea83b30525259e30ccef6af39b31c240bda578889494c5392d331" -dependencies = [ - "libc", - "ndarray", - "num-complex", - "num-integer", - "num-traits", - "pyo3", - "rustc-hash", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - -[[package]] -name = "objc-sys" -version = "0.2.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7" - -[[package]] -name = "objc2" -version = "0.3.0-beta.3.patch-leaks.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e01640f9f2cb1220bbe80325e179e532cb3379ebcd1bf2279d703c19fe3a468" -dependencies = [ - "block2", - "objc-sys", - "objc2-encode", -] - -[[package]] -name = "objc2-encode" -version = "2.0.0-pre.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" -dependencies = [ - "objc-sys", -] - -[[package]] -name = "objc_exception" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", -] - -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - -[[package]] -name = "object" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -dependencies = [ - "memchr", -] - -[[package]] -name = "oboe" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" -dependencies = [ - "jni", - "ndk 0.8.0", - "ndk-context", - "num-derive", - "num-traits", - "oboe-sys", -] - -[[package]] -name = "oboe-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" -dependencies = [ - "cc", -] - -[[package]] -name = "ogg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" -dependencies = [ - "byteorder", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "orbclient" -version = "0.3.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" -dependencies = [ - "libredox", -] - -[[package]] -name = "ordered-multimap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" -dependencies = [ - "dlv-list", - "hashbrown 0.14.5", -] - -[[package]] -name = "ordered-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" -dependencies = [ - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "ouroboros" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2ba07320d39dfea882faa70554b4bd342a5f273ed59ba7c1c6b4c840492c954" -dependencies = [ - "aliasable", - "ouroboros_macro", - "static_assertions", -] - -[[package]] -name = "ouroboros_macro" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec4c6225c69b4ca778c0aea097321a64c421cf4577b331c61b229267edabb6f8" -dependencies = [ - "heck 0.4.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "owned_ttf_parser" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4586edfe4c648c71797a74c84bacb32b52b212eff5dfe2bb9f2c599844023e7" -dependencies = [ - "ttf-parser 0.20.0", -] - -[[package]] -name = "palette" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" -dependencies = [ - "approx", - "fast-srgb8", - "palette_derive", - "phf", -] - -[[package]] -name = "palette_derive" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" -dependencies = [ - "by_address", - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.10", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.5.1", - "smallvec", - "windows-targets 0.52.5", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pest" -version = "2.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "pest_meta" -version = "2.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" -dependencies = [ - "once_cell", - "pest", - "sha2", -] - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "piper" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" -dependencies = [ - "atomic-waker", - "fastrand 2.1.0", - "futures-io", -] - -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "png" -version = "0.17.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] - -[[package]] -name = "polling" -version = "3.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645493cf344456ef24219d02a768cf1fb92ddf8c92161679ae3d91b91a637be3" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi", - "pin-project-lite", - "rustix 0.38.34", - "tracing", - "windows-sys 0.52.0", -] - -[[package]] -name = "portable-atomic" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "primal-check" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9df7f93fd637f083201473dab4fee2db4c429d32e55e3299980ab3957ab916a0" -dependencies = [ - "num-integer", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-crate" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" -dependencies = [ - "toml_edit 0.21.1", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.81" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "profiling" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" - -[[package]] -name = "prost" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-derive" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" -dependencies = [ - "anyhow", - "itertools 0.10.5", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "pyo3" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53bdbb96d49157e65d45cc287af5f32ffadd5f4761438b527b055fb0d4bb8233" -dependencies = [ - "cfg-if", - "indoc", - "libc", - "memoffset 0.9.1", - "parking_lot 0.12.2", - "portable-atomic", - "pyo3-build-config", - "pyo3-ffi", - "pyo3-macros", - "unindent", -] - -[[package]] -name = "pyo3-build-config" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deaa5745de3f5231ce10517a1f5dd97d53e5a2fd77aa6b5842292085831d48d7" -dependencies = [ - "once_cell", - "target-lexicon", -] - -[[package]] -name = "pyo3-ffi" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b42531d03e08d4ef1f6e85a2ed422eb678b8cd62b762e53891c05faf0d4afa" -dependencies = [ - "libc", - "pyo3-build-config", -] - -[[package]] -name = "pyo3-macros" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7305c720fa01b8055ec95e484a6eca7a83c841267f0dd5280f0c8b8551d2c158" -dependencies = [ - "proc-macro2", - "pyo3-macros-backend", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "pyo3-macros-backend" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c7e9b68bb9c3149c5b0cade5d07f953d6d125eb4337723c4ccdb665f1f96185" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "pyo3-build-config", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "qoi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "quick-xml" -version = "0.28.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" -dependencies = [ - "memchr", -] - -[[package]] -name = "quick-xml" -version = "0.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" -dependencies = [ - "memchr", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_distr" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" -dependencies = [ - "num-traits", - "rand", -] - -[[package]] -name = "rand_xoshiro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" -dependencies = [ - "rand_core", -] - -[[package]] -name = "range-alloc" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" - -[[package]] -name = "rangemap" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684" - -[[package]] -name = "raw-window-handle" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" - -[[package]] -name = "rawpointer" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "read-fonts" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4749db2bd1c853db31a7ae5ee2fc6c30bbddce353ea8fedf673fed187c68c7" -dependencies = [ - "bytemuck", - "font-types", -] - -[[package]] -name = "realfft" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953d9f7e5cdd80963547b456251296efc2626ed4e3cbf36c869d9564e0220571" -dependencies = [ - "rustfft", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" -dependencies = [ - "bitflags 2.5.0", -] - -[[package]] -name = "regex" -version = "1.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" - -[[package]] -name = "relative-path" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" - -[[package]] -name = "renderdoc-sys" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" - -[[package]] -name = "ringbuf" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79abed428d1fd2a128201cec72c5f6938e2da607c6f3745f769fabea399d950a" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "roots" -version = "0.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c36d2bbc763f480668d6d6790ae2fdd2e52ac0c21a3a26d156f3534a3d9eea9" - -[[package]] -name = "rstest" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5316d2a1479eeef1ea21e7f9ddc67c191d497abc8fc3ba2467857abbb68330" -dependencies = [ - "futures", - "futures-timer", - "rstest_macros", - "rustc_version", -] - -[[package]] -name = "rstest_macros" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04a9df72cc1f67020b0d63ad9bfe4a323e459ea7eb68e03bd9824db49f9a4c25" -dependencies = [ - "cfg-if", - "glob", - "proc-macro2", - "quote", - "regex", - "relative-path", - "rustc_version", - "syn 2.0.60", - "unicode-ident", -] - -[[package]] -name = "rubato" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6dd52e80cfc21894deadf554a5673002938ae4625f7a283e536f9cf7c17b0d5" -dependencies = [ - "num-complex", - "num-integer", - "num-traits", - "realfft", -] - -[[package]] -name = "rust-ini" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d625ed57d8f49af6cfa514c42e1a71fadcff60eb0b1c517ff82fe41aa025b41" -dependencies = [ - "cfg-if", - "ordered-multimap", - "trim-in-place", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "rustfft" -version = "6.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43806561bc506d0c5d160643ad742e3161049ac01027b5e6d7524091fd401d86" -dependencies = [ - "num-complex", - "num-integer", - "num-traits", - "primal-check", - "strength_reduce", - "transpose", - "version_check", -] - -[[package]] -name = "rustix" -version = "0.37.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags 2.5.0", - "errno", - "libc", - "linux-raw-sys 0.4.13", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustybuzz" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82eea22c8f56965eeaf3a209b3d24508256c7b920fb3b6211b8ba0f7c0583250" -dependencies = [ - "bitflags 1.3.2", - "bytemuck", - "libm", - "smallvec", - "ttf-parser 0.19.2", - "unicode-bidi-mirroring", - "unicode-ccc", - "unicode-general-category", - "unicode-script", -] - -[[package]] -name = "ryu" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scan_fmt" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248" -dependencies = [ - "regex", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sctk-adwaita" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda4e97be1fd174ccc2aae81c8b694e803fa99b34e8fd0f057a9d70698e3ed09" -dependencies = [ - "ab_glyph", - "log", - "memmap2 0.5.10", - "smithay-client-toolkit 0.16.1", - "tiny-skia 0.8.4", -] - -[[package]] -name = "semver" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" - -[[package]] -name = "serde" -version = "1.0.200" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.200" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "serde_json" -version = "1.0.116" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_repr" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "slotmap" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" -dependencies = [ - "version_check", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "smithay-client-toolkit" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870427e30b8f2cbe64bf43ec4b86e88fe39b0a84b3f15efd9c9c2d020bc86eb9" -dependencies = [ - "bitflags 1.3.2", - "calloop 0.10.6", - "dlib", - "lazy_static", - "log", - "memmap2 0.5.10", - "nix 0.24.3", - "pkg-config", - "wayland-client 0.29.5", - "wayland-cursor 0.29.5", - "wayland-protocols 0.29.5", -] - -[[package]] -name = "smithay-client-toolkit" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" -dependencies = [ - "bitflags 2.5.0", - "calloop 0.12.4", - "calloop-wayland-source", - "cursor-icon", - "libc", - "log", - "memmap2 0.9.4", - "rustix 0.38.34", - "thiserror", - "wayland-backend 0.3.3", - "wayland-client 0.31.2", - "wayland-csd-frame", - "wayland-cursor 0.31.1", - "wayland-protocols 0.31.2", - "wayland-protocols-wlr", - "wayland-scanner 0.31.1", - "xkeysym", -] - -[[package]] -name = "smithay-clipboard" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c091e7354ea8059d6ad99eace06dd13ddeedbb0ac72d40a9a6e7ff790525882d" -dependencies = [ - "libc", - "smithay-client-toolkit 0.18.1", - "wayland-backend 0.3.3", -] - -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "softbuffer" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2b953f6ba7285f0af131eb748aabd8ddaf53e0b81dda3ba5d803b0847d6559f" -dependencies = [ - "bytemuck", - "cfg_aliases", - "cocoa", - "core-graphics", - "fastrand 1.9.0", - "foreign-types", - "log", - "nix 0.26.4", - "objc", - "raw-window-handle", - "redox_syscall 0.3.5", - "thiserror", - "wasm-bindgen", - "wayland-backend 0.1.2", - "wayland-client 0.30.2", - "wayland-sys 0.30.1", - "web-sys", - "windows-sys 0.48.0", - "x11-dl", - "x11rb 0.11.1", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - -[[package]] -name = "spirv" -version = "0.2.0+1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" -dependencies = [ - "bitflags 1.3.2", - "num-traits", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "str-buf" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" - -[[package]] -name = "strength_reduce" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" - -[[package]] -name = "strict-num" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" - -[[package]] -name = "string-interner" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07f9fdfdd31a0ff38b59deb401be81b73913d76c9cc5b1aed4e1330a223420b9" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "serde", -] - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "svg_fmt" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83ba502a3265efb76efb89b0a2f7782ad6f2675015d4ce37e4b547dda42b499" - -[[package]] -name = "swash" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ec889a8e0a6fcb91041996c8f1f6be0fe1a09e94478785e07c32ce2bca2d2b" -dependencies = [ - "read-fonts", - "yazi", - "zeno", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sys-locale" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0" -dependencies = [ - "libc", -] - -[[package]] -name = "tar" -version = "0.4.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" -dependencies = [ - "filetime", - "libc", - "xattr", -] - -[[package]] -name = "target-lexicon" -version = "0.12.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" - -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand 2.1.0", - "rustix 0.38.34", - "windows-sys 0.52.0", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.59" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.59" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "tiff" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tiny-skia" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8493a203431061e901613751931f047d1971337153f96d0e5e363d6dbf6a67" -dependencies = [ - "arrayref", - "arrayvec", - "bytemuck", - "cfg-if", - "png", - "tiny-skia-path 0.8.4", -] - -[[package]] -name = "tiny-skia" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db11798945fa5c3e5490c794ccca7c6de86d3afdd54b4eb324109939c6f37bc" -dependencies = [ - "arrayref", - "arrayvec", - "bytemuck", - "cfg-if", - "log", - "png", - "tiny-skia-path 0.10.0", -] - -[[package]] -name = "tiny-skia-path" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adbfb5d3f3dd57a0e11d12f4f13d4ebbbc1b5c15b7ab0a156d030b21da5f677c" -dependencies = [ - "arrayref", - "bytemuck", - "strict-num", -] - -[[package]] -name = "tiny-skia-path" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f60aa35c89ac2687ace1a2556eaaea68e8c0d47408a2e3e7f5c98a489e7281c" -dependencies = [ - "arrayref", - "bytemuck", - "strict-num", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" -dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", -] - -[[package]] -name = "toml_datetime" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" - -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow", -] - -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.2.6", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "tract-core" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ef3e1f2d94e88d007811e78a3dcc9e5734bfd841849416fab09a407488cb7d" -dependencies = [ - "anyhow", - "bit-set", - "derive-new", - "downcast-rs", - "dyn-clone", - "lazy_static", - "log", - "maplit", - "ndarray", - "num-complex", - "num-integer", - "num-traits", - "paste", - "rustfft", - "smallvec", - "tract-data", - "tract-linalg", -] - -[[package]] -name = "tract-data" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "580103fb6de703d9bff3d64cfe76c26d454cbcb4b84716d3f2936e36c8a88d67" -dependencies = [ - "anyhow", - "half", - "itertools 0.12.1", - "lazy_static", - "maplit", - "ndarray", - "nom", - "num-integer", - "num-traits", - "scan_fmt", - "smallvec", - "string-interner", -] - -[[package]] -name = "tract-hir" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14a1deb233efc188da3617e66160202ef08247f91f6e12a39940dcb74b5a6af3" -dependencies = [ - "derive-new", - "log", - "tract-core", -] - -[[package]] -name = "tract-linalg" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58f074c94c74ea736a75b7ac6f696add05c62fc4745d1c420cf7d4d42eb7b2b" -dependencies = [ - "cc", - "derive-new", - "downcast-rs", - "dyn-clone", - "half", - "lazy_static", - "liquid", - "liquid-core", - "log", - "num-traits", - "paste", - "scan_fmt", - "smallvec", - "time", - "tract-data", - "unicode-normalization", - "walkdir", -] - -[[package]] -name = "tract-nnef" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630653ba2da4e55bddf1e7fad9d4e128dcb87200de621d12dc9a48a81bdaedd8" -dependencies = [ - "byteorder", - "flate2", - "log", - "nom", - "tar", - "tract-core", - "walkdir", -] - -[[package]] -name = "tract-onnx" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb5d5898db7dd7d7051d50365aebcb48b075d6f8bb17ce1f9e75e6e452aed2a" -dependencies = [ - "bytes", - "derive-new", - "log", - "memmap2 0.9.4", - "num-integer", - "prost", - "smallvec", - "tract-hir", - "tract-nnef", - "tract-onnx-opl", -] - -[[package]] -name = "tract-onnx-opl" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "620e3c0036ad846d62cc44c3b430ba0e1a22afe9d1abf0cc7f0e4caa3e232186" -dependencies = [ - "getrandom", - "log", - "rand", - "rand_distr", - "rustfft", - "tract-nnef", -] - -[[package]] -name = "tract-pulse" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dcd04336e207e760ce1a47f152664f34c14f3a9ead3af7c16ea2d9d520cf8ac" -dependencies = [ - "downcast-rs", - "lazy_static", - "log", - "tract-pulse-opl", -] - -[[package]] -name = "tract-pulse-opl" -version = "0.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acc42aebbb6ae3300e2435c3ff67f1520636f1b9196644d0f92edcd8b94c88bc" -dependencies = [ - "downcast-rs", - "lazy_static", - "tract-nnef", -] - -[[package]] -name = "transpose" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" -dependencies = [ - "num-integer", - "strength_reduce", -] - -[[package]] -name = "trim-in-place" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc" - -[[package]] -name = "ttf-parser" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49d64318d8311fc2668e48b63969f4343e0a85c4a109aa8460d6672e364b8bd1" - -[[package]] -name = "ttf-parser" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" - -[[package]] -name = "twox-hash" -version = "1.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" -dependencies = [ - "cfg-if", - "rand", - "static_assertions", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - -[[package]] -name = "uds_windows" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" -dependencies = [ - "memoffset 0.9.1", - "tempfile", - "winapi", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] -name = "unicode-bidi-mirroring" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56d12260fb92d52f9008be7e4bca09f584780eb2266dc8fecc6a192bec561694" - -[[package]] -name = "unicode-ccc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2520efa644f8268dce4dcd3050eaa7fc044fca03961e9998ac7e2e92b77cf1" - -[[package]] -name = "unicode-general-category" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2281c8c1d221438e373249e065ca4989c4c36952c211ff21a0ee91c44a3869e7" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-linebreak" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-script" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8d71f5726e5f285a935e9fe8edfd53f0491eb6e9a5774097fdabee7cd8c9cd" - -[[package]] -name = "unicode-segmentation" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" - -[[package]] -name = "unicode-width" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "unindent" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "uuid" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" -dependencies = [ - "getrandom", - "rand", -] - -[[package]] -name = "vec_map" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cdc8b93bd0198ed872357fb2e667f7125646b1762f16d60b2c96350d361897" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "waker-fn" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.60", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" - -[[package]] -name = "wasm-timer" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" -dependencies = [ - "futures", - "js-sys", - "parking_lot 0.11.2", - "pin-utils", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wayland-backend" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41b48e27457e8da3b2260ac60d0a94512f5cba36448679f3747c0865b7893ed8" -dependencies = [ - "cc", - "downcast-rs", - "io-lifetimes", - "nix 0.26.4", - "scoped-tls", - "smallvec", - "wayland-sys 0.30.1", -] - -[[package]] -name = "wayland-backend" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40" -dependencies = [ - "cc", - "downcast-rs", - "rustix 0.38.34", - "scoped-tls", - "smallvec", - "wayland-sys 0.31.1", -] - -[[package]] -name = "wayland-client" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" -dependencies = [ - "bitflags 1.3.2", - "downcast-rs", - "libc", - "nix 0.24.3", - "scoped-tls", - "wayland-commons", - "wayland-scanner 0.29.5", - "wayland-sys 0.29.5", -] - -[[package]] -name = "wayland-client" -version = "0.30.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489c9654770f674fc7e266b3c579f4053d7551df0ceb392f153adb1f9ed06ac8" -dependencies = [ - "bitflags 1.3.2", - "nix 0.26.4", - "wayland-backend 0.1.2", - "wayland-scanner 0.30.1", -] - -[[package]] -name = "wayland-client" -version = "0.31.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" -dependencies = [ - "bitflags 2.5.0", - "rustix 0.38.34", - "wayland-backend 0.3.3", - "wayland-scanner 0.31.1", -] - -[[package]] -name = "wayland-commons" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" -dependencies = [ - "nix 0.24.3", - "once_cell", - "smallvec", - "wayland-sys 0.29.5", -] - -[[package]] -name = "wayland-csd-frame" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" -dependencies = [ - "bitflags 2.5.0", - "cursor-icon", - "wayland-backend 0.3.3", -] - -[[package]] -name = "wayland-cursor" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" -dependencies = [ - "nix 0.24.3", - "wayland-client 0.29.5", - "xcursor", -] - -[[package]] -name = "wayland-cursor" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71ce5fa868dd13d11a0d04c5e2e65726d0897be8de247c0c5a65886e283231ba" -dependencies = [ - "rustix 0.38.34", - "wayland-client 0.31.2", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" -dependencies = [ - "bitflags 1.3.2", - "wayland-client 0.29.5", - "wayland-commons", - "wayland-scanner 0.29.5", -] - -[[package]] -name = "wayland-protocols" -version = "0.31.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" -dependencies = [ - "bitflags 2.5.0", - "wayland-backend 0.3.3", - "wayland-client 0.31.2", - "wayland-scanner 0.31.1", -] - -[[package]] -name = "wayland-protocols-wlr" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" -dependencies = [ - "bitflags 2.5.0", - "wayland-backend 0.3.3", - "wayland-client 0.31.2", - "wayland-protocols 0.31.2", - "wayland-scanner 0.31.1", -] - -[[package]] -name = "wayland-scanner" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" -dependencies = [ - "proc-macro2", - "quote", - "xml-rs", -] - -[[package]] -name = "wayland-scanner" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9b873b257fbc32ec909c0eb80dea312076a67014e65e245f5eb69a6b8ab330e" -dependencies = [ - "proc-macro2", - "quick-xml 0.28.2", - "quote", -] - -[[package]] -name = "wayland-scanner" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283" -dependencies = [ - "proc-macro2", - "quick-xml 0.31.0", - "quote", -] - -[[package]] -name = "wayland-sys" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" -dependencies = [ - "dlib", - "lazy_static", - "pkg-config", -] - -[[package]] -name = "wayland-sys" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b2a02ac608e07132978689a6f9bf4214949c85998c247abadd4f4129b1aa06" -dependencies = [ - "dlib", - "lazy_static", - "log", - "pkg-config", -] - -[[package]] -name = "wayland-sys" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af" -dependencies = [ - "dlib", - "log", - "once_cell", - "pkg-config", -] - -[[package]] -name = "web-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "weezl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" - -[[package]] -name = "wgpu" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "480c965c9306872eb6255fa55e4b4953be55a8b64d57e61d7ff840d3dcc051cd" -dependencies = [ - "arrayvec", - "cfg-if", - "js-sys", - "log", - "naga", - "parking_lot 0.12.2", - "profiling", - "raw-window-handle", - "smallvec", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f478237b4bf0d5b70a39898a66fa67ca3a007d79f2520485b8b0c3dfc46f8c2" -dependencies = [ - "arrayvec", - "bit-vec", - "bitflags 2.5.0", - "codespan-reporting", - "log", - "naga", - "parking_lot 0.12.2", - "profiling", - "raw-window-handle", - "rustc-hash", - "smallvec", - "thiserror", - "web-sys", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-hal" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecb3258078e936deee14fd4e0febe1cfe9bbb5ffef165cb60218d2ee5eb4448" -dependencies = [ - "android_system_properties", - "arrayvec", - "ash", - "bit-set", - "bitflags 2.5.0", - "block", - "core-graphics-types", - "d3d12", - "foreign-types", - "glow", - "gpu-alloc", - "gpu-allocator", - "gpu-descriptor", - "hassle-rs", - "js-sys", - "khronos-egl", - "libc", - "libloading 0.8.3", - "log", - "metal", - "naga", - "objc", - "parking_lot 0.12.2", - "profiling", - "range-alloc", - "raw-window-handle", - "renderdoc-sys", - "rustc-hash", - "smallvec", - "thiserror", - "wasm-bindgen", - "web-sys", - "wgpu-types", - "winapi", -] - -[[package]] -name = "wgpu-types" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c153280bb108c2979eb5c7391cb18c56642dd3c072e55f52065e13e2a1252a" -dependencies = [ - "bitflags 2.5.0", - "js-sys", - "web-sys", -] - -[[package]] -name = "widestring" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "winapi-wsapoll" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1eafc5f679c576995526e81635d0cf9695841736712b4e892f87abbe6fed3f28" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "window_clipboard" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63287c9c4396ccf5346d035a9b0fcaead9e18377637f5eaa78b7ac65c873ff7d" -dependencies = [ - "clipboard-win", - "clipboard_macos", - "clipboard_wayland", - "clipboard_x11", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "windows" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" -dependencies = [ - "windows-core", - "windows-targets 0.52.5", -] - -[[package]] -name = "windows-core" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" -dependencies = [ - "windows-result", - "windows-targets 0.52.5", -] - -[[package]] -name = "windows-result" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" -dependencies = [ - "windows-targets 0.52.5", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.5", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" -dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] [[package]] -name = "windows_i686_msvc" -version = "0.52.5" +name = "time-core" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +name = "time-macros" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +dependencies = [ + "num-conv", + "time-core", +] [[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +name = "tiny-keccak" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] [[package]] -name = "windows_x86_64_gnu" -version = "0.52.5" +name = "tinyvec" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] [[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +name = "tinyvec_macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" +name = "tract-core" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "7d72bdfb1d8809fc16b7e3496c8a3a31e8c55eeec8f648f2715d87bd25e9db1c" +dependencies = [ + "anyhow", + "anymap3", + "bit-set", + "derive-new", + "downcast-rs", + "dyn-clone", + "lazy_static", + "log", + "maplit", + "ndarray", + "num-complex", + "num-integer", + "num-traits", + "pastey", + "rustfft", + "smallvec", + "tract-data", + "tract-linalg", +] [[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.5" +name = "tract-data" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "fb9833e90b72a7a8e7abc517e79a90c1463d88550531deaabd4b5dbf706a091b" +dependencies = [ + "anyhow", + "downcast-rs", + "dyn-clone", + "dyn-hash", + "half", + "itertools 0.12.1", + "lazy_static", + "libm", + "maplit", + "ndarray", + "nom", + "nom-language", + "num-integer", + "num-traits", + "parking_lot", + "scan_fmt", + "smallvec", + "string-interner", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +name = "tract-hir" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "0fe98f1a0fe9d7bcc39a64258729940da99a26e0ecac8d474d17cfd15f9e4ecf" +dependencies = [ + "derive-new", + "log", + "tract-core", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +name = "tract-linalg" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "d09562926176740991a4e74ada093ed4edc155a585c45e2dd6fa13994a89f04f" +dependencies = [ + "byteorder", + "cc", + "derive-new", + "downcast-rs", + "dyn-clone", + "dyn-hash", + "half", + "lazy_static", + "liquid", + "liquid-core", + "liquid-derive", + "log", + "num-traits", + "pastey", + "scan_fmt", + "smallvec", + "time", + "tract-data", + "unicode-normalization", + "walkdir", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.52.5" +name = "tract-nnef" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "160625a1b79132698ac292ff555c575a567a2c27cd2371c53c13225cbda8d1de" +dependencies = [ + "byteorder", + "flate2", + "liquid", + "liquid-core", + "log", + "nom", + "nom-language", + "safetensors", + "serde_json", + "tar", + "tract-core", + "walkdir", +] [[package]] -name = "winit" -version = "0.28.7" +name = "tract-onnx" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9596d90b45384f5281384ab204224876e8e8bf7d58366d9b795ad99aa9894b94" +checksum = "e96a3bf1d24b5ca9e4371dac498c6c3cb47d1e4eb7fede41a5750e611da45274" dependencies = [ - "android-activity", - "bitflags 1.3.2", - "cfg_aliases", - "core-foundation", - "core-graphics", - "dispatch", - "instant", - "libc", + "bytes", + "derive-new", "log", - "mio", - "ndk 0.7.0", - "objc2", - "once_cell", - "orbclient", - "percent-encoding", - "raw-window-handle", - "redox_syscall 0.3.5", - "sctk-adwaita", - "smithay-client-toolkit 0.16.1", - "wasm-bindgen", - "wayland-client 0.29.5", - "wayland-commons", - "wayland-protocols 0.29.5", - "wayland-scanner 0.29.5", - "web-sys", - "windows-sys 0.45.0", - "x11-dl", + "memmap2", + "num-integer", + "prost", + "smallvec", + "tract-hir", + "tract-nnef", + "tract-onnx-opl", ] [[package]] -name = "winnow" -version = "0.5.40" +name = "tract-onnx-opl" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +checksum = "6d1e8a95ae93fdc53143586ec00d816c2831c6958a8a59cc4122ca5b8dba6070" dependencies = [ - "memchr", + "getrandom", + "log", + "rand", + "rand_distr", + "rustfft", + "tract-nnef", ] [[package]] -name = "winreg" -version = "0.50.0" +name = "tract-pulse" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +checksum = "e1639fdc774ddc71eb91d78fdd13565fee5b402baafb8197410e96f55b976093" dependencies = [ - "cfg-if", - "serde", - "windows-sys 0.48.0", + "downcast-rs", + "lazy_static", + "log", + "tract-pulse-opl", ] [[package]] -name = "x11-dl" -version = "2.21.0" +name = "tract-pulse-opl" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +checksum = "c0397744e1ef31cc27c8fd4e17fb261e549c05aae28dd33367fab4e4af8cf68b" dependencies = [ - "libc", - "once_cell", - "pkg-config", + "downcast-rs", + "lazy_static", + "tract-nnef", ] [[package]] -name = "x11rb" -version = "0.11.1" +name = "transpose" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf3c79412dd91bae7a7366b8ad1565a85e35dd049affc3a6a2c549e97419617" +checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" dependencies = [ - "gethostname 0.2.3", - "libc", - "libloading 0.7.4", - "nix 0.25.1", - "once_cell", - "winapi", - "winapi-wsapoll", - "x11rb-protocol 0.11.1", + "num-integer", + "strength_reduce", ] [[package]] -name = "x11rb" -version = "0.13.1" +name = "typenum" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" -dependencies = [ - "gethostname 0.4.3", - "rustix 0.38.34", - "x11rb-protocol 0.13.1", -] +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] -name = "x11rb-protocol" -version = "0.11.1" +name = "ucd-trie" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0b1513b141123073ce54d5bb1d33f801f17508fbd61e02060b1214e96d39c56" -dependencies = [ - "nix 0.25.1", -] +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] -name = "x11rb-protocol" -version = "0.13.1" +name = "unicode-ident" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] -name = "xattr" -version = "1.3.1" +name = "unicode-normalization" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ - "libc", - "linux-raw-sys 0.4.13", - "rustix 0.38.34", + "tinyvec", ] [[package]] -name = "xcursor" -version = "0.3.5" +name = "unicode-segmentation" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a0ccd7b4a5345edfcd0c3535718a4e9ff7798ffc536bb5b5a0e26ff84732911" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] -name = "xdg-home" -version = "1.1.0" +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ - "libc", - "winapi", + "same-file", + "winapi-util", ] [[package]] -name = "xkeysym" -version = "0.2.0" +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "054a8e68b76250b253f671d1268cb7f1ae089ec35e195b2efb2a4e9a836d0621" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "xml-rs" -version = "0.8.20" +name = "winapi-util" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] [[package]] -name = "yazi" -version = "0.1.6" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94451ac9513335b5e23d7a8a2b61a7102398b8cca5160829d313e84c9d98be1" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "zbus" -version = "3.15.2" +name = "windows-sys" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "async-broadcast", - "async-executor", - "async-fs", - "async-io 1.13.0", - "async-lock 2.8.0", - "async-process", - "async-recursion", - "async-task", - "async-trait", - "blocking", - "byteorder", - "derivative", - "enumflags2", - "event-listener 2.5.3", - "futures-core", - "futures-sink", - "futures-util", - "hex", - "nix 0.26.4", - "once_cell", - "ordered-stream", - "rand", - "serde", - "serde_repr", - "sha1", - "static_assertions", - "tracing", - "uds_windows", - "winapi", - "xdg-home", - "zbus_macros", - "zbus_names", - "zvariant", + "windows-targets", ] [[package]] -name = "zbus_macros" -version = "3.15.2" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7131497b0f887e8061b430c530240063d33bf9455fa34438f388a245da69e0a5" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "regex", - "syn 1.0.109", - "zvariant_utils", + "windows-link", ] [[package]] -name = "zbus_names" -version = "2.6.1" +name = "windows-targets" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "serde", - "static_assertions", - "zvariant", + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] -name = "zeno" -version = "0.2.3" +name = "windows_aarch64_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd15f8e0dbb966fd9245e7498c7e9e5055d9e5c8b676b95bd67091cd11a1e697" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] -name = "zerocopy" -version = "0.7.33" +name = "windows_aarch64_msvc" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "087eca3c1eaf8c47b94d02790dd086cd594b912d2043d4de4bfdd466b3befb7c" -dependencies = [ - "zerocopy-derive", -] +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] -name = "zerocopy-derive" -version = "0.7.33" +name = "windows_i686_gnu" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f4b6c273f496d8fd4eaf18853e6b448760225dc030ff2c485a786859aea6393" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", -] +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] -name = "zune-inflate" -version = "0.2.54" +name = "windows_i686_gnullvm" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" -dependencies = [ - "simd-adler32", -] +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] -name = "zvariant" -version = "3.15.2" +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "xattr" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eef2be88ba09b358d3b58aca6e41cd853631d44787f319a1383ca83424fb2db" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ - "byteorder", - "enumflags2", "libc", - "serde", - "static_assertions", - "zvariant_derive", + "rustix", ] [[package]] -name = "zvariant_derive" -version = "3.15.2" +name = "zerocopy" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", - "zvariant_utils", + "zerocopy-derive", ] [[package]] -name = "zvariant_utils" -version = "1.0.1" +name = "zerocopy-derive" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.110", ] diff --git a/libDF/Cargo.toml b/libDF/Cargo.toml index c0f3271ef..d6ba5fde4 100644 --- a/libDF/Cargo.toml +++ b/libDF/Cargo.toml @@ -1,165 +1,30 @@ [package] name = "deep_filter" version = "0.5.7-pre" -authors = ["Hendrik Schröter"] +authors = ["tonari & Hendrik Schröter"] edition = "2021" -description = "Noise supression using deep filtering" -repository = "https://github.com/Rikorose/DeepFilterNet" +description = "Noise suppression using deep filtering" +repository = "https://github.com/tonarino/DeepFilterNet" license = "MIT/Apache-2.0" -readme = "../README.md" -rust-version = "1.70" - -[lib] -name = "df" -path = "src/lib.rs" -crate-type = ["cdylib", "rlib", "staticlib"] - -[[bin]] -name = "sample-hdf5" -path = "src/bin/sample-hdf5.rs" -required-features = ["dataset", "bin"] - -[[bin]] -name = "sample-dataset" -path = "src/bin/sample-dataset.rs" -required-features = ["dataset", "bin"] - -[[bin]] -name = "deep-filter" -path = "src/bin/enhance_wav.rs" -required-features = ["bin", "tract", "wav-utils", "transforms"] - -[features] -default = ["default-model", "vorbis", "flac"] - -transforms = ["dep:thiserror", "dep:ndarray", "dep:rubato"] -dataset = [ - "dep:thiserror", - "dep:ndarray", - "dep:ndarray-rand", - "dep:rand_xoshiro", - "dep:hdf5", - "dep:rayon", - "dep:crossbeam-channel", - "dep:serde_json", - "dep:serde", - "dep:hound", - "dep:rubato", - "dep:roots", - "dep:log", - "dep:anyhow", -] -timings = [] -logging = ["dep:log", "dep:crossbeam-channel"] -vorbis = ["dep:lewton", "dep:ogg"] -flac = ["dep:claxon"] -bin = [ - "dep:clap", - "dep:anyhow", - "dep:ctrlc", - "dep:env_logger", - "dep:rand", - "dep:ndarray-rand", - "dep:rust-ini", - "logging", -] -wav-utils = ["dep:ndarray", "dep:hound"] -use-jemalloc = ["dep:jemallocator"] -tract = [ - "transforms", - "logging", - "dep:tract-core", - "dep:tract-onnx", - "dep:tract-pulse", - "dep:tract-hir", - "dep:rust-ini", - "dep:ndarray", - "dep:anyhow", - "dep:flate2", - "dep:tar", -] -default-model = [] # Include default DFN3 model -default-model-ll = [] # Include default DFN3 low latency model -nightly-features = [] -capi = ["tract", "default-model", "dep:ndarray", "logging"] -wasm = [ - "tract", - "default-model", - "dep:ndarray", - "dep:wasm-bindgen", - "dep:getrandom", - "dep:console_error_panic_hook", - "dep:js-sys", -] -hdf5-static = ["hdf5?/static"] +publish = false +rust-version = "1.91" [dependencies] -rustfft = "^6.1.0" -realfft = "^3.1.0" -itertools = "0.12" -num-complex = { version = "^0.4", features = ["serde"] } -log = { version = "0.4", features = ["std"], optional = true } -rand = { version = "0.8", optional = true } -rubato = { version = "0.14", optional = true } -roots = { version = "0.0.7", optional = true } -rand_xoshiro = { version = "0.6", optional = true } -thiserror = { version = "1.0", optional = true } -anyhow = { version = "1.0", optional = true, features = ["backtrace"] } -ctrlc = { version = "3.2", optional = true } -hound = { version = "3.4", optional = true } -hdf5 = { optional = true, git = "https://github.com/aldanor/hdf5-rust.git", rev = "26046fb" } -ndarray = { version = "^0.15", optional = true, features = ["serde"] } -ndarray-rand = { version = "^0.14", optional = true } -rayon = { version = "1.5", optional = true } -crossbeam-channel = { version = "^0.5", optional = true } -serde_json = { version = "1.0", optional = true } -serde = { version = "1.0", features = ["derive"], optional = true } -lewton = { version = "^0.10", optional = true } -ogg = { version = "^0.8", optional = true } -claxon = { version = "^0.4", optional = true } -env_logger = { version = "0.11", optional = true } -clap = { version = "4.0", optional = true, features = ["derive"] } -rust-ini = { version = "^0.21", optional = true } -tract-core = { version = "^0.21.4", optional = true } -tract-onnx = { version = "^0.21.4", optional = true } -tract-pulse = { version = "^0.21.4", optional = true } -tract-hir = { version = "^0.21.4", optional = true } -flate2 = { version = "1.0.24", optional = true } -tar = { version = "0.4.38", optional = true } -wasm-bindgen = { version = "0.2.87", optional = true } -getrandom = { version = "0.2", features = ["js"], optional = true } -console_error_panic_hook = { version = "0.1.1", optional = true } -js-sys = { version = "0.3", optional = true } - - -[target.'cfg(all(not(windows), not(target_os = "android"), not(target_os = "macos"), not(target_os = "freebsd"), not(target_env = "musl"), not(target_arch = "riscv64")))'.dependencies] -jemallocator = { version = "0.5.0", optional = true } - -[dev-dependencies] -rand = "0.8" -rstest = "0.19" -env_logger = "0.11" +anyhow = "1" +flate2 = "1" +itertools = "0.10" log = { version = "0.4", features = ["std"] } -[package.metadata.capi.header] -name = "deep_filter" -subdirectory = "deep_filter" -[package.metadata.capi.pkg_config] -name = "libdeepfilter" -filename = "deepfilter" -[package.metadata.capi.library] -name = "deepfilter" +ndarray = "^0.16" +num-complex = { version = "^0.4", features = ["serde"] } +realfft = "^3.5" +rust-ini = "^0.21" +rustfft = "^6.4" +tar = "^0.4" +tract-core = "^0.22" +tract-hir = "^0.22" +tract-onnx = "^0.22" +tract-pulse = "^0.22" -[package.metadata.deb] -assets = [ - [ - "LICENSE-MIT", - "usr/share/doc/deep_filter/", - "644", - ], - [ - "LICENSE-APACHE", - "usr/share/doc/deep_filter/", - "644", - ], -] +[dev-dependencies] +rand = "^0.8" diff --git a/libDF/src/lib.rs b/libDF/src/lib.rs index 7ab568856..d72e040ee 100644 --- a/libDF/src/lib.rs +++ b/libDF/src/lib.rs @@ -1,44 +1,13 @@ -#![allow(dead_code)] - -use std::ops::MulAssign; -use std::sync::Arc; -use std::vec::Vec; - use itertools::izip; +pub use num_complex::Complex32; use realfft::{ComplexToReal, RealFftPlanner, RealToComplex}; - -pub type Complex32 = num_complex::Complex32; +use std::{ops::MulAssign, sync::Arc, vec::Vec}; pub const MEAN_NORM_INIT: [f32; 2] = [-60., -90.]; pub const UNIT_NORM_INIT: [f32; 2] = [0.001, 0.0001]; -#[cfg(any(feature = "transforms", feature = "dataset"))] -pub mod transforms; -#[cfg(feature = "dataset")] -#[path = ""] -mod reexport_dataset_modules { - pub mod augmentations; - pub mod dataloader; - pub mod dataset; - pub mod hdf5_key_cache; - pub mod util; - pub mod wav_utils; -} -#[cfg(feature = "dataset")] -pub use reexport_dataset_modules::*; -#[cfg(feature = "capi")] -mod capi; -#[cfg(feature = "logging")] -pub mod logging; -#[cfg(feature = "tract")] pub mod tract; -#[cfg(feature = "wasm")] -mod wasm; - -#[cfg(all(feature = "wav-utils", not(feature = "dataset")))] -pub mod wav_utils; - pub(crate) fn freq2erb(freq_hz: f32) -> f32 { 9.265 * (freq_hz / (24.7 * 9.265)).ln_1p() } @@ -153,11 +122,6 @@ impl DFState { } } - pub fn reset(&mut self) { - self.analysis_mem.fill(0.); - self.synthesis_mem.fill(0.); - } - pub fn process_frame(&mut self, input: &[f32], output: &mut [f32]) { debug_assert_eq!(input.len(), self.frame_size); debug_assert_eq!(output.len(), self.frame_size); @@ -192,6 +156,7 @@ impl DFState { } self.mean_norm_state = state; } + pub fn init_unit_norm_state(&mut self, nb_freqs: usize) { let min = UNIT_NORM_INIT[0]; let max = UNIT_NORM_INIT[1]; @@ -216,10 +181,6 @@ impl DFState { band_unit_norm(output, &mut self.unit_norm_state, alpha) } - pub fn feat_cplx_t(&mut self, input: &[Complex32], alpha: f32, output: &mut [f32]) { - band_unit_norm_t(input, &mut self.unit_norm_state, alpha, output) - } - pub fn apply_mask(&self, output: &mut [Complex32], gains: &[f32]) { apply_interp_band_gain(output, gains, &self.erb) } @@ -231,16 +192,6 @@ impl Default for DFState { } } -pub fn band_mean_norm_freq(xs: &[Complex32], xout: &mut [f32], state: &mut [f32], alpha: f32) { - debug_assert_eq!(xs.len(), state.len()); - debug_assert_eq!(xout.len(), state.len()); - for (x, s, xo) in izip!(xs.iter(), state.iter_mut(), xout.iter_mut()) { - let xabs = x.norm(); - *s = xabs * (1. - alpha) + *s * alpha; - *xo = xabs - *s; - } -} - pub fn band_mean_norm_erb(xs: &mut [f32], state: &mut [f32], alpha: f32) { debug_assert_eq!(xs.len(), state.len()); for (x, s) in xs.iter_mut().zip(state.iter_mut()) { @@ -294,23 +245,6 @@ pub fn compute_band_corr(out: &mut [f32], x: &[Complex32], p: &[Complex32], erb_ } } -pub fn band_compr(out: &mut [f32], x: &[f32], erb_fb: &[usize]) { - for y in out.iter_mut() { - *y = 0.0; - } - debug_assert_eq!(erb_fb.len(), out.len()); - - let mut bcsum = 0; - for (&band_size, out_b) in erb_fb.iter().zip(out.iter_mut()) { - let k = 1. / band_size as f32; - for j in 0..band_size { - let idx = bcsum + j; - *out_b += x[idx] * k; - } - bcsum += band_size; - } -} - pub fn apply_interp_band_gain(out: &mut [T], band_e: &[f32], erb_fb: &[usize]) where T: MulAssign, @@ -325,28 +259,6 @@ where } } -fn interp_band_gain(out: &mut [f32], band_e: &[f32], erb_fb: &[usize]) { - let mut bcsum = 0; - for (&band_size, &b) in erb_fb.iter().zip(band_e.iter()) { - for j in 0..band_size { - let idx = bcsum + j; - out[idx] = b; - } - bcsum += band_size; - } -} - -fn apply_band_gain(out: &mut [Complex32], band_e: &[f32], erb_fb: &[usize]) { - let mut bcsum = 0; - for (&band_size, b) in erb_fb.iter().zip(band_e.iter()) { - for j in 0..band_size { - let idx = bcsum + j; - out[idx] *= *b; - } - bcsum += band_size; - } -} - fn process_frame(input: &[f32], output: &mut [f32], state: &mut DFState) { let mut freq_mem = vec![Complex32::default(); state.freq_size]; frame_analysis(input, &mut freq_mem, state); @@ -400,7 +312,7 @@ fn frame_synthesis(input: &mut [Complex32], output: &mut [f32], state: &mut DFSt .process_with_scratch(input, &mut x, &mut state.synthesis_scratch) { Err(realfft::FftError::InputValues(_, _)) => (), - Err(e) => panic!("Error during fft_inverse: {:?}", e), + Err(e) => panic!("Error during fft_inverse: {e:?}"), Ok(_) => (), } apply_window_in_place(&mut x, &state.window); @@ -426,14 +338,6 @@ fn frame_synthesis(input: &mut [Complex32], output: &mut [f32], state: &mut DFSt } } -fn apply_window(xs: &[f32], window: &[f32]) -> Vec { - let mut out = vec![0.; window.len()]; - for (&x, &w, o) in izip!(xs.iter(), window.iter(), out.iter_mut()) { - *o = x * w; - } - out -} - fn apply_window_in_place<'a, I>(xs: &mut [f32], window: I) where I: IntoIterator, @@ -470,158 +374,21 @@ pub fn post_filter(noisy: &[Complex32], enh: &mut [Complex32], beta: f32) { } } -pub(crate) struct NonNan(f32); - -impl NonNan { - fn new(val: f32) -> Option { - if val.is_nan() { - None - } else { - Some(NonNan(val)) - } - } - fn get(&self) -> f32 { - self.0 - } -} - -pub fn find_max<'a, I>(vals: I) -> Option -where - I: IntoIterator, -{ - vals.into_iter().try_fold(f32::MIN, |acc, v| { - let nonnan: NonNan = match NonNan::new(*v) { - None => return None, - Some(x) => x, - }; - Some(nonnan.get().max(acc)) - }) -} - -pub fn find_max_abs<'a, I>(vals: I) -> Option -where - I: IntoIterator, -{ - vals.into_iter().try_fold(0., |acc, v| { - let nonnan: NonNan = match NonNan::new(v.abs()) { - None => return None, - Some(x) => x, - }; - Some(nonnan.get().max(acc)) - }) -} - -pub fn find_min<'a, I>(vals: I) -> Option -where - I: IntoIterator, -{ - vals.into_iter().try_fold(f32::MAX, |acc, v| { - let nonnan: NonNan = match NonNan::new(*v) { - None => return None, - Some(x) => x, - }; - Some(nonnan.get().min(acc)) - }) -} - -pub fn find_min_abs<'a, I>(vals: I) -> Option -where - I: IntoIterator, -{ - vals.into_iter().try_fold(0., |acc, v| { - let nonnan: NonNan = match NonNan::new(v.abs()) { - None => return None, - Some(x) => x, - }; - Some(nonnan.get().min(acc)) - }) -} - -pub fn argmax<'a, I>(vals: I) -> Option -where - I: IntoIterator, -{ - let mut index = 0; - let mut high = f32::MIN; - vals.into_iter().enumerate().for_each(|(i, v)| { - if v > &high { - high = *v; - index = i; - } - }); - Some(index) -} - -pub fn argmax_abs<'a, I>(vals: I) -> Option -where - I: IntoIterator, -{ - let mut index = 0; - let mut high = f32::MIN; - vals.into_iter().enumerate().for_each(|(i, v)| { - if v > &high { - high = v.abs(); - index = i; - } - }); - Some(index) -} - -pub fn rms<'a, I>(vals: I) -> f32 -where - I: IntoIterator, -{ - let mut n = 0; - let pow_sum = vals.into_iter().fold(0., |acc, v| { - n += 1; - acc + v.powi(2) - }); - (pow_sum / n as f32).sqrt() -} -pub fn rms_v(vals: I) -> f32 -where - I: IntoIterator, -{ - let mut n = 0; - let pow_sum = vals.into_iter().fold(0., |acc, v| { - n += 1; - acc + v.powi(2) - }); - (pow_sum / n as f32).sqrt() -} - -pub fn mean<'a, I>(vals: I) -> f32 -where - I: IntoIterator, -{ - let mut n = 0; - let sum = vals.into_iter().fold(0., |acc, v| { - n += 1; - acc + v - }); - sum / n as f32 -} - -pub fn median(x: &mut [T]) -> T -where - T: PartialOrd + Copy, -{ - if x.len() == 1 { - return x[0]; - } - if x.is_empty() { - panic!("Empty input slice"); - } - x.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)); - let mid = x.len() / 2; - x[mid] -} - #[cfg(test)] mod tests { + use super::*; use rand::distributions::{Distribution, Uniform}; - use super::*; + fn apply_band_gain(out: &mut [Complex32], band_e: &[f32], erb_fb: &[usize]) { + let mut bcsum = 0; + for (&band_size, b) in erb_fb.iter().zip(band_e.iter()) { + for j in 0..band_size { + let idx = bcsum + j; + out[idx] *= *b; + } + bcsum += band_size; + } + } #[test] fn test_erb_inout() { diff --git a/libDF/src/tract.rs b/libDF/src/tract.rs index b39a98726..a4a4bb0d1 100644 --- a/libDF/src/tract.rs +++ b/libDF/src/tract.rs @@ -1,23 +1,23 @@ -use std::fs::File; -use std::io::{Cursor, Read}; -use std::path::{Path, PathBuf}; -#[cfg(feature = "timings")] -use std::time::Instant; - -use anyhow::{bail, Context, Result}; +use crate::DFState; +use anyhow::{Context, Result}; use flate2::read::GzDecoder; use ini::Ini; use ndarray::{prelude::*, Axis}; +use num_complex::Complex32; +use std::{ + fs::File, + io::{Cursor, Read}, + path::PathBuf, +}; use tar::Archive; -use tract_core::internal::tract_itertools::izip; -use tract_core::internal::tract_smallvec::alloc::collections::VecDeque; -use tract_core::ops; -use tract_core::prelude::*; +use tract_core::{ + internal::{tract_itertools::izip, tract_smallvec::alloc::collections::VecDeque}, + ops, + prelude::*, +}; use tract_onnx::{prelude::*, tract_hir::shapefactoid}; use tract_pulse::{internal::ToDim, model::*}; -use crate::*; - #[derive(Clone)] pub struct DfParams { config: Ini, @@ -28,12 +28,15 @@ pub struct DfParams { impl DfParams { pub fn new(tar_file: PathBuf) -> Result { - let file = File::open(tar_file).context("Could not open model tar file.")?; - Self::from_targz(file) + let file = File::open(&tar_file).context("Could not open model tar file.")?; + let params = Self::from_targz(file)?; + Ok(params) } + pub fn from_bytes(tar_buf: &[u8]) -> Result { Self::from_targz(tar_buf) } + fn from_targz(f: R) -> Result { let tar = GzDecoder::new(f); let mut archive = Archive::new(tar); @@ -43,7 +46,7 @@ impl DfParams { let mut config = Ini::new(); for e in archive.entries().context("Could not extract models from tar file.")? { let mut file = e.context("Could not open model tar entry.")?; - let path = file.path().unwrap(); + let path = file.path()?; if path.ends_with("enc.onnx") { file.read_to_end(&mut enc)?; } else if path.ends_with("erb_dec.onnx") { @@ -56,52 +59,22 @@ impl DfParams { } else if path.ends_with("version.txt") { let mut version = String::new(); file.read_to_string(&mut version).expect("Could not read version.txt"); - log::info!("Loading model with id: {}", version); + log::debug!("Loading model with id: {version}"); } else { - log::warn!("Found non-matching item in model tar file: {:?}", path) + log::warn!("Found non-matching item in model tar file: {path:?}") } } - Ok(Self { - config, - enc, - erb_dec, - df_dec, - }) - } -} -impl Default for DfParams { - #[allow(unreachable_code)] - fn default() -> Self { - #[cfg(feature = "default-model-ll")] - { - log::debug!("Loading model DeepFilterNet3_ll_onnx.tar.gz"); - return DfParams::from_bytes(include_bytes!( - "../../models/DeepFilterNet3_ll_onnx.tar.gz" - )) - .expect("Could not load model config"); - } - #[cfg(feature = "default-model")] - { - log::debug!("Loading model DeepFilterNet3_onnx.tar.gz"); - DfParams::from_bytes(include_bytes!("../../models/DeepFilterNet3_onnx.tar.gz")) - .expect("Could not load model config") - } - #[cfg(not(feature = "default-model"))] - panic!("Not compiled with a default model") + Ok(Self { config, enc, erb_dec, df_dec }) } } -#[derive(Clone)] +#[derive(Clone, Default)] pub enum ReduceMask { + #[default] NONE = 0, MAX = 1, MEAN = 2, } -impl Default for ReduceMask { - fn default() -> Self { - ReduceMask::NONE - } -} impl TryFrom for ReduceMask { type Error = (); @@ -134,7 +107,7 @@ impl RuntimeParams { max_db_df_thresh: f32, reduce_mask: ReduceMask, ) -> Self { - let post_filter = post_filter_beta > 0.; + let post_filter = post_filter_beta > 0.0; Self { n_ch, post_filter, @@ -146,18 +119,21 @@ impl RuntimeParams { reduce_mask, } } + pub fn with_post_filter(mut self, beta: f32) -> Self { - assert!(beta >= 0.); // Cannot be negative - if beta > 0. { + assert!(beta >= 0.0); // Cannot be negative + if beta > 0.0 { self.post_filter = true; } self.post_filter_beta = beta; self } + pub fn with_atten_lim(mut self, atten_lim_db: f32) -> Self { self.atten_lim_db = atten_lim_db; self } + pub fn with_thresholds( mut self, min_db_thresh: f32, @@ -169,19 +145,20 @@ impl RuntimeParams { self.max_db_df_thresh = max_db_df_thresh; self } + pub fn with_mask_reduce(mut self, red: ReduceMask) -> Self { self.reduce_mask = red; self } - pub fn default_with_ch(channels: usize) -> Self { + pub const fn default_with_ch(channels: usize) -> Self { RuntimeParams { n_ch: channels, post_filter: false, post_filter_beta: 0.02, - atten_lim_db: 100., - min_db_thresh: -10., - max_db_erb_thresh: 30., - max_db_df_thresh: 20., + atten_lim_db: 100.0, + min_db_thresh: -10.0, + max_db_erb_thresh: 30.0, + max_db_df_thresh: 20.0, reduce_mask: ReduceMask::MEAN, } } @@ -223,25 +200,14 @@ pub struct DfTract { pub spec_buf: Tensor, // Real-valued spectrogram buffer of shape [n_ch, 1, 1, n_freqs, 2] erb_buf: TValue, // Real-valued ERB feature buffer of shape [n_ch, 1, 1, n_erb] cplx_buf: TValue, // Real-valued complex epectrum shape for DF of shape [n_ch, 1, nb_df, 2] - m_zeros: Vec, // Preallocated buffer for applying a zero mask + _m_zeros: Vec, // Preallocated buffer for applying a zero mask rolling_spec_buf_y: VecDeque, // Enhanced stage 1 spec buf rolling_spec_buf_x: VecDeque, // Noisy spec buf skip_counter: usize, // Increment when wanting to skip processing due to low RMS } -#[cfg(all(not(feature = "capi"), feature = "default-model"))] -impl Default for DfTract { - fn default() -> Self { - let r_params = RuntimeParams::default(); - let df_params = DfParams::default(); - DfTract::new(df_params, &r_params).expect("Could not load DfTract") - } -} - impl DfTract { pub fn new(dfp: DfParams, rp: &RuntimeParams) -> Result { - #[cfg(feature = "timings")] - let t0 = Instant::now(); let config = dfp.config; let model_cfg = config.section(Some("deepfilternet")).unwrap(); let df_cfg = config.section(Some("df")).unwrap(); @@ -260,8 +226,6 @@ impl DfTract { let enc = SimpleState::new(enc.into_runnable()?)?; let erb_dec = SimpleState::new(erb_dec.into_runnable()?)?; let df_dec = SimpleState::new(df_dec.into_runnable()?)?; - #[cfg(feature = "timings")] - let t1 = Instant::now(); let sr = df_cfg.get("sr").unwrap().parse::()?; let hop_size = df_cfg.get("hop_size").unwrap().parse::()?; @@ -292,7 +256,7 @@ impl DfTract { log::warn!("Attenuation limit too strong. No noise reduction will be performed"); Some(1.) } else { - log::info!("Running with an attenuation limit of {:.0} dB", atten_lim); + log::debug!("Running with an attenuation limit of {atten_lim:.0} dB"); Some(10f32.powf(-atten_lim / 20.)) }; let spec_shape = [1, 1, 1, n_freqs, 2]; @@ -303,21 +267,12 @@ impl DfTract { let cplx_buf = TValue::from(unsafe { Tensor::uninitialized_dt(f32::datum_type(), &[1, 1, nb_df, 2])? }); - let m_zeros = vec![0.; nb_erb]; + let _m_zeros = vec![0.0; nb_erb]; let model_type = config.section(Some("train")).unwrap().get("model").unwrap(); - let lookahead = match model_type { - "deepfilternet2" => bail!( - "DeepFilterNet2 models are deprecated. Please use version v0.3.1 for these models." - ), - "deepfilternet3" => conv_lookahead.max(df_lookahead), - _ => bail!("Unsupported model type {}", model_type), - }; - log::info!( - "Running with model type {} lookahead {}", - model_type, - lookahead - ); + let lookahead = conv_lookahead.max(df_lookahead); + + log::debug!("Running with model type {model_type} lookahead {lookahead}"); let rolling_spec_buf_y = VecDeque::with_capacity(df_order + lookahead); let rolling_spec_buf_x = VecDeque::with_capacity(lookahead.max(df_order)); @@ -351,7 +306,7 @@ impl DfTract { spec_buf, erb_buf, cplx_buf, - m_zeros, + _m_zeros, rolling_spec_buf_y, rolling_spec_buf_x, df_states, @@ -360,12 +315,6 @@ impl DfTract { skip_counter: 0, }; m.init()?; - #[cfg(feature = "timings")] - log::info!( - "Init DfTract in {:.2}ms (models in {:.2}ms)", - t0.elapsed().as_secs_f32() * 1000., - (t1 - t0).as_secs_f32() * 1000. - ); Ok(m) } @@ -373,14 +322,14 @@ impl DfTract { pub fn set_pf_beta(&mut self, beta: f32) { log::debug!("Setting post-filter beta to {beta}"); self.post_filter_beta = beta; - if beta > 0. { + if beta > 0.0 { self.post_filter = true; - } else if beta == 0. { + } else if beta == 0.0 { self.post_filter = false; } else { log::warn!("Post-filter beta cannot be smaller than 0."); self.post_filter = false; - self.post_filter_beta = 0.; + self.post_filter_beta = 0.0; } } @@ -392,7 +341,7 @@ impl DfTract { log::warn!("Attenuation limit too strong. No noise reduction will be performed"); Some(1.) } else { - log::debug!("Setting attenuation limit to {:.1} dB", lim); + log::debug!("Setting attenuation limit to {lim:.1} dB"); Some(10f32.powf(-lim / 20.)) }; } @@ -403,11 +352,11 @@ impl DfTract { self.rolling_spec_buf_y.clear(); for _ in 0..(self.df_order + self.conv_lookahead) { self.rolling_spec_buf_y - .push_back(tensor0(0f32).broadcast_scalar_to_shape(&spec_shape)?); + .push_back(tensor0(0.0f32).broadcast_scalar_to_shape(&spec_shape)?); } for _ in 0..self.df_order.max(self.lookahead) { self.rolling_spec_buf_x - .push_back(tensor0(0f32).broadcast_scalar_to_shape(&spec_shape)?); + .push_back(tensor0(0.0f32).broadcast_scalar_to_shape(&spec_shape)?); } if ch > self.df_states.len() { for _ in self.df_states.len()..ch { @@ -462,6 +411,7 @@ impl DfTract { TValue::from(self.cplx_buf.clone().into_tensor().permute_axes(&[0, 3, 1, 2])?) ))?; + // Note: This will fail if multiple channels are passed in. let &lsnr = enc_emb.pop().unwrap().to_scalar::()?; let c0 = enc_emb.pop().unwrap(); let emb = enc_emb.pop().unwrap(); @@ -469,10 +419,8 @@ impl DfTract { let (apply_gains, apply_gain_zeros, apply_df) = self.apply_stages(lsnr); log::trace!( - "Enhancing frame with lsnr {:>5.1} dB. Applying stage 1: {} and stage 2: {}.", - lsnr, - apply_gains, - apply_df + "Enhancing frame with lsnr {lsnr:>5.1} dB. Applying stage 1: {apply_gains} and stage + 2: {apply_df}." ); let m = if apply_gains { @@ -510,9 +458,8 @@ impl DfTract { debug_assert_eq!(noisy.len_of(Axis(0)), enh.len_of(Axis(0))); debug_assert_eq!(noisy.len_of(Axis(1)), enh.len_of(Axis(1))); debug_assert_eq!(noisy.len_of(Axis(1)), self.hop_size); - let (max_a, e) = noisy.iter().fold((0f32, 0f32), |acc, x| { - (acc.0.max(x.abs()), acc.1 + x.powi(2)) - }); + let (_max_a, e) = + noisy.iter().fold((0.0f32, 0.0f32), |acc, x| (acc.0.max(x.abs()), acc.1 + x.powi(2))); let rms = e / noisy.len() as f32; if rms < 1e-7 { self.skip_counter += 1; @@ -520,11 +467,8 @@ impl DfTract { self.skip_counter = 0; } if self.skip_counter > 5 { - enh.fill(0.); - return Ok(-15.); - } - if max_a > 0.9999 { - log::warn!("Possible clipping detected ({:.3}).", max_a) + enh.fill(0.0); + return Ok(-15.0); } // Signal model: y = f(s + n) = f(x) @@ -540,19 +484,16 @@ impl DfTract { } self.rolling_spec_buf_y.push_back(self.spec_buf.clone()); self.rolling_spec_buf_x.push_back(self.spec_buf.clone()); - if self.atten_lim.unwrap_or_default() == 1. { + if self.atten_lim.unwrap_or_default() == 1.0 { enh.assign(&noisy); - return Ok(35.); + return Ok(35.0); } let (lsnr, gains, coefs) = self.process_raw()?; let (apply_erb, _, _) = self.apply_stages(lsnr); - let mut spec = self - .rolling_spec_buf_y - .get_mut(self.df_order - 1) - .unwrap() - .to_array_view_mut()?; + let mut spec = + self.rolling_spec_buf_y.get_mut(self.df_order - 1).unwrap().to_array_view_mut()?; if let Some(gains) = gains { let mut gains = gains.into_array()?; if gains.shape()[0] < noisy.shape()[0] { @@ -615,7 +556,7 @@ impl DfTract { // Run post filter if apply_erb && self.post_filter { - post_filter( + crate::post_filter( spec_noisy.as_slice().unwrap(), spec_enh.as_slice_mut().unwrap(), self.post_filter_beta, @@ -624,7 +565,7 @@ impl DfTract { // Limit noise attenuation by mixing back some of the noisy signal if let Some(lim) = self.atten_lim { - spec_enh.map_inplace(|x| *x *= 1. - lim); + spec_enh.map_inplace(|x| *x *= 1.0 - lim); spec_enh.scaled_add(lim.into(), &spec_noisy); } @@ -673,16 +614,17 @@ impl DfTract { pub fn set_spec_buffer(&mut self, spec: ArrayView2) -> Result<()> { debug_assert_eq!(self.spec_buf.shape(), spec.shape()); - let mut buf = self.spec_buf.to_array_view_mut()?.into_shape([self.ch, self.n_freqs])?; + let view = self.spec_buf.to_array_view_mut()?; + let mut buf = view.to_shape([self.ch, self.n_freqs])?; for (i_ch, mut b_ch) in spec.outer_iter().zip(buf.outer_iter_mut()) { for (&i, b) in i_ch.iter().zip(b_ch.iter_mut()) { - *b = i + *b = i; } } Ok(()) } - pub fn get_spec_noisy(&self) -> ArrayView2 { + pub fn get_spec_noisy(&self) -> ArrayView2<'_, Complex32> { as_arrayview_complex( self.rolling_spec_buf_x .get(self.lookahead.max(self.df_order) - self.lookahead - 1) @@ -694,7 +636,8 @@ impl DfTract { .into_dimensionality::() .unwrap() } - pub fn get_spec_enh(&self) -> ArrayView2 { + + pub fn get_spec_enh(&self) -> ArrayView2<'_, Complex32> { as_arrayview_complex( self.spec_buf.to_array_view::().unwrap(), &[self.ch, self.n_freqs], @@ -702,7 +645,8 @@ impl DfTract { .into_dimensionality::() .unwrap() } - pub fn get_mut_spec_enh(&mut self) -> ArrayViewMut2 { + + pub fn get_mut_spec_enh(&mut self) -> ArrayViewMut2<'_, Complex32> { as_arrayview_mut_complex( self.spec_buf.to_array_view_mut::().unwrap(), &[self.ch, self.n_freqs], @@ -759,7 +703,7 @@ fn df( { // Apply DF for each frequency bin up to `nb_df` for (&s, &c, o) in izip!(s_ch, c_ch, o_ch.iter_mut()) { - *o += s * c + *o += s * c; } } } @@ -772,7 +716,7 @@ fn init_encoder_impl( n_ch: usize, ) -> Result { log::debug!("Start init encoder."); - let s = m.symbol_table.sym("S"); + let s = m.symbols.sym("S"); let nb_erb = df_cfg.get("nb_erb").unwrap().parse::()?; let nb_df = df_cfg.get("nb_df").unwrap().parse::()?; @@ -795,14 +739,10 @@ fn init_encoder_impl( m.declutter()?; let pulsed = PulsedModel::new(&m, s, &1.to_dim())?; - log::info!("Init encoder"); + log::debug!("Init encoder"); let m = pulsed.into_typed()?.into_optimized()?; Ok(m) } -fn init_encoder(m: &Path, df_cfg: &ini::Properties, n_ch: usize) -> Result { - let m = tract_onnx::onnx().with_ignore_output_shapes(true).model_for_path(m)?; - init_encoder_impl(m, df_cfg, n_ch) -} fn init_encoder_from_read( m: &mut dyn Read, @@ -821,7 +761,7 @@ fn init_erb_decoder_impl( mask_reduction: Option, ) -> Result { log::debug!("Start init ERB decoder."); - let s = m.symbol_table.sym("S"); + let s = m.symbols.sym("S"); let nb_erb = df_cfg.get("nb_erb").unwrap().parse::()?; let layer_width = net_cfg.get("conv_ch").unwrap().parse::()?; @@ -833,17 +773,15 @@ fn init_erb_decoder_impl( let e2 = InferenceFact::dt_shape(f32::datum_type(), shapefactoid!(n_ch, layer_width, s, e3f)); let e1f = nb_erb / 2; let e1 = InferenceFact::dt_shape(f32::datum_type(), shapefactoid!(n_ch, layer_width, s, e1f)); - let e0 = InferenceFact::dt_shape( - f32::datum_type(), - shapefactoid!(n_ch, layer_width, s, nb_erb), - ); + let e0 = + InferenceFact::dt_shape(f32::datum_type(), shapefactoid!(n_ch, layer_width, s, nb_erb)); log::debug!( "ERB decoder input: \n emb [{:?}]\n e3 [{:?}]\n e2 [{:?}]\n e1 [{:?}]\n e0 [{:?}]", emb.shape, e3.shape, e2.shape, e1.shape, - e0.shape + e0.shape, ); let mut output_name = "m".to_string(); @@ -863,7 +801,7 @@ fn init_erb_decoder_impl( m.declutter()?; let pulsed = PulsedModel::new(&m, s, &1.to_dim())?; let mut m = pulsed.into_typed()?; - log::info!("Init ERB decoder"); + log::debug!("Init ERB decoder"); if let Some(r) = mask_reduction { let outlets = m.output_outlets()?; @@ -877,7 +815,7 @@ fn init_erb_decoder_impl( ops::nn::Reduce::new(tvec!(ch_axis), ops::nn::Reducer::Max), &[mask_outlet], )?; - } + }, ReduceMask::MEAN => { let sum = m.wire_node( "reduce_mask_sum".to_string(), @@ -887,16 +825,12 @@ fn init_erb_decoder_impl( let ch_i = m .add_const( "ch".to_string(), - Tensor::from_shape(&[1, 1, 1, 1], &[1. / n_ch as f32])?, + Tensor::from_shape(&[1, 1, 1, 1], &[1.0 / n_ch as f32])?, ) .unwrap(); output_name = "reduce_mask_div_ch".to_string(); - m.wire_node( - "reduce_mask_div_ch", - tract_core::ops::math::mul(), - &[sum, ch_i], - )?; - } + m.wire_node("reduce_mask_div_ch", tract_core::ops::math::mul(), &[sum, ch_i])?; + }, _ => (), } } @@ -906,16 +840,7 @@ fn init_erb_decoder_impl( Ok(m) } -fn init_erb_decoder( - m: &Path, - net_cfg: &ini::Properties, - df_cfg: &ini::Properties, - n_ch: usize, - mask_reduction: Option, -) -> Result { - let m = tract_onnx::onnx().with_ignore_output_shapes(true).model_for_path(m)?; - init_erb_decoder_impl(m, net_cfg, df_cfg, n_ch, mask_reduction) -} + fn init_erb_decoder_from_read( m: &mut dyn Read, net_cfg: &ini::Properties, @@ -934,7 +859,7 @@ fn init_df_decoder_impl( n_ch: usize, ) -> Result { log::debug!("Start init DF decoder."); - let s = m.symbol_table.sym("S"); + let s = m.symbols.sym("S"); let nb_erb = df_cfg.get("nb_erb").unwrap().parse::()?; let nb_df = df_cfg.get("nb_df").unwrap().parse::()?; @@ -942,16 +867,9 @@ fn init_df_decoder_impl( let n_hidden = layer_width * nb_erb / 4; let emb = InferenceFact::dt_shape(f32::datum_type(), shapefactoid!(n_ch, s, n_hidden)); - let c0 = InferenceFact::dt_shape( - f32::datum_type(), - shapefactoid!(n_ch, layer_width, s, nb_df), - ); + let c0 = InferenceFact::dt_shape(f32::datum_type(), shapefactoid!(n_ch, layer_width, s, nb_df)); - log::debug!( - "ERB decoder input: \n emb [{:?}]\n c0 [{:?}]", - emb.shape, - c0.shape, - ); + log::debug!("ERB decoder input: \n emb [{:?}]\n c0 [{:?}]", emb.shape, c0.shape,); m = m .with_input_fact(0, emb)? .with_input_fact(1, c0)? @@ -963,19 +881,11 @@ fn init_df_decoder_impl( m.declutter()?; let pulsed = PulsedModel::new(&m, s, &1.to_dim())?; - log::info!("Init DF decoder"); + log::debug!("Init DF decoder"); let m = pulsed.into_typed()?.into_optimized()?; Ok(m) } -fn init_df_decoder( - m: &Path, - net_cfg: &ini::Properties, - df_cfg: &ini::Properties, - n_ch: usize, -) -> Result { - let m = tract_onnx::onnx().with_ignore_output_shapes(true).model_for_path(m)?; - init_df_decoder_impl(m, net_cfg, df_cfg, n_ch) -} + fn init_df_decoder_from_read( m: &mut dyn Read, net_cfg: &ini::Properties, @@ -986,7 +896,7 @@ fn init_df_decoder_from_read( init_df_decoder_impl(m, net_cfg, df_cfg, n_ch) } -fn calc_norm_alpha(sr: usize, hop_size: usize, tau: f32) -> f32 { +pub fn calc_norm_alpha(sr: usize, hop_size: usize, tau: f32) -> f32 { let dt = hop_size as f32 / sr as f32; let alpha = f32::exp(-dt / tau); let mut a = 1.0; @@ -1006,7 +916,6 @@ pub fn as_slice_complex(buffer: &[f32]) -> &[Complex32] { } } -#[allow(clippy::needless_pass_by_ref_mut)] pub fn as_slice_mut_complex(buffer: &mut [f32]) -> &mut [Complex32] { unsafe { let ptr = buffer.as_ptr() as *mut Complex32; @@ -1015,7 +924,6 @@ pub fn as_slice_mut_complex(buffer: &mut [f32]) -> &mut [Complex32] { } } -#[allow(clippy::needless_pass_by_ref_mut)] pub fn as_slice_mut_real(buffer: &mut [Complex32]) -> &mut [f32] { unsafe { let ptr = buffer.as_ptr() as *mut f32; @@ -1066,15 +974,15 @@ pub fn as_arrayview_mut_complex<'a>( ArrayViewMutD::from_shape_ptr(shape, ptr) } } -pub fn tvalue_to_array_view_mut(x: &mut TValue) -> ArrayViewMutD { +pub fn tvalue_to_array_view_mut(x: &mut TValue) -> ArrayViewMutD<'_, f32> { unsafe { match x { TValue::Var(x) => { ArrayViewMutD::from_shape_ptr(x.shape(), x.as_ptr_unchecked::() as *mut f32) - } + }, TValue::Const(x) => { ArrayViewMutD::from_shape_ptr(x.shape(), x.as_ptr_unchecked::() as *mut f32) - } + }, } } } From de82a0c2eb48375e6a68be430d6e15d6d8f5d3d0 Mon Sep 17 00:00:00 2001 From: Jackson Goode <54308792+jacksongoode@users.noreply.github.com> Date: Sat, 6 Jun 2026 21:01:21 +0900 Subject: [PATCH 4/5] Add example to enhance wav files with a given model --- Cargo.lock | 102 ++++++++++++++++++----------------- libDF/Cargo.toml | 9 ++++ libDF/src/bin/deep-filter.rs | 82 ++++++++++++++++++++++++++++ libDF/src/bin/enhance_wav.rs | 98 +++++++++++++++++++++++++++++++++ 4 files changed, 243 insertions(+), 48 deletions(-) create mode 100644 libDF/src/bin/deep-filter.rs create mode 100644 libDF/src/bin/enhance_wav.rs diff --git a/Cargo.lock b/Cargo.lock index 47a96d2f4..d33b536d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,9 +97,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.45" +version = "1.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35900b6c8d709fb1d854671ae27aeaa9eec2f8b01b364e1619a40da3e6fe2afe" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ "find-msvc-tools", "shlex", @@ -171,6 +171,7 @@ version = "0.5.7-pre" dependencies = [ "anyhow", "flate2", + "hound", "itertools 0.10.5", "log", "ndarray", @@ -188,9 +189,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", ] @@ -273,9 +274,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.4" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "flate2" @@ -310,14 +311,13 @@ dependencies = [ [[package]] name = "half" -version = "2.7.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ "cfg-if", "crunchy", "num-traits", - "zerocopy", ] [[package]] @@ -329,6 +329,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hound" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" + [[package]] name = "itertools" version = "0.10.5" @@ -386,9 +392,9 @@ checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libm" -version = "0.2.15" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -472,9 +478,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.28" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "maplit" @@ -562,9 +568,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-integer" @@ -752,9 +758,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.42" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -825,9 +831,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -1059,30 +1065,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -1099,9 +1105,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -1114,9 +1120,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tract-core" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d72bdfb1d8809fc16b7e3496c8a3a31e8c55eeec8f648f2715d87bd25e9db1c" +checksum = "b65d67f5190132365dda73fe215bfc5e01b031e8cbfbea9d486bb5b0dbba3545" dependencies = [ "anyhow", "anymap3", @@ -1140,9 +1146,9 @@ dependencies = [ [[package]] name = "tract-data" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb9833e90b72a7a8e7abc517e79a90c1463d88550531deaabd4b5dbf706a091b" +checksum = "73cd7fda1e5e8b854ea3abdd09126a87fc4af81e6d1e29ec1710a8a4abf4f13a" dependencies = [ "anyhow", "downcast-rs", @@ -1166,9 +1172,9 @@ dependencies = [ [[package]] name = "tract-hir" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fe98f1a0fe9d7bcc39a64258729940da99a26e0ecac8d474d17cfd15f9e4ecf" +checksum = "554df991b647dba8af0547ee5838b6912ed20b424f2adda0ea0b7faf8db1b151" dependencies = [ "derive-new", "log", @@ -1177,9 +1183,9 @@ dependencies = [ [[package]] name = "tract-linalg" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d09562926176740991a4e74ada093ed4edc155a585c45e2dd6fa13994a89f04f" +checksum = "e72097a89cc4e7c5f1bc4f854b9294dd30fa6f6d8f7f409c556953b49078c94f" dependencies = [ "byteorder", "cc", @@ -1205,9 +1211,9 @@ dependencies = [ [[package]] name = "tract-nnef" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "160625a1b79132698ac292ff555c575a567a2c27cd2371c53c13225cbda8d1de" +checksum = "45b3755dd0948111b407085d11033ba218cb85b85ce8d795cec2b8353db552ea" dependencies = [ "byteorder", "flate2", @@ -1225,9 +1231,9 @@ dependencies = [ [[package]] name = "tract-onnx" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96a3bf1d24b5ca9e4371dac498c6c3cb47d1e4eb7fede41a5750e611da45274" +checksum = "ac23ad1d2d5da3256ae1a78757b1072a8a3fac2a4b28d27cfb561c5942ec2701" dependencies = [ "bytes", "derive-new", @@ -1243,9 +1249,9 @@ dependencies = [ [[package]] name = "tract-onnx-opl" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1e8a95ae93fdc53143586ec00d816c2831c6958a8a59cc4122ca5b8dba6070" +checksum = "87561bf0b84f74a124afc0f1997682728da6cd821083511e0357432954fd24f6" dependencies = [ "getrandom", "log", @@ -1257,9 +1263,9 @@ dependencies = [ [[package]] name = "tract-pulse" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1639fdc774ddc71eb91d78fdd13565fee5b402baafb8197410e96f55b976093" +checksum = "ff926428bf533d0d8ee70e2626fb9f8197d33d3cc9e0cafc3f9acf8e11b4dd93" dependencies = [ "downcast-rs", "lazy_static", @@ -1269,9 +1275,9 @@ dependencies = [ [[package]] name = "tract-pulse-opl" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0397744e1ef31cc27c8fd4e17fb261e549c05aae28dd33367fab4e4af8cf68b" +checksum = "5621466758a263fb3baf6494a9aca555dd90c1c0c5216186987a1857bca21f87" dependencies = [ "downcast-rs", "lazy_static", @@ -1317,9 +1323,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.12.0" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "version_check" diff --git a/libDF/Cargo.toml b/libDF/Cargo.toml index d6ba5fde4..4deb93dec 100644 --- a/libDF/Cargo.toml +++ b/libDF/Cargo.toml @@ -9,9 +9,18 @@ license = "MIT/Apache-2.0" publish = false rust-version = "1.91" +[[bin]] +name = "deep-filter" +path = "src/bin/deep-filter.rs" + +[[bin]] +name = "enhance-wav" +path = "src/bin/enhance_wav.rs" + [dependencies] anyhow = "1" flate2 = "1" +hound = "3.5" itertools = "0.10" log = { version = "0.4", features = ["std"] } diff --git a/libDF/src/bin/deep-filter.rs b/libDF/src/bin/deep-filter.rs new file mode 100644 index 000000000..f588edb98 --- /dev/null +++ b/libDF/src/bin/deep-filter.rs @@ -0,0 +1,82 @@ +use anyhow::Result; +use deep_filter::tract::{DfParams, DfTract, RuntimeParams}; +use hound; +use ndarray::prelude::*; +use std::{path::PathBuf, time::Instant}; + +fn main() -> Result<()> { + let args: Vec = std::env::args().collect(); + if args.len() < 3 { + eprintln!("Usage: {} [model.tar.gz]", args[0]); + std::process::exit(1); + } + + let input_path = &args[1]; + let output_path = &args[2]; + let model_path = args.get(3).map(|s| PathBuf::from(s)); + + // Load specified model + let dfp = if let Some(path) = model_path { + DfParams::new(path)? + } else { + // Try to find default model + let models_dir = PathBuf::from("models"); + let model_tar = models_dir.join("DeepFilterNet3.tar.gz"); + if model_tar.exists() { + DfParams::new(model_tar)? + } else { + anyhow::bail!("No model provided and default model not found"); + } + }; + + let rp = RuntimeParams::default_with_ch(1); + let mut df = DfTract::new(dfp, &rp)?; + + // Load input WAV + let mut reader = hound::WavReader::open(input_path)?; + let spec = reader.spec(); + let samples: Vec = reader.samples::().map(|s| s.unwrap()).collect(); + + // Convert to ndarray + let hop_size = df.hop_size; + let num_frames = (samples.len() + hop_size - 1) / hop_size; + + let mut noisy = Array2::zeros((1, hop_size)); + let mut enhanced = Array2::zeros((1, hop_size)); + let mut output_samples = Vec::with_capacity(samples.len()); + + let start = Instant::now(); + for i in 0..num_frames { + let start_idx = i * hop_size; + let end_idx = (start_idx + hop_size).min(samples.len()); + let frame_len = end_idx - start_idx; + + noisy.fill(0.0); + for j in 0..frame_len { + noisy[[0, j]] = samples[start_idx + j]; + } + + df.process(noisy.view(), enhanced.view_mut())?; + + for j in 0..frame_len { + output_samples.push(enhanced[[0, j]]); + } + } + let duration = start.elapsed(); + + println!("Processed {} frames in {:.2?}", num_frames, duration); + println!( + "RTF: {:.3}", + duration.as_secs_f32() / (samples.len() as f32 / spec.sample_rate as f32) + ); + + // Write output WAV + let mut writer = hound::WavWriter::create(output_path, spec)?; + for s in output_samples { + writer.write_sample(s)?; + } + writer.finalize()?; + + println!("Wrote output to: {}", output_path); + Ok(()) +} diff --git a/libDF/src/bin/enhance_wav.rs b/libDF/src/bin/enhance_wav.rs new file mode 100644 index 000000000..b36d0921a --- /dev/null +++ b/libDF/src/bin/enhance_wav.rs @@ -0,0 +1,98 @@ +//! Process WAV files with a DeepFilterNet model. +//! +//! Usage: `enhance-wav ...` +//! +//! Inputs must be 16-bit 48 kHz WAV. Stereo files are processed per-channel +//! (the model is mono-only) and re-interleaved on write. Output preserves the +//! input's channel layout and sample rate. + +use std::{path::PathBuf, process::exit, time::Instant}; + +use anyhow::Result; +use deep_filter::tract::{DfParams, DfTract, RuntimeParams}; +use ndarray::{Array2, Axis}; + +fn main() -> Result<()> { + let args: Vec = std::env::args().collect(); + if args.len() < 4 { + eprintln!( + "Usage: {} [input2.wav ...]", + args[0] + ); + exit(1); + } + + let model_path = PathBuf::from(&args[1]); + let output_dir = PathBuf::from(&args[2]); + let files: Vec = args[3..].iter().map(PathBuf::from).collect(); + + let df_params = match DfParams::new(model_path) { + Ok(p) => p, + Err(e) => { + eprintln!("Error opening model: {e}"); + exit(1) + } + }; + + let r_params = RuntimeParams::default(); + let hop = DfTract::new(df_params.clone(), &r_params)?.hop_size; + + if !output_dir.is_dir() { + std::fs::create_dir_all(&output_dir)?; + } + + for file in &files { + let mut reader = hound::WavReader::open(file)?; + let spec = reader.spec(); + let n_ch = spec.channels as usize; + let samples: Vec = reader + .samples::() + .map(|s| s.map(|v| v as f32 / 32768.0)) + .collect::, _>>()?; + + let n_frames = samples.len() / n_ch; + let t0 = Instant::now(); + + let mut channels: Vec> = Vec::with_capacity(n_ch); + for ch in 0..n_ch { + let mut model = DfTract::new(df_params.clone(), &r_params)?; + let mut ch_noisy = Array2::::zeros((1, n_frames)); + for i in 0..n_frames { + ch_noisy[[0, i]] = samples[i * n_ch + ch]; + } + let mut ch_enh = Array2::::zeros((1, n_frames)); + for (ns_f, enh_f) in ch_noisy + .view() + .axis_chunks_iter(Axis(1), hop) + .zip(ch_enh.view_mut().axis_chunks_iter_mut(Axis(1), hop)) + { + if ns_f.len_of(Axis(1)) < hop { + break; + } + model.process(ns_f, enh_f)?; + } + channels.push(ch_enh.row(0).to_vec()); + } + + let elapsed = t0.elapsed().as_secs_f32(); + eprintln!( + "Enhanced {} in {:.2}s (RTF: {:.3})", + file.display(), + elapsed, + elapsed / (n_frames as f32 / 48000.0) + ); + + let mut out_path = output_dir.clone(); + out_path.push(file.file_name().unwrap()); + let mut writer = hound::WavWriter::create(&out_path, spec)?; + for i in 0..n_frames { + for ch in 0..n_ch { + writer.write_sample(channels[ch][i] as i16)?; + } + } + writer.finalize()?; + eprintln!("Wrote: {}", out_path.display()); + } + + Ok(()) +} From 0124b92a902371b482ea6eadf045887b26276a00 Mon Sep 17 00:00:00 2001 From: Jackson Goode <54308792+jacksongoode@users.noreply.github.com> Date: Sat, 6 Jun 2026 21:58:47 +0900 Subject: [PATCH 5/5] tract 0.23.0 --- Cargo.lock | 814 +++++++++++++++++++++++++-------------------- libDF/Cargo.toml | 10 +- libDF/src/tract.rs | 67 ++-- 3 files changed, 493 insertions(+), 398 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d33b536d9..60340edb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,18 +8,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" version = "1.1.4" @@ -30,16 +18,16 @@ dependencies = [ ] [[package]] -name = "anyhow" -version = "1.0.100" +name = "allocator-api2" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] -name = "anymap2" -version = "0.13.0" +name = "anyhow" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "anymap3" @@ -55,18 +43,21 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bit-set" -version = "0.5.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +checksum = "09ec2f926cc3060f09db9ebc5b52823d85268d24bb917e472c0c4bea35780a7d" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" -version = "0.6.3" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" +dependencies = [ + "serde", +] [[package]] name = "bitflags" @@ -74,15 +65,6 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - [[package]] name = "byteorder" version = "1.5.0" @@ -111,6 +93,17 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core 0.10.1", +] + [[package]] name = "const-random" version = "0.1.18" @@ -126,16 +119,16 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom", + "getrandom 0.2.16", "once_cell", "tiny-keccak", ] [[package]] name = "cpufeatures" -version = "0.2.17" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] @@ -155,16 +148,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "typenum", -] - [[package]] name = "deep_filter" version = "0.5.7-pre" @@ -176,7 +159,7 @@ dependencies = [ "log", "ndarray", "num-complex", - "rand", + "rand 0.8.5", "realfft", "rust-ini", "rustfft", @@ -187,34 +170,15 @@ dependencies = [ "tract-pulse", ] -[[package]] -name = "deranged" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "powerfmt", -] - [[package]] name = "derive-new" -version = "0.5.9" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" +checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", + "syn", ] [[package]] @@ -228,9 +192,9 @@ dependencies = [ [[package]] name = "downcast-rs" -version = "1.2.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" [[package]] name = "dyn-clone" @@ -238,11 +202,17 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +[[package]] +name = "dyn-eq" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2d035d21af5cde1a6f5c7b444a5bf963520a9f142e5d06931178433d7d5388" + [[package]] name = "dyn-hash" -version = "0.2.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15401da73a9ed8c80e3b2d4dc05fe10e7b72d7243b9f614e516a44fa99986e88" +checksum = "5fdab65db9274e0168143841eb8f864a0a21f8b1b8d2ba6812bbe6024346e99e" [[package]] name = "either" @@ -250,6 +220,23 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "erased-serde" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + [[package]] name = "errno" version = "0.3.14" @@ -289,14 +276,22 @@ dependencies = [ ] [[package]] -name = "generic-array" -version = "0.14.7" +name = "float-ord" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] +checksum = "8ce81f49ae8a0482e4c55ea62ebbd7e5a686af544c00b9d090bba3ff9be97b3d" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "getrandom" @@ -309,6 +304,20 @@ dependencies = [ "wasi", ] +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "rand_core 0.10.1", + "wasip2", + "wasip3", +] + [[package]] name = "half" version = "2.4.1" @@ -325,10 +334,41 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "ahash", + "foldhash 0.1.5", ] +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", + "serde", + "serde_core", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hound" version = "3.5.1" @@ -336,19 +376,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" [[package]] -name = "itertools" -version = "0.10.5" +name = "id-arena" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ - "either", + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "inventory" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" +dependencies = [ + "rustversion", ] [[package]] name = "itertools" -version = "0.12.1" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] @@ -368,22 +426,18 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" -[[package]] -name = "kstring" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1" -dependencies = [ - "serde", - "static_assertions", -] - [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libc" version = "0.2.177" @@ -413,60 +467,6 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" -[[package]] -name = "liquid" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a494c3f9dad3cb7ed16f1c51812cbe4b29493d6c2e5cd1e2b87477263d9534d" -dependencies = [ - "liquid-core", - "liquid-derive", - "liquid-lib", - "serde", -] - -[[package]] -name = "liquid-core" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc623edee8a618b4543e8e8505584f4847a4e51b805db1af6d9af0a3395d0d57" -dependencies = [ - "anymap2", - "itertools 0.14.0", - "kstring", - "liquid-derive", - "pest", - "pest_derive", - "regex", - "serde", - "time", -] - -[[package]] -name = "liquid-derive" -version = "0.26.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de66c928222984aea59fcaed8ba627f388aaac3c1f57dcb05cc25495ef8faefe" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "liquid-lib" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9befeedd61f5995bc128c571db65300aeb50d62e4f0542c88282dbcb5f72372a" -dependencies = [ - "itertools 0.14.0", - "liquid-core", - "percent-encoding", - "regex", - "time", - "unicode-segmentation", -] - [[package]] name = "lock_api" version = "0.4.14" @@ -513,6 +513,22 @@ dependencies = [ "libc", ] +[[package]] +name = "memo-map" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d1115007560874e373613744c6fba374c17688327a71c1476d1a5954cc857b" + +[[package]] +name = "minijinja" +version = "2.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2929e494b2280e1e18959bb2e121da03347ae896896fdfaceaab43c88a02803f" +dependencies = [ + "memo-map", + "serde", +] + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -525,9 +541,9 @@ dependencies = [ [[package]] name = "ndarray" -version = "0.16.1" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" +checksum = "520080814a7a6b4a6e9070823bb24b4531daac8c4627e08ba5de8c5ef2f2752d" dependencies = [ "matrixmultiply", "num-complex", @@ -566,12 +582,6 @@ dependencies = [ "serde", ] -[[package]] -name = "num-conv" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" - [[package]] name = "num-integer" version = "0.1.46" @@ -604,7 +614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" dependencies = [ "dlv-list", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -632,58 +642,9 @@ dependencies = [ [[package]] name = "pastey" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "pest" -version = "2.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e7521a040efde50c3ab6bbadafbe15ab6dc042686926be59ac35d74607df4" -dependencies = [ - "memchr", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187da9a3030dbafabbbfb20cb323b976dc7b7ce91fcd84f2f74d6e31d378e2de" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b401d98f5757ebe97a26085998d6c0eecec4995cad6ab7fc30ffdf4b052843" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "pest_meta" -version = "2.8.3" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f27a2cfee9f9039c4d86faa5af122a0ac3851441a34865b8a043b46be0065a" -dependencies = [ - "pest", - "sha2", -] +checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" [[package]] name = "portable-atomic" @@ -700,12 +661,6 @@ dependencies = [ "portable-atomic", ] -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - [[package]] name = "ppv-lite86" version = "0.2.21" @@ -715,6 +670,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "primal-check" version = "0.3.4" @@ -735,9 +700,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.11.9" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" dependencies = [ "bytes", "prost-derive", @@ -745,15 +710,15 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.9" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.14.0", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -765,6 +730,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.8.5" @@ -773,7 +744,18 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", ] [[package]] @@ -783,7 +765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -792,17 +774,23 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.16", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "rand_distr" -version = "0.4.3" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +checksum = "4d431c2703ccf129de4d45253c03f49ebb22b97d6ad79ee3ecfc7e3f4862c1d8" dependencies = [ "num-traits", - "rand", + "rand 0.10.1", ] [[package]] @@ -895,6 +883,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "ryu" version = "1.0.20" @@ -903,10 +897,11 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "safetensors" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172dd94c5a87b5c79f945c863da53b2ebc7ccef4eca24ac63cca66a41aab2178" +checksum = "675656c1eabb620b921efea4f9199f97fc86e36dd6ffd1fbbe48d0f59a4987f5" dependencies = [ + "hashbrown 0.16.1", "serde", "serde_json", ] @@ -935,6 +930,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + [[package]] name = "serde" version = "1.0.228" @@ -962,7 +963,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.110", + "syn", ] [[package]] @@ -978,17 +979,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "shlex" version = "1.3.0" @@ -1007,12 +997,6 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strength_reduce" version = "0.2.4" @@ -1021,26 +1005,14 @@ checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" [[package]] name = "string-interner" -version = "0.15.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07f9fdfdd31a0ff38b59deb401be81b73913d76c9cc5b1aed4e1330a223420b9" +checksum = "ad3df9b59e2eded8d825c7c4363ad339a20fb6bc0b9a4778560f518f59910b15" dependencies = [ - "cfg-if", - "hashbrown", + "hashbrown 0.16.1", "serde", ] -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.110" @@ -1063,37 +1035,6 @@ dependencies = [ "xattr", ] -[[package]] -name = "time" -version = "0.3.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde_core", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" - -[[package]] -name = "time-macros" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" -dependencies = [ - "num-conv", - "time-core", -] - [[package]] name = "tiny-keccak" version = "2.0.2" @@ -1103,26 +1044,11 @@ dependencies = [ "crunchy", ] -[[package]] -name = "tinyvec" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tract-core" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65d67f5190132365dda73fe215bfc5e01b031e8cbfbea9d486bb5b0dbba3545" +checksum = "d5f279712ddd97c72a910ad8df0095c9e1de1df02feb5c0ab27d1c798f70dbee" dependencies = [ "anyhow", "anymap3", @@ -1130,6 +1056,9 @@ dependencies = [ "derive-new", "downcast-rs", "dyn-clone", + "dyn-eq", + "erased-serde", + "inventory", "lazy_static", "log", "maplit", @@ -1139,6 +1068,7 @@ dependencies = [ "num-traits", "pastey", "rustfft", + "serde", "smallvec", "tract-data", "tract-linalg", @@ -1146,16 +1076,17 @@ dependencies = [ [[package]] name = "tract-data" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73cd7fda1e5e8b854ea3abdd09126a87fc4af81e6d1e29ec1710a8a4abf4f13a" +checksum = "c67b4e3956d3ac679775f9696ca30b488b6f9a2b87e867dceb7e44a3d59f087c" dependencies = [ "anyhow", "downcast-rs", "dyn-clone", + "dyn-eq", "dyn-hash", "half", - "itertools 0.12.1", + "itertools 0.14.0", "lazy_static", "libm", "maplit", @@ -1170,11 +1101,21 @@ dependencies = [ "string-interner", ] +[[package]] +name = "tract-extra" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1943b46901d8c56a21e837fd617d0aa1fa3939cb1ee02da2671d94df88efb0" +dependencies = [ + "tract-nnef", + "tract-pulse", +] + [[package]] name = "tract-hir" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "554df991b647dba8af0547ee5838b6912ed20b424f2adda0ea0b7faf8db1b151" +checksum = "d7b6de9f37fce071636b0021201e50e580270b4cf35bfaf02f39747c7ec7d253" dependencies = [ "derive-new", "log", @@ -1183,47 +1124,45 @@ dependencies = [ [[package]] name = "tract-linalg" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72097a89cc4e7c5f1bc4f854b9294dd30fa6f6d8f7f409c556953b49078c94f" +checksum = "b9b62c33f06c11aa179c4f2d3d7774ee399bdb2f682441d61f25045da6f75096" dependencies = [ "byteorder", "cc", "derive-new", "downcast-rs", "dyn-clone", + "dyn-eq", "dyn-hash", "half", "lazy_static", - "liquid", - "liquid-core", - "liquid-derive", "log", + "minijinja", "num-traits", "pastey", "scan_fmt", - "smallvec", - "time", "tract-data", - "unicode-normalization", "walkdir", ] [[package]] name = "tract-nnef" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45b3755dd0948111b407085d11033ba218cb85b85ce8d795cec2b8353db552ea" +checksum = "5d211d77f640feae72c84e980fd9f83c1613054f93bd8163cb8b2f39864e6f74" dependencies = [ "byteorder", + "erased-serde", "flate2", - "liquid", - "liquid-core", "log", + "minijinja", "nom", "nom-language", "safetensors", + "serde", "serde_json", + "simd-adler32", "tar", "tract-core", "walkdir", @@ -1231,59 +1170,79 @@ dependencies = [ [[package]] name = "tract-onnx" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac23ad1d2d5da3256ae1a78757b1072a8a3fac2a4b28d27cfb561c5942ec2701" +checksum = "bc7113a76468378f5e0ad6c6fcfb75c36c03761cf7561a1c35a1047eef3f0c86" dependencies = [ "bytes", "derive-new", + "dyn-eq", "log", "memmap2", "num-integer", "prost", "smallvec", + "tract-extra", "tract-hir", "tract-nnef", "tract-onnx-opl", + "tract-transformers", ] [[package]] name = "tract-onnx-opl" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87561bf0b84f74a124afc0f1997682728da6cd821083511e0357432954fd24f6" +checksum = "fd5004ba96b12e372a4c7a5b35e664549980be4e258076a452ad39c1d0993a69" dependencies = [ - "getrandom", + "dyn-eq", + "getrandom 0.4.2", "log", - "rand", + "rand 0.10.1", "rand_distr", "rustfft", + "tract-extra", "tract-nnef", ] [[package]] name = "tract-pulse" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff926428bf533d0d8ee70e2626fb9f8197d33d3cc9e0cafc3f9acf8e11b4dd93" +checksum = "4407005adcdb45c4edb4f37bc5dc75125c212bb499e6a67a5013c53c6093f5b8" dependencies = [ "downcast-rs", + "dyn-eq", + "erased-serde", "lazy_static", "log", + "serde", "tract-pulse-opl", + "tract-transformers", ] [[package]] name = "tract-pulse-opl" -version = "0.22.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5621466758a263fb3baf6494a9aca555dd90c1c0c5216186987a1857bca21f87" +checksum = "946214c9bd9f801f3c3e448808f5fa0405829ba7bf8fe73cd7f0df54aeb1d3c0" dependencies = [ "downcast-rs", + "dyn-eq", "lazy_static", "tract-nnef", ] +[[package]] +name = "tract-transformers" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c6b4c22125bd5c653e57df2cc6db754878515dffd9232fc1aff5d0ded2dd9e5" +dependencies = [ + "float-ord", + "tract-nnef", +] + [[package]] name = "transpose" version = "0.2.3" @@ -1295,16 +1254,10 @@ dependencies = [ ] [[package]] -name = "typenum" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" - -[[package]] -name = "ucd-trie" -version = "0.1.7" +name = "typeid" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "unicode-ident" @@ -1313,25 +1266,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] -name = "unicode-normalization" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" - -[[package]] -name = "version_check" -version = "0.9.5" +name = "unicode-xid" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "walkdir" @@ -1349,6 +1287,58 @@ version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "winapi-util" version = "0.1.11" @@ -1447,6 +1437,100 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + [[package]] name = "xattr" version = "1.6.1" @@ -1474,5 +1558,5 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn 2.0.110", + "syn", ] diff --git a/libDF/Cargo.toml b/libDF/Cargo.toml index 4deb93dec..e83c39812 100644 --- a/libDF/Cargo.toml +++ b/libDF/Cargo.toml @@ -24,16 +24,16 @@ hound = "3.5" itertools = "0.10" log = { version = "0.4", features = ["std"] } -ndarray = "^0.16" +ndarray = "^0.17" num-complex = { version = "^0.4", features = ["serde"] } realfft = "^3.5" rust-ini = "^0.21" rustfft = "^6.4" tar = "^0.4" -tract-core = "^0.22" -tract-hir = "^0.22" -tract-onnx = "^0.22" -tract-pulse = "^0.22" +tract-core = "^0.23" +tract-hir = "^0.23" +tract-onnx = "^0.23" +tract-pulse = "^0.23" [dev-dependencies] rand = "^0.8" diff --git a/libDF/src/tract.rs b/libDF/src/tract.rs index a4a4bb0d1..958567b3d 100644 --- a/libDF/src/tract.rs +++ b/libDF/src/tract.rs @@ -2,7 +2,7 @@ use crate::DFState; use anyhow::{Context, Result}; use flate2::read::GzDecoder; use ini::Ini; -use ndarray::{prelude::*, Axis}; +use ndarray::{s, ArrayView2, ArrayView3, ArrayViewD, ArrayViewMut2, ArrayViewMutD, Axis, Ix2}; use num_complex::Complex32; use std::{ fs::File, @@ -14,6 +14,7 @@ use tract_core::{ internal::{tract_itertools::izip, tract_smallvec::alloc::collections::VecDeque}, ops, prelude::*, + runtime::{runtime_for_name, State}, }; use tract_onnx::{prelude::*, tract_hir::shapefactoid}; use tract_pulse::{internal::ToDim, model::*}; @@ -169,9 +170,8 @@ impl Default for RuntimeParams { } } -pub type TractModel = TypedSimpleState>; +pub type TractModel = Box; -#[derive(Clone)] pub struct DfTract { enc: TractModel, erb_dec: TractModel, @@ -213,6 +213,7 @@ impl DfTract { let df_cfg = config.section(Some("df")).unwrap(); let ch = rp.n_ch; + let runtime = runtime_for_name("cpu")?.context("cpu runtime not available")?; let enc = init_encoder_from_read(&mut Cursor::new(dfp.enc), df_cfg, ch)?; let erb_dec = init_erb_decoder_from_read( &mut Cursor::new(dfp.erb_dec), @@ -223,9 +224,9 @@ impl DfTract { )?; let df_dec = init_df_decoder_from_read(&mut Cursor::new(dfp.df_dec), model_cfg, df_cfg, ch)?; - let enc = SimpleState::new(enc.into_runnable()?)?; - let erb_dec = SimpleState::new(erb_dec.into_runnable()?)?; - let df_dec = SimpleState::new(df_dec.into_runnable()?)?; + let enc: TractModel = runtime.prepare(enc)?.spawn()?; + let erb_dec: TractModel = runtime.prepare(erb_dec)?.spawn()?; + let df_dec: TractModel = runtime.prepare(df_dec)?.spawn()?; let sr = df_cfg.get("sr").unwrap().parse::()?; let hop_size = df_cfg.get("hop_size").unwrap().parse::()?; @@ -388,13 +389,15 @@ impl DfTract { /// - gains: Gain estimates of shape `[n_ch, 1, 1, n_erb]`. /// - coefs: Real-valued DF coefficients estimates of shape `[n_ch, 1, 1, n_erb, 2]`. pub fn process_raw(&mut self) -> Result<(f32, Option, Option)> { - let spec = self.spec_buf.to_array_view()?; + let spec = self.spec_buf.to_plain_array_view()?; let ch = spec.len_of(Axis(0)); + let mut erb_view = tvalue_to_array_view_mut(&mut self.erb_buf); + let mut cplx_view = tvalue_to_array_view_mut(&mut self.cplx_buf); for (nsy_ch, mut erb_ch, mut cplx_ch, state) in izip!( spec.axis_iter(Axis(0)), - tvalue_to_array_view_mut(&mut self.erb_buf).axis_iter_mut(Axis(0)), - tvalue_to_array_view_mut(&mut self.cplx_buf).axis_iter_mut(Axis(0)), + erb_view.axis_iter_mut(Axis(0)), + cplx_view.axis_iter_mut(Axis(0)), self.df_states.iter_mut() ) { let nsy_ch = as_slice_complex(nsy_ch.as_slice().unwrap()); @@ -412,7 +415,11 @@ impl DfTract { ))?; // Note: This will fail if multiple channels are passed in. - let &lsnr = enc_emb.pop().unwrap().to_scalar::()?; + let lsnr_t = enc_emb.pop().unwrap(); + let lsnr = lsnr_t + .into_tensor() + .to_plain_array_view::() + .unwrap()[[0, 0, 0]]; let c0 = enc_emb.pop().unwrap(); let emb = enc_emb.pop().unwrap(); @@ -474,9 +481,10 @@ impl DfTract { // Signal model: y = f(s + n) = f(x) self.rolling_spec_buf_y.pop_front(); self.rolling_spec_buf_x.pop_front(); + let mut spec_buf_view = self.spec_buf.to_plain_array_view_mut()?; for (ns_ch, mut rbuf, state) in izip!( noisy.axis_iter(Axis(0)), - self.spec_buf.to_array_view_mut()?.axis_iter_mut(Axis(0)), + spec_buf_view.axis_iter_mut(Axis(0)), self.df_states.iter_mut(), ) { let spec = as_slice_mut_complex(rbuf.as_slice_mut().unwrap()); @@ -492,10 +500,13 @@ impl DfTract { let (lsnr, gains, coefs) = self.process_raw()?; let (apply_erb, _, _) = self.apply_stages(lsnr); - let mut spec = - self.rolling_spec_buf_y.get_mut(self.df_order - 1).unwrap().to_array_view_mut()?; + let mut spec = self + .rolling_spec_buf_y + .get_mut(self.df_order - 1) + .unwrap() + .to_plain_array_view_mut()?; if let Some(gains) = gains { - let mut gains = gains.into_array()?; + let mut gains = gains.into_plain_array()?; if gains.shape()[0] < noisy.shape()[0] { // Mask was reduced to single channel let gain_slc = gains.as_slice_mut().unwrap(); @@ -541,14 +552,14 @@ impl DfTract { self.rolling_spec_buf_x .get(self.lookahead.max(self.df_order) - self.lookahead - 1) .unwrap() - .to_array_view::() + .to_plain_array_view::() .unwrap(), &[self.ch, self.n_freqs], ) .into_dimensionality::() .unwrap(); let mut spec_enh = as_arrayview_mut_complex( - self.spec_buf.to_array_view_mut::().unwrap(), + self.spec_buf.to_plain_array_view_mut::().unwrap(), &[self.ch, self.n_freqs], ) .into_dimensionality::() @@ -614,7 +625,7 @@ impl DfTract { pub fn set_spec_buffer(&mut self, spec: ArrayView2) -> Result<()> { debug_assert_eq!(self.spec_buf.shape(), spec.shape()); - let view = self.spec_buf.to_array_view_mut()?; + let view = self.spec_buf.to_plain_array_view_mut()?; let mut buf = view.to_shape([self.ch, self.n_freqs])?; for (i_ch, mut b_ch) in spec.outer_iter().zip(buf.outer_iter_mut()) { for (&i, b) in i_ch.iter().zip(b_ch.iter_mut()) { @@ -629,7 +640,7 @@ impl DfTract { self.rolling_spec_buf_x .get(self.lookahead.max(self.df_order) - self.lookahead - 1) .unwrap() - .to_array_view::() + .to_plain_array_view::() .unwrap(), &[self.ch, self.n_freqs], ) @@ -639,7 +650,7 @@ impl DfTract { pub fn get_spec_enh(&self) -> ArrayView2<'_, Complex32> { as_arrayview_complex( - self.spec_buf.to_array_view::().unwrap(), + self.spec_buf.to_plain_array_view::().unwrap(), &[self.ch, self.n_freqs], ) .into_dimensionality::() @@ -648,7 +659,7 @@ impl DfTract { pub fn get_mut_spec_enh(&mut self) -> ArrayViewMut2<'_, Complex32> { as_arrayview_mut_complex( - self.spec_buf.to_array_view_mut::().unwrap(), + self.spec_buf.to_plain_array_view_mut::().unwrap(), &[self.ch, self.n_freqs], ) .into_dimensionality::() @@ -682,16 +693,16 @@ fn df( debug_assert_eq!(ch, spec_out.shape()[0]); debug_assert!(spec.len() >= df_order); let mut o_f: ArrayViewMut2 = - as_arrayview_mut_complex(spec_out.to_array_view_mut::()?, &[ch, n_freqs]) + as_arrayview_mut_complex(spec_out.to_plain_array_view_mut::()?, &[ch, n_freqs]) .into_dimensionality()?; // Zero relevant frequency bins of output o_f.slice_mut(s![.., ..nb_df]).fill(Complex32::default()); let coefs_arr: ArrayView3 = - as_arrayview_complex(coefs.to_array_view::()?, &[ch, nb_df, df_order]) + as_arrayview_complex(coefs.to_plain_array_view::()?, &[ch, nb_df, df_order]) .into_dimensionality()?; // Transform spec to an complex array and iterate over time frames of spec and coefs let spec_iter = spec.iter().map(|s| { - as_arrayview_complex(s.to_array_view::().unwrap(), &[ch, n_freqs]) + as_arrayview_complex(s.to_plain_array_view::().unwrap(), &[ch, n_freqs]) .into_dimensionality::() .unwrap() }); @@ -732,7 +743,7 @@ fn init_encoder_impl( .with_input_fact(0, feat_erb)? .with_input_fact(1, feat_spec)? .with_input_names(["feat_erb", "feat_spec"])? - .with_output_names(["e0", "e1", "e2", "e3", "emb", "c0", "lsnr"])?; + .with_outputs_by_name(["e0", "e1", "e2", "e3", "emb", "c0", "lsnr"])?; m.analyse(true)?; let mut m = m.into_typed()?; @@ -834,7 +845,7 @@ fn init_erb_decoder_impl( _ => (), } } - m = m.with_output_names(&[output_name])?; + m = m.with_outputs_by_name(&[output_name])?; let m = m.into_optimized()?; @@ -874,7 +885,7 @@ fn init_df_decoder_impl( .with_input_fact(0, emb)? .with_input_fact(1, c0)? .with_input_names(["emb", "c0"])? - .with_output_names(["coefs"])?; + .with_outputs_by_name(["coefs"])?; m.analyse(true)?; let mut m = m.into_typed()?; @@ -979,10 +990,10 @@ pub fn tvalue_to_array_view_mut(x: &mut TValue) -> ArrayViewMutD<'_, f32> { match x { TValue::Var(x) => { ArrayViewMutD::from_shape_ptr(x.shape(), x.as_ptr_unchecked::() as *mut f32) - }, + } TValue::Const(x) => { ArrayViewMutD::from_shape_ptr(x.shape(), x.as_ptr_unchecked::() as *mut f32) - }, + } } } }