From e949023dda970bf7386664c27cc6bbb052cfe753 Mon Sep 17 00:00:00 2001 From: rustdesk Date: Sun, 1 Aug 2021 11:01:04 +0800 Subject: [PATCH] try out the other audio resampler --- Cargo.lock | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 8 ++++- src/common.rs | 78 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index e0f543cd1..a72527f73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -338,6 +338,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "cmake" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb6210b637171dfba4cda12e579ac6dc73f5165ad56133e5d72ef3131f320855" +dependencies = [ + "cc", +] + [[package]] name = "cocoa" version = "0.24.0" @@ -1605,6 +1614,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "libsamplerate-sys" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403163258e75b5780cd6245c04cddd7f3166c5f8dd2bf5462e596c9ca4eb9653" +dependencies = [ + "cmake", +] + [[package]] name = "libsodium-sys" version = "0.2.7" @@ -1901,6 +1919,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "num-complex" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" +dependencies = [ + "num-traits 0.2.14", +] + [[package]] name = "num-derive" version = "0.3.3" @@ -2191,6 +2218,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5c99d529f0d30937f6f4b8a86d988047327bb88d04d2c4afc356de74722131" +[[package]] +name = "primal-check" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01419cee72c1a1ca944554e23d83e483e1bccf378753344e881de28b5487511d" +dependencies = [ + "num-integer", +] + [[package]] name = "proc-macro-crate" version = "0.1.5" @@ -2557,6 +2593,15 @@ dependencies = [ "rand_core 0.3.1", ] +[[package]] +name = "realfft" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7695c87f31dc3644760f23fb59a3fed47659703abf76cf2d111f03b9e712342" +dependencies = [ + "rustfft", +] + [[package]] name = "redox_syscall" version = "0.2.9" @@ -2648,6 +2693,19 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "rubato" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b32df824bfec62fa252d850f346e867f43b66e5d429161f99ccfb7f1cb9ec148" +dependencies = [ + "log", + "num-complex", + "num-integer", + "num-traits 0.2.14", + "realfft", +] + [[package]] name = "runas" version = "0.2.1" @@ -2712,8 +2770,10 @@ dependencies = [ "psutil", "repng", "rpassword 5.0.1", + "rubato", "runas", "rust-pulsectl", + "samplerate", "sciter-rs", "scrap", "serde 1.0.126", @@ -2728,6 +2788,20 @@ dependencies = [ "winres", ] +[[package]] +name = "rustfft" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d089e5c57521629a59f5f39bca7434849ff89bd6873b521afe389c1c602543" +dependencies = [ + "num-complex", + "num-integer", + "num-traits 0.2.14", + "primal-check", + "strength_reduce", + "transpose", +] + [[package]] name = "rustls" version = "0.17.0" @@ -2774,6 +2848,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "samplerate" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e032b2b24715c4f982f483ea3abdb3c9ba444d9f63e87b2843d6f998f5ba2698" +dependencies = [ + "libsamplerate-sys", +] + [[package]] name = "schannel" version = "0.1.19" @@ -3032,6 +3115,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" +[[package]] +name = "strength_reduce" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3ff2f71c82567c565ba4b3009a9350a96a7269eaa4001ebedae926230bc2254" + [[package]] name = "strsim" version = "0.8.0" @@ -3295,6 +3384,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "transpose" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95f9c900aa98b6ea43aee227fd680550cdec726526aab8ac801549eadb25e39f" +dependencies = [ + "num-integer", + "strength_reduce", +] + [[package]] name = "typenum" version = "1.13.0" diff --git a/Cargo.toml b/Cargo.toml index a2cdc4c2e..7b0971f54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,10 @@ description = "A remote control software." [features] inline = [] cli = [] +use_samplerate = ["samplerate"] +use_rubato = ["rubato"] +use_dasp = ["dasp"] +default = ["use_dasp"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -29,7 +33,9 @@ parity-tokio-ipc = { git = "https://github.com/open-trade/parity-tokio-ipc" } flexi_logger = "0.16" runas = "0.2" magnum-opus = { git = "https://github.com/open-trade/magnum-opus" } -dasp = { version = "0.11", features = ["signal", "interpolate-linear", "interpolate"] } +dasp = { version = "0.11", features = ["signal", "interpolate-linear", "interpolate"], optional = true } +rubato = { version = "0.8", optional = true } +samplerate = { version = "0.2", optional = true } async-trait = "0.1" crc32fast = "1.2" uuid = { version = "0.8", features = ["v4"] } diff --git a/src/common.rs b/src/common.rs index 6005e3cca..bbb641f53 100644 --- a/src/common.rs +++ b/src/common.rs @@ -105,6 +105,66 @@ pub fn update_clipboard(clipboard: Clipboard, old: Option<&Arc>>) } } +#[cfg(feature = "use_rubato")] +pub fn resample_channels( + data: &[f32], + sample_rate0: u32, + sample_rate: u32, + channels: u16, +) -> Vec { + use rubato::{ + InterpolationParameters, InterpolationType, Resampler, SincFixedIn, WindowFunction, + }; + let params = InterpolationParameters { + sinc_len: 256, + f_cutoff: 0.95, + interpolation: InterpolationType::Nearest, + oversampling_factor: 160, + window: WindowFunction::BlackmanHarris2, + }; + let mut resampler = SincFixedIn::::new( + sample_rate as f64 / sample_rate0 as f64, + params, + data.len() / (channels as usize), + channels as _, + ); + let mut waves_in = Vec::new(); + if channels == 2 { + waves_in.push( + data.iter() + .step_by(2) + .map(|x| *x as f64) + .collect::>(), + ); + waves_in.push( + data.iter() + .skip(1) + .step_by(2) + .map(|x| *x as f64) + .collect::>(), + ); + } else { + waves_in.push(data.iter().map(|x| *x as f64).collect::>()); + } + if let Ok(x) = resampler.process(&waves_in) { + if x.is_empty() { + Vec::new() + } else if waves_in.len() == 2 { + waves_in[0] + .chunks(1) + .zip(waves_in[1].chunks(1)) + .flat_map(|(a, b)| a.into_iter().chain(b)) + .map(|x| *x as f32) + .collect() + } else { + waves_in[0].iter().map(|x| *x as f32).collect() + } + } else { + Vec::new() + } +} + +#[cfg(feature = "use_dasp")] pub fn resample_channels( data: &[f32], sample_rate0: u32, @@ -140,6 +200,24 @@ pub fn resample_channels( } } +#[cfg(feature = "use_samplerate")] +pub fn resample_channels( + data: &[f32], + sample_rate0: u32, + sample_rate: u32, + channels: u16, +) -> Vec { + use samplerate::{convert, ConverterType}; + convert( + sample_rate0 as _, + sample_rate as _, + channels as _, + ConverterType::SincBestQuality, + data, + ) + .unwrap_or_default() +} + pub fn test_nat_type() { std::thread::spawn(move || loop { match test_nat_type_() {