From afe7e682a0c28eb5a24df7c62b717af7240b7717 Mon Sep 17 00:00:00 2001 From: ToBinio Date: Wed, 24 Jun 2026 08:22:51 +0200 Subject: [PATCH] correct implementation --- src/main.rs | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/main.rs b/src/main.rs index d84a907..accedc3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,21 @@ fn main() { nannou::app(Model::new).update(update).run(); } +struct Complex { + real: f32, + imag: f32, +} + +impl Complex { + fn new(real: f32, imag: f32) -> Self { + Self { real, imag } + } + + fn length(&self) -> f32 { + self.real.hypot(self.imag) + } +} + struct Settings { width: f32, offset: u32, @@ -18,7 +33,7 @@ struct Model { window: Entity, target_samples: Vec, result_samples: Vec, - dft_result: Vec, + dft_result: Vec, } const MAX_SAMPLES: usize = 1024; @@ -41,21 +56,25 @@ fn dot_product(a: &[f32], b: &[f32]) -> f32 { a.iter().zip(b.iter()).map(|(a, b)| a * b).sum() } -fn naive_dft(samples: &[f32]) -> Vec { +fn naive_dft(samples: &[f32]) -> Vec { let mut result = Vec::new(); for i in 0..(samples.len() / 2) { let sin = generate_sin(i); let cos = generate_cos(i); - let dot = dot_product(samples, &sin) + dot_product(samples, &cos); - result.push(dot * (2. / MAX_SAMPLES as f32)); + let dot = Complex::new( + dot_product(samples, &sin) * (2. / MAX_SAMPLES as f32), + dot_product(samples, &cos) * (2. / MAX_SAMPLES as f32), + ); + + result.push(dot); } result } -fn inverse_dft(samples: &[f32]) -> Vec { +fn inverse_dft(samples: &[Complex]) -> Vec { let mut result = Vec::new(); for i in 0..MAX_SAMPLES { @@ -64,8 +83,8 @@ fn inverse_dft(samples: &[f32]) -> Vec { let sample = (i as f32) * (freq as f32 / MAX_SAMPLES as f32) * (2.0 * std::f32::consts::PI); - sum += f32::sin(sample) * amplitude; - sum += f32::cos(sample) * amplitude; + sum += f32::sin(sample) * amplitude.real; + sum += f32::cos(sample) * amplitude.imag; } result.push(sum); @@ -106,19 +125,17 @@ impl Model { .iter() .collect(); - let sample_compression = window.len() / MAX_SAMPLES; - let mut samples = Vec::with_capacity(MAX_SAMPLES); - let mut current_sample = 0; - for sample in window { - if current_sample > 0 { - current_sample -= 1; + let sample_compression = window.len() as f32 / MAX_SAMPLES as f32; + let mut next_pick = 0.; + for (i, sample) in window.into_iter().enumerate() { + if next_pick > i as f32 { continue; } samples.push(*sample); - current_sample = sample_compression; + next_pick += sample_compression; } samples @@ -183,15 +200,15 @@ fn draw_samples_point(draw: &Draw, samples: &[f32], area: Rect) { } } -fn draw_samples_bar(draw: &Draw, samples: &[f32], area: Rect) { +fn draw_samples_bar(draw: &Draw, samples: &[Complex], area: Rect) { let sample_width = area.w() / samples.len() as f32; - for (i, &sample) in samples.iter().enumerate() { + for (i, sample) in samples.iter().enumerate() { let left = i as f32 * sample_width + area.left(); draw.rect() .x_y(left, area.bottom() + area.h() / 2.0) - .w_h(sample_width, sample.abs() * area.h()) + .w_h(sample_width, sample.length().abs() * area.h()) .color(BLACK); } } -- 2.51.2