From 5d3bf24c8fe8d737d12b6e4f0b87b93617862f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ju=CC=88rgen=20Hock?= Date: Sun, 18 Jun 2023 00:33:09 +0200 Subject: [PATCH] Create a prototype #7 --- rust/Cargo.toml | 16 ++++++++++ rust/Makefile | 19 +++++++++++ rust/examples/analysis.rs | 14 +++++++++ rust/src/lib.rs | 66 +++++++++++++++++++++++++++++++++++++++ rust/tests/test.rs | 29 +++++++++++++++++ 5 files changed, 144 insertions(+) create mode 100644 rust/Cargo.toml create mode 100644 rust/Makefile create mode 100644 rust/examples/analysis.rs create mode 100644 rust/src/lib.rs create mode 100644 rust/tests/test.rs diff --git a/rust/Cargo.toml b/rust/Cargo.toml new file mode 100644 index 0000000..f729ad4 --- /dev/null +++ b/rust/Cargo.toml @@ -0,0 +1,16 @@ +[package] +edition = "2021" +name = "qdft" +version = "0.1.0" +authors = ["Juergen Hock "] +repository = "https://github.com/jurihock/qdft" +description = "Constant-Q Sliding DFT" +readme = "README.md" +license = "MIT" +keywords = ["cqt", "constant-q", "sliding", "dft", "discrete", "fourier", "transform", "audio", "signal-processing", "dsp", "spectrum", "frequencies", "hz"] +categories = ["algorithms", "mathematics", "multimedia", "science"] + +[dependencies] +num = "*" + +[dev-dependencies] diff --git a/rust/Makefile b/rust/Makefile new file mode 100644 index 0000000..10058ad --- /dev/null +++ b/rust/Makefile @@ -0,0 +1,19 @@ +.PHONY: help build clean example test + +help: + @echo build + @echo clean + +build: + @cargo build + +clean: + @rm -rf target + +example: + @cargo build --examples + @cargo run --example analysis + +test: + @cargo build --tests + @cargo test --workspace diff --git a/rust/examples/analysis.rs b/rust/examples/analysis.rs new file mode 100644 index 0000000..7a765d8 --- /dev/null +++ b/rust/examples/analysis.rs @@ -0,0 +1,14 @@ +use num::Zero; +use num::complex::Complex; +use qdft::QDFT; + +fn main() { + let mut qdft = QDFT::new(44100.0, (100.0, 20000.0)); + + let n = 1; + let mut samples = vec![f32::zero(); n]; + let mut dfts = vec![Complex::::zero(); n]; + + qdft.qdft(&samples, &mut dfts); + qdft.iqdft(&dfts, &mut samples); +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs new file mode 100644 index 0000000..5bec4a4 --- /dev/null +++ b/rust/src/lib.rs @@ -0,0 +1,66 @@ +#![allow(unused)] + +use num::Float; +use num::Zero; +use num::complex::Complex; +use std::marker::PhantomData; + +pub struct QDFT + where T: Float, + F: Float { + samplerate: f64, + bandwidth: (f64, f64), + t: PhantomData, + f: PhantomData, +} + +pub type QDFT32 = QDFT; +pub type QDFT64 = QDFT; + +impl QDFT + where T: Float, + F: Float { + + pub fn new(samplerate: f64, + bandwidth: (f64, f64) + ) -> Self { + QDFT { + samplerate: samplerate, + bandwidth: bandwidth, + t: PhantomData, + f: PhantomData, + } + } + + pub fn qdft_scalar(&mut self, sample: &T, dft: &mut Complex::) { + *dft = Complex::::zero(); + } + + pub fn iqdft_scalar(&mut self, dft: &Complex::, sample: &mut T) { + *sample = T::zero(); + } + + #[inline] + pub fn qdft_vector(&mut self, samples: &[T], dfts: &mut [Complex::]) { + for i in 0..samples.len() { + self.qdft_scalar(&samples[i], &mut dfts[i]); + } + } + + #[inline] + pub fn iqdft_vector(&mut self, dfts: &[Complex::], samples: &mut [T]) { + for i in 0..samples.len() { + self.iqdft_scalar(&dfts[i], &mut samples[i]); + } + } + + #[inline] + pub fn qdft(&mut self, samples: &[T], dfts: &mut [Complex::]) { + self.qdft_vector(samples, dfts); + } + + #[inline] + pub fn iqdft(&mut self, dfts: &[Complex::], samples: &mut [T]) { + self.iqdft_vector(dfts, samples); + } +} diff --git a/rust/tests/test.rs b/rust/tests/test.rs new file mode 100644 index 0000000..16f9017 --- /dev/null +++ b/rust/tests/test.rs @@ -0,0 +1,29 @@ +#[cfg(test)] +mod tests { + + use num::One; + use num::Zero; + use num::complex::Complex; + use qdft::QDFT; + + #[test] + fn test() { + let mut qdft = QDFT::new(44100.0, (100.0, 20000.0)); + + let n = 1; + let mut samples = vec![f32::zero(); n]; + let mut dfts = vec![Complex::::zero(); n]; + + dfts[0] = Complex::one(); + assert_ne!(dfts[0], Complex::zero()); + + qdft.qdft(&samples, &mut dfts); + assert_eq!(dfts[0], Complex::zero()); + + samples[0] = f32::one(); + assert_ne!(samples[0], f32::zero()); + + qdft.iqdft(&dfts, &mut samples); + assert_eq!(samples[0], f32::zero()); + } +}