From 5aacf6edbfdceb49e8568a88e0c85554bfb02a42 Mon Sep 17 00:00:00 2001 From: Nathan Graule Date: Tue, 6 Feb 2024 11:22:34 +0100 Subject: [PATCH 1/4] feat: initial integration with fundsp under a flag --- Cargo.lock | 318 +++++++++++ Cargo.toml | 4 + src/contrib/fundsp.rs | 37 ++ src/contrib/mod.rs | 2 + ...alib__contrib__fundsp__tests__wrapper.snap | 516 ++++++++++++++++++ src/lib.rs | 6 +- 6 files changed, 881 insertions(+), 2 deletions(-) create mode 100644 src/contrib/fundsp.rs create mode 100644 src/contrib/mod.rs create mode 100644 src/contrib/snapshots/valib__contrib__fundsp__tests__wrapper.snap diff --git a/Cargo.lock b/Cargo.lock index f22d7f8..f52bc12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1256,12 +1256,37 @@ dependencies = [ "dtoa", ] +[[package]] +name = "duplicate" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de78e66ac9061e030587b2a2e75cc88f22304913c907b11307bca737141230cb" +dependencies = [ + "heck", + "proc-macro-error", +] + +[[package]] +name = "dyn-clone" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" + [[package]] name = "encode_unicode" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + [[package]] name = "enum-map" version = "2.7.3" @@ -1469,6 +1494,37 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "fundsp" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3141b9fedca9574471937068b7f8c38bb6da78e11db06aa72f0586e7cdb8de8" +dependencies = [ + "duplicate", + "dyn-clone", + "funutd", + "generic-array", + "lazy_static", + "num-complex", + "numeric-array", + "realfft", + "rsor", + "rustfft", + "symphonia", + "thingbuf", + "tinyvec", +] + +[[package]] +name = "funutd" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3abd023cc7d4c09be0925c855ba1d09a235c3e702c036a688086bf76960938" +dependencies = [ + "dyn-clone", + "glam", +] + [[package]] name = "futures" version = "0.3.30" @@ -1666,6 +1722,12 @@ dependencies = [ "xml-rs", ] +[[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" @@ -2538,6 +2600,16 @@ dependencies = [ "libc", ] +[[package]] +name = "numeric-array" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c59a9b227913a685ed84aa0de5ded58274e8bcfa55760faae07bc82aee64ccf" +dependencies = [ + "generic-array", + "num-traits", +] + [[package]] name = "numeric_literals" version = "0.2.0" @@ -2806,6 +2878,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -2927,6 +3019,30 @@ dependencies = [ "toml_edit", ] +[[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-macro-hack" version = "0.5.20+deprecated" @@ -3142,6 +3258,12 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "rsor" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85513d00796366e2d0acbfff0e7d6c7b916dab787712de18eb0a67776f8e7629" + [[package]] name = "rstest" version = "0.18.2" @@ -3546,6 +3668,189 @@ dependencies = [ "zeno", ] +[[package]] +name = "symphonia" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e48dba70095f265fdb269b99619b95d04c89e619538138383e63310b14d941" +dependencies = [ + "lazy_static", + "symphonia-bundle-flac", + "symphonia-bundle-mp3", + "symphonia-codec-aac", + "symphonia-codec-adpcm", + "symphonia-codec-alac", + "symphonia-codec-pcm", + "symphonia-codec-vorbis", + "symphonia-core", + "symphonia-format-isomp4", + "symphonia-format-mkv", + "symphonia-format-ogg", + "symphonia-format-wav", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-bundle-flac" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f23b0482a7cb18fcdf9981ab0b78df800ef0080187d294650023c462439058d" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-bundle-mp3" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f31d7fece546f1e6973011a9eceae948133bbd18fd3d52f6073b1e38ae6368a" +dependencies = [ + "bitflags 1.3.2", + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-codec-aac" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68bdd75b25ce4b84b12a4bd20bfea2460c2dbd7fc1d227ef5533504d3168109d" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-adpcm" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "870e7dc1865d818c7b6318879d060553a73a3b2a3b8443dff90910f10ac41150" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-alac" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a27e8763d1c9eff666faf903e73a99d4de2f7a93fca4e3c214c1d68432903b9" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-pcm" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47f1fbd220a06a641c8ce2ddad10f5ef6ee5cc0c54d9044d25d43b0d3119deaa" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-vorbis" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3953397e3506aa01350c4205817e4f95b58d476877a42f0458d07b665749e203" +dependencies = [ + "log", + "symphonia-core", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-core" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c73eb88fee79705268cc7b742c7bc93a7b76e092ab751d0833866970754142" +dependencies = [ + "arrayvec", + "bitflags 1.3.2", + "bytemuck", + "lazy_static", + "log", +] + +[[package]] +name = "symphonia-format-isomp4" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf14bae5cf352032416bc64151e5d6242d29d33cbf3238513b44d4427a1efb" +dependencies = [ + "encoding_rs", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-mkv" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5c61dfc851ad25d4043d8c231d8617e8f7cd02a6cc0edad21ade21848d58895" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-ogg" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bf1a00ccd11452d44048a0368828040f778ae650418dbd9d8765b7ee2574c8d" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-wav" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da76614728fa27c003bdcdfbac51396bd8fcbf94c95fe8e62f1d2bac58ef03a4" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-metadata" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89c3e1937e31d0e068bbe829f66b2f2bfaa28d056365279e0ef897172c3320c0" +dependencies = [ + "encoding_rs", + "lazy_static", + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-utils-xiph" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a450ca645b80d69aff8b35576cbfdc7f20940b29998202aab910045714c951f8" +dependencies = [ + "symphonia-core", + "symphonia-metadata", +] + [[package]] name = "syn" version = "1.0.109" @@ -3609,6 +3914,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "thingbuf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4706f1bfb859af03f099ada2de3cea3e515843c2d3e93b7893f16d94a37f9415" +dependencies = [ + "parking_lot", + "pin-project", +] + [[package]] name = "thiserror" version = "1.0.50" @@ -3923,15 +4238,18 @@ version = "0.1.0" dependencies = [ "az", "csv", + "fundsp", "enum-map", "insta", "nalgebra", "num-traits", + "numeric-array", "numeric_literals", "portable-atomic", "rstest", "serde", "simba", + "typenum", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 84adef2..8337b71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,11 +27,14 @@ nalgebra = "0.32.3" [dependencies] az = "1.2.1" enum-map.workspace = true +fundsp = { version = "0.16.0", optional = true } nalgebra.workspace = true num-traits = "0.2.17" +numeric-array = { version = "0.5.2", optional = true } numeric_literals = "0.2.0" portable-atomic = { version = "1.6.0", features = ["float"] } simba = { version = "0.8.1", features = ["wide"] } +typenum = { version = "1.17.0", optional = true } [dev-dependencies] csv = "1.1.6" @@ -41,6 +44,7 @@ serde = "*" [features] unstable-wdf = [] +fundsp = ["dep:fundsp", "dep:numeric-array", "dep:typenum"] [profile.dev] opt-level = 1 diff --git a/src/contrib/fundsp.rs b/src/contrib/fundsp.rs new file mode 100644 index 0000000..f1f28d6 --- /dev/null +++ b/src/contrib/fundsp.rs @@ -0,0 +1,37 @@ +use crate::dsp::DSP; +use fundsp::audionode::{AudioNode, Frame}; +use fundsp::combinator::An; +use typenum::Unsigned; + +impl DSP<{ Node::Inputs::USIZE }, { Node::Outputs::USIZE }> for An +where + Node::Sample: crate::Scalar, +{ + type Sample = Node::Sample; + + fn process( + &mut self, + x: [Self::Sample; Node::Inputs::USIZE], + ) -> [Self::Sample; Node::Outputs::USIZE] { + let input = Frame::from_slice(&x); + let output = self.tick(input); + std::array::from_fn(|i| output[i]) + } +} + +#[cfg(test)] +mod tests { + use crate::dsp::{utils::slice_to_mono_block_mut, DSPBlock}; + + use fundsp::hacker32::*; + + #[test] + fn test_wrapper() { + let mut dsp = sine_hz(440.0) * sine_hz(10.0); + let input = [[]; 512]; + let mut output = [0.0; 512]; + dsp.process_block(&input, slice_to_mono_block_mut(&mut output)); + + insta::assert_csv_snapshot!(&output as &[_], { "[]" => insta::rounded_redaction(3) }) + } +} diff --git a/src/contrib/mod.rs b/src/contrib/mod.rs new file mode 100644 index 0000000..f9ebcc7 --- /dev/null +++ b/src/contrib/mod.rs @@ -0,0 +1,2 @@ +#[cfg(feature = "fundsp")] +pub mod fundsp; \ No newline at end of file diff --git a/src/contrib/snapshots/valib__contrib__fundsp__tests__wrapper.snap b/src/contrib/snapshots/valib__contrib__fundsp__tests__wrapper.snap new file mode 100644 index 0000000..5ac83f1 --- /dev/null +++ b/src/contrib/snapshots/valib__contrib__fundsp__tests__wrapper.snap @@ -0,0 +1,516 @@ +--- +source: src/contrib/fundsp.rs +expression: "&output as &[_]" +--- +-0.222 +-0.229 +-0.235 +-0.24 +-0.245 +-0.248 +-0.25 +-0.252 +-0.252 +-0.252 +-0.25 +-0.248 +-0.244 +-0.24 +-0.234 +-0.227 +-0.22 +-0.211 +-0.202 +-0.191 +-0.18 +-0.168 +-0.155 +-0.142 +-0.127 +-0.112 +-0.097 +-0.08 +-0.064 +-0.047 +-0.029 +-0.012 +0.006 +0.024 +0.042 +0.06 +0.078 +0.096 +0.114 +0.131 +0.148 +0.165 +0.181 +0.197 +0.211 +0.226 +0.239 +0.252 +0.263 +0.274 +0.284 +0.292 +0.3 +0.306 +0.312 +0.316 +0.319 +0.32 +0.321 +0.32 +0.317 +0.314 +0.309 +0.303 +0.296 +0.287 +0.278 +0.267 +0.255 +0.241 +0.227 +0.212 +0.196 +0.179 +0.161 +0.142 +0.122 +0.102 +0.082 +0.06 +0.039 +0.017 +-0.005 +-0.027 +-0.05 +-0.072 +-0.094 +-0.116 +-0.138 +-0.159 +-0.18 +-0.2 +-0.22 +-0.238 +-0.256 +-0.274 +-0.29 +-0.305 +-0.319 +-0.332 +-0.344 +-0.354 +-0.363 +-0.371 +-0.377 +-0.382 +-0.385 +-0.387 +-0.387 +-0.386 +-0.383 +-0.379 +-0.373 +-0.366 +-0.357 +-0.346 +-0.335 +-0.321 +-0.307 +-0.291 +-0.274 +-0.256 +-0.236 +-0.216 +-0.194 +-0.172 +-0.148 +-0.125 +-0.1 +-0.075 +-0.049 +-0.023 +0.003 +0.029 +0.056 +0.082 +0.108 +0.134 +0.16 +0.185 +0.209 +0.233 +0.256 +0.278 +0.299 +0.32 +0.339 +0.356 +0.373 +0.388 +0.401 +0.413 +0.424 +0.433 +0.44 +0.446 +0.449 +0.452 +0.452 +0.45 +0.447 +0.442 +0.435 +0.426 +0.416 +0.404 +0.39 +0.375 +0.358 +0.34 +0.32 +0.298 +0.276 +0.252 +0.227 +0.201 +0.175 +0.147 +0.119 +0.09 +0.06 +0.03 +-0.0 +-0.03 +-0.061 +-0.091 +-0.121 +-0.151 +-0.18 +-0.209 +-0.237 +-0.264 +-0.291 +-0.316 +-0.34 +-0.363 +-0.385 +-0.405 +-0.424 +-0.441 +-0.457 +-0.47 +-0.482 +-0.493 +-0.501 +-0.507 +-0.512 +-0.514 +-0.514 +-0.512 +-0.509 +-0.503 +-0.495 +-0.485 +-0.474 +-0.46 +-0.444 +-0.427 +-0.408 +-0.387 +-0.365 +-0.341 +-0.315 +-0.288 +-0.26 +-0.231 +-0.201 +-0.17 +-0.137 +-0.105 +-0.072 +-0.038 +-0.004 +0.03 +0.065 +0.099 +0.132 +0.166 +0.199 +0.231 +0.263 +0.293 +0.323 +0.351 +0.379 +0.404 +0.429 +0.452 +0.473 +0.492 +0.509 +0.525 +0.538 +0.55 +0.559 +0.566 +0.571 +0.574 +0.574 +0.572 +0.568 +0.562 +0.553 +0.542 +0.529 +0.514 +0.497 +0.478 +0.456 +0.433 +0.408 +0.382 +0.353 +0.324 +0.293 +0.26 +0.227 +0.192 +0.157 +0.12 +0.083 +0.046 +0.009 +-0.029 +-0.067 +-0.105 +-0.142 +-0.179 +-0.216 +-0.251 +-0.286 +-0.32 +-0.353 +-0.384 +-0.414 +-0.443 +-0.47 +-0.495 +-0.518 +-0.54 +-0.559 +-0.576 +-0.591 +-0.604 +-0.614 +-0.622 +-0.627 +-0.63 +-0.631 +-0.629 +-0.625 +-0.618 +-0.608 +-0.597 +-0.582 +-0.566 +-0.547 +-0.526 +-0.503 +-0.478 +-0.45 +-0.421 +-0.391 +-0.358 +-0.324 +-0.289 +-0.252 +-0.214 +-0.176 +-0.136 +-0.096 +-0.055 +-0.014 +0.027 +0.069 +0.11 +0.151 +0.191 +0.231 +0.27 +0.308 +0.345 +0.38 +0.415 +0.448 +0.479 +0.508 +0.536 +0.561 +0.584 +0.605 +0.624 +0.64 +0.654 +0.666 +0.674 +0.68 +0.684 +0.685 +0.683 +0.678 +0.671 +0.661 +0.648 +0.633 +0.615 +0.595 +0.572 +0.547 +0.52 +0.491 +0.46 +0.426 +0.391 +0.355 +0.316 +0.277 +0.236 +0.194 +0.152 +0.108 +0.064 +0.02 +-0.024 +-0.069 +-0.113 +-0.157 +-0.201 +-0.244 +-0.286 +-0.327 +-0.367 +-0.405 +-0.442 +-0.478 +-0.512 +-0.543 +-0.573 +-0.6 +-0.626 +-0.648 +-0.669 +-0.686 +-0.701 +-0.714 +-0.723 +-0.73 +-0.734 +-0.735 +-0.733 +-0.728 +-0.721 +-0.71 +-0.697 +-0.681 +-0.662 +-0.64 +-0.616 +-0.59 +-0.561 +-0.529 +-0.496 +-0.46 +-0.423 +-0.384 +-0.343 +-0.301 +-0.258 +-0.213 +-0.167 +-0.121 +-0.074 +-0.027 +0.021 +0.068 +0.116 +0.163 +0.209 +0.255 +0.3 +0.344 +0.387 +0.428 +0.467 +0.505 +0.541 +0.575 +0.607 +0.636 +0.663 +0.688 +0.709 +0.729 +0.745 +0.758 +0.768 +0.776 +0.78 +0.781 +0.78 +0.775 +0.767 +0.756 +0.742 +0.725 +0.705 +0.682 +0.657 +0.629 +0.598 +0.565 +0.53 +0.493 +0.453 +0.412 +0.369 +0.324 +0.278 +0.231 +0.183 +0.134 +0.084 +0.034 +-0.016 +-0.066 +-0.117 +-0.167 +-0.216 +-0.264 +-0.312 +-0.358 +-0.404 +-0.447 +-0.489 +-0.529 +-0.568 +-0.604 +-0.637 +-0.669 +-0.697 +-0.723 +-0.746 +-0.767 +-0.784 +-0.798 +-0.81 +-0.818 +-0.822 +-0.824 +-0.822 +-0.817 +-0.809 diff --git a/src/lib.rs b/src/lib.rs index 875d34e..b6b9b67 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,13 @@ -extern crate core; - +#![cfg_attr(feature = "fundsp", feature(generic_const_exprs))] use az::CastFrom; use num_traits::Zero; use simba::simd::{AutoSimd, SimdRealField, SimdValue}; pub use simba::simd; +#[cfg(feature = "fundsp")] +pub use contrib::fundsp; +pub mod contrib; pub mod dsp; pub mod filters; pub mod fir; From 185945459ea8faeacdd42e0c5d114bb48c36fa06 Mon Sep 17 00:00:00 2001 From: Nathan Graule Date: Wed, 7 Feb 2024 09:01:55 +0100 Subject: [PATCH 2/4] add vscode settings to turn on fundsp feature by default --- .vscode/settings.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..87ef995 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "rust-analyzer.cargo.features": [ + "fundsp" + ] +} \ No newline at end of file From 0a88289d8a888943d4e048389d357e8fd8607c4e Mon Sep 17 00:00:00 2001 From: Nathan Graule Date: Sun, 11 Feb 2024 15:28:44 +0100 Subject: [PATCH 3/4] fix: implementation of freestanding integrator --- src/dsp/blocks.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/dsp/blocks.rs b/src/dsp/blocks.rs index e5f0b89..f0eaf1f 100644 --- a/src/dsp/blocks.rs +++ b/src/dsp/blocks.rs @@ -33,10 +33,12 @@ impl Default for Integrator { impl DSP<1, 1> for Integrator { type Sample = T; + #[replace_float_literals(T::from_f64(literal))] fn process(&mut self, x: [Self::Sample; 1]) -> [Self::Sample; 1] { - let in0 = x[0] + self.0; - self.0 += in0; - [self.0] + let x2 = x[0] / 2.0; + let out = x2 + self.0; + self.0 = x2 + out; + [out] } } From e0e64eb93a685d248d91a0b9b7df22797cfbe929 Mon Sep 17 00:00:00 2001 From: Nathan Graule Date: Sun, 11 Feb 2024 15:29:15 +0100 Subject: [PATCH 4/4] feat: implement adaptor to turn DSP instances into fundsp nodes --- src/contrib/fundsp.rs | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/contrib/fundsp.rs b/src/contrib/fundsp.rs index f1f28d6..33bc9e5 100644 --- a/src/contrib/fundsp.rs +++ b/src/contrib/fundsp.rs @@ -1,6 +1,9 @@ use crate::dsp::DSP; use fundsp::audionode::{AudioNode, Frame}; use fundsp::combinator::An; +use fundsp::Float; +use numeric_array::ArrayLength; +use std::marker::PhantomData; use typenum::Unsigned; impl DSP<{ Node::Inputs::USIZE }, { Node::Outputs::USIZE }> for An @@ -19,12 +22,51 @@ where } } +#[derive(Debug, Clone)] +pub struct DspNode(PhantomData, PhantomData, P); + +pub fn dsp_node>( + dsp: P, +) -> DspNode { + DspNode(PhantomData, PhantomData, dsp) +} + +impl< + In: Send + Sync + Unsigned, + Out: Send + Sync + Unsigned, + P: Send + Sync + DSP<{ In::USIZE }, { Out::USIZE }>, + > AudioNode for DspNode +where + Self: Clone, + P::Sample: Float, + In: ArrayLength, + Out: ArrayLength, +{ + const ID: u64 = 0; + type Sample = P::Sample; + type Inputs = In; + type Outputs = Out; + type Setting = (); + + fn tick( + &mut self, + input: &Frame, + ) -> Frame { + let input = std::array::from_fn(|i| input[i]); + let output = self.2.process(input.into()); + Frame::from_iter(output) + } +} + #[cfg(test)] mod tests { use crate::dsp::{utils::slice_to_mono_block_mut, DSPBlock}; + use crate::dsp::blocks::Integrator; use fundsp::hacker32::*; + use super::*; + #[test] fn test_wrapper() { let mut dsp = sine_hz(440.0) * sine_hz(10.0); @@ -34,4 +76,15 @@ mod tests { insta::assert_csv_snapshot!(&output as &[_], { "[]" => insta::rounded_redaction(3) }) } + + #[test] + fn test_dsp_node() { + let mut integrator_node = dsp_node::(Integrator::::default()); + integrator_node.filter_mono(0.0); + integrator_node.filter_mono(1.0); + let actual = integrator_node.filter_mono(0.0); + let expected = 1.0; + + assert_eq!(expected, actual); + } }